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 #======================================================================
 
  52   $main::lxdebug->enter_sub();
 
  54   my ( $self, $myconfig, $form ) = @_;
 
  56   my $cv = $form->{db} eq "customer" ? "customer" : "vendor";
 
  58   my $dbh   = $form->dbconnect($myconfig);
 
  60     qq|SELECT ct.*, b.id AS business, cp.* | .
 
  62     qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
 
  63     qq|LEFT JOIN contacts cp ON (ct.id = cp.cp_cv_id) | .
 
  64     qq|WHERE (ct.id = ?) | .
 
  65     qq|ORDER BY cp.cp_id LIMIT 1|;
 
  66   my $sth = prepare_execute_query($form, $dbh, $query, $form->{id});
 
  68   my $ref = $sth->fetchrow_hashref("NAME_lc");
 
  70   map { $form->{$_} = $ref->{$_} } keys %$ref;
 
  72   # remove any trailing whitespace
 
  73   $form->{curr} =~ s/\s*$//;
 
  76   if ( $form->{salesman_id} ) {
 
  78       qq|SELECT ct.name AS salesman | .
 
  82       selectrow_query($form, $dbh, $query, $form->{salesman_id});
 
  85   my ($employee_id) = selectrow_query($form, $dbh, qq|SELECT id FROM employee WHERE login = ?|, $form->{login});
 
  87     qq|SELECT n.*, n.itime::DATE AS created_on,
 
  88          e.name AS created_by_name, e.login AS created_by_login
 
  90        LEFT JOIN employee e ON (n.created_by = e.id)
 
  91        WHERE (n.trans_id = ?) AND (n.trans_module = 'ct')|;
 
  92   $form->{NOTES} = selectall_hashref_query($form, $dbh, $query, conv_i($form->{id}));
 
  95     qq|SELECT fu.follow_up_date, fu.done AS follow_up_done, e.name AS created_for_name, e.name AS created_for_login
 
  97        LEFT JOIN employee e ON (fu.created_for_user = e.id)
 
  98        WHERE (fu.note_id = ?)
 
  99          AND NOT COALESCE(fu.done, FALSE)
 
 100          AND (   (fu.created_by = ?)
 
 101               OR (fu.created_by IN (SELECT DISTINCT what FROM follow_up_access WHERE who = ?)))|;
 
 102   $sth = prepare_query($form, $dbh, $query);
 
 104   foreach my $note (@{ $form->{NOTES} }) {
 
 105     do_statement($form, $sth, $query, conv_i($note->{id}), conv_i($note->{created_by}), conv_i($employee_id));
 
 106     $ref = $sth->fetchrow_hashref();
 
 108     map { $note->{$_} = $ref->{$_} } keys %{ $ref } if ($ref);
 
 113   if ($form->{edit_note_id}) {
 
 115       qq|SELECT n.id AS NOTE_id, n.subject AS NOTE_subject, n.body AS NOTE_body,
 
 116            fu.id AS FU_id, fu.follow_up_date AS FU_date, fu.done AS FU_done, fu.created_for_user AS FU_created_for_user
 
 118          LEFT JOIN follow_ups fu ON ((n.id = fu.note_id) AND NOT COALESCE(fu.done, FALSE))
 
 120     $ref = selectfirst_hashref_query($form, $dbh, $query, conv_i($form->{edit_note_id}));
 
 123       foreach my $key (keys %{ $ref }) {
 
 125         $new_key          =~ s/^([^_]+)/\U$1\E/;
 
 126         $form->{$new_key} =  $ref->{$key};
 
 131   # check if it is orphaned
 
 132   my $arap      = ( $form->{db} eq 'customer' ) ? "ar" : "ap";
 
 135   if ($form->{db} eq 'vendor') {
 
 136     $makemodel = qq| UNION SELECT 1 FROM makemodel mm WHERE mm.make = ?|;
 
 143     qq|JOIN $cv ct ON (a.${cv}_id = ct.id) | .
 
 144     qq|WHERE ct.id = ? | .
 
 148     qq|JOIN $cv ct ON (a.${cv}_id = ct.id) | .
 
 151   my ($dummy) = selectrow_query($form, $dbh, $query, (conv_i($form->{id})) x $num_args);
 
 153   $form->{status} = "orphaned" unless ($dummy);
 
 157   $main::lxdebug->leave_sub();
 
 160 sub populate_drop_down_boxes {
 
 161   $main::lxdebug->enter_sub();
 
 163   my ($self, $myconfig, $form, $provided_dbh) = @_;
 
 166   my $dbh = $provided_dbh ? $provided_dbh : $form->dbconnect($myconfig);
 
 169   $query = qq|SELECT id, description FROM business ORDER BY id|;
 
 170   $form->{all_business} = selectall_hashref_query($form, $dbh, $query);
 
 174     qq|SELECT shipto_id, shiptoname, shiptodepartment_1, shiptostreet, shiptocity
 
 176        WHERE (trans_id = ?) AND (module = 'CT')|;
 
 177   $form->{SHIPTO} = selectall_hashref_query($form, $dbh, $query, $form->{id});
 
 180   $query  = qq|SELECT cp_id, cp_name, cp_givenname FROM contacts WHERE cp_cv_id = ? ORDER BY cp_name|;
 
 181   $form->{CONTACTS} = selectall_hashref_query($form, $dbh, $query, $form->{id});
 
 184   $query = qq|SELECT id, description FROM language ORDER BY id|;
 
 185   $form->{languages} = selectall_hashref_query($form, $dbh, $query);
 
 188   $query = qq|SELECT id, description FROM payment_terms ORDER BY sortkey|;
 
 189   $form->{payment_terms} = selectall_hashref_query($form, $dbh, $query);
 
 191   $dbh->disconnect() unless ($provided_dbh);
 
 193   $main::lxdebug->leave_sub();
 
 196 sub query_titles_and_greetings {
 
 197   $main::lxdebug->enter_sub();
 
 199   my ( $self, $myconfig, $form ) = @_;
 
 200   my ( %tmp,  $ref, $query );
 
 202   my $dbh = $form->dbconnect($myconfig);
 
 205     qq|SELECT DISTINCT(greeting) | .
 
 207     qq|WHERE greeting ~ '[a-zA-Z]' | .
 
 209     qq|SELECT DISTINCT(greeting) | .
 
 211     qq|WHERE greeting ~ '[a-zA-Z]' | .
 
 212     qq|ORDER BY greeting|;
 
 214   map({ $tmp{$_} = 1; } selectall_array_query($form, $dbh, $query));
 
 215   $form->{COMPANY_GREETINGS} = [ sort(keys(%tmp)) ];
 
 218     qq|SELECT DISTINCT(cp_title) | .
 
 220     qq|WHERE cp_title ~ '[a-zA-Z]'|;
 
 221   $form->{TITLES} = [ selectall_array_query($form, $dbh, $query) ];
 
 224     qq|SELECT DISTINCT(cp_abteilung) | .
 
 226     qq|WHERE cp_abteilung ~ '[a-zA-Z]'|;
 
 227   $form->{DEPARTMENT} = [ selectall_array_query($form, $dbh, $query) ];
 
 230   $main::lxdebug->leave_sub();
 
 234   $main::lxdebug->enter_sub();
 
 236   my ( $self, $myconfig, $form ) = @_;
 
 238   # set pricegroup to default
 
 239   $form->{klass} = 0 unless ($form->{klass});
 
 241   # connect to database
 
 242   my $dbh = $form->get_standard_dbh;
 
 245     $form->{"cp_${_}"} = $form->{"selected_cp_${_}"}
 
 246     if ( $form->{"selected_cp_${_}"} );
 
 247        } qw(title greeting abteilung) );
 
 248   $form->{"greeting"} = $form->{"selected_company_greeting"}
 
 249   if ( $form->{"selected_company_greeting"} );
 
 251   # assign value discount, terms, creditlimit
 
 252   $form->{discount} = $form->parse_amount( $myconfig, $form->{discount} );
 
 253   $form->{discount} /= 100;
 
 254   $form->{creditlimit} = $form->parse_amount( $myconfig, $form->{creditlimit} );
 
 256   my ( $query, $sth, $f_id );
 
 259     $query = qq|SELECT id FROM customer WHERE customernumber = ?|;
 
 260     ($f_id) = selectrow_query($form, $dbh, $query, $form->{customernumber});
 
 262     if (($f_id ne $form->{id}) && ($f_id ne "")) {
 
 263       $main::lxdebug->leave_sub();
 
 268     my $customernumber      = SL::TransNumber->new(type        => 'customer',
 
 270                                                    number      => $form->{customernumber},
 
 271                                                    business_id => $form->{business},
 
 273     $form->{customernumber} = $customernumber->create_unique unless $customernumber->is_unique;
 
 275     $query = qq|SELECT nextval('id')|;
 
 276     ($form->{id}) = selectrow_query($form, $dbh, $query);
 
 278     $query = qq|INSERT INTO customer (id, name) VALUES (?, '')|;
 
 279     do_query($form, $dbh, $query, $form->{id});
 
 282   $query = qq|UPDATE customer SET | .
 
 283     qq|customernumber = ?, | .
 
 286     qq|department_1 = ?, | .
 
 287     qq|department_2 = ?, | .
 
 301     qq|creditlimit = ?, | .
 
 303     qq|business_id = ?, | .
 
 304     qq|taxnumber = ?, | .
 
 306     qq|account_number = ?, | .
 
 307     qq|bank_code = ?, | .
 
 312     qq|direct_debit = ?, | .
 
 315     qq|salesman_id = ?, | .
 
 316     qq|language_id = ?, | .
 
 317     qq|payment_id = ?, | .
 
 318     qq|taxzone_id = ?, | .
 
 319     qq|user_password = ?, | .
 
 320     qq|c_vendor_id = ?, | .
 
 323     qq|taxincluded_checked = ? | .
 
 326     $form->{customernumber},
 
 329     $form->{department_1},
 
 330     $form->{department_2},
 
 344     $form->{creditlimit},
 
 345     conv_i($form->{terms}),
 
 346     conv_i($form->{business}),
 
 349     $form->{account_number},
 
 354     $form->{obsolete} ? 't' : 'f',
 
 355     $form->{direct_debit} ? 't' : 'f',
 
 358     conv_i($form->{salesman_id}),
 
 359     conv_i($form->{language_id}),
 
 360     conv_i($form->{payment_id}),
 
 361     conv_i($form->{taxzone_id}, 0),
 
 362     $form->{user_password},
 
 363     $form->{c_vendor_id},
 
 364     conv_i($form->{klass}),
 
 365     substr($form->{currency}, 0, 3),
 
 366     $form->{taxincluded_checked} ne '' ? $form->{taxincluded_checked} : undef,
 
 369   do_query( $form, $dbh, $query, @values );
 
 372   my @columns = qw(cp_title cp_givenname cp_name cp_email cp_phone1 cp_phone2 cp_abteilung cp_fax
 
 373                    cp_mobile1 cp_mobile2 cp_satphone cp_satfax cp_project cp_privatphone cp_privatemail cp_birthday cp_gender
 
 374                    cp_street cp_zipcode cp_city);
 
 375   @values     = map { $_ eq 'cp_gender' ? ($form->{$_} eq 'f' ? 'f' : 'm') : $form->{$_} } @columns;
 
 377   if ( $form->{cp_id} ) {
 
 378     $query = qq|UPDATE contacts SET | . join(', ', map { "${_} = ?" } @columns) . qq| WHERE cp_id = ?|;
 
 379     push @values, $form->{cp_id};
 
 381   } elsif ( $form->{cp_name} || $form->{cp_givenname} ) {
 
 382     $query = qq|INSERT INTO contacts (| . join(', ', 'cp_cv_id', @columns) . qq|) VALUES (?, | . join(', ', ('?') x scalar(@columns)) . qq|)|;
 
 383     unshift @values, $form->{id};
 
 385   do_query( $form, $dbh, $query, @values ) if ($query);
 
 388   $form->add_shipto( $dbh, $form->{id}, "CT" );
 
 390   $self->_save_note('dbh' => $dbh);
 
 391   $self->_delete_selected_notes('dbh' => $dbh);
 
 393   CVar->save_custom_variables('dbh'       => $dbh,
 
 395                               'trans_id'  => $form->{id},
 
 396                               'variables' => $form,
 
 397                               'always_valid' => 1);
 
 398   if ($form->{cp_id}) {
 
 399     CVar->save_custom_variables('dbh'       => $dbh,
 
 400                                 'module'    => 'Contacts',
 
 401                                 'trans_id'  => $form->{cp_id},
 
 402                                 'variables' => $form,
 
 403                                 'name_prefix'  => 'cp',
 
 404                                 'always_valid' => 1);
 
 407   my $rc = $dbh->commit();
 
 409   $main::lxdebug->leave_sub();
 
 414   $main::lxdebug->enter_sub();
 
 416   my ( $self, $myconfig, $form ) = @_;
 
 418   $form->{taxzone_id} *= 1;
 
 419   # connect to database
 
 420   my $dbh = $form->get_standard_dbh;
 
 423     $form->{"cp_${_}"} = $form->{"selected_cp_${_}"}
 
 424     if ( $form->{"selected_cp_${_}"} );
 
 425        } qw(title greeting abteilung) );
 
 426   $form->{"greeting"} = $form->{"selected_company_greeting"}
 
 427   if ( $form->{"selected_company_greeting"} );
 
 429   $form->{discount} = $form->parse_amount( $myconfig, $form->{discount} );
 
 430   $form->{discount} /= 100;
 
 431   $form->{creditlimit} = $form->parse_amount( $myconfig, $form->{creditlimit} );
 
 436     $query = qq|SELECT nextval('id')|;
 
 437     ($form->{id}) = selectrow_query($form, $dbh, $query);
 
 439     $query = qq|INSERT INTO vendor (id, name) VALUES (?, '')|;
 
 440     do_query($form, $dbh, $query, $form->{id});
 
 442     my $vendornumber      = SL::TransNumber->new(type   => 'vendor',
 
 444                                                  number => $form->{vendornumber},
 
 446     $form->{vendornumber} = $vendornumber->create_unique unless $vendornumber->is_unique;
 
 450     qq|UPDATE vendor SET | .
 
 451     qq|  vendornumber = ?, | .
 
 453     qq|  greeting = ?, | .
 
 454     qq|  department_1 = ?, | .
 
 455     qq|  department_2 = ?, | .
 
 460     qq|  homepage = ?, | .
 
 469     qq|  discount = ?, | .
 
 470     qq|  creditlimit = ?, | .
 
 471     qq|  business_id = ?, | .
 
 472     qq|  taxnumber = ?, | .
 
 473     qq|  language = ?, | .
 
 474     qq|  account_number = ?, | .
 
 475     qq|  bank_code = ?, | .
 
 479     qq|  obsolete = ?, | .
 
 480     qq|  direct_debit = ?, | .
 
 482     qq|  payment_id = ?, | .
 
 483     qq|  taxzone_id = ?, | .
 
 484     qq|  language_id = ?, | .
 
 485     qq|  username = ?, | .
 
 486     qq|  user_password = ?, | .
 
 487     qq|  v_customer_id = ?, | .
 
 491     $form->{vendornumber},
 
 494     $form->{department_1},
 
 495     $form->{department_2},
 
 508     conv_i($form->{terms}),
 
 510     $form->{creditlimit},
 
 511     conv_i($form->{business}),
 
 514     $form->{account_number},
 
 519     $form->{obsolete} ? 't' : 'f',
 
 520     $form->{direct_debit} ? 't' : 'f',
 
 522     conv_i($form->{payment_id}),
 
 523     conv_i($form->{taxzone_id}, 0),
 
 524     conv_i( $form->{language_id}),
 
 526     $form->{user_password},
 
 527     $form->{v_customer_id},
 
 528     substr($form->{currency}, 0, 3),
 
 531   do_query($form, $dbh, $query, @values);
 
 534   if ( $form->{cp_id} ) {
 
 535     $query = qq|UPDATE contacts SET | .
 
 537       qq|cp_givenname = ?, | .
 
 540       qq|cp_phone1 = ?, | .
 
 541       qq|cp_phone2 = ?, | .
 
 542       qq|cp_abteilung = ?, | .
 
 544       qq|cp_mobile1 = ?, | .
 
 545       qq|cp_mobile2 = ?, | .
 
 546       qq|cp_satphone = ?, | .
 
 547       qq|cp_satfax = ?, | .
 
 548       qq|cp_project = ?, | .
 
 549       qq|cp_privatphone = ?, | .
 
 550       qq|cp_privatemail = ?, | .
 
 551       qq|cp_birthday = ?, | .
 
 556       $form->{cp_givenname},
 
 561       $form->{cp_abteilung},
 
 565       $form->{cp_satphone},
 
 568       $form->{cp_privatphone},
 
 569       $form->{cp_privatemail},
 
 570       $form->{cp_birthday},
 
 571       $form->{cp_gender} eq 'f' ? 'f' : 'm',
 
 574   } elsif ( $form->{cp_name} || $form->{cp_givenname} ) {
 
 576       qq|INSERT INTO contacts ( cp_cv_id, cp_title, cp_givenname,  | .
 
 577       qq|  cp_name, cp_email, cp_phone1, cp_phone2, cp_abteilung, cp_fax, cp_mobile1, | .
 
 578       qq|  cp_mobile2, cp_satphone, cp_satfax, cp_project, cp_privatphone, cp_privatemail, | .
 
 579       qq|  cp_birthday, cp_gender) | .
 
 580       qq|VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)|;
 
 584       $form->{cp_givenname},
 
 589       $form->{cp_abteilung},
 
 593       $form->{cp_satphone},
 
 596       $form->{cp_privatphone},
 
 597       $form->{cp_privatemail},
 
 598       $form->{cp_birthday},
 
 602   do_query($form, $dbh, $query, @values) if ($query);
 
 605   $form->add_shipto( $dbh, $form->{id}, "CT" );
 
 607   $self->_save_note('dbh' => $dbh);
 
 608   $self->_delete_selected_notes('dbh' => $dbh);
 
 610   CVar->save_custom_variables('dbh'       => $dbh,
 
 612                               'trans_id'  => $form->{id},
 
 613                               'variables' => $form,
 
 614                               'always_valid' => 1);
 
 615   if ($form->{cp_id}) {
 
 616     CVar->save_custom_variables('dbh'       => $dbh,
 
 617                                 'module'    => 'Contacts',
 
 618                                 'trans_id'  => $form->{cp_id},
 
 619                                 'variables' => $form,
 
 620                                 'name_prefix'  => 'cp',
 
 621                                 'always_valid' => 1);
 
 624   my $rc = $dbh->commit();
 
 626   $main::lxdebug->leave_sub();
 
 631   $main::lxdebug->enter_sub();
 
 633   my ( $self, $myconfig, $form ) = @_;
 
 634   # connect to database
 
 635   my $dbh = $form->dbconnect($myconfig);
 
 638   my $cv = $form->{db} eq "customer" ? "customer" : "vendor";
 
 639   my $query = qq|DELETE FROM $cv WHERE id = ?|;
 
 640   do_query($form, $dbh, $query, $form->{id});
 
 644   $main::lxdebug->leave_sub();
 
 648   $main::lxdebug->enter_sub();
 
 650   my ( $self, $myconfig, $form ) = @_;
 
 652   # connect to database
 
 653   my $dbh = $form->dbconnect($myconfig);
 
 655   my $cv = $form->{db} eq "customer" ? "customer" : "vendor";
 
 660   my %allowed_sort_columns =
 
 662       id customernumber vendornumber name contact phone fax email street
 
 663       taxnumber business invnumber ordnumber quonumber zipcode city
 
 665   my $sortorder    = $form->{sort} && $allowed_sort_columns{$form->{sort}} ? $form->{sort} : "name";
 
 666   $form->{sort} = $sortorder;
 
 667   my $sortdir   = !defined $form->{sortdir} ? 'ASC' : $form->{sortdir} ? 'ASC' : 'DESC';
 
 669   if ($sortorder !~ /(business|id)/ && 1 >= scalar grep { $form->{$_} } qw(l_ordnumber l_quonumber l_invnumber )) {
 
 670     $sortorder  = "lower($sortorder) ${sortdir}";
 
 672     $sortorder .= " ${sortdir}";
 
 675   if ($form->{"${cv}number"}) {
 
 676     $where .= " AND ct.${cv}number ILIKE ?";
 
 677     push(@values, '%' . $form->{"${cv}number"} . '%');
 
 680   foreach my $key (qw(name contact email)) {
 
 682       $where .= " AND ct.$key ILIKE ?";
 
 683       push(@values, '%' . $form->{$key} . '%');
 
 687   if ($form->{cp_name}) {
 
 688     $where .= " AND ct.id IN (SELECT cp_cv_id FROM contacts WHERE lower(cp_name) LIKE lower(?))";
 
 689     push @values, '%' . $form->{cp_name} . '%';
 
 692   if ($form->{addr_city}) {
 
 693     $where .= " AND ((lower(ct.city) LIKE lower(?))
 
 698                         WHERE (module = 'CT')
 
 699                           AND (lower(shiptocity) LIKE lower(?))
 
 702     push @values, ('%' . $form->{addr_city} . '%') x 2;
 
 705   if ( $form->{status} eq 'orphaned' ) {
 
 707       qq| AND ct.id NOT IN | .
 
 708       qq|   (SELECT o.${cv}_id FROM oe o, $cv cv WHERE cv.id = o.${cv}_id)|;
 
 709     if ($cv eq 'customer') {
 
 711         qq| AND ct.id NOT IN | .
 
 712         qq| (SELECT a.customer_id FROM ar a, customer cv | .
 
 713         qq|  WHERE cv.id = a.customer_id)|;
 
 715     if ($cv eq 'vendor') {
 
 717         qq| AND ct.id NOT IN | .
 
 718         qq| (SELECT a.vendor_id FROM ap a, vendor cv | .
 
 719         qq|  WHERE cv.id = a.vendor_id)|;
 
 721     $form->{l_invnumber} = $form->{l_ordnumber} = $form->{l_quonumber} = "";
 
 724   if ($form->{obsolete} eq "Y") {
 
 725     $where .= qq| AND obsolete|;
 
 726   } elsif ($form->{obsolete} eq "N") {
 
 727     $where .= qq| AND NOT obsolete|;
 
 730   if ($form->{business_id}) {
 
 731     $where .= qq| AND (business_id = ?)|;
 
 732     push(@values, conv_i($form->{business_id}));
 
 735   # Nur Kunden finden, bei denen ich selber der Verkäufer bin
 
 736   # Gilt nicht für Lieferanten
 
 737   if ($cv eq 'customer' &&   !$main::auth->assert('customer_vendor_all_edit', 1)) {
 
 738     $where .= qq| AND ct.salesman_id = (select id from employee where login= ?)|;
 
 739     push(@values, $form->{login});
 
 742   my ($cvar_where, @cvar_values) = CVar->build_filter_query('module'         => 'CT',
 
 743                                                             'trans_id_field' => 'ct.id',
 
 747     $where .= qq| AND ($cvar_where)|;
 
 748     push @values, @cvar_values;
 
 751   if ($form->{addr_street}) {
 
 752     $where .= qq| AND (street ILIKE ?)|;
 
 753     push @values, '%' . $form->{addr_street} . '%';
 
 756   if ($form->{addr_zipcode}) {
 
 757     $where .= qq| AND (zipcode ILIKE ?)|;
 
 758     push @values, $form->{addr_zipcode} . '%';
 
 762     qq|SELECT ct.*, b.description AS business | .
 
 764     qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
 
 767   my @saved_values = @values;
 
 768   # redo for invoices, orders and quotations
 
 769   if ($form->{l_invnumber} || $form->{l_ordnumber} || $form->{l_quonumber}) {
 
 770     my ($ar, $union, $module);
 
 773     if ($form->{l_invnumber}) {
 
 774       my $ar = $cv eq 'customer' ? 'ar' : 'ap';
 
 775       my $module = $ar eq 'ar' ? 'is' : 'ir';
 
 778         qq|SELECT ct.*, b.description AS business, | .
 
 779         qq|  a.invnumber, a.ordnumber, a.quonumber, a.id AS invid, | .
 
 780         qq|  '$module' AS module, 'invoice' AS formtype, | .
 
 781         qq|  (a.amount = a.paid) AS closed | .
 
 783         qq|JOIN $ar a ON (a.${cv}_id = ct.id) | .
 
 784         qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
 
 785         qq|WHERE $where AND (a.invoice = '1')|;
 
 790     if ( $form->{l_ordnumber} ) {
 
 791       if ($union eq "UNION") {
 
 792         push(@values, @saved_values);
 
 796         qq|SELECT ct.*, b.description AS business,| .
 
 797         qq|  ' ' AS invnumber, o.ordnumber, o.quonumber, o.id AS invid, | .
 
 798         qq|  'oe' AS module, 'order' AS formtype, o.closed | .
 
 800         qq|JOIN oe o ON (o.${cv}_id = ct.id) | .
 
 801         qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
 
 802         qq|WHERE $where AND (o.quotation = '0')|;
 
 807     if ( $form->{l_quonumber} ) {
 
 808       if ($union eq "UNION") {
 
 809         push(@values, @saved_values);
 
 813         qq|SELECT ct.*, b.description AS business, | .
 
 814         qq|  ' ' AS invnumber, o.ordnumber, o.quonumber, o.id AS invid, | .
 
 815         qq|  'oe' AS module, 'quotation' AS formtype, o.closed | .
 
 817         qq|JOIN oe o ON (o.${cv}_id = ct.id) | .
 
 818         qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
 
 819         qq|WHERE $where AND (o.quotation = '1')|;
 
 823   $query .= qq| ORDER BY $sortorder|;
 
 825   $form->{CT} = selectall_hashref_query($form, $dbh, $query, @values);
 
 827   $main::lxdebug->leave_sub();
 
 831   $main::lxdebug->enter_sub();
 
 833   my ( $self, $myconfig, $form ) = @_;
 
 835   die 'Missing argument: cp_id' unless $::form->{cp_id};
 
 837   my $dbh   = $form->dbconnect($myconfig);
 
 839     qq|SELECT * FROM contacts c | .
 
 840     qq|WHERE cp_id = ? ORDER BY cp_id limit 1|;
 
 841   my $sth = prepare_execute_query($form, $dbh, $query, $form->{cp_id});
 
 842   my $ref = $sth->fetchrow_hashref("NAME_lc");
 
 844   map { $form->{$_} = $ref->{$_} } keys %$ref;
 
 846   $query = qq|SELECT COUNT(cp_id) AS used FROM (
 
 847     SELECT cp_id FROM oe UNION
 
 848     SELECT cp_id FROM ar UNION
 
 849     SELECT cp_id FROM ap UNION
 
 850     SELECT cp_id FROM delivery_orders
 
 851   ) AS cpid WHERE cp_id = ? OR ? = 0|;
 
 852   ($form->{cp_used}) = selectfirst_array_query($form, $dbh, $query, ($form->{cp_id})x2);
 
 857   $main::lxdebug->leave_sub();
 
 861   $main::lxdebug->enter_sub();
 
 863   my ( $self, $myconfig, $form ) = @_;
 
 864   my $dbh   = $form->dbconnect($myconfig);
 
 865   my $query = qq|SELECT * FROM shipto WHERE shipto_id = ?|;
 
 866   my $sth = prepare_execute_query($form, $dbh, $query, $form->{shipto_id});
 
 868   my $ref = $sth->fetchrow_hashref("NAME_lc");
 
 870   map { $form->{$_} = $ref->{$_} } keys %$ref;
 
 872   $query = qq|SELECT COUNT(shipto_id) AS used FROM (
 
 873     SELECT shipto_id FROM oe UNION
 
 874     SELECT shipto_id FROM ar UNION
 
 875     SELECT shipto_id FROM delivery_orders
 
 876   ) AS stid WHERE shipto_id = ? OR ? = 0|;
 
 877   ($form->{shiptoused}) = selectfirst_array_query($form, $dbh, $query, ($form->{shipto_id})x2);
 
 882   $main::lxdebug->leave_sub();
 
 886   $main::lxdebug->enter_sub();
 
 888   my ( $self, $myconfig, $form ) = @_;
 
 889   my $dbh = $form->dbconnect($myconfig);
 
 891   my $arap = $form->{db} eq "vendor" ? "ap" : "ar";
 
 892   my $db = $form->{db} eq "customer" ? "customer" : "vendor";
 
 893   my $qty_sign = $form->{db} eq 'vendor' ? ' * -1 AS qty' : '';
 
 895   my $where = " WHERE 1=1 ";
 
 898   if ($form->{shipto_id} && ($arap eq "ar")) {
 
 899     $where .= "AND ${arap}.shipto_id = ?";
 
 900     push(@values, $form->{shipto_id});
 
 902     $where .= "AND ${arap}.${db}_id = ?";
 
 903     push(@values, $form->{id});
 
 907     $where .= "AND ${arap}.transdate >= ?";
 
 908     push(@values, conv_date($form->{from}));
 
 911     $where .= "AND ${arap}.transdate <= ?";
 
 912     push(@values, conv_date($form->{to}));
 
 915     qq|SELECT s.shiptoname, i.qty $qty_sign, | .
 
 916     qq|  ${arap}.id, ${arap}.transdate, ${arap}.invnumber, ${arap}.ordnumber, | .
 
 917     qq|  i.description, i.unit, i.sellprice, | .
 
 918     qq|  oe.id AS oe_id, invoice | .
 
 920     qq|LEFT JOIN shipto s ON | .
 
 922      ? qq|(ar.shipto_id = s.shipto_id) |
 
 923      : qq|(ap.id = s.trans_id) |) .
 
 924     qq|LEFT JOIN invoice i ON (${arap}.id = i.trans_id) | .
 
 925     qq|LEFT join parts p ON (p.id = i.parts_id) | .
 
 926     qq|LEFT JOIN oe ON (oe.ordnumber = ${arap}.ordnumber AND NOT ${arap}.ordnumber = '') | .
 
 928     qq|ORDER BY ${arap}.transdate DESC LIMIT 15|;
 
 930   $form->{DELIVERY} = selectall_hashref_query($form, $dbh, $query, @values);
 
 934   $main::lxdebug->leave_sub();
 
 938   $main::lxdebug->enter_sub();
 
 943   my $form   = $main::form;
 
 945   Common::check_params(\%params, 'dbh');
 
 947   if (!$form->{NOTE_subject}) {
 
 948     $main::lxdebug->leave_sub();
 
 952   my $dbh = $params{dbh};
 
 956     'id'           => $form->{NOTE_id},
 
 957     'subject'      => $form->{NOTE_subject},
 
 958     'body'         => $form->{NOTE_body},
 
 959     'trans_id'     => $form->{id},
 
 960     'trans_module' => 'ct',
 
 963   $note{id} = Notes->save(%note);
 
 965   if ($form->{FU_date}) {
 
 967       'id'               => $form->{FU_id},
 
 968       'note_id'          => $note{id},
 
 969       'follow_up_date'   => $form->{FU_date},
 
 970       'created_for_user' => $form->{FU_created_for_user},
 
 971       'done'             => $form->{FU_done} ? 1 : 0,
 
 972       'subject'          => $form->{NOTE_subject},
 
 973       'body'             => $form->{NOTE_body},
 
 976           'trans_id'     => $form->{id},
 
 977           'trans_type'   => $form->{db} eq 'customer' ? 'customer' : 'vendor',
 
 978           'trans_info'   => $form->{name},
 
 983     $follow_up{id} = FU->save(%follow_up);
 
 985   } elsif ($form->{FU_id}) {
 
 986     do_query($form, $dbh, qq|DELETE FROM follow_up_links WHERE follow_up_id = ?|, conv_i($form->{FU_id}));
 
 987     do_query($form, $dbh, qq|DELETE FROM follow_ups      WHERE id = ?|,           conv_i($form->{FU_id}));
 
 990   delete @{$form}{grep { /^NOTE_|^FU_/ } keys %{ $form }};
 
 992   $main::lxdebug->leave_sub();
 
 995 sub _delete_selected_notes {
 
 996   $main::lxdebug->enter_sub();
 
1001   Common::check_params(\%params, 'dbh');
 
1003   my $form = $main::form;
 
1004   my $dbh  = $params{dbh};
 
1006   foreach my $i (1 .. $form->{NOTES_rowcount}) {
 
1007     next unless ($form->{"NOTE_delete_$i"} && $form->{"NOTE_id_$i"});
 
1009     Notes->delete('dbh' => $params{dbh},
 
1010                   'id'  => $form->{"NOTE_id_$i"});
 
1013   $main::lxdebug->leave_sub();
 
1016 # TODO: remove in 2.7.0 stable
 
1018   $main::lxdebug->enter_sub();
 
1021   my $shipto_id = shift;
 
1023   my $form      = $main::form;
 
1024   my %myconfig  = %main::myconfig;
 
1025   my $dbh       = $form->get_standard_dbh(\%myconfig);
 
1027   do_query($form, $dbh, qq|UPDATE shipto SET trans_id = NULL WHERE shipto_id = ?|, $shipto_id);
 
1031   $main::lxdebug->leave_sub();
 
1034 # TODO: remove in 2.7.0 stable
 
1035 sub delete_contact {
 
1036   $main::lxdebug->enter_sub();
 
1041   my $form      = $main::form;
 
1042   my %myconfig  = %main::myconfig;
 
1043   my $dbh       = $form->get_standard_dbh(\%myconfig);
 
1045   do_query($form, $dbh, qq|UPDATE contacts SET cp_cv_id = NULL WHERE cp_id = ?|, $cp_id);
 
1049   $main::lxdebug->leave_sub();
 
1053   $main::lxdebug->enter_sub();
 
1058   Common::check_params(\%params, qw(vc id));
 
1060   my $myconfig = \%main::myconfig;
 
1061   my $form     = $main::form;
 
1063   my $dbh      = $params{dbh} || $form->get_standard_dbh($myconfig);
 
1065   my $table        = $params{vc} eq 'customer' ? 'customer' : 'vendor';
 
1066   my @ids          = ref $params{id} eq 'ARRAY' ? @{ $params{id} } : ($params{id});
 
1067   my $placeholders = join ", ", ('?') x scalar @ids;
 
1068   my $query        = qq|SELECT id, name, account_number, bank, bank_code, iban, bic
 
1070                         WHERE id IN (${placeholders})|;
 
1072   my $result       = selectall_hashref_query($form, $dbh, $query, map { conv_i($_) } @ids);
 
1074   if (ref $params{id} eq 'ARRAY') {
 
1075     $result = { map { $_->{id} => $_ } @{ $result } };
 
1077     $result = $result->[0] || { 'id' => $params{id} };
 
1080   $main::lxdebug->leave_sub();
 
1085 sub parse_excel_file {
 
1086   $main::lxdebug->enter_sub();
 
1088   my ($self, $myconfig, $form) = @_;
 
1089   my $locale = $main::locale;
 
1091   $form->{formname}   = 'sales_quotation';
 
1092   $form->{type}   = 'sales_quotation';
 
1093   $form->{format} = 'excel';
 
1094   $form->{media}  = 'screen';
 
1095   $form->{quonumber} = 1;
 
1098   # $form->{"notes"} will be overridden by the customer's/vendor's "notes" field. So save it here.
 
1099   $form->{ $form->{"formname"} . "notes" } = $form->{"notes"};
 
1103   $form->{"${inv}date"} = $form->{transdate};
 
1104   $form->{label}        = $locale->text('Quotation');
 
1105   my $numberfld            = "sqnumber";
 
1109   $form->{what_done} = $form->{formname};
 
1111   map({ delete($form->{$_}); } grep(/^cp_/, keys(%{ $form })));
 
1113   my $output_dateformat = $myconfig->{"dateformat"};
 
1114   my $output_numberformat = $myconfig->{"numberformat"};
 
1115   my $output_longdates = 1;
 
1117   # map login user variables
 
1118   map { $form->{"login_$_"} = $myconfig->{$_} } ("name", "email", "fax", "tel", "company");
 
1121   for my $field (qw(transdate_oe deliverydate_oe)) {
 
1123       $form->{$field}[$_] = $locale->date($myconfig, $form->{$field}[$_], 1);
 
1124     } 0 .. $#{ $form->{$field} };
 
1127   if ($form->{shipto_id}) {
 
1128     $form->get_shipto($myconfig);
 
1131   $form->{notes} =~ s/^\s+//g;
 
1133   $form->{templates} = $myconfig->{templates};
 
1135   delete $form->{printer_command};
 
1137   $form->get_employee_info($myconfig);
 
1139   my ($cvar_date_fields, $cvar_number_fields) = CVar->get_field_format_list('module' => 'CT', 'prefix' => 'vc_');
 
1141   if (scalar @{ $cvar_date_fields }) {
 
1142     format_dates($output_dateformat, $output_longdates, @{ $cvar_date_fields });
 
1145   while (my ($precision, $field_list) = each %{ $cvar_number_fields }) {
 
1146     reformat_numbers($output_numberformat, $precision, @{ $field_list });
 
1150   my $extension            = 'xls';
 
1152   $form->{IN}         = "$form->{formname}.${extension}";
 
1154   delete $form->{OUT};
 
1156   $form->parse_template($myconfig);
 
1158   $main::lxdebug->leave_sub();
 
1161 sub search_contacts {
 
1162   $::lxdebug->enter_sub;
 
1167   my $dbh       = $params{dbh} || $::form->get_standard_dbh;
 
1168   my $vc        = $params{db} eq 'customer' ? 'customer' : 'vendor';
 
1171     'cp_name'   => 'cp_name, cp_givenname',
 
1172     'vcname'    => 'vcname, cp_name, cp_givenname',
 
1173     'vcnumber'  => 'vcnumber, cp_name, cp_givenname',
 
1176   my %sortcols  = map { $_ => 1 } qw(cp_name cp_givenname cp_phone1 cp_phone2 cp_mobile1 cp_email cp_street cp_zipcode cp_city vcname vcnumber);
 
1178   my $order_by  = $sortcols{$::form->{sort}} ? $::form->{sort} : 'cp_name';
 
1179   $::form->{sort} = $order_by;
 
1180   $order_by     = $sortspecs{$order_by} if ($sortspecs{$order_by});
 
1182   my $sortdir   = $::form->{sortdir} ? 'ASC' : 'DESC';
 
1183   $order_by     =~ s/,/ ${sortdir},/g;
 
1184   $order_by    .= " $sortdir";
 
1186   my @where_tokens = ();
 
1189   if ($params{search_term}) {
 
1192       'cp.cp_name      ILIKE ?',
 
1193       'cp.cp_givenname ILIKE ?',
 
1194       'cp.cp_email     ILIKE ?';
 
1195     push @values, ('%' . $params{search_term} . '%') x 3;
 
1197     if (($params{search_term} =~ m/\d/) && ($params{search_term} !~ m/[^\d \(\)+\-]/)) {
 
1198       my $number =  $params{search_term};
 
1199       $number    =~ s/[^\d]//g;
 
1200       $number    =  join '[ /\(\)+\-]*', split(m//, $number);
 
1202       push @tokens, map { "($_ ~ '$number')" } qw(cp_phone1 cp_phone2 cp_mobile1 cp_mobile2);
 
1205     push @where_tokens, map { "($_)" } join ' OR ', @tokens;
 
1208   my ($cvar_where, @cvar_values) = CVar->build_filter_query('module'         => 'Contacts',
 
1209                                                             'trans_id_field' => 'cp.cp_id',
 
1210                                                             'filter'         => $params{filter});
 
1213     push @where_tokens, $cvar_where;
 
1214     push @values, @cvar_values;
 
1217   if (my $filter = $params{filter}) {
 
1218     for (qw(name title givenname email project abteilung)) {
 
1219       next unless $filter->{"cp_$_"};
 
1220       add_token(\@where_tokens, \@values, col =>  "cp.cp_$_", val => $filter->{"cp_$_"}, method => 'ILIKE', esc => 'substr');
 
1223     push @where_tokens, 'cp.cp_cv_id IS NOT NULL' if $filter->{status} eq 'active';
 
1224     push @where_tokens, 'cp.cp_cv_id IS NULL'     if $filter->{status} eq 'orphaned';
 
1227   my $where = @where_tokens ? 'WHERE ' . join ' AND ', @where_tokens : '';
 
1229   my $query     = qq|SELECT cp.*,
 
1230                        COALESCE(c.id,             v.id)           AS vcid,
 
1231                        COALESCE(c.name,           v.name)         AS vcname,
 
1232                        COALESCE(c.customernumber, v.vendornumber) AS vcnumber,
 
1233                        CASE WHEN c.name IS NULL THEN 'vendor' ELSE 'customer' END AS db
 
1235                      LEFT JOIN customer c ON (cp.cp_cv_id = c.id)
 
1236                      LEFT JOIN vendor v   ON (cp.cp_cv_id = v.id)
 
1238                      ORDER BY $order_by|;
 
1240   my $contacts  = selectall_hashref_query($::form, $dbh, $query, @values);
 
1242   $::lxdebug->leave_sub;
 
1244   return @{ $contacts };