1 #=====================================================================
4 # Based on SQL-Ledger Version 2.1.9
5 # Web http://www.lx-office.org
7 #=====================================================================
8 # SQL-Ledger Accounting
11 # Author: Dieter Simader
12 # Email: dsimader@sql-ledger.org
13 # Web: http://www.sql-ledger.org
17 # This program is free software; you can redistribute it and/or modify
18 # it under the terms of the GNU General Public License as published by
19 # the Free Software Foundation; either version 2 of the License, or
20 # (at your option) any later version.
22 # This program is distributed in the hope that it will be useful,
23 # but WITHOUT ANY WARRANTY; without even the implied warranty of
24 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 # GNU General Public License for more details.
26 # You should have received a copy of the GNU General Public License
27 # along with this program; if not, write to the Free Software
28 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #======================================================================
31 # backend code for customers and vendors
34 # DS. 2000-07-04 Created
36 #======================================================================
47 $main::lxdebug->enter_sub();
49 my ( $self, $myconfig, $form ) = @_;
52 my $dbh = $form->dbconnect($myconfig);
54 my $cv = $form->{db} eq "customer" ? "customer" : "vendor";
55 my $join_records = $form->{l_invnumber} || $form->{l_ordnumber} || $form->{l_quonumber};
60 my %allowed_sort_columns = (
62 "customernumber" => "ct.customernumber",
63 "vendornumber" => "ct.vendornumber",
65 "contact" => "ct.contact",
66 "phone" => "ct.phone",
68 "email" => "ct.email",
69 "street" => "ct.street",
70 "taxnumber" => "ct.taxnumber",
71 "business" => "b.description",
72 "invnumber" => "ct.invnumber",
73 "ordnumber" => "ct.ordnumber",
74 "quonumber" => "ct.quonumber",
75 "zipcode" => "ct.zipcode",
77 "country" => "ct.country",
79 "discount" => "ct.discount",
80 "insertdate" => "ct.itime",
81 "salesman" => "e.name",
82 "payment" => "pt.description",
83 "pricegroup" => "pg.pricegroup",
86 $form->{sort} ||= "name";
88 if ( $join_records ) {
89 # in UNION case order by hash key, e.g. salesman
90 # the UNION created an implicit select around the result
91 $sortorder = $allowed_sort_columns{$form->{sort}} ? $form->{sort} : "name";
93 # in not UNION case order by hash value, e.g. e.name
94 $sortorder = $allowed_sort_columns{$form->{sort}} ? $allowed_sort_columns{$form->{sort}} : "ct.name";
96 my $sortdir = !defined $form->{sortdir} ? 'ASC' : $form->{sortdir} ? 'ASC' : 'DESC';
98 if ($sortorder !~ /(business|id|discount|itime)/ && !$join_records) {
99 $sortorder = "lower($sortorder) ${sortdir}";
101 $sortorder .= " ${sortdir}";
104 if ($form->{"${cv}number"}) {
105 $where .= " AND ct.${cv}number ILIKE ?";
106 push(@values, '%' . $form->{"${cv}number"} . '%');
109 foreach my $key (qw(name contact email)) {
111 $where .= " AND ct.$key ILIKE ?";
112 push(@values, '%' . $form->{$key} . '%');
116 if ($form->{cp_name}) {
117 $where .= " AND ct.id IN (SELECT cp_cv_id FROM contacts WHERE lower(cp_name) LIKE lower(?))";
118 push @values, '%' . $form->{cp_name} . '%';
121 if ($form->{addr_city}) {
122 $where .= " AND ((lower(ct.city) LIKE lower(?))
127 WHERE (sc.module = 'CT')
128 AND (lower(sc.shiptocity) LIKE lower(?))
131 push @values, ('%' . $form->{addr_city} . '%') x 2;
134 if ($form->{addr_country}) {
135 $where .= " AND ((lower(ct.country) LIKE lower(?))
140 WHERE (so.module = 'CT')
141 AND (lower(so.shiptocountry) LIKE lower(?))
144 push @values, ('%' . $form->{addr_country} . '%') x 2;
147 if ($form->{addr_gln}) {
148 $where .= " AND ((lower(ct.gln) LIKE lower(?))
153 WHERE (so.module = 'CT')
154 AND (lower(so.shiptogln) LIKE lower(?))
157 push @values, ('%' . $form->{addr_gln} . '%') x 2;
160 if ( $form->{status} eq 'orphaned' ) {
162 qq| AND ct.id NOT IN | .
163 qq| (SELECT o.${cv}_id FROM oe o, $cv cv WHERE cv.id = o.${cv}_id)|;
164 if ($cv eq 'customer') {
166 qq| AND ct.id NOT IN | .
167 qq| (SELECT a.customer_id FROM ar a, customer cv | .
168 qq| WHERE cv.id = a.customer_id)|;
170 if ($cv eq 'vendor') {
172 qq| AND ct.id NOT IN | .
173 qq| (SELECT a.vendor_id FROM ap a, vendor cv | .
174 qq| WHERE cv.id = a.vendor_id)|;
176 $form->{l_invnumber} = $form->{l_ordnumber} = $form->{l_quonumber} = "";
179 if ($form->{obsolete} eq "Y") {
180 $where .= qq| AND ct.obsolete|;
181 } elsif ($form->{obsolete} eq "N") {
182 $where .= qq| AND NOT ct.obsolete|;
185 if ($form->{business_id}) {
186 $where .= qq| AND (ct.business_id = ?)|;
187 push(@values, conv_i($form->{business_id}));
190 if ($form->{salesman_id}) {
191 $where .= qq| AND (ct.salesman_id = ?)|;
192 push(@values, conv_i($form->{salesman_id}));
195 if($form->{insertdatefrom}) {
196 $where .= qq| AND (ct.itime::DATE >= ?)|;
197 push@values, conv_date($form->{insertdatefrom});
200 if($form->{insertdateto}) {
201 $where .= qq| AND (ct.itime::DATE <= ?)|;
202 push @values, conv_date($form->{insertdateto});
205 # Nur Kunden finden, bei denen ich selber der Verkäufer bin
206 # Gilt nicht für Lieferanten
207 if ($cv eq 'customer' && !$main::auth->assert('customer_vendor_all_edit', 1)) {
208 $where .= qq| AND ct.salesman_id = (select em.id from employee em where em.login = ?)|;
209 push(@values, $::myconfig{login});
212 my ($cvar_where, @cvar_values) = CVar->build_filter_query('module' => 'CT',
213 'trans_id_field' => 'ct.id',
217 $where .= qq| AND ($cvar_where)|;
218 push @values, @cvar_values;
221 if ($form->{addr_street}) {
222 $where .= qq| AND (ct.street ILIKE ?)|;
223 push @values, '%' . $form->{addr_street} . '%';
226 if ($form->{addr_zipcode}) {
227 $where .= qq| AND (ct.zipcode ILIKE ?)|;
228 push @values, $form->{addr_zipcode} . '%';
231 my $pg_select = $form->{l_pricegroup} ? qq|, pg.pricegroup as pricegroup | : '';
232 my $pg_join = $form->{l_pricegroup} ? qq|LEFT JOIN pricegroup pg ON (ct.klass = pg.id) | : '';
234 qq|SELECT ct.*, ct.itime::DATE AS insertdate, b.description AS business, e.name as salesman, | .
235 qq| pt.description as payment | .
237 (qq|, NULL AS invnumber, NULL AS ordnumber, NULL AS quonumber, NULL AS invid, NULL AS module, NULL AS formtype, NULL AS closed | x!! $join_records) .
239 qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
240 qq|LEFT JOIN employee e ON (ct.salesman_id = e.id) | .
241 qq|LEFT JOIN payment_terms pt ON (ct.payment_id = pt.id) | .
245 my @saved_values = @values;
246 # redo for invoices, orders and quotations
250 if ($form->{l_invnumber}) {
251 my $ar = $cv eq 'customer' ? 'ar' : 'ap';
252 my $module = $ar eq 'ar' ? 'is' : 'ir';
253 push(@values, @saved_values);
256 qq|SELECT ct.*, ct.itime::DATE AS insertdate, b.description AS business, e.name as salesman, | .
257 qq| pt.description as payment | .
259 qq|, a.invnumber, a.ordnumber, a.quonumber, a.id AS invid, | .
260 qq| '$module' AS module, 'invoice' AS formtype, | .
261 qq| (a.amount = a.paid) AS closed | .
263 qq|JOIN $ar a ON (a.${cv}_id = ct.id) | .
264 qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
265 qq|LEFT JOIN employee e ON (ct.salesman_id = e.id) | .
266 qq|LEFT JOIN payment_terms pt ON (ct.payment_id = pt.id) | .
268 qq|WHERE $where AND (a.invoice = '1')|;
271 if ( $form->{l_ordnumber} ) {
272 push(@values, @saved_values);
275 qq|SELECT ct.*, ct.itime::DATE AS insertdate, b.description AS business, e.name as salesman, | .
276 qq| pt.description as payment | .
278 qq|, ' ' AS invnumber, o.ordnumber, o.quonumber, o.id AS invid, | .
279 qq| 'oe' AS module, 'order' AS formtype, o.closed | .
281 qq|JOIN oe o ON (o.${cv}_id = ct.id) | .
282 qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
283 qq|LEFT JOIN employee e ON (ct.salesman_id = e.id) | .
284 qq|LEFT JOIN payment_terms pt ON (ct.payment_id = pt.id) | .
286 qq|WHERE $where AND (o.quotation = '0')|;
289 if ( $form->{l_quonumber} ) {
290 push(@values, @saved_values);
293 qq|SELECT ct.*, ct.itime::DATE AS insertdate, b.description AS business, e.name as salesman, | .
294 qq| pt.description as payment | .
296 qq|, ' ' AS invnumber, o.ordnumber, o.quonumber, o.id AS invid, | .
297 qq| 'oe' AS module, 'quotation' AS formtype, o.closed | .
299 qq|JOIN oe o ON (o.${cv}_id = ct.id) | .
300 qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
301 qq|LEFT JOIN employee e ON (ct.salesman_id = e.id) | .
302 qq|LEFT JOIN payment_terms pt ON (ct.payment_id = pt.id) | .
304 qq|WHERE $where AND (o.quotation = '1')|;
308 $query .= qq| ORDER BY $sortorder|;
310 $form->{CT} = selectall_hashref_query($form, $dbh, $query, @values);
312 $main::lxdebug->leave_sub();
316 $main::lxdebug->enter_sub();
318 my ( $self, $myconfig, $form ) = @_;
320 die 'Missing argument: cp_id' unless $::form->{cp_id};
322 my $dbh = $form->dbconnect($myconfig);
324 qq|SELECT * FROM contacts c | .
325 qq|WHERE cp_id = ? ORDER BY cp_id limit 1|;
326 my $sth = prepare_execute_query($form, $dbh, $query, $form->{cp_id});
327 my $ref = $sth->fetchrow_hashref("NAME_lc");
329 map { $form->{$_} = $ref->{$_} } keys %$ref;
331 $query = qq|SELECT COUNT(cp_id) AS used FROM (
332 SELECT cp_id FROM oe UNION
333 SELECT cp_id FROM ar UNION
334 SELECT cp_id FROM ap UNION
335 SELECT cp_id FROM delivery_orders
336 ) AS cpid WHERE cp_id = ? OR ? = 0|;
337 ($form->{cp_used}) = selectfirst_array_query($form, $dbh, $query, ($form->{cp_id})x2);
342 $main::lxdebug->leave_sub();
346 $main::lxdebug->enter_sub();
351 Common::check_params(\%params, qw(vc id));
353 my $myconfig = \%main::myconfig;
354 my $form = $main::form;
356 my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig);
358 my $table = $params{vc} eq 'customer' ? 'customer' : 'vendor';
359 my @ids = ref $params{id} eq 'ARRAY' ? @{ $params{id} } : ($params{id});
360 my $placeholders = join ", ", ('?') x scalar @ids;
361 my $c_mandate = $params{vc} eq 'customer' ? ', mandator_id, mandate_date_of_signature' : '';
362 my $query = qq|SELECT id, name, account_number, bank, bank_code, iban, bic ${c_mandate}
364 WHERE id IN (${placeholders})|;
366 my $result = selectall_hashref_query($form, $dbh, $query, map { conv_i($_) } @ids);
368 if (ref $params{id} eq 'ARRAY') {
369 $result = { map { $_->{id} => $_ } @{ $result } };
371 $result = $result->[0] || { 'id' => $params{id} };
374 $main::lxdebug->leave_sub();
379 sub search_contacts {
380 $::lxdebug->enter_sub;
385 my $dbh = $params{dbh} || $::form->get_standard_dbh;
388 'cp_name' => 'cp_name, cp_givenname',
389 'vcname' => 'vcname, cp_name, cp_givenname',
390 'vcnumber' => 'vcnumber, cp_name, cp_givenname',
393 my %sortcols = map { $_ => 1 } qw(cp_name cp_givenname cp_phone1 cp_phone2 cp_mobile1 cp_email cp_street cp_zipcode cp_city cp_position vcname vcnumber);
395 my $order_by = $sortcols{$::form->{sort}} ? $::form->{sort} : 'cp_name';
396 $::form->{sort} = $order_by;
397 $order_by = $sortspecs{$order_by} if ($sortspecs{$order_by});
399 my $sortdir = $::form->{sortdir} ? 'ASC' : 'DESC';
400 $order_by =~ s/,/ ${sortdir},/g;
401 $order_by .= " $sortdir";
403 my @where_tokens = ();
406 if ($params{search_term}) {
409 'cp.cp_name ILIKE ?',
410 'cp.cp_givenname ILIKE ?',
411 'cp.cp_email ILIKE ?';
412 push @values, ('%' . $params{search_term} . '%') x 3;
414 if (($params{search_term} =~ m/\d/) && ($params{search_term} !~ m/[^\d \(\)+\-]/)) {
415 my $number = $params{search_term};
416 $number =~ s/[^\d]//g;
417 $number = join '[ /\(\)+\-]*', split(m//, $number);
419 push @tokens, map { "($_ ~ '$number')" } qw(cp_phone1 cp_phone2 cp_mobile1 cp_mobile2);
422 push @where_tokens, map { "($_)" } join ' OR ', @tokens;
425 my ($cvar_where, @cvar_values) = CVar->build_filter_query('module' => 'Contacts',
426 'trans_id_field' => 'cp.cp_id',
427 'filter' => $params{filter});
430 push @where_tokens, $cvar_where;
431 push @values, @cvar_values;
434 if (my $filter = $params{filter}) {
435 for (qw(name title givenname email project abteilung)) {
436 next unless $filter->{"cp_$_"};
437 add_token(\@where_tokens, \@values, col => "cp.cp_$_", val => $filter->{"cp_$_"}, method => 'ILIKE', esc => 'substr');
440 push @where_tokens, 'cp.cp_cv_id IS NOT NULL' if $filter->{status} eq 'active';
441 push @where_tokens, 'cp.cp_cv_id IS NULL' if $filter->{status} eq 'orphaned';
444 my $where = @where_tokens ? 'WHERE ' . join ' AND ', @where_tokens : '';
446 my $query = qq|SELECT cp.*,
447 COALESCE(c.id, v.id) AS vcid,
448 COALESCE(c.name, v.name) AS vcname,
449 COALESCE(c.customernumber, v.vendornumber) AS vcnumber,
450 CASE WHEN c.name IS NULL THEN 'vendor' ELSE 'customer' END AS db
452 LEFT JOIN customer c ON (cp.cp_cv_id = c.id)
453 LEFT JOIN vendor v ON (cp.cp_cv_id = v.id)
457 my $contacts = selectall_hashref_query($::form, $dbh, $query, @values);
459 $::lxdebug->leave_sub;
461 return @{ $contacts };