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
 
  16 # This program is free software; you can redistribute it and/or modify
 
  17 # it under the terms of the GNU General Public License as published by
 
  18 # the Free Software Foundation; either version 2 of the License, or
 
  19 # (at your option) any later version.
 
  21 # This program is distributed in the hope that it will be useful,
 
  22 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  23 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  24 # GNU General Public License for more details.
 
  25 # You should have received a copy of the GNU General Public License
 
  26 # along with this program; if not, write to the Free Software
 
  27 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
  28 #======================================================================
 
  30 # common routines for gl, ar, ap, is, ir, oe
 
  37 # any custom scripts for this one
 
  38 if (-f "bin/mozilla/custom_arap.pl") {
 
  39   eval { require "bin/mozilla/custom_arap.pl"; };
 
  41 if (-f "bin/mozilla/$main::form->{login}_arap.pl") {
 
  42   eval { require "bin/mozilla/$main::form->{login}_arap.pl"; };
 
  47 require "bin/mozilla/common.pl";
 
  52   $main::lxdebug->enter_sub();
 
  54   my $form     = $main::form;
 
  55   my %myconfig = %main::myconfig;
 
  56   my $locale   = $main::locale;
 
  58   $main::auth->assert('general_ledger               | vendor_invoice_edit       | sales_order_edit    | invoice_edit |' .
 
  59                 'request_quotation_edit       | sales_quotation_edit      | purchase_order_edit | cash         |' .
 
  60                 'purchase_delivery_order_edit | sales_delivery_order_edit');
 
  62   my ($name, %params) = @_;
 
  64   $name = $name eq "customer" ? "customer" : "vendor";
 
  66   my ($new_name, $new_id) = split /--/, $form->{$name};
 
  68   # if we use a selection
 
  69   if ($form->{"select$name"}) {
 
  70     if ($form->{"old$name"} ne $form->{$name}) {
 
  72       # this is needed for is, ir and oe
 
  74       # for credit calculations
 
  75       $form->{oldinvtotal}  = 0;
 
  76       $form->{oldtotalpaid} = 0;
 
  79       $form->{"${name}_id"} = $new_id;
 
  82       IS->get_customer(\%myconfig, \%$form) if ($name eq 'customer');
 
  83       IR->get_vendor(\%myconfig, \%$form) if ($name eq 'vendor');
 
  85       $form->{$name} = $form->{"old$name"} = "$new_name--$new_id";
 
  91     # check name, combine name and id
 
  92     if ($form->{"old$name"} ne qq|$form->{$name}--$form->{"${name}_id"}|) {
 
  94       # this is needed for is, ir and oe
 
  97       # for credit calculations
 
  98       $form->{oldinvtotal}  = 0;
 
  99       $form->{oldtotalpaid} = 0;
 
 100       $form->{calctax}      = 1;
 
 102       # return one name or a list of names in $form->{name_list}
 
 103       $i = $form->get_name(\%myconfig, $name);
 
 106         if ($params{no_select}) {
 
 107           # $locale->text('Customer')
 
 108           # $locale->text('Vendor')
 
 109           $form->error($locale->text("More than one #1 found matching, please be more specific.", $locale->text(ucfirst $name)));
 
 119         $form->{"${name}_id"} = $form->{name_list}[0]->{id};
 
 120         $form->{$name}        = $form->{name_list}[0]->{name};
 
 121         $form->{"old$name"}   = qq|$form->{$name}--$form->{"${name}_id"}|;
 
 123         _reset_salesman_id();
 
 124         IS->get_customer(\%myconfig, \%$form) if ($name eq 'customer');
 
 125         IR->get_vendor(\%myconfig, \%$form) if ($name eq 'vendor');
 
 129         # name is not on file
 
 130         # $locale->text('Customer not on file or locked!')
 
 131         # $locale->text('Vendor not on file or locked!')
 
 132         my $msg = ucfirst $name . " not on file or locked!";
 
 133         $form->error($locale->text($msg));
 
 137   $form->language_payment(\%myconfig);
 
 139   $main::lxdebug->leave_sub();
 
 144 # $locale->text('Customer not on file!')
 
 145 # $locale->text('Vendor not on file!')
 
 148   $main::lxdebug->enter_sub();
 
 150   my $form     = $main::form;
 
 151   my $locale   = $main::locale;
 
 153   $main::auth->assert('general_ledger         | vendor_invoice_edit  | sales_order_edit    | invoice_edit |' .
 
 154                 'request_quotation_edit | sales_quotation_edit | purchase_order_edit | cash');
 
 158   my @column_index = qw(ndx name address);
 
 160   my $label             = ucfirst $table;
 
 162   $column_data{ndx}  = qq|<th> </th>|;
 
 164     qq|<th class=listheading>| . $locale->text($label) . qq|</th>|;
 
 165   $column_data{address} =
 
 166     qq|<th class=listheading>| . $locale->text('Address') . qq|</th>|;
 
 168   # list items with radio button on a form
 
 171   my $title = $locale->text('Select from one of the names below');
 
 174 <form method=post action=$form->{script}>
 
 178     <th class=listtop>$title</th>
 
 184         <tr class=listheading>|;
 
 186   map { print "\n$column_data{$_}" } @column_index;
 
 194   foreach my $ref (@{ $form->{name_list} }) {
 
 195     my $checked = ($i++) ? "" : "checked";
 
 197     $ref->{name} =~ s/\"/"/g;
 
 200       qq|<td><input name=ndx class=radio type=radio value=$i $checked></td>|;
 
 202       qq|<td><input name="new_name_$i" type=hidden value="$ref->{name}">$ref->{name}</td>|;
 
 203     $column_data{address} = qq|<td>$ref->{address} </td>|;
 
 208         <tr class=listrow$j>|;
 
 210     map { print "\n$column_data{$_}" } @column_index;
 
 215 <input name="new_id_$i" type=hidden value=$ref->{id}>
 
 226     <td><hr size=3 noshade></td>
 
 230 <input name=lastndx type=hidden value=$i>
 
 235   map { delete $form->{$_} } qw(action name_list header);
 
 237   # save all other form variables
 
 238   foreach my $key (keys %${form}) {
 
 239     next if (($key eq 'login') || ($key eq 'password') || ('' ne ref $form->{$key}));
 
 240     $form->{$key} =~ s/\"/"/g;
 
 241     print qq|<input name=$key type=hidden value="$form->{$key}">\n|;
 
 245 <input type=hidden name=nextsub value=name_selected>
 
 247 <input type=hidden name=vc value=$table>
 
 249 <input class=submit type=submit name=action value="|
 
 250     . $locale->text('Continue') . qq|">
 
 254   $main::lxdebug->leave_sub();
 
 258   $main::lxdebug->enter_sub();
 
 260   my $form     = $main::form;
 
 261   my %myconfig = %main::myconfig;
 
 263   $main::auth->assert('general_ledger         | vendor_invoice_edit  | sales_order_edit    | invoice_edit |' .
 
 264                 'request_quotation_edit | sales_quotation_edit | purchase_order_edit | cash');
 
 266   # replace the variable with the one checked
 
 269   my $i = $form->{ndx};
 
 271   _reset_salesman_id();
 
 273   $form->{ $form->{vc} }    = $form->{"new_name_$i"};
 
 274   $form->{"$form->{vc}_id"} = $form->{"new_id_$i"};
 
 275   $form->{"old$form->{vc}"} =
 
 276     qq|$form->{$form->{vc}}--$form->{"$form->{vc}_id"}|;
 
 278   # delete all the new_ variables
 
 279   for $i (1 .. $form->{lastndx}) {
 
 280     map { delete $form->{"new_${_}_$i"} } qw(id name);
 
 283   map { delete $form->{$_} } qw(ndx lastndx nextsub);
 
 285   IS->get_customer(\%myconfig, \%$form) if ($form->{vc} eq 'customer');
 
 286   IR->get_vendor(\%myconfig, \%$form) if ($form->{vc} eq 'vendor');
 
 290   $main::lxdebug->leave_sub();
 
 293 # Reset the $::form field 'salesman_id' to the ID of the currently
 
 294 # logged in user. Useful when changing to a customer/vendor that has
 
 295 # no salesman listed in their master data.
 
 296 sub _reset_salesman_id {
 
 297   my $current_employee   = SL::DB::Manager::Employee->current;
 
 298   $::form->{salesman_id} = $current_employee->id if $current_employee && exists $::form->{salesman_id};
 
 302   $main::lxdebug->enter_sub();
 
 304   my $form     = $main::form;
 
 305   my $locale   = $main::locale;
 
 307   $main::auth->assert('general_ledger         | vendor_invoice_edit  | sales_order_edit    | invoice_edit |' .
 
 308                 'request_quotation_edit | sales_quotation_edit | purchase_order_edit | cash         | report');
 
 310   my $nextsub = shift || 'update';
 
 312   for my $i (1 .. $form->{rowcount}) {
 
 313     my $suffix = $i ? "_$i" : "";
 
 314     my $prefix = $i ? "" : "global";
 
 315     $form->{"${prefix}project_id${suffix}"} = "" unless $form->{"${prefix}projectnumber$suffix"};
 
 316     if ($form->{"${prefix}projectnumber${suffix}"} ne $form->{"old${prefix}projectnumber${suffix}"}) {
 
 317       if ($form->{"${prefix}projectnumber${suffix}"}) {
 
 320         $form->{projectnumber} = $form->{"${prefix}projectnumber${suffix}"};
 
 321         my %params             = map { $_ => $form->{$_} } qw(projectnumber description active);
 
 323         if (($rows = Projects->search_projects(%params)) > 1) {
 
 325           # check form->{project_list} how many there are
 
 326           $form->{rownumber} = $i;
 
 327           &select_project($i ? undef : 1, $nextsub);
 
 332           $form->{"${prefix}project_id${suffix}"}       = $form->{project_list}->[0]->{id};
 
 333           $form->{"${prefix}projectnumber${suffix}"}    = $form->{project_list}->[0]->{projectnumber};
 
 334           $form->{"old${prefix}projectnumber${suffix}"} = $form->{project_list}->[0]->{projectnumber};
 
 338           $form->error($locale->text('Project not on file!'));
 
 341         $form->{"old${prefix}projectnumber${suffix}"} = "";
 
 346   $main::lxdebug->leave_sub();
 
 350   $::lxdebug->enter_sub;
 
 352   $::auth->assert('general_ledger         | vendor_invoice_edit  | sales_order_edit    | invoice_edit |' .
 
 353                   'request_quotation_edit | sales_quotation_edit | purchase_order_edit | cash         | report');
 
 355   my ($is_global, $nextsub) = @_;
 
 356   my $project_list = delete $::form->{project_list};
 
 358   map { delete $::form->{$_} } qw(action header update);
 
 361   for my $key (keys %$::form) {
 
 362     next if $key eq 'login' || $key eq 'password' || '' ne ref $::form->{$key};
 
 363     push @hiddens, { key => $key, value => $::form->{$key} };
 
 365   push @hiddens, { key => 'is_global',                value => $is_global },
 
 366                  { key => 'project_selected_nextsub', value => $nextsub };
 
 369   print $::form->parse_html_template('arap/select_project', { hiddens => \@hiddens, project_list => $project_list });
 
 371   $::lxdebug->leave_sub;
 
 374 sub project_selected {
 
 375   $main::lxdebug->enter_sub();
 
 377   my $form     = $main::form;
 
 379   $main::auth->assert('general_ledger         | vendor_invoice_edit  | sales_order_edit    | invoice_edit |' .
 
 380                 'request_quotation_edit | sales_quotation_edit | purchase_order_edit | cash         | report');
 
 382   # replace the variable with the one checked
 
 385   my $i = $form->{ndx};
 
 387   my $prefix = $form->{"is_global"} ? "global" : "";
 
 388   my $suffix = $form->{"is_global"} ? "" : "_$form->{rownumber}";
 
 390   $form->{"${prefix}projectnumber${suffix}"} =
 
 391     $form->{"new_projectnumber_$i"};
 
 392   $form->{"old${prefix}projectnumber${suffix}"} =
 
 393     $form->{"new_projectnumber_$i"};
 
 394   $form->{"${prefix}project_id${suffix}"} = $form->{"new_id_$i"};
 
 396   # delete all the new_ variables
 
 397   for $i (1 .. $form->{lastndx}) {
 
 398     map { delete $form->{"new_${_}_$i"} } qw(id projectnumber description);
 
 401   my $nextsub = $form->{project_selected_nextsub} || 'update';
 
 403   map { delete $form->{$_} } qw(ndx lastndx nextsub is_global project_selected_nextsub);
 
 407   $main::lxdebug->leave_sub();
 
 410 sub continue       { call_sub($main::form->{"nextsub"}); }
 
 418 arap.pl - helper functions or customer/vendor retrieval
 
 427 Don't use anyting in this file without extreme care, and even then be prepared for massive headaches.
 
 429 It's a collection of helper routines that wrap the customer/vendor dropdown/textfield duality into something even complexer.
 
 433 =head2 check_name customer|vendor
 
 435 check_name was originally meant to update the selected customer or vendor. The
 
 436 way it does that has generted more hate than almost any other part of this
 
 445 It checks if a vendor or customer is given. No failsafe, vendor fallback if
 
 446 $_[0] is something fancy.
 
 450 It assumes, that there is a field named customer or vendor in $form.
 
 454 It assumes, that this field is filled with name--id, and tries to split that.
 
 455 sql ledger uses that combination to get ids into the select keys.
 
 459 It looks for a field selectcustomer or selectvendor in $form. sql ledger used
 
 460 to store a copy of the html select in there. (again, don't ask)
 
 464 If this field exists, it looks for a field called oldcustomer or oldvendor, in
 
 465 which the old name--id string was stored in sql ledger, and compares those.
 
 469 if they don't match, it will set customer_id or vendor_id in $form, load the
 
 470 entry (which will clobber everything in $form named like a column in customer
 
 471 oder vendor) and return.
 
 475 If there was no select* entry, it assumes that vclimit was lower than the
 
 476 number of entries, and that an input field was generated. In that case the
 
 477 splitting is omitted (since users don't generally include ids in entered names)
 
 481 It looks for a *_id field, and combines it with the given input into a name--id
 
 482 entry and compares it to the old* entry. (Missing any of these will instantly
 
 487 If those do not match, $form->get_name is called to get matching results.
 
 488 get_name only matches by *number and name, not by id, don't try to get it to do
 
 493 The results are stored in $form>{name_list} but a count is returned, and
 
 498 If only one result was found, *_id, * and old* are copied into $form, the entry
 
 499 is loaded (like above, clobbering)
 
 503 If there is more than one, a selection dialog is rendered
 
 507 If none is found, an error is generated.
 
 511 =head3 I built a customer/vendor box somewhere and it doesn't work, what's wrong?
 
 513 Make sure a select* field is given if and only if you render a select box. The
 
 514 actual contents are ignored, but recognition fails if not present.
 
 516 Make sure old* and *_id fields are set correctly (name--id form for old*). They
 
 517 are necessary in all steps and branches.
 
 519 Since get_customer and get_vendor clobber a lot of fields, make sure what
 
 522 =head3 select- version works fine, but things go awry when I use a textbox, any idea?
 
 524 If there is more than one match, check_name will display a select form, that
 
 525 will redirect to the original C<nextsub>. Unfortunately any hidden vars or
 
 526 input fields will be lost in the process unless saved before in a callback.
 
 528 If you still want to use it, you can disable this feature, like this:
 
 530   check_name('customer', no_select => 1)
 
 532 In that case multiple matches will trigger an error.
 
 534 Otherwise you'll have to care to include a complete state in callback.