Einkaufspreis bei Einkaufsauftrag aus Verkaufsauftrag 2
[kivitendo-erp.git] / SL / OE.pm
index 9adbee2..b1e1f9f 100644 (file)
--- a/SL/OE.pm
+++ b/SL/OE.pm
@@ -37,9 +37,12 @@ package OE;
 use List::Util qw(max first);
 use SL::AM;
 use SL::Common;
+use SL::CVar;
 use SL::DBUtils;
 use SL::IC;
 
+use strict;
+
 sub transactions {
   $main::lxdebug->enter_sub();
 
@@ -72,7 +75,8 @@ sub transactions {
     qq|  o.marge_total, o.marge_percent, | .
     qq|  ex.$rate AS exchangerate, | .
     qq|  pr.projectnumber AS globalprojectnumber, | .
-    qq|  e.name AS employee, s.name AS salesman | .
+    qq|  e.name AS employee, s.name AS salesman, | .
+    qq|  ct.${vc}number AS vcnumber, ct.country, ct.ustid  | .
     qq|FROM oe o | .
     qq|JOIN $vc ct ON (o.${vc}_id = ct.id) | .
     qq|LEFT JOIN employee e ON (o.employee_id = e.id) | .
@@ -95,7 +99,18 @@ sub transactions {
       qq|AND ((globalproject_id = ?) OR EXISTS | .
       qq|  (SELECT * FROM orderitems oi | .
       qq|   WHERE oi.project_id = ? AND oi.trans_id = o.id))|;
-    push(@values, $form->{"project_id"}, $form->{"project_id"});
+    push(@values, conv_i($form->{"project_id"}), conv_i($form->{"project_id"}));
+  }
+
+  if ($form->{"projectnumber"}) {
+    $query .= <<SQL;
+      AND (pr.projectnumber ILIKE ?) OR EXISTS (
+        SELECT * FROM orderitems oi
+        LEFT JOIN project proi ON proi.id = oi.project_id
+        WHERE proi.projectnumber ILIKE ? AND oi.trans_id = o.id
+      )
+SQL
+    push @values, "%" . $form->{"projectnumber"} . "%", "%" . $form->{"projectnumber"} . "%" ;
   }
 
   if ($form->{"${vc}_id"}) {
@@ -184,7 +199,7 @@ sub transactions {
 
   my %id = ();
   $form->{OE} = [];
-  while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
+  while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
     $ref->{exchangerate} = 1 unless $ref->{exchangerate};
     push @{ $form->{OE} }, $ref if $ref->{id} != $id{ $ref->{id} };
     $id{ $ref->{id} } = $ref->{id};
@@ -248,6 +263,9 @@ sub save {
   my $all_units = AM->retrieve_units($myconfig, $form);
   $form->{all_units} = $all_units;
 
+  my $ic_cvar_configs = CVar->get_configs(module => 'IC',
+                                          dbh    => $dbh);
+
   $form->{employee_id} = (split /--/, $form->{employee})[1] if !$form->{employee_id};
   unless ($form->{employee_id}) {
     $form->get_employee($dbh);
@@ -256,6 +274,11 @@ sub save {
   my $ml = ($form->{type} eq 'sales_order') ? 1 : -1;
 
   if ($form->{id}) {
+    $query = qq|DELETE FROM custom_variables
+                WHERE (config_id IN (SELECT id FROM custom_variable_configs WHERE module = 'IC'))
+                  AND (sub_module = 'orderitems')
+                  AND (trans_id IN (SELECT id FROM orderitems WHERE trans_id = ?))|;
+    do_query($form, $dbh, $query, $form->{id});
 
     $query = qq|DELETE FROM orderitems WHERE trans_id = ?|;
     do_query($form, $dbh, $query, $form->{id});
@@ -279,6 +302,8 @@ sub save {
   my $project_id;
   my $reqdate;
   my $taxrate;
+  my $taxbase;
+  my $taxdiff;
   my $taxamount = 0;
   my $fxsellprice;
   my %taxbase;
@@ -350,7 +375,7 @@ sub save {
 
       if ($form->round_amount($taxrate, 7) == 0) {
         if ($form->{taxincluded}) {
-          foreach $item (@taxaccounts) {
+          foreach my $item (@taxaccounts) {
             $taxamount = $form->round_amount($linetotal * $form->{"${item}_rate"} / (1 + abs($form->{"${item}_rate"})), 2);
             $taxaccounts{$item} += $taxamount;
             $taxdiff            += $taxamount;
@@ -358,13 +383,13 @@ sub save {
           }
           $taxaccounts{ $taxaccounts[0] } += $taxdiff;
         } else {
-          foreach $item (@taxaccounts) {
+          foreach my $item (@taxaccounts) {
             $taxaccounts{$item} += $linetotal * $form->{"${item}_rate"};
             $taxbase{$item}     += $taxbase;
           }
         }
       } else {
-        foreach $item (@taxaccounts) {
+        foreach my $item (@taxaccounts) {
           $taxaccounts{$item} += $taxamount * $form->{"${item}_rate"} / $taxrate;
           $taxbase{$item} += $taxbase;
         }
@@ -379,24 +404,19 @@ sub save {
       $pricegroup_id *= 1;
 
       # save detail record in orderitems table
+      my $orderitems_id = $form->{"orderitems_id_$i"};
+      ($orderitems_id)  = selectfirst_array_query($form, $dbh, qq|SELECT nextval('orderitemsid')|) if (!$orderitems_id);
+
       @values = ();
-      $query = qq|INSERT INTO orderitems (|;
-      if ($form->{"orderitems_id_$i"}) {
-        $query .= "id, ";
-      }
-      $query .= qq|trans_id, parts_id, description, longdescription, qty, base_qty, | .
-                qq|sellprice, discount, unit, reqdate, project_id, serialnumber, ship, | .
-                qq|pricegroup_id, ordnumber, transdate, cusordnumber, subtotal, | .
-                qq|marge_percent, marge_total, lastcost, price_factor_id, price_factor, marge_price_factor) | .
-                qq|VALUES (|;
-      if($form->{"orderitems_id_$i"}) {
-        $query .= qq|?,|;
-        push(@values, $form->{"orderitems_id_$i"});
-      }
-      $query .= qq|?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
-                   (SELECT factor FROM price_factors WHERE id = ?), ?)|;
+      $query = qq|INSERT INTO orderitems (
+                    id, trans_id, parts_id, description, longdescription, qty, base_qty,
+                    sellprice, discount, unit, reqdate, project_id, serialnumber, ship,
+                    pricegroup_id, ordnumber, transdate, cusordnumber, subtotal,
+                    marge_percent, marge_total, lastcost, price_factor_id, price_factor, marge_price_factor)
+                  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
+                          (SELECT factor FROM price_factors WHERE id = ?), ?)|;
       push(@values,
-           conv_i($form->{id}), conv_i($form->{"id_$i"}),
+           conv_i($orderitems_id), conv_i($form->{id}), conv_i($form->{"id_$i"}),
            $form->{"description_$i"}, $form->{"longdescription_$i"},
            $form->{"qty_$i"}, $baseqty,
            $fxsellprice, $form->{"discount_$i"},
@@ -412,6 +432,15 @@ sub save {
 
       $form->{"sellprice_$i"} = $fxsellprice;
       $form->{"discount_$i"} *= 100;
+
+      CVar->save_custom_variables(module       => 'IC',
+                                  sub_module   => 'orderitems',
+                                  trans_id     => $orderitems_id,
+                                  configs      => $ic_cvar_configs,
+                                  variables    => $form,
+                                  name_prefix  => 'ic_',
+                                  name_postfix => "_$i",
+                                  dbh          => $dbh);
     }
   }
 
@@ -580,7 +609,7 @@ sub delete {
   my $query = qq|SELECT s.spoolfile FROM status s | .
               qq|WHERE s.trans_id = ?|;
   my @values = (conv_i($form->{id}));
-  $sth = $dbh->prepare($query);
+  my $sth = $dbh->prepare($query);
   $sth->execute(@values) || $self->dberror($query);
 
   my $spoolfile;
@@ -637,6 +666,9 @@ sub retrieve {
 
   my ($query, $query_add, @values, @ids, $sth);
 
+  my $ic_cvar_configs = CVar->get_configs(module => 'IC',
+                                          dbh    => $dbh);
+
   # 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_$_"}
@@ -653,7 +685,9 @@ sub retrieve {
     undef @ids;
   }
 
-  my $query_add = '';
+  # and remember for the rest of the function
+  my $is_collective_order = scalar @ids;
+
   if (!$form->{id}) {
     my $wday         = (localtime(time))[6];
     my $next_workday = $wday == 5 ? 3 : $wday == 6 ? 2 : 1;
@@ -708,14 +742,14 @@ sub retrieve {
     @values = $form->{id} ? ($form->{id}) : @ids;
     $sth = prepare_execute_query($form, $dbh, $query, @values);
 
-    $ref = $sth->fetchrow_hashref(NAME_lc);
+    $ref = $sth->fetchrow_hashref("NAME_lc");
     map { $form->{$_} = $ref->{$_} } keys %$ref;
 
     $form->{saved_xyznumber} = $form->{$form->{type} =~ /_quotation$/ ?
                                          "quonumber" : "ordnumber"};
 
     # set all entries for multiple ids blank that yield different information
-    while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
+    while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
       map { $form->{$_} = '' if ($ref->{$_} ne $form->{$_}) } keys %$ref;
     }
 
@@ -740,7 +774,7 @@ sub retrieve {
       $query = qq|SELECT s.* FROM shipto s WHERE s.trans_id = ? AND s.module = 'OE'|;
       $sth = prepare_execute_query($form, $dbh, $query, $form->{id});
 
-      $ref = $sth->fetchrow_hashref(NAME_lc);
+      $ref = $sth->fetchrow_hashref("NAME_lc");
       delete($ref->{id});
       map { $form->{$_} = $ref->{$_} } keys %$ref;
       $sth->finish;
@@ -749,7 +783,7 @@ sub retrieve {
       $query = qq|SELECT s.printed, s.emailed, s.spoolfile, s.formname FROM status s WHERE s.trans_id = ?|;
       $sth = prepare_execute_query($form, $dbh, $query, $form->{id});
 
-      while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
+      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};
@@ -797,7 +831,16 @@ sub retrieve {
     @ids = $form->{id} ? ($form->{id}) : @ids;
     $sth = prepare_execute_query($form, $dbh, $query, @values);
 
-    while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
+    while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
+      # Retrieve custom variables.
+      my $cvars = CVar->get_custom_variables(dbh        => $dbh,
+                                             module     => 'IC',
+                                             sub_module => 'orderitems',
+                                             trans_id   => $ref->{orderitems_id},
+                                            );
+      map { $ref->{"ic_cvar_$_->{name}"} = $_->{value} } @{ $cvars };
+
+      # Handle accounts.
       if (!$ref->{"part_inventory_accno_id"}) {
         map({ delete($ref->{$_}); } qw(inventory_accno inventory_new_chart inventory_valid));
       }
@@ -847,7 +890,7 @@ sub retrieve {
       delete $ref->{orderitems_id} if (@ids);
 
       # get tax rates and description
-      $accno_id = ($form->{vc} eq "customer") ? $ref->{income_accno} : $ref->{expense_accno};
+      my $accno_id = ($form->{vc} eq "customer") ? $ref->{income_accno} : $ref->{expense_accno};
       $query =
         qq|SELECT c.accno, t.taxdescription, t.rate, t.taxnumber | .
         qq|FROM tax t LEFT JOIN chart c on (c.id = t.chart_id) | .
@@ -855,10 +898,10 @@ sub retrieve {
         qq|               WHERE tk.chart_id = (SELECT id FROM chart WHERE accno = ?) | .
         qq|                 AND startdate <= $transdate ORDER BY startdate DESC LIMIT 1) | .
         qq|ORDER BY c.accno|;
-      $stw = prepare_execute_query($form, $dbh, $query, $accno_id);
+      my $stw = prepare_execute_query($form, $dbh, $query, $accno_id);
       $ref->{taxaccounts} = "";
       my $i = 0;
-      while ($ptr = $stw->fetchrow_hashref(NAME_lc)) {
+      while (my $ptr = $stw->fetchrow_hashref("NAME_lc")) {
         if (($ptr->{accno} eq "") && ($ptr->{rate} == 0)) {
           $i++;
           $ptr->{accno} = $i;
@@ -874,6 +917,7 @@ sub retrieve {
       }
 
       chop $ref->{taxaccounts};
+
       push @{ $form->{form_details} }, $ref;
       $stw->finish;
     }
@@ -899,6 +943,30 @@ sub retrieve {
   return $rc;
 }
 
+sub retrieve_simple {
+  $main::lxdebug->enter_sub();
+
+  my $self     = shift;
+  my %params   = @_;
+
+  Common::check_params(\%params, qw(id));
+
+  my $myconfig    = \%main::myconfig;
+  my $form        = $main::form;
+
+  my $dbh         = $params{dbh} || $form->get_standard_dbh($myconfig);
+
+  my $oe_query    = qq|SELECT * FROM oe         WHERE id = ?|;
+  my $oi_query    = qq|SELECT * FROM orderitems WHERE trans_id = ?|;
+
+  my $order            = selectfirst_hashref_query($form, $dbh, $oe_query, conv_i($params{id}));
+  $order->{orderitems} = selectall_hashref_query(  $form, $dbh, $oi_query, conv_i($params{id}));
+
+  $main::lxdebug->leave_sub();
+
+  return $order;
+}
+
 sub order_details {
   $main::lxdebug->enter_sub();
 
@@ -920,6 +988,11 @@ sub order_details {
   my $position = 0;
   my $subtotal_header = 0;
   my $subposition = 0;
+  my %taxaccounts;
+  my %taxbase;
+  my $tax_rate;
+  my $taxamount;
+
 
   my %oid = ('Pg'     => 'oid',
              'Oracle' => 'rowid');
@@ -969,8 +1042,11 @@ sub order_details {
 
   $form->{discount} = [];
 
+  $form->{TEMPLATE_ARRAYS} = { };
   IC->prepare_parts_for_printing();
 
+  my $ic_cvar_configs = CVar->get_configs(module => 'IC');
+
   my @arrays =
     qw(runningnumber number description longdescription qty ship unit bin
        partnotes serialnumber reqdate sellprice listprice netprice
@@ -978,9 +1054,11 @@ sub order_details {
        linetotal  nodiscount_linetotal tax_rate projectnumber
        price_factor price_factor_name partsgroup);
 
+  push @arrays, map { "ic_cvar_$_->{name}" } @{ $ic_cvar_configs };
+
   my @tax_arrays = qw(taxbase tax taxdescription taxrate taxnumber);
 
-  $form->{TEMPLATE_ARRAYS} = { map { $_ => [] } (@arrays, @tax_arrays) };
+  map { $form->{TEMPLATE_ARRAYS}->{$_} = [] } (@arrays, @tax_arrays);
 
   my $sameitem = "";
   foreach $item (sort { $a->[1] cmp $b->[1] } @partsgroup) {
@@ -1119,17 +1197,17 @@ sub order_details {
         }
 
         $query = qq|SELECT p.partnumber, p.description, p.unit, a.qty, | .
-                      qq|pg.partsgroup | .
-                      qq|FROM assembly a | .
-                            qq|  JOIN parts p ON (a.parts_id = p.id) | .
-                            qq|    LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) | .
-                            qq|    WHERE a.bom = '1' | .
-                            qq|    AND a.id = ? | . $sortorder;
-                   @values = ($form->{"id_$i"});
+                 qq|pg.partsgroup | .
+                 qq|FROM assembly a | .
+                 qq|  JOIN parts p ON (a.parts_id = p.id) | .
+                 qq|    LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) | .
+                 qq|    WHERE a.bom = '1' | .
+                 qq|    AND a.id = ? | . $sortorder;
+        @values = ($form->{"id_$i"});
         $sth = $dbh->prepare($query);
         $sth->execute(@values) || $form->dberror($query);
 
-        while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
+        while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
           if ($form->{groupitems} && $ref->{partsgroup} ne $sameitem) {
             map({ push(@{ $form->{TEMPLATE_ARRAYS}->{$_} }, "") } grep({ $_ ne "description" } @arrays));
             $sameitem = ($ref->{partsgroup}) ? $ref->{partsgroup} : "--";
@@ -1142,6 +1220,7 @@ sub order_details {
         $sth->finish;
       }
 
+      map { push @{ $form->{TEMPLATE_ARRAYS}->{"ic_cvar_$_->{name}"} }, $form->{"ic_cvar_$_->{name}_$i"} } @{ $ic_cvar_configs };
     }
   }
 
@@ -1191,11 +1270,77 @@ sub project_description {
   my ($self, $dbh, $id) = @_;
 
   my $query = qq|SELECT description FROM project WHERE id = ?|;
-  my ($value) = selectrow_query($form, $dbh, $query, $id);
+  my ($value) = selectrow_query($main::form, $dbh, $query, $id);
 
   $main::lxdebug->leave_sub();
 
   return $value;
 }
 
+##########################
+# Get data for the submitted order id
+# from database
+#
+sub get_order_data_by_ordnumber {
+  $main::lxdebug->enter_sub();
+
+  my $self      = shift;
+  my %params    = @_;
+
+  Common::check_params(\%params, qw(ordnumber));
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $dbh      = $form->get_standard_dbh();
+
+  my @values = ($params{ordnumber});
+
+  # We query the database for the fields we need using the submitted "ordnumber"
+  my $query = <<SQL;
+    SELECT o.payment_id, o.salesman_id, o.transdate AS orddate, o.taxzone_id, o.quonumber
+    FROM oe o
+    WHERE o.ordnumber = ?;
+SQL
+
+  # Do the actual query and return the results for later processing by our "frontend"
+  my $result = selectfirst_hashref_query($form, $dbh, $query, @values);
+
+  $main::lxdebug->leave_sub();
+
+  return $result;
+}
+
 1;
+
+__END__
+
+=head1 NAME
+
+OE.pm - Order entry module
+
+=head1 DESCRIPTION
+
+OE.pm is part of the OE module. OE is responsible for sales and purchase orders, as well as sales quotations and purchase requests. This file abstracts the database tables C<oe> and C<orderitems>.
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item retrieve_simple PARAMS
+
+simple OE retrieval by id. does not look up customer, vendor, units or any other stuff. only oe and orderitems.
+
+  my $order = retrieve_simple(id => 2);
+
+  $order => {
+    %_OE_CONTENT,
+    orderitems => [
+      %_ORDERITEM_ROW_1,
+      %_ORDERITEM_ROW_2,
+      ...
+    ]
+  }
+
+=back
+
+=cut