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 );
 
 371   $form->{cp_id} = $self->_save_contact($form, $dbh);
 
 374   $form->add_shipto( $dbh, $form->{id}, "CT" );
 
 376   $self->_save_note('dbh' => $dbh);
 
 377   $self->_delete_selected_notes('dbh' => $dbh);
 
 379   CVar->save_custom_variables('dbh'       => $dbh,
 
 381                               'trans_id'  => $form->{id},
 
 382                               'variables' => $form,
 
 383                               'always_valid' => 1);
 
 384   if ($form->{cp_id}) {
 
 385     CVar->save_custom_variables('dbh'       => $dbh,
 
 386                                 'module'    => 'Contacts',
 
 387                                 'trans_id'  => $form->{cp_id},
 
 388                                 'variables' => $form,
 
 389                                 'name_prefix'  => 'cp',
 
 390                                 'always_valid' => 1);
 
 393   my $rc = $dbh->commit();
 
 395   $main::lxdebug->leave_sub();
 
 400   $main::lxdebug->enter_sub();
 
 402   my ( $self, $myconfig, $form ) = @_;
 
 404   $form->{taxzone_id} *= 1;
 
 405   # connect to database
 
 406   my $dbh = $form->get_standard_dbh;
 
 409     $form->{"cp_${_}"} = $form->{"selected_cp_${_}"}
 
 410     if ( $form->{"selected_cp_${_}"} );
 
 411        } qw(title greeting abteilung) );
 
 412   $form->{"greeting"} = $form->{"selected_company_greeting"}
 
 413   if ( $form->{"selected_company_greeting"} );
 
 415   $form->{discount} = $form->parse_amount( $myconfig, $form->{discount} );
 
 416   $form->{discount} /= 100;
 
 417   $form->{creditlimit} = $form->parse_amount( $myconfig, $form->{creditlimit} );
 
 422     $query = qq|SELECT nextval('id')|;
 
 423     ($form->{id}) = selectrow_query($form, $dbh, $query);
 
 425     $query = qq|INSERT INTO vendor (id, name) VALUES (?, '')|;
 
 426     do_query($form, $dbh, $query, $form->{id});
 
 428     my $vendornumber      = SL::TransNumber->new(type   => 'vendor',
 
 430                                                  number => $form->{vendornumber},
 
 432     $form->{vendornumber} = $vendornumber->create_unique unless $vendornumber->is_unique;
 
 436     qq|UPDATE vendor SET | .
 
 437     qq|  vendornumber = ?, | .
 
 439     qq|  greeting = ?, | .
 
 440     qq|  department_1 = ?, | .
 
 441     qq|  department_2 = ?, | .
 
 446     qq|  homepage = ?, | .
 
 455     qq|  discount = ?, | .
 
 456     qq|  creditlimit = ?, | .
 
 457     qq|  business_id = ?, | .
 
 458     qq|  taxnumber = ?, | .
 
 459     qq|  language = ?, | .
 
 460     qq|  account_number = ?, | .
 
 461     qq|  bank_code = ?, | .
 
 465     qq|  obsolete = ?, | .
 
 466     qq|  direct_debit = ?, | .
 
 468     qq|  payment_id = ?, | .
 
 469     qq|  taxzone_id = ?, | .
 
 470     qq|  language_id = ?, | .
 
 471     qq|  username = ?, | .
 
 472     qq|  user_password = ?, | .
 
 473     qq|  v_customer_id = ?, | .
 
 477     $form->{vendornumber},
 
 480     $form->{department_1},
 
 481     $form->{department_2},
 
 494     conv_i($form->{terms}),
 
 496     $form->{creditlimit},
 
 497     conv_i($form->{business}),
 
 500     $form->{account_number},
 
 505     $form->{obsolete} ? 't' : 'f',
 
 506     $form->{direct_debit} ? 't' : 'f',
 
 508     conv_i($form->{payment_id}),
 
 509     conv_i($form->{taxzone_id}, 0),
 
 510     conv_i( $form->{language_id}),
 
 512     $form->{user_password},
 
 513     $form->{v_customer_id},
 
 514     substr($form->{currency}, 0, 3),
 
 517   do_query($form, $dbh, $query, @values);
 
 519   $form->{cp_id} = $self->_save_contact($form, $dbh);
 
 522   $form->add_shipto( $dbh, $form->{id}, "CT" );
 
 524   $self->_save_note('dbh' => $dbh);
 
 525   $self->_delete_selected_notes('dbh' => $dbh);
 
 527   CVar->save_custom_variables('dbh'       => $dbh,
 
 529                               'trans_id'  => $form->{id},
 
 530                               'variables' => $form,
 
 531                               'always_valid' => 1);
 
 532   if ($form->{cp_id}) {
 
 533     CVar->save_custom_variables('dbh'       => $dbh,
 
 534                                 'module'    => 'Contacts',
 
 535                                 'trans_id'  => $form->{cp_id},
 
 536                                 'variables' => $form,
 
 537                                 'name_prefix'  => 'cp',
 
 538                                 'always_valid' => 1);
 
 541   my $rc = $dbh->commit();
 
 543   $main::lxdebug->leave_sub();
 
 548   my ($self, $form, $dbh) = @_;
 
 550   return undef unless $form->{cp_id} || $form->{cp_name} || $form->{cp_givenname};
 
 552   my @columns = qw(cp_title cp_givenname cp_name cp_email cp_phone1 cp_phone2 cp_abteilung cp_fax
 
 553                    cp_mobile1 cp_mobile2 cp_satphone cp_satfax cp_project cp_privatphone cp_privatemail cp_birthday cp_gender
 
 554                    cp_street cp_zipcode cp_city cp_position);
 
 557       if ( $_ eq 'cp_gender' ) {
 
 558         $form->{$_} eq 'f' ? 'f' : 'm';
 
 559       } elsif ( $_ eq 'cp_birthday' && $form->{cp_birthday} eq '' ) {
 
 569   if ($form->{cp_id}) {
 
 570     $query = qq|UPDATE contacts SET | . join(', ', map { "${_} = ?" } @columns) . qq| WHERE cp_id = ?|;
 
 571     push @values, $form->{cp_id};
 
 572     $cp_id = $form->{cp_id};
 
 575     ($cp_id) = selectrow_query($form, $dbh, qq|SELECT nextval('id')|);
 
 577     $query = qq|INSERT INTO contacts (| . join(', ', @columns, 'cp_cv_id', 'cp_id') . qq|) VALUES (| . join(', ', ('?') x (2 + scalar @columns)) . qq|)|;
 
 578     push @values, $form->{id}, $cp_id;
 
 581   do_query($form, $dbh, $query, @values);
 
 587   $main::lxdebug->enter_sub();
 
 589   my ( $self, $myconfig, $form ) = @_;
 
 590   # connect to database
 
 591   my $dbh = $form->dbconnect($myconfig);
 
 594   my $cv = $form->{db} eq "customer" ? "customer" : "vendor";
 
 595   my $query = qq|DELETE FROM $cv WHERE id = ?|;
 
 596   do_query($form, $dbh, $query, $form->{id});
 
 600   $main::lxdebug->leave_sub();
 
 604   $main::lxdebug->enter_sub();
 
 606   my ( $self, $myconfig, $form ) = @_;
 
 608   # connect to database
 
 609   my $dbh = $form->dbconnect($myconfig);
 
 611   my $cv = $form->{db} eq "customer" ? "customer" : "vendor";
 
 612   my $join_records = $form->{l_invnumber} || $form->{l_ordnumber} || $form->{l_quonumber};
 
 617   my %allowed_sort_columns = (
 
 619       "customernumber" => "customernumber",
 
 620       "vendornumber" => "vendornumber",
 
 622       "contact" => "contact",
 
 626       "street" => "street",
 
 627       "taxnumber" => "taxnumber",
 
 628       "business" => "business",
 
 629       "invnumber" => "invnumber",
 
 630       "ordnumber" => "ordnumber",
 
 631       "quonumber" => "quonumber",
 
 632       "zipcode" => "zipcode",
 
 634       "country" => "country",
 
 635       "salesman" => "e.name"
 
 638   $form->{sort} ||= "name";
 
 640   if ( $join_records ) {
 
 641     # in UNION case order by hash key, e.g. salesman
 
 642     # the UNION created an implicit select around the result
 
 643     $sortorder = $allowed_sort_columns{$form->{sort}} ? $form->{sort} : "name";
 
 645     # in not UNION case order by hash value, e.g. e.name
 
 646     $sortorder = $allowed_sort_columns{$form->{sort}} ?  $allowed_sort_columns{$form->{sort}} : "ct.name";
 
 648   my $sortdir   = !defined $form->{sortdir} ? 'ASC' : $form->{sortdir} ? 'ASC' : 'DESC';
 
 650   if ($sortorder !~ /(business|id)/ && !$join_records) {
 
 651     $sortorder  = "lower($sortorder) ${sortdir}";
 
 653     $sortorder .= " ${sortdir}";
 
 656   if ($form->{"${cv}number"}) {
 
 657     $where .= " AND ct.${cv}number ILIKE ?";
 
 658     push(@values, '%' . $form->{"${cv}number"} . '%');
 
 661   foreach my $key (qw(name contact email)) {
 
 663       $where .= " AND ct.$key ILIKE ?";
 
 664       push(@values, '%' . $form->{$key} . '%');
 
 668   if ($form->{cp_name}) {
 
 669     $where .= " AND ct.id IN (SELECT cp_cv_id FROM contacts WHERE lower(cp_name) LIKE lower(?))";
 
 670     push @values, '%' . $form->{cp_name} . '%';
 
 673   if ($form->{addr_city}) {
 
 674     $where .= " AND ((lower(ct.city) LIKE lower(?))
 
 679                         WHERE (module = 'CT')
 
 680                           AND (lower(shiptocity) LIKE lower(?))
 
 683     push @values, ('%' . $form->{addr_city} . '%') x 2;
 
 686   if ($form->{addr_country}) {
 
 687     $where .= " AND ((lower(ct.country) LIKE lower(?))
 
 692                         WHERE (module = 'CT')
 
 693                           AND (lower(shiptocountry) LIKE lower(?))
 
 696     push @values, ('%' . $form->{addr_country} . '%') x 2;
 
 699   if ( $form->{status} eq 'orphaned' ) {
 
 701       qq| AND ct.id NOT IN | .
 
 702       qq|   (SELECT o.${cv}_id FROM oe o, $cv cv WHERE cv.id = o.${cv}_id)|;
 
 703     if ($cv eq 'customer') {
 
 705         qq| AND ct.id NOT IN | .
 
 706         qq| (SELECT a.customer_id FROM ar a, customer cv | .
 
 707         qq|  WHERE cv.id = a.customer_id)|;
 
 709     if ($cv eq 'vendor') {
 
 711         qq| AND ct.id NOT IN | .
 
 712         qq| (SELECT a.vendor_id FROM ap a, vendor cv | .
 
 713         qq|  WHERE cv.id = a.vendor_id)|;
 
 715     $form->{l_invnumber} = $form->{l_ordnumber} = $form->{l_quonumber} = "";
 
 718   if ($form->{obsolete} eq "Y") {
 
 719     $where .= qq| AND obsolete|;
 
 720   } elsif ($form->{obsolete} eq "N") {
 
 721     $where .= qq| AND NOT obsolete|;
 
 724   if ($form->{business_id}) {
 
 725     $where .= qq| AND (business_id = ?)|;
 
 726     push(@values, conv_i($form->{business_id}));
 
 729   # Nur Kunden finden, bei denen ich selber der Verkäufer bin
 
 730   # Gilt nicht für Lieferanten
 
 731   if ($cv eq 'customer' &&   !$main::auth->assert('customer_vendor_all_edit', 1)) {
 
 732     $where .= qq| AND ct.salesman_id = (select id from employee where login= ?)|;
 
 733     push(@values, $form->{login});
 
 736   my ($cvar_where, @cvar_values) = CVar->build_filter_query('module'         => 'CT',
 
 737                                                             'trans_id_field' => 'ct.id',
 
 741     $where .= qq| AND ($cvar_where)|;
 
 742     push @values, @cvar_values;
 
 745   if ($form->{addr_street}) {
 
 746     $where .= qq| AND (street ILIKE ?)|;
 
 747     push @values, '%' . $form->{addr_street} . '%';
 
 750   if ($form->{addr_zipcode}) {
 
 751     $where .= qq| AND (zipcode ILIKE ?)|;
 
 752     push @values, $form->{addr_zipcode} . '%';
 
 756     qq|SELECT ct.*, b.description AS business, e.name as salesman | .
 
 757     (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) .
 
 759     qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
 
 760     qq|LEFT JOIN employee e ON (ct.salesman_id = e.id) | .
 
 763   my @saved_values = @values;
 
 764   # redo for invoices, orders and quotations
 
 768     if ($form->{l_invnumber}) {
 
 769       my $ar = $cv eq 'customer' ? 'ar' : 'ap';
 
 770       my $module = $ar eq 'ar' ? 'is' : 'ir';
 
 771       push(@values, @saved_values);
 
 774         qq|SELECT ct.*, b.description AS business, e.name as salesman, | .
 
 775         qq|  a.invnumber, a.ordnumber, a.quonumber, a.id AS invid, | .
 
 776         qq|  '$module' AS module, 'invoice' AS formtype, | .
 
 777         qq|  (a.amount = a.paid) AS closed | .
 
 779         qq|JOIN $ar a ON (a.${cv}_id = ct.id) | .
 
 780         qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
 
 781         qq|LEFT JOIN employee e ON (ct.salesman_id = e.id) | .
 
 782         qq|WHERE $where AND (a.invoice = '1')|;
 
 785     if ( $form->{l_ordnumber} ) {
 
 786       push(@values, @saved_values);
 
 789         qq|SELECT ct.*, b.description AS business, e.name as salesman, | .
 
 790         qq|  ' ' AS invnumber, o.ordnumber, o.quonumber, o.id AS invid, | .
 
 791         qq|  'oe' AS module, 'order' AS formtype, o.closed | .
 
 793         qq|JOIN oe o ON (o.${cv}_id = ct.id) | .
 
 794         qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
 
 795         qq|LEFT JOIN employee e ON (ct.salesman_id = e.id) | .
 
 796         qq|WHERE $where AND (o.quotation = '0')|;
 
 799     if ( $form->{l_quonumber} ) {
 
 800       push(@values, @saved_values);
 
 803         qq|SELECT ct.*, b.description AS business, e.name as salesman, | .
 
 804         qq|  ' ' AS invnumber, o.ordnumber, o.quonumber, o.id AS invid, | .
 
 805         qq|  'oe' AS module, 'quotation' AS formtype, o.closed | .
 
 807         qq|JOIN oe o ON (o.${cv}_id = ct.id) | .
 
 808         qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
 
 809         qq|LEFT JOIN employee e ON (ct.salesman_id = e.id) | .
 
 810         qq|WHERE $where AND (o.quotation = '1')|;
 
 814   $query .= qq| ORDER BY $sortorder|;
 
 816   $form->{CT} = selectall_hashref_query($form, $dbh, $query, @values);
 
 818   $main::lxdebug->leave_sub();
 
 822   $main::lxdebug->enter_sub();
 
 824   my ( $self, $myconfig, $form ) = @_;
 
 826   die 'Missing argument: cp_id' unless $::form->{cp_id};
 
 828   my $dbh   = $form->dbconnect($myconfig);
 
 830     qq|SELECT * FROM contacts c | .
 
 831     qq|WHERE cp_id = ? ORDER BY cp_id limit 1|;
 
 832   my $sth = prepare_execute_query($form, $dbh, $query, $form->{cp_id});
 
 833   my $ref = $sth->fetchrow_hashref("NAME_lc");
 
 835   map { $form->{$_} = $ref->{$_} } keys %$ref;
 
 837   $query = qq|SELECT COUNT(cp_id) AS used FROM (
 
 838     SELECT cp_id FROM oe UNION
 
 839     SELECT cp_id FROM ar UNION
 
 840     SELECT cp_id FROM ap UNION
 
 841     SELECT cp_id FROM delivery_orders
 
 842   ) AS cpid WHERE cp_id = ? OR ? = 0|;
 
 843   ($form->{cp_used}) = selectfirst_array_query($form, $dbh, $query, ($form->{cp_id})x2);
 
 848   $main::lxdebug->leave_sub();
 
 852   $main::lxdebug->enter_sub();
 
 854   my ( $self, $myconfig, $form ) = @_;
 
 855   my $dbh   = $form->dbconnect($myconfig);
 
 856   my $query = qq|SELECT * FROM shipto WHERE shipto_id = ?|;
 
 857   my $sth = prepare_execute_query($form, $dbh, $query, $form->{shipto_id});
 
 859   my $ref = $sth->fetchrow_hashref("NAME_lc");
 
 861   map { $form->{$_} = $ref->{$_} } keys %$ref;
 
 863   $query = qq|SELECT COUNT(shipto_id) AS used FROM (
 
 864     SELECT shipto_id FROM oe UNION
 
 865     SELECT shipto_id FROM ar UNION
 
 866     SELECT shipto_id FROM delivery_orders
 
 867   ) AS stid WHERE shipto_id = ? OR ? = 0|;
 
 868   ($form->{shiptoused}) = selectfirst_array_query($form, $dbh, $query, ($form->{shipto_id})x2);
 
 873   $main::lxdebug->leave_sub();
 
 877   $main::lxdebug->enter_sub();
 
 879   my ( $self, $myconfig, $form ) = @_;
 
 880   my $dbh = $form->dbconnect($myconfig);
 
 882   my $arap = $form->{db} eq "vendor" ? "ap" : "ar";
 
 883   my $db = $form->{db} eq "customer" ? "customer" : "vendor";
 
 884   my $qty_sign = $form->{db} eq 'vendor' ? ' * -1 AS qty' : '';
 
 886   my $where = " WHERE 1=1 ";
 
 889   if ($form->{shipto_id} && ($arap eq "ar")) {
 
 890     $where .= "AND ${arap}.shipto_id = ?";
 
 891     push(@values, $form->{shipto_id});
 
 893     $where .= "AND ${arap}.${db}_id = ?";
 
 894     push(@values, $form->{id});
 
 898     $where .= "AND ${arap}.transdate >= ?";
 
 899     push(@values, conv_date($form->{from}));
 
 902     $where .= "AND ${arap}.transdate <= ?";
 
 903     push(@values, conv_date($form->{to}));
 
 906     qq|SELECT s.shiptoname, i.qty $qty_sign, | .
 
 907     qq|  ${arap}.id, ${arap}.transdate, ${arap}.invnumber, ${arap}.ordnumber, | .
 
 908     qq|  i.description, i.unit, i.sellprice, | .
 
 909     qq|  oe.id AS oe_id, invoice | .
 
 911     qq|LEFT JOIN shipto s ON | .
 
 913      ? qq|(ar.shipto_id = s.shipto_id) |
 
 914      : qq|(ap.id = s.trans_id) |) .
 
 915     qq|LEFT JOIN invoice i ON (${arap}.id = i.trans_id) | .
 
 916     qq|LEFT join parts p ON (p.id = i.parts_id) | .
 
 917     qq|LEFT JOIN oe ON (oe.ordnumber = ${arap}.ordnumber AND NOT ${arap}.ordnumber = '') | .
 
 919     qq|ORDER BY ${arap}.transdate DESC LIMIT 15|;
 
 921   $form->{DELIVERY} = selectall_hashref_query($form, $dbh, $query, @values);
 
 925   $main::lxdebug->leave_sub();
 
 929   $main::lxdebug->enter_sub();
 
 934   my $form   = $main::form;
 
 936   Common::check_params(\%params, 'dbh');
 
 938   if (!$form->{NOTE_subject}) {
 
 939     $main::lxdebug->leave_sub();
 
 943   my $dbh = $params{dbh};
 
 947     'id'           => $form->{NOTE_id},
 
 948     'subject'      => $form->{NOTE_subject},
 
 949     'body'         => $form->{NOTE_body},
 
 950     'trans_id'     => $form->{id},
 
 951     'trans_module' => 'ct',
 
 954   $note{id} = Notes->save(%note);
 
 956   if ($form->{FU_date}) {
 
 958       'id'               => $form->{FU_id},
 
 959       'note_id'          => $note{id},
 
 960       'follow_up_date'   => $form->{FU_date},
 
 961       'created_for_user' => $form->{FU_created_for_user},
 
 962       'done'             => $form->{FU_done} ? 1 : 0,
 
 963       'subject'          => $form->{NOTE_subject},
 
 964       'body'             => $form->{NOTE_body},
 
 967           'trans_id'     => $form->{id},
 
 968           'trans_type'   => $form->{db} eq 'customer' ? 'customer' : 'vendor',
 
 969           'trans_info'   => $form->{name},
 
 974     $follow_up{id} = FU->save(%follow_up);
 
 976   } elsif ($form->{FU_id}) {
 
 977     do_query($form, $dbh, qq|DELETE FROM follow_up_links WHERE follow_up_id = ?|, conv_i($form->{FU_id}));
 
 978     do_query($form, $dbh, qq|DELETE FROM follow_ups      WHERE id = ?|,           conv_i($form->{FU_id}));
 
 981   delete @{$form}{grep { /^NOTE_|^FU_/ } keys %{ $form }};
 
 983   $main::lxdebug->leave_sub();
 
 986 sub _delete_selected_notes {
 
 987   $main::lxdebug->enter_sub();
 
 992   Common::check_params(\%params, 'dbh');
 
 994   my $form = $main::form;
 
 995   my $dbh  = $params{dbh};
 
 997   foreach my $i (1 .. $form->{NOTES_rowcount}) {
 
 998     next unless ($form->{"NOTE_delete_$i"} && $form->{"NOTE_id_$i"});
 
1000     Notes->delete('dbh' => $params{dbh},
 
1001                   'id'  => $form->{"NOTE_id_$i"});
 
1004   $main::lxdebug->leave_sub();
 
1007 # TODO: remove in 2.7.0 stable
 
1009   $main::lxdebug->enter_sub();
 
1012   my $shipto_id = shift;
 
1014   my $form      = $main::form;
 
1015   my %myconfig  = %main::myconfig;
 
1016   my $dbh       = $form->get_standard_dbh(\%myconfig);
 
1018   do_query($form, $dbh, qq|UPDATE shipto SET trans_id = NULL WHERE shipto_id = ?|, $shipto_id);
 
1022   $main::lxdebug->leave_sub();
 
1025 # TODO: remove in 2.7.0 stable
 
1026 sub delete_contact {
 
1027   $main::lxdebug->enter_sub();
 
1032   my $form      = $main::form;
 
1033   my %myconfig  = %main::myconfig;
 
1034   my $dbh       = $form->get_standard_dbh(\%myconfig);
 
1036   do_query($form, $dbh, qq|UPDATE contacts SET cp_cv_id = NULL WHERE cp_id = ?|, $cp_id);
 
1040   $main::lxdebug->leave_sub();
 
1044   $main::lxdebug->enter_sub();
 
1049   Common::check_params(\%params, qw(vc id));
 
1051   my $myconfig = \%main::myconfig;
 
1052   my $form     = $main::form;
 
1054   my $dbh      = $params{dbh} || $form->get_standard_dbh($myconfig);
 
1056   my $table        = $params{vc} eq 'customer' ? 'customer' : 'vendor';
 
1057   my @ids          = ref $params{id} eq 'ARRAY' ? @{ $params{id} } : ($params{id});
 
1058   my $placeholders = join ", ", ('?') x scalar @ids;
 
1059   my $query        = qq|SELECT id, name, account_number, bank, bank_code, iban, bic
 
1061                         WHERE id IN (${placeholders})|;
 
1063   my $result       = selectall_hashref_query($form, $dbh, $query, map { conv_i($_) } @ids);
 
1065   if (ref $params{id} eq 'ARRAY') {
 
1066     $result = { map { $_->{id} => $_ } @{ $result } };
 
1068     $result = $result->[0] || { 'id' => $params{id} };
 
1071   $main::lxdebug->leave_sub();
 
1076 sub parse_excel_file {
 
1077   $main::lxdebug->enter_sub();
 
1079   my ($self, $myconfig, $form) = @_;
 
1080   my $locale = $main::locale;
 
1082   $form->{formname}   = 'sales_quotation';
 
1083   $form->{type}   = 'sales_quotation';
 
1084   $form->{format} = 'excel';
 
1085   $form->{media}  = 'screen';
 
1086   $form->{quonumber} = 1;
 
1089   # $form->{"notes"} will be overridden by the customer's/vendor's "notes" field. So save it here.
 
1090   $form->{ $form->{"formname"} . "notes" } = $form->{"notes"};
 
1094   $form->{"${inv}date"} = $form->{transdate};
 
1095   $form->{label}        = $locale->text('Quotation');
 
1096   my $numberfld            = "sqnumber";
 
1100   $form->{what_done} = $form->{formname};
 
1102   map({ delete($form->{$_}); } grep(/^cp_/, keys(%{ $form })));
 
1104   my $output_dateformat = $myconfig->{"dateformat"};
 
1105   my $output_numberformat = $myconfig->{"numberformat"};
 
1106   my $output_longdates = 1;
 
1108   # map login user variables
 
1109   map { $form->{"login_$_"} = $myconfig->{$_} } ("name", "email", "fax", "tel", "company");
 
1112   for my $field (qw(transdate_oe deliverydate_oe)) {
 
1114       $form->{$field}[$_] = $locale->date($myconfig, $form->{$field}[$_], 1);
 
1115     } 0 .. $#{ $form->{$field} };
 
1118   if ($form->{shipto_id}) {
 
1119     $form->get_shipto($myconfig);
 
1122   $form->{notes} =~ s/^\s+//g;
 
1124   $form->{templates} = $myconfig->{templates};
 
1126   delete $form->{printer_command};
 
1128   $form->get_employee_info($myconfig);
 
1130   my ($cvar_date_fields, $cvar_number_fields) = CVar->get_field_format_list('module' => 'CT', 'prefix' => 'vc_');
 
1132   if (scalar @{ $cvar_date_fields }) {
 
1133     format_dates($output_dateformat, $output_longdates, @{ $cvar_date_fields });
 
1136   while (my ($precision, $field_list) = each %{ $cvar_number_fields }) {
 
1137     reformat_numbers($output_numberformat, $precision, @{ $field_list });
 
1141   my $extension            = 'xls';
 
1143   $form->{IN}         = "$form->{formname}.${extension}";
 
1145   delete $form->{OUT};
 
1147   $form->parse_template($myconfig);
 
1149   $main::lxdebug->leave_sub();
 
1152 sub search_contacts {
 
1153   $::lxdebug->enter_sub;
 
1158   my $dbh       = $params{dbh} || $::form->get_standard_dbh;
 
1161     'cp_name'   => 'cp_name, cp_givenname',
 
1162     'vcname'    => 'vcname, cp_name, cp_givenname',
 
1163     'vcnumber'  => 'vcnumber, cp_name, cp_givenname',
 
1166   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);
 
1168   my $order_by  = $sortcols{$::form->{sort}} ? $::form->{sort} : 'cp_name';
 
1169   $::form->{sort} = $order_by;
 
1170   $order_by     = $sortspecs{$order_by} if ($sortspecs{$order_by});
 
1172   my $sortdir   = $::form->{sortdir} ? 'ASC' : 'DESC';
 
1173   $order_by     =~ s/,/ ${sortdir},/g;
 
1174   $order_by    .= " $sortdir";
 
1176   my @where_tokens = ();
 
1179   if ($params{search_term}) {
 
1182       'cp.cp_name      ILIKE ?',
 
1183       'cp.cp_givenname ILIKE ?',
 
1184       'cp.cp_email     ILIKE ?';
 
1185     push @values, ('%' . $params{search_term} . '%') x 3;
 
1187     if (($params{search_term} =~ m/\d/) && ($params{search_term} !~ m/[^\d \(\)+\-]/)) {
 
1188       my $number =  $params{search_term};
 
1189       $number    =~ s/[^\d]//g;
 
1190       $number    =  join '[ /\(\)+\-]*', split(m//, $number);
 
1192       push @tokens, map { "($_ ~ '$number')" } qw(cp_phone1 cp_phone2 cp_mobile1 cp_mobile2);
 
1195     push @where_tokens, map { "($_)" } join ' OR ', @tokens;
 
1198   my ($cvar_where, @cvar_values) = CVar->build_filter_query('module'         => 'Contacts',
 
1199                                                             'trans_id_field' => 'cp.cp_id',
 
1200                                                             'filter'         => $params{filter});
 
1203     push @where_tokens, $cvar_where;
 
1204     push @values, @cvar_values;
 
1207   if (my $filter = $params{filter}) {
 
1208     for (qw(name title givenname email project abteilung)) {
 
1209       next unless $filter->{"cp_$_"};
 
1210       add_token(\@where_tokens, \@values, col =>  "cp.cp_$_", val => $filter->{"cp_$_"}, method => 'ILIKE', esc => 'substr');
 
1213     push @where_tokens, 'cp.cp_cv_id IS NOT NULL' if $filter->{status} eq 'active';
 
1214     push @where_tokens, 'cp.cp_cv_id IS NULL'     if $filter->{status} eq 'orphaned';
 
1217   my $where = @where_tokens ? 'WHERE ' . join ' AND ', @where_tokens : '';
 
1219   my $query     = qq|SELECT cp.*,
 
1220                        COALESCE(c.id,             v.id)           AS vcid,
 
1221                        COALESCE(c.name,           v.name)         AS vcname,
 
1222                        COALESCE(c.customernumber, v.vendornumber) AS vcnumber,
 
1223                        CASE WHEN c.name IS NULL THEN 'vendor' ELSE 'customer' END AS db
 
1225                      LEFT JOIN customer c ON (cp.cp_cv_id = c.id)
 
1226                      LEFT JOIN vendor v   ON (cp.cp_cv_id = v.id)
 
1228                      ORDER BY $order_by|;
 
1230   my $contacts  = selectall_hashref_query($::form, $dbh, $query, @values);
 
1232   $::lxdebug->leave_sub;
 
1234   return @{ $contacts };