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., 51 Franklin Street, Fifth Floor, Boston,
 
  30 #======================================================================
 
  32 # backend code for customers and vendors
 
  35 #   DS. 2000-07-04  Created
 
  37 #======================================================================
 
  50   $main::lxdebug->enter_sub();
 
  52   my ( $self, $myconfig, $form ) = @_;
 
  55   my $dbh = $form->dbconnect($myconfig);
 
  57   my $cv = $form->{db} eq "customer" ? "customer" : "vendor";
 
  58   my $join_records = $form->{l_invnumber} || $form->{l_ordnumber} || $form->{l_quonumber};
 
  63   my %allowed_sort_columns = (
 
  65       "customernumber"     => "ct.customernumber",
 
  66       "vendornumber"       => "ct.vendornumber",
 
  68       "contact"            => "ct.contact",
 
  69       "phone"              => "ct.phone",
 
  71       "email"              => "ct.email",
 
  72       "street"             => "ct.street",
 
  73       "taxnumber"          => "ct.taxnumber",
 
  74       "business"           => "b.description",
 
  75       "invnumber"          => "ct.invnumber",
 
  76       "ordnumber"          => "ct.ordnumber",
 
  77       "quonumber"          => "ct.quonumber",
 
  78       "zipcode"            => "ct.zipcode",
 
  80       "country"            => "ct.country",
 
  82       "discount"           => "ct.discount",
 
  83       "insertdate"         => "ct.itime",
 
  84       "salesman"           => "e.name",
 
  85       "payment"            => "pt.description",
 
  86       "pricegroup"         => "pg.pricegroup",
 
  89   $form->{sort} ||= "name";
 
  91   if ( $join_records ) {
 
  92     # in UNION case order by hash key, e.g. salesman
 
  93     # the UNION created an implicit select around the result
 
  94     $sortorder = $allowed_sort_columns{$form->{sort}} ? $form->{sort} : "name";
 
  96     # in not UNION case order by hash value, e.g. e.name
 
  97     $sortorder = $allowed_sort_columns{$form->{sort}} ?  $allowed_sort_columns{$form->{sort}} : "ct.name";
 
  99   my $sortdir   = !defined $form->{sortdir} ? 'ASC' : $form->{sortdir} ? 'ASC' : 'DESC';
 
 101   if ($sortorder !~ /(business|id|discount|itime)/ && !$join_records) {
 
 102     $sortorder  = "lower($sortorder) ${sortdir}";
 
 104     $sortorder .= " ${sortdir}";
 
 107   if ($form->{"${cv}number"}) {
 
 108     $where .= " AND ct.${cv}number ILIKE ?";
 
 109     push(@values, like($form->{"${cv}number"}));
 
 112   foreach my $key (qw(name contact email)) {
 
 114       $where .= " AND ct.$key ILIKE ?";
 
 115       push(@values, like($form->{$key}));
 
 119   if ($form->{cp_name}) {
 
 120     $where .= " AND ct.id IN (SELECT cp_cv_id FROM contacts WHERE lower(cp_name) LIKE lower(?))";
 
 121     push @values, like($form->{cp_name});
 
 124   if ($form->{addr_street}) {
 
 125     $where .= qq| AND ((ct.street ILIKE ?) | .
 
 128               qq|         SELECT sc.trans_id FROM shipto sc | .
 
 129               qq|         WHERE (sc.module = 'CT') | .
 
 130               qq|           AND (sc.shiptostreet ILIKE ?) | .
 
 132     push @values, (like($form->{addr_street})) x 2;
 
 135   if ($form->{addr_zipcode}) {
 
 136     $where .= qq| AND ((ct.zipcode ILIKE ?) | .
 
 139               qq|         SELECT sc.trans_id FROM shipto sc | .
 
 140               qq|         WHERE (sc.module = 'CT') | .
 
 141               qq|           AND (sc.shiptozipcode ILIKE ?) | .
 
 143     push @values, (like($form->{addr_zipcode})) x 2;
 
 146   if ($form->{addr_city}) {
 
 147     $where .= " AND ((lower(ct.city) LIKE lower(?))
 
 152                         WHERE (sc.module = 'CT')
 
 153                           AND (lower(sc.shiptocity) LIKE lower(?))
 
 156     push @values, (like($form->{addr_city})) x 2;
 
 159   if ($form->{addr_country}) {
 
 160     $where .= " AND ((lower(ct.country) LIKE lower(?))
 
 165                         WHERE (so.module = 'CT')
 
 166                           AND (lower(so.shiptocountry) LIKE lower(?))
 
 169     push @values, (like($form->{addr_country})) x 2;
 
 172   if ($form->{addr_gln}) {
 
 173     $where .= " AND ((lower(ct.gln) LIKE lower(?))
 
 178                         WHERE (so.module = 'CT')
 
 179                           AND (lower(so.shiptogln) LIKE lower(?))
 
 182     push @values, (like($form->{addr_gln})) x 2;
 
 185   if ( $form->{status} eq 'orphaned' ) {
 
 187       qq| AND ct.id NOT IN | .
 
 188       qq|   (SELECT o.${cv}_id FROM oe o, $cv cv WHERE cv.id = o.${cv}_id)|;
 
 189     if ($cv eq 'customer') {
 
 191         qq| AND ct.id NOT IN | .
 
 192         qq| (SELECT a.customer_id FROM ar a, customer cv | .
 
 193         qq|  WHERE cv.id = a.customer_id)|;
 
 195     if ($cv eq 'vendor') {
 
 197         qq| AND ct.id NOT IN | .
 
 198         qq| (SELECT a.vendor_id FROM ap a, vendor cv | .
 
 199         qq|  WHERE cv.id = a.vendor_id)|;
 
 201     $form->{l_invnumber} = $form->{l_ordnumber} = $form->{l_quonumber} = "";
 
 204   if ($form->{obsolete} eq "Y") {
 
 205     $where .= qq| AND ct.obsolete|;
 
 206   } elsif ($form->{obsolete} eq "N") {
 
 207     $where .= qq| AND NOT ct.obsolete|;
 
 210   if ($form->{business_id}) {
 
 211     $where .= qq| AND (ct.business_id = ?)|;
 
 212     push(@values, conv_i($form->{business_id}));
 
 215   if ($form->{salesman_id}) {
 
 216     $where .= qq| AND (ct.salesman_id = ?)|;
 
 217     push(@values, conv_i($form->{salesman_id}));
 
 220   if($form->{insertdatefrom}) {
 
 221     $where .= qq| AND (ct.itime::DATE >= ?)|;
 
 222     push@values, conv_date($form->{insertdatefrom});
 
 225   if($form->{insertdateto}) {
 
 226     $where .= qq| AND (ct.itime::DATE <= ?)|;
 
 227     push @values, conv_date($form->{insertdateto});
 
 231     my @tokens = parse_line('\s+', 0, $form->{all});
 
 233           ct.${cv}number ILIKE ? OR
 
 236     push @values, ("%$_%")x2 for @tokens;
 
 239   # Nur Kunden finden, bei denen ich selber der Verkäufer bin
 
 240   # Gilt nicht für Lieferanten
 
 241   if ($cv eq 'customer' &&   !$main::auth->assert('customer_vendor_all_edit', 1)) {
 
 242     $where .= qq| AND ct.salesman_id = (select em.id from employee em where em.login = ?)|;
 
 243     push(@values, $::myconfig{login});
 
 246   my ($cvar_where, @cvar_values) = CVar->build_filter_query('module'         => 'CT',
 
 247                                                             'trans_id_field' => 'ct.id',
 
 251     $where .= qq| AND ($cvar_where)|;
 
 252     push @values, @cvar_values;
 
 255   my $pg_select = $form->{l_pricegroup} ? qq|, pg.pricegroup as pricegroup | : '';
 
 256   my $pg_join   = $form->{l_pricegroup} ? qq|LEFT JOIN pricegroup pg ON (ct.pricegroup_id = pg.id) | : '';
 
 258     qq|SELECT ct.*, ct.itime::DATE AS insertdate, b.description AS business, e.name as salesman, | .
 
 259     qq|  pt.description as payment | .
 
 261     (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) .
 
 263     qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
 
 264     qq|LEFT JOIN employee e ON (ct.salesman_id = e.id) | .
 
 265     qq|LEFT JOIN payment_terms pt ON (ct.payment_id = pt.id) | .
 
 269   my @saved_values = @values;
 
 270   # redo for invoices, orders and quotations
 
 274     if ($form->{l_invnumber}) {
 
 275       my $ar = $cv eq 'customer' ? 'ar' : 'ap';
 
 276       my $module = $ar eq 'ar' ? 'is' : 'ir';
 
 277       push(@values, @saved_values);
 
 280         qq|SELECT ct.*, ct.itime::DATE AS insertdate, b.description AS business, e.name as salesman, | .
 
 281         qq|  pt.description as payment | .
 
 283         qq|, a.invnumber, a.ordnumber, a.quonumber, a.id AS invid, | .
 
 284         qq|  '$module' AS module, 'invoice' AS formtype, | .
 
 285         qq|  (a.amount = a.paid) AS closed | .
 
 287         qq|JOIN $ar a ON (a.${cv}_id = ct.id) | .
 
 288         qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
 
 289         qq|LEFT JOIN employee e ON (ct.salesman_id = e.id) | .
 
 290         qq|LEFT JOIN payment_terms pt ON (ct.payment_id = pt.id) | .
 
 292         qq|WHERE $where AND (a.invoice = '1')|;
 
 295     if ( $form->{l_ordnumber} ) {
 
 296       push(@values, @saved_values);
 
 299         qq|SELECT ct.*, ct.itime::DATE AS insertdate, b.description AS business, e.name as salesman, | .
 
 300         qq|  pt.description as payment | .
 
 302         qq|, ' ' AS invnumber, o.ordnumber, o.quonumber, o.id AS invid, | .
 
 303         qq|  'oe' AS module, 'order' AS formtype, o.closed | .
 
 305         qq|JOIN oe o ON (o.${cv}_id = ct.id) | .
 
 306         qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
 
 307         qq|LEFT JOIN employee e ON (ct.salesman_id = e.id) | .
 
 308         qq|LEFT JOIN payment_terms pt ON (ct.payment_id = pt.id) | .
 
 310         qq|WHERE $where AND (o.quotation = '0')|;
 
 313     if ( $form->{l_quonumber} ) {
 
 314       push(@values, @saved_values);
 
 317         qq|SELECT ct.*, ct.itime::DATE AS insertdate, b.description AS business, e.name as salesman, | .
 
 318         qq|  pt.description as payment | .
 
 320         qq|, ' ' AS invnumber, o.ordnumber, o.quonumber, o.id AS invid, | .
 
 321         qq|  'oe' AS module, 'quotation' AS formtype, o.closed | .
 
 323         qq|JOIN oe o ON (o.${cv}_id = ct.id) | .
 
 324         qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
 
 325         qq|LEFT JOIN employee e ON (ct.salesman_id = e.id) | .
 
 326         qq|LEFT JOIN payment_terms pt ON (ct.payment_id = pt.id) | .
 
 328         qq|WHERE $where AND (o.quotation = '1')|;
 
 332   $query .= qq| ORDER BY $sortorder|;
 
 334   $form->{CT} = selectall_hashref_query($form, $dbh, $query, @values);
 
 336   $main::lxdebug->leave_sub();
 
 340   $main::lxdebug->enter_sub();
 
 342   my ( $self, $myconfig, $form ) = @_;
 
 344   die 'Missing argument: cp_id' unless $::form->{cp_id};
 
 346   my $dbh   = SL::DB->client->dbh;
 
 348     qq|SELECT * FROM contacts c | .
 
 349     qq|WHERE cp_id = ? ORDER BY cp_id limit 1|;
 
 350   my $sth = prepare_execute_query($form, $dbh, $query, $form->{cp_id});
 
 351   my $ref = $sth->fetchrow_hashref("NAME_lc");
 
 353   map { $form->{$_} = $ref->{$_} } keys %$ref;
 
 355   $query = qq|SELECT COUNT(cp_id) AS used FROM (
 
 356     SELECT cp_id FROM oe UNION
 
 357     SELECT cp_id FROM ar UNION
 
 358     SELECT cp_id FROM ap UNION
 
 359     SELECT cp_id FROM delivery_orders
 
 360   ) AS cpid WHERE cp_id = ? OR ? = 0|;
 
 361   ($form->{cp_used}) = selectfirst_array_query($form, $dbh, $query, ($form->{cp_id})x2);
 
 365   $main::lxdebug->leave_sub();
 
 369   $main::lxdebug->enter_sub();
 
 374   Common::check_params(\%params, qw(vc id));
 
 376   my $myconfig = \%main::myconfig;
 
 377   my $form     = $main::form;
 
 379   my $dbh      = $params{dbh} || $form->get_standard_dbh($myconfig);
 
 381   my $table        = $params{vc} eq 'customer' ? 'customer' : 'vendor';
 
 382   my @ids          = ref $params{id} eq 'ARRAY' ? @{ $params{id} } : ($params{id});
 
 383   my $placeholders = join ", ", ('?') x scalar @ids;
 
 384   my $c_mandate    = $params{vc} eq 'customer' ? ', mandator_id, mandate_date_of_signature' : '';
 
 385   my $query        = qq|SELECT id, name, account_number, bank, bank_code, iban, bic ${c_mandate}
 
 387                         WHERE id IN (${placeholders})|;
 
 389   my $result       = selectall_hashref_query($form, $dbh, $query, map { conv_i($_) } @ids);
 
 391   if (ref $params{id} eq 'ARRAY') {
 
 392     $result = { map { $_->{id} => $_ } @{ $result } };
 
 394     $result = $result->[0] || { 'id' => $params{id} };
 
 397   $main::lxdebug->leave_sub();
 
 402 sub search_contacts {
 
 403   $::lxdebug->enter_sub;
 
 408   my $dbh       = $params{dbh} || $::form->get_standard_dbh;
 
 411     'cp_name'   => 'cp_name, cp_givenname',
 
 412     'vcname'    => 'vcname, cp_name, cp_givenname',
 
 413     'vcnumber'  => 'vcnumber, cp_name, cp_givenname',
 
 416   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);
 
 418   my $order_by  = $sortcols{$::form->{sort}} ? $::form->{sort} : 'cp_name';
 
 419   $::form->{sort} = $order_by;
 
 420   $order_by     = $sortspecs{$order_by} if ($sortspecs{$order_by});
 
 422   my $sortdir   = $::form->{sortdir} ? 'ASC' : 'DESC';
 
 423   $order_by     =~ s/,/ ${sortdir},/g;
 
 424   $order_by    .= " $sortdir";
 
 426   my @where_tokens = ();
 
 429   if ($params{search_term}) {
 
 432       'cp.cp_name      ILIKE ?',
 
 433       'cp.cp_givenname ILIKE ?',
 
 434       'cp.cp_email     ILIKE ?';
 
 435     push @values, (like($params{search_term})) x 3;
 
 437     if (($params{search_term} =~ m/\d/) && ($params{search_term} !~ m/[^\d \(\)+\-]/)) {
 
 438       my $number =  $params{search_term};
 
 439       $number    =~ s/[^\d]//g;
 
 440       $number    =  join '[ /\(\)+\-]*', split(m//, $number);
 
 442       push @tokens, map { "($_ ~ '$number')" } qw(cp_phone1 cp_phone2 cp_mobile1 cp_mobile2);
 
 445     push @where_tokens, map { "($_)" } join ' OR ', @tokens;
 
 448   my ($cvar_where, @cvar_values) = CVar->build_filter_query('module'         => 'Contacts',
 
 449                                                             'trans_id_field' => 'cp.cp_id',
 
 450                                                             'filter'         => $params{filter});
 
 453     push @where_tokens, $cvar_where;
 
 454     push @values, @cvar_values;
 
 457   if (my $filter = $params{filter}) {
 
 458     for (qw(name title givenname email project abteilung)) {
 
 459       next unless $filter->{"cp_$_"};
 
 460       add_token(\@where_tokens, \@values, col =>  "cp.cp_$_", val => $filter->{"cp_$_"}, method => 'ILIKE', esc => 'substr');
 
 463     push @where_tokens, 'cp.cp_cv_id IS NOT NULL' if $filter->{status} eq 'active';
 
 464     push @where_tokens, 'cp.cp_cv_id IS NULL'     if $filter->{status} eq 'orphaned';
 
 467   my $where = @where_tokens ? 'WHERE ' . join ' AND ', @where_tokens : '';
 
 469   my $query     = qq|SELECT cp.*,
 
 470                        COALESCE(c.id,             v.id)           AS vcid,
 
 471                        COALESCE(c.name,           v.name)         AS vcname,
 
 472                        COALESCE(c.customernumber, v.vendornumber) AS vcnumber,
 
 473                        CASE WHEN c.name IS NULL THEN 'vendor' ELSE 'customer' END AS db
 
 475                      LEFT JOIN customer c ON (cp.cp_cv_id = c.id)
 
 476                      LEFT JOIN vendor v   ON (cp.cp_cv_id = v.id)
 
 480   my $contacts  = selectall_hashref_query($::form, $dbh, $query, @values);
 
 482   $::lxdebug->leave_sub;
 
 484   return @{ $contacts };