Feature Sammelauftraege fuer Antivir
authorSven Schöling <s.schoeling@linet-services.de>
Tue, 6 Dec 2005 16:18:00 +0000 (16:18 +0000)
committerSven Schöling <s.schoeling@linet-services.de>
Tue, 6 Dec 2005 16:18:00 +0000 (16:18 +0000)
- Kann jetzt mehrere Auftraege in der Suchmaske anwaehlen und zusammenfassen zu einem Sammelauftrag.
- Kann diesen Sammelauftrag als neu speichern und eine Rechnung dafuer ausstellen.
- Kann die folgende Rechnung wiederum speichern und buchen.
- Wird Sammelauftraege mit nur einem Auftrag abfangen und wie gehabt als einzelnen behandeln.
- Wird soviele Daten wie moeglich im Header des Sammelauftrags beibehalten, wobei customer, ordnumber und transdate eindeutig sein muessen.
- transdate und ordnumber werden bei Bedarf ueberschrieben, nicht eindeutiger customer wird mit Fehlermeldung quittiert

Zusaetzlich:
- Bugfix in Form::get_exchangerate, genauso gefixt wie in Form::check_exchangerate
- neue Routine OE:close_orders, die genau das tut.
- Der Versuch oe::edit ohne eine id aufzurufen wird nun auf oe::add umgeleitet

SL/Form.pm
SL/OE.pm
bin/mozilla/io.pl
bin/mozilla/oe.pl
locale/de/all
locale/en_GB/all

index 867f946..5fb58af 100644 (file)
@@ -1,4 +1,4 @@
-#=====================================================================
+#====================================================================
 # LX-Office ERP
 # Copyright (C) 2004
 # Based on SQL-Ledger Version 2.1.9
@@ -1277,6 +1277,11 @@ sub get_exchangerate {
   $main::lxdebug->enter_sub();
 
   my ($self, $dbh, $curr, $transdate, $fld) = @_;
+  
+  unless ($transdate) {
+    $main::lxdebug->leave_sub();
+    return "";
+  }
 
   my $query = qq|SELECT e.$fld FROM exchangerate e
                  WHERE e.curr = '$curr'
index ac507d0..c6316f6 100644 (file)
--- a/SL/OE.pm
+++ b/SL/OE.pm
@@ -1,4 +1,4 @@
-#=====================================================================
+#====================================================================
 # LX-Office ERP
 # Copyright (C) 2004
 # Based on SQL-Ledger Version 2.1.9
@@ -464,6 +464,27 @@ Message: $form->{message}\r| if $form->{message};
   return $rc;
 }
 
+# this function closes multiple orders given in $form->{ordnumber_#}. 
+# use this for multiple orders that don't have to be saved back
+# single orders should use OE::save instead.
+sub close_orders {
+  $main::lxdebug->enter_sub();
+
+  my ($self, $myconfig ,$form) = @_;
+
+  # get ids from $form
+  map { push @ids, $form->{"ordnumber_$_"} if $form->{"ordnumber_$_"} } (1 .. $form->{rowcount});
+  
+  my $dbh = $form->dbconnect($myconfig);
+  $query = qq|UPDATE oe SET
+              closed = TRUE
+              WHERE ordnumber IN (|.join(', ', map{ $dbh->quote($_) }@ids).qq|)|;
+  $dbh->do($query) || $form->dberror($query);
+  $dbh->disconnect;
+
+  $main::lxdebug->leave_sub();
+}
+
 sub delete {
   $main::lxdebug->enter_sub();
 
@@ -544,6 +565,15 @@ sub retrieve {
 
   my $query;
 
+  # translate the ids (given by id_# and trans_id_#) into one array of ids, so we can join them later
+  map { push @ids, $form->{"trans_id_$_"} if ($form->{"id_$_"}) } (1 .. $form->{"rowcount"});
+
+  # if called in multi id mode, and still only got one id, switch back to single id 
+  if ($form->{"rowcount"} and $#ids == 0) {
+    $form->{"id"} = $ids[0];
+    undef @ids;
+  }
+
   if ($form->{id}) {
 
     # get default accounts and last order number
@@ -583,10 +613,13 @@ sub retrieve {
 
   ($form->{currency}) = split /:/, $form->{currencies};
 
-  if ($form->{id}) {
+  if ($form->{id} or @ids) {
 
-    # retrieve order
-    $query = qq|SELECT o.cp_id,o.ordnumber, o.transdate, o.reqdate,
+    # retrieve order for single id
+    # NOTE: this query is intended to fetch all information only ONCE.
+    # so if any of these infos is important (or even different) for any item, 
+    # it will be killed out and then has to be fetched from the item scope query further down
+    $query = qq|SELECT o.cp_id, o.ordnumber, o.transdate, o.reqdate,
                 o.taxincluded, o.shippingpoint, o.shipvia, o.notes, o.intnotes,
                o.curr AS currency, e.name AS employee, o.employee_id,
                o.$form->{vc}_id, cv.name AS $form->{vc}, o.amount AS invtotal,
@@ -596,47 +629,67 @@ sub retrieve {
                JOIN $form->{vc} cv ON (o.$form->{vc}_id = cv.id)
                LEFT JOIN employee e ON (o.employee_id = e.id)
                LEFT JOIN department d ON (o.department_id = d.id)
-               WHERE o.id = $form->{id}|;
-    $sth = $dbh->prepare($query);
-    $sth->execute || $form->dberror($query);
+               |. ($form->{id} 
+                  ? qq|WHERE o.id = $form->{id}| 
+                   : qq|WHERE o.id IN (|.join(', ', @ids).qq|)|
+                  );
 
-    $ref = $sth->fetchrow_hashref(NAME_lc);
-    map { $form->{$_} = $ref->{$_} } keys %$ref;
-    $sth->finish;
+#$main::lxdebug->message(0, $query);
 
-    $query = qq|SELECT s.* FROM shipto s
-                WHERE s.trans_id = $form->{id}|;
     $sth = $dbh->prepare($query);
     $sth->execute || $form->dberror($query);
 
     $ref = $sth->fetchrow_hashref(NAME_lc);
     map { $form->{$_} = $ref->{$_} } keys %$ref;
-    $sth->finish;
-
-    # get printed, emailed and queued
-    $query = qq|SELECT s.printed, s.emailed, s.spoolfile, s.formname
-                FROM status s
-               WHERE s.trans_id = $form->{id}|;
-    $sth = $dbh->prepare($query);
-    $sth->execute || $form->dberror($query);
 
+    # destroy all entries for multiple ids that yield different information
     while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
-      $form->{printed} .= "$ref->{formname} " if $ref->{printed};
-      $form->{emailed} .= "$ref->{formname} " if $ref->{emailed};
-      $form->{queued} .= "$ref->{formname} $ref->{spoolfile} "
-        if $ref->{spoolfile};
+      map { undef $form->{$_} if ($ref->{$_} ne $form->{$_}) } keys %$ref;
     }
+
+    # if not given, fill transdate with current_date
+    $form->{transdate} = $form->current_date($myconfig) unless $form->{transdate};
+
     $sth->finish;
-    map { $form->{$_} =~ s/ +$//g } qw(printed emailed queued);
+
+    # shipto and pinted/mailed/queued status makes only sense for single id retrieve 
+    if (!@ids) {
+      $query = qq|SELECT s.* FROM shipto s
+                  WHERE s.trans_id = $form->{id}|;
+      $sth = $dbh->prepare($query);
+      $sth->execute || $form->dberror($query);
+
+      $ref = $sth->fetchrow_hashref(NAME_lc);
+      map { $form->{$_} = $ref->{$_} } keys %$ref;
+      $sth->finish;
+
+      # get printed, emailed and queued
+      $query = qq|SELECT s.printed, s.emailed, s.spoolfile, s.formname
+                  FROM status s
+                  WHERE s.trans_id = $form->{id}|;
+      $sth = $dbh->prepare($query);
+      $sth->execute || $form->dberror($query);
+
+      while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
+        $form->{printed} .= "$ref->{formname} " if $ref->{printed};
+        $form->{emailed} .= "$ref->{formname} " if $ref->{emailed};
+        $form->{queued} .= "$ref->{formname} $ref->{spoolfile} " if $ref->{spoolfile};
+      }
+      $sth->finish;
+      map { $form->{$_} =~ s/ +$//g } qw(printed emailed queued);
+    } # if !@ids
 
     my %oid = ('Pg'     => 'oid',
                'Oracle' => 'rowid');
 
     # retrieve individual items
+    # this query looks up all information about the items
+    # stuff different from the whole will not be overwritten, but saved with a suffix.
     $query = qq|SELECT o.id AS orderitems_id,
                 c1.accno AS inventory_accno,
                 c2.accno AS income_accno,
                c3.accno AS expense_accno,
+               oe.ordnumber, oe.transdate, oe.cusordnumber, 
                 p.partnumber, p.assembly, o.description, o.qty,
                o.sellprice, o.parts_id AS id, o.unit, o.discount, p.bin, p.notes AS partnotes,
                 o.reqdate, o.project_id, o.serialnumber, o.ship,
@@ -644,13 +697,18 @@ sub retrieve {
                pg.partsgroup, o.pricegroup_id, (SELECT pricegroup FROM pricegroup WHERE id=o.pricegroup_id) as pricegroup
                FROM orderitems o
                JOIN parts p ON (o.parts_id = p.id)
+               JOIN oe ON (o.trans_id = oe.id)
                LEFT JOIN chart c1 ON (p.inventory_accno_id = c1.id)
                LEFT JOIN chart c2 ON (p.income_accno_id = c2.id)
                LEFT JOIN chart c3 ON (p.expense_accno_id = c3.id)
                LEFT JOIN project pr ON (o.project_id = pr.id)
                LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
-               WHERE o.trans_id = $form->{id}
+               |. ($form->{id} 
+                  ? qq|WHERE o.trans_id = $form->{id}| 
+                  : qq|WHERE o.trans_id IN (|.join(", ", @ids).qq|)| 
+                  ).qq|
                 ORDER BY o.$oid{$myconfig->{dbdriver}}|;
+    
     $sth = $dbh->prepare($query);
     $sth->execute || $form->dberror($query);
 
index ae8f500..d4eabdf 100644 (file)
@@ -357,6 +357,9 @@ sub display_row {
 <input type=hidden name="listprice_$i" value="$form->{"listprice_$i"}">
 <input type=hidden name="assembly_$i" value="$form->{"assembly_$i"}">
 <input type=hidden name="taxaccounts_$i" value="$form->{"taxaccounts_$i"}">
+<input type=hidden name="ordnumber_$i" value="$form->{"ordnumber_$i"}">
+<input type=hidden name="transdate_$i" value="$form->{"transdate_$i"}">
+<input type=hidden name="cusordnumber_$i" value="$form->{"cusordnumber_$i"}">
 
 |;
 
index cf6bd40..dbb74a9 100644 (file)
@@ -1,4 +1,4 @@
-#=====================================================================
+# #=====================================================================
 # LX-Office ERP
 # Copyright (C) 2004
 # Based on SQL-Ledger Version 2.1.9
@@ -77,6 +77,22 @@ sub add {
 sub edit {
   $lxdebug->enter_sub();
 
+  # editing without stuff to edit? try adding it first
+  if ($form->{rowcount}) {
+    map {$id++ if $form->{"id_$_"}} (1 .. $form->{rowcount});
+    if (!$id) {
+      # reset rowcount
+      undef $form->{rowcount};
+      &add;
+      return;
+    }
+  } else {
+    if (!$form->{id}) {
+      &add;
+      return;
+    }
+  }
+
   if ($form->{type} eq 'purchase_order') {
     $form->{title}   = $locale->text('Edit Purchase Order');
     $form->{heading} = $locale->text('Purchase Order');
@@ -121,6 +137,14 @@ sub order_links {
 
   OE->retrieve(\%myconfig, \%$form);
 
+  # if multiple rowcounts (== collective order) then check if the
+  # there were more than one customer (in that case OE::retrieve removes 
+  # the content from the field)
+  if ($form->{rowcount} && $form->{type} eq 'sales_order' && $form->{customer} eq '') {
+#    $main::lxdebug->message(0, "Detected Edit order with concurrent customers");
+    $form->error($locale->text('Collective Orders only work for orders from one customer!'));
+  }
+
   $taxincluded = $form->{taxincluded};
   $form->{shipto} = 1 if $form->{id};
 
@@ -197,40 +221,20 @@ sub prepare_order {
   $form->{media}    = "screen";
   $form->{formname} = $form->{type};
 
-  if ($form->{id}) {
-
     map { $form->{$_} =~ s/\"/&quot;/g }
       qw(ordnumber quonumber shippingpoint shipvia notes intnotes shiptoname shiptostreet shiptozipcode shiptocity shiptocountry shiptocontact);
 
     foreach $ref (@{ $form->{form_details} }) {
-      $i++;
-      map { $form->{"${_}_$i"} = $ref->{$_} } keys %{$ref};
-      $form->{"discount_$i"} =
-        $form->format_amount(\%myconfig, $form->{"discount_$i"} * 100);
+      $form->{rowcount} = ++$i;
 
-      ($dec) = ($form->{"sellprice_$i"} =~ /\.(\d+)/);
-      $dec           = length $dec;
-      $decimalplaces = ($dec > 2) ? $dec : 2;
-
-      $form->{"sellprice_$i"} =
-        $form->format_amount(\%myconfig, $form->{"sellprice_$i"},
-                             $decimalplaces);
-
-      (my $dec_qty) = ($form->{"qty_$i"} =~ /\.(\d+)/);
-      $dec_qty      = length $dec_qty;
-
-      $form->{"qty_$i"} = $form->format_amount(\%myconfig, $form->{"qty_$i"}, $dec_qty);
-
-      map { $form->{"${_}_$i"} =~ s/\"/&quot;/g }
-        qw(partnumber description unit);
-      $form->{rowcount} = $i;
+      map { $form->{"${_}_$i"} = $ref->{$_} } keys %{$ref};
     }
-  } elsif ($form->{rowcount}) {
+    
     for my $i (1 .. $form->{rowcount}) {
        $form->{"discount_$i"} =
         $form->format_amount(\%myconfig, $form->{"discount_$i"} * 100);
 
-      ($dec) = ($form->{"sellprice_$i"} =~ /\.(\d+)/);
+      ($dec) = ($form->{"sellprice_$i"} =~ /\.(\d+)/);    
       $dec           = length $dec;
       $decimalplaces = ($dec > 2) ? $dec : 2;
 
@@ -245,7 +249,6 @@ sub prepare_order {
       map { $form->{"${_}_$i"} =~ s/\"/&quot;/g }
         qw(partnumber description unit);
     }
-  }
 
   $lxdebug->leave_sub();
 }
@@ -860,7 +863,16 @@ Bearbeiten des $form->{heading}<br>
         . $locale->text('Order') . qq|">
 |;
     }
+  } elsif ($form->{type} =~ /sales_order$/ && $form->{rowcount}) {
+    print qq|
+<br>Workflow  $form->{heading}<br>
+<input class=submit type=submit name=action value="|
+      . $locale->text('Save as new') . qq|">
+<input class=submit type=submit name=action value="|
+      . $locale->text('Invoice') . qq|">
+|;
   }
+  
 
   if ($form->{menubar}) {
     require "$form->{path}/menu.pl";
@@ -1312,6 +1324,11 @@ sub orders {
     }
   }
 
+  # only show checkboxes if gotten here via sales_order form.
+  if ($form->{type} =~ /sales_order/) {
+    unshift @column_index, "ids";
+  }
+
   if ($form->{l_subtotal} eq 'Y') {
     $callback .= "&l_subtotal=Y";
     $href     .= "&l_subtotal=Y";
@@ -1384,6 +1401,8 @@ sub orders {
   $column_header{employee} =
     qq|<th><a class=listheading href=$href&sort=employee>$employee</a></th>|;
 
+  $column_header{ids} = qq|<th></th>|;
+
   if ($form->{ $form->{vc} }) {
     $option = $locale->text(ucfirst $form->{vc});
     $option .= " : $form->{$form->{vc}}";
@@ -1423,6 +1442,7 @@ sub orders {
   print qq|
 <body>
 
+<form method="post" action="oe.pl">
 <table width=100%>
   <tr>
     <th class=listtop>$form->{title}</th>
@@ -1443,7 +1463,7 @@ sub orders {
 |;
 
   # add sort and escape callback
-  $callback = $form->escape($callback . "&sort=$form->{sort}");
+  $callback_escaped = $form->escape($callback . "&sort=$form->{sort}");
 
   if (@{ $form->{OE} }) {
     $sameitem = $form->{OE}->[0]->{ $form->{sort} };
@@ -1455,6 +1475,7 @@ sub orders {
   $warehouse = $form->escape($form->{warehouse});
 
   foreach $oe (@{ $form->{OE} }) {
+    $form->{rowcount} = ++$j;
 
     if ($form->{l_subtotal} eq 'Y') {
       if ($sameitem ne $oe->{ $form->{sort} }) {
@@ -1483,12 +1504,13 @@ sub orders {
     $subtotalnetamount += $oe->{netamount};
     $subtotalamount    += $oe->{amount};
 
+    $column_data{ids}    = qq|<td><input name="id_$j" class=checkbox type=checkbox><input type="hidden" name="trans_id_$j" value="$oe->{id}"></td>|;
     $column_data{id}        = "<td>$oe->{id}</td>";
     $column_data{transdate} = "<td>$oe->{transdate}&nbsp;</td>";
     $column_data{reqdate}   = "<td>$oe->{reqdate}&nbsp;</td>";
 
     $column_data{$ordnumber} =
-      "<td><a href=oe.pl?path=$form->{path}&action=$action&type=$form->{type}&id=$oe->{id}&warehouse=$warehouse&vc=$form->{vc}&login=$form->{login}&password=$form->{password}&callback=$callback>$oe->{$ordnumber}</a></td>";
+      "<td><a href=oe.pl?path=$form->{path}&action=$action&type=$form->{type}&id=$oe->{id}&warehouse=$warehouse&vc=$form->{vc}&login=$form->{login}&password=$form->{password}&callback=$callback_escaped>$oe->{$ordnumber}</a></td>";
     $column_data{name} = "<td>$oe->{name}</td>";
 
     $column_data{employee} = "<td>$oe->{employee}&nbsp;</td>";
@@ -1546,7 +1568,27 @@ sub orders {
   <tr>
     <td><hr size=3 noshade></td>
   </tr>
-</table>
+</table>|;
+
+# multiple invoice edit button only if gotten there via sales_order form.
+
+if ($form->{type} =~ /sales_order/) {
+print qq|
+  <input type="hidden" name="path" value="$form->{path}">
+  <input class"submit" type="submit" name="action" value="|
+. $locale->text('Continue') .qq|">
+  <input type="hidden" name="nextsub" value="edit">
+  <input type="hidden" name="type" value="$form->{type}">
+  <input type="hidden" name="warehouse" value="$warehouse">
+  <input type="hidden" name="vc" value="$form->{vc}">
+  <input type="hidden" name="login" value="$form->{login}">
+  <input type="hidden" name="password" value="$form->{password}">
+  <input type="hidden" name="callback" value="$callback">
+  <input type="hidden" name="rowcount" value="$form->{rowcount}">|;
+}
+
+print qq|
+</form>
 
 <br>
 <form method=post action=$form->{script}>
@@ -1751,8 +1793,10 @@ sub invoice {
   $lxdebug->enter_sub();
 
   if ($form->{type} =~ /_order$/) {
-    $form->isblank("ordnumber", $locale->text('Order Number missing!'));
-    $form->isblank("transdate", $locale->text('Order Date missing!'));
+    # these checks only apply if the items don't bring their own ordnumbers/transdates.
+    # The if clause ensures that by searching for empty ordnumber_#/transdate_# fields.
+    $form->isblank("ordnumber", $locale->text('Order Number missing!')) if ( +{ map { $form->{"ordnumber_$_"}, 1 } ( 1 .. $form->{rowcount}-1 ) }->{''} );
+    $form->isblank("transdate", $locale->text('Order Date missing!'))   if ( +{ map { $form->{"transdate_$_"}, 1 } ( 1 .. $form->{rowcount}-1 ) }->{''} );
 
   } else {
     $form->isblank("quonumber", $locale->text('Quotation Number missing!'));
@@ -1788,7 +1832,15 @@ sub invoice {
 
   # close orders/quotations
   $form->{closed} = 1;
-  OE->save(\%myconfig, \%$form);
+
+  # save order iff one ordnumber has been given 
+  # if not it's most likely a collective order, which can't be saved back
+  # so they just have to be closed
+  if ($form->{ordnumber} ne '') {
+    OE->save(\%myconfig, \%$form);
+  } else {
+    OE->close_orders(\%myconfig, \%$form);
+  }
 
   $form->{transdate} = $form->{invdate} = $form->current_date(\%myconfig);
   $form->{duedate} =
index 058564c..e442d3f 100644 (file)
@@ -174,6 +174,7 @@ $self{texts} = {
   'Closed'                      => 'Geschlossen',
   'Code'                        => 'kode',
   'Code missing!'               => 'kode fehlt!',
+  'Collective Orders only work for orders from one customer!' => 'Sammelaufträge funktionieren nur für Aufträge von einem Kunden!',
   'Comment'                     => 'Kommentar',
   'Company'                     => 'Firma',
   'Company Name'                => 'Firmenname',
index e45542a..bed4415 100644 (file)
@@ -114,6 +114,7 @@ $self{texts} = {
   'Click on login name to edit!' => '',
   'Close Books up to'           => '',
   'Closed'                      => '',
+  'Collective Orders only work for orders from one customer!' => '',
   'Company'                     => '',
   'Compare to'                  => '',
   'Confirm!'                    => '',