Part Controller - falschen Code aus kivi.Order.js wieder entfernt
[kivitendo-erp.git] / SL / IC.pm
index dc86484..2cf7996 100644 (file)
--- a/SL/IC.pm
+++ b/SL/IC.pm
@@ -42,6 +42,9 @@ use SL::CVar;
 use SL::DBUtils;
 use SL::HTML::Restrict;
 use SL::TransNumber;
+use SL::Util qw(trim);
+use SL::DB;
+use Carp;
 
 use strict;
 
@@ -77,9 +80,7 @@ sub get_part {
   $form->{onhand} *= 1;
 
   # part or service item
-  $form->{item} = ($form->{inventory_accno}) ? 'part' : 'service';
-  if ($form->{assembly}) {
-    $form->{item} = 'assembly';
+  if ($form->{part_type} eq 'assembly') {
 
     # retrieve assembly items
     $query =
@@ -192,8 +193,7 @@ sub get_pricegroups {
 
   my $i = 1;
   foreach my $pg (@{ $pricegroups }) {
-    $form->{"klass_$i"} = "$pg->{id}";
-    $form->{"price_$i"} = $form->format_amount($myconfig, $form->{"price_$i"}, -2);
+    $form->{"price_$i"}         = $form->format_amount($myconfig, $form->{"price_$i"}, -2);
     $form->{"pricegroup_id_$i"} = "$pg->{id}";
     $form->{"pricegroup_$i"}    = "$pg->{pricegroup}";
     $i++;
@@ -224,12 +224,20 @@ sub retrieve_buchungsgruppen {
 }
 
 sub save {
+  my ($self, $myconfig, $form) = @_;
   $main::lxdebug->enter_sub();
 
+  my $rc = SL::DB->client->with_transaction(\&_save, $self, $myconfig, $form);
+
+  $main::lxdebug->leave_sub();
+  return $rc;
+}
+
+sub _save {
   my ($self, $myconfig, $form) = @_;
   my @values;
-  # connect to database, turn off AutoCommit
-  my $dbh = $form->get_standard_dbh;
+
+  my $dbh = SL::DB->client->dbh;
   my $restricter = SL::HTML::Restrict->create;
 
   # save the part
@@ -247,35 +255,26 @@ sub save {
 
   my $makemodel = ($form->{make_1} || $form->{model_1} || ($form->{makemodel_rows} > 1)) ? 1 : 0;
 
-  $form->{assembly} = ($form->{item} eq 'assembly') ? 1 : 0;
 
   my ($query, $sth);
 
   my $priceupdate = ', priceupdate = current_date';
 
   if ($form->{id}) {
-    my $trans_number = SL::TransNumber->new(type => $form->{item}, dbh => $dbh, number => $form->{partnumber}, id => $form->{id});
+    my $trans_number = SL::TransNumber->new(type => $form->{part_type}, dbh => $dbh, number => $form->{partnumber}, id => $form->{id});
     if (!$trans_number->is_unique) {
       $::lxdebug->leave_sub;
       return 3;
     }
 
     # get old price
-    $query = qq|SELECT sellprice, weight FROM parts WHERE id = ?|;
-    my ($sellprice, $weight) = selectrow_query($form, $dbh, $query, conv_i($form->{id}));
-
-    # if item is part of an assembly adjust all assemblies
-    $query = qq|SELECT id, qty FROM assembly WHERE parts_id = ?|;
-    $sth = prepare_execute_query($form, $dbh, $query, conv_i($form->{id}));
-    while (my ($id, $qty) = $sth->fetchrow_array) {
-      &update_assembly($dbh, $form, $id, $qty, $sellprice * 1, $weight * 1);
-    }
-    $sth->finish;
+    $query = qq|SELECT sellprice FROM parts WHERE id = ?|;
+    my ($sellprice) = selectrow_query($form, $dbh, $query, conv_i($form->{id}));
 
     # delete makemodel records
     do_query($form, $dbh, qq|DELETE FROM makemodel WHERE parts_id = ?|, conv_i($form->{id}));
 
-    if ($form->{item} eq 'assembly') {
+    if ($form->{part_type} eq 'assembly') {
       # delete assembly records
       do_query($form, $dbh, qq|DELETE FROM assembly WHERE id = ?|, conv_i($form->{id}));
     }
@@ -289,7 +288,7 @@ sub save {
     $priceupdate        = '' if (all { $previous_values->{$_} == $form->{$_} } qw(sellprice lastcost listprice));
 
   } else {
-    my $trans_number = SL::TransNumber->new(type => $form->{item}, dbh => $dbh, number => $form->{partnumber}, save => 1);
+    my $trans_number = SL::TransNumber->new(type => $form->{part_type}, dbh => $dbh, number => $form->{partnumber}, save => 1);
 
     if ($form->{partnumber} && !$trans_number->is_unique) {
       $::lxdebug->leave_sub;
@@ -299,7 +298,7 @@ sub save {
     $form->{partnumber} ||= $trans_number->create_unique;
 
     ($form->{id}) = selectrow_query($form, $dbh, qq|SELECT nextval('id')|);
-    do_query($form, $dbh, qq|INSERT INTO parts (id, partnumber, unit) VALUES (?, ?, ?)|, $form->{id}, $form->{partnumber}, $form->{unit});
+    do_query($form, $dbh, qq|INSERT INTO parts (id, partnumber, unit, part_type) VALUES (?, ?, ?, ?)|, $form->{id}, $form->{partnumber}, $form->{unit}, $form->{part_type});
 
     $form->{orphaned} = 1;
   }
@@ -310,7 +309,7 @@ sub save {
   }
 
   my ($subq_inventory, $subq_expense, $subq_income);
-  if ($form->{"item"} eq "part") {
+  if ($form->{part_type} eq "part") {
     $subq_inventory =
       qq|(SELECT bg.inventory_accno_id
           FROM buchungsgruppen bg
@@ -319,7 +318,7 @@ sub save {
     $subq_inventory = "NULL";
   }
 
-  if ($form->{"item"} ne "assembly") {
+  if ($form->{part_type} ne "assembly") {
     $subq_expense =
       qq|(SELECT tc.expense_accno_id
           FROM taxzone_charts tc
@@ -335,8 +334,6 @@ sub save {
          partnumber = ?,
          description = ?,
          makemodel = ?,
-         alternate = 'f',
-         assembly = ?,
          listprice = ?,
          sellprice = ?,
          lastcost = ?,
@@ -362,6 +359,7 @@ sub save {
          has_sernumber = ?,
          not_discountable = ?,
          microfiche = ?,
+         part_type = ?,
          partsgroup_id = ?,
          price_factor_id = ?
          $priceupdate
@@ -369,7 +367,6 @@ sub save {
   @values = ($form->{partnumber},
              $form->{description},
              $makemodel ? 't' : 'f',
-             $form->{assembly} ? 't' : 'f',
              $form->{listprice},
              $form->{sellprice},
              $form->{lastcost},
@@ -393,12 +390,15 @@ sub save {
              $form->{has_sernumber} ? 't' : 'f',
              $form->{not_discountable} ? 't' : 'f',
              $form->{microfiche},
+             $form->{part_type},
              conv_i($partsgroup_id),
              conv_i($form->{price_factor_id}),
              conv_i($form->{id})
   );
   do_query($form, $dbh, $query, @values);
 
+  $form->new_lastmtime('parts');
+
   # delete translation records
   do_query($form, $dbh, qq|DELETE FROM translation WHERE parts_id = ?|, conv_i($form->{id}));
 
@@ -457,7 +457,7 @@ sub save {
     }
 
   # add assembly records
-  if ($form->{item} eq 'assembly') {
+  if ($form->{part_type} eq 'assembly') {
     # check additional assembly row
     my $i = $form->{assembly_rows};
     # if last row is not empty add them
@@ -542,35 +542,7 @@ sub save {
 SQL
   do_query($form, $dbh, $query, ($form->{id}) x 2);
 
-  # commit
-  my $rc = $dbh->commit;
-
-  $main::lxdebug->leave_sub();
-
-  return $rc;
-}
-
-sub update_assembly {
-  $main::lxdebug->enter_sub();
-
-  my ($dbh, $form, $id, $qty, $sellprice, $weight) = @_;
-
-  my $query = qq|SELECT id, qty FROM assembly WHERE parts_id = ?|;
-  my $sth = prepare_execute_query($form, $dbh, $query, conv_i($id));
-
-  while (my ($pid, $aqty) = $sth->fetchrow_array) {
-    &update_assembly($dbh, $form, $pid, $aqty * $qty, $sellprice, $weight);
-  }
-  $sth->finish;
-
-  $query =
-    qq|UPDATE parts SET sellprice = sellprice + ?, weight = weight + ?
-       WHERE id = ?|;
-  my @values = ($qty * ($form->{sellprice} - $sellprice),
-             $qty * ($form->{weight} - $weight), conv_i($id));
-  do_query($form, $dbh, $query, @values);
-
-  $main::lxdebug->leave_sub();
+  return 1;
 }
 
 sub retrieve_assemblies {
@@ -586,12 +558,12 @@ sub retrieve_assemblies {
 
   if ($form->{partnumber}) {
     $where .= qq| AND (p.partnumber ILIKE ?)|;
-    push(@values, '%' . $form->{partnumber} . '%');
+    push(@values, like($form->{partnumber}));
   }
 
   if ($form->{description}) {
     $where .= qq| AND (p.description ILIKE ?)|;
-    push(@values, '%' . $form->{description} . '%');
+    push(@values, like($form->{description}));
   }
 
   # retrieve assembly items
@@ -602,7 +574,7 @@ sub retrieve_assemblies {
           FROM parts p2, assembly a
           WHERE (p2.id = a.parts_id) AND (a.id = p.id)) AS inventory
        FROM parts p
-       WHERE NOT p.obsolete AND p.assembly $where|;
+       WHERE NOT p.obsolete AND p.part_type = 'assembly' $where|;
 
   $form->{assembly_items} = selectall_hashref_query($form, $dbh, $query, @values);
 
@@ -610,26 +582,27 @@ sub retrieve_assemblies {
 }
 
 sub delete {
+  my ($self, $myconfig, $form) = @_;
   $main::lxdebug->enter_sub();
 
+  my $rc = SL::DB->client->with_transaction(\&_delete, $self, $myconfig, $form);
+
+  $main::lxdebug->leave_sub();
+  return $rc;
+}
+
+sub _delete {
   my ($self, $myconfig, $form) = @_;
   my @values = (conv_i($form->{id}));
-  # connect to database, turn off AutoCommit
-  my $dbh = $form->get_standard_dbh;
 
   my %columns = ( "assembly" => "id", "parts" => "id" );
 
   for my $table (qw(prices makemodel inventory assembly translation parts)) {
     my $column = defined($columns{$table}) ? $columns{$table} : "parts_id";
-    do_query($form, $dbh, qq|DELETE FROM $table WHERE $column = ?|, @values);
+    do_query($form, SL::DB->client->dbh, qq|DELETE FROM $table WHERE $column = ?|, @values);
   }
 
-  # commit
-  my $rc = $dbh->commit;
-
-  $main::lxdebug->leave_sub();
-
-  return $rc;
+  return 1;
 }
 
 sub assembly_item {
@@ -647,7 +620,7 @@ sub assembly_item {
   while (my ($column, $table) = each(%columns)) {
     next unless ($form->{"${column}_$i"});
     $where .= qq| AND ${table}.${column} ILIKE ?|;
-    push(@values, '%' . $form->{"${column}_$i"} . '%');
+    push(@values, like($form->{"${column}_$i"}));
   }
 
   if ($form->{id}) {
@@ -667,18 +640,15 @@ sub assembly_item {
     $where .= qq| ORDER BY p.description|;
   }
 
-  # connect to database
-  my $dbh = $form->get_standard_dbh;
-
   my $query =
     qq|SELECT p.id, p.partnumber, p.description, p.sellprice,
        p.weight, p.onhand, p.unit, pg.partsgroup, p.lastcost,
-       p.price_factor_id, pfac.factor AS price_factor
+       p.price_factor_id, pfac.factor AS price_factor, p.notes as longdescription
        FROM parts p
        LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
        LEFT JOIN price_factors pfac ON pfac.id = p.price_factor_id
        WHERE $where|;
-  $form->{item_list} = selectall_hashref_query($form, $dbh, $query, @values);
+  $form->{item_list} = selectall_hashref_query($form, SL::DB->client->dbh, $query, @values);
 
   $main::lxdebug->leave_sub();
 }
@@ -858,18 +828,26 @@ sub all_parts {
   #===== switches and simple filters ========#
 
   # special case transdate
-  if (grep { $form->{$_} } qw(transdatefrom transdateto)) {
+  if (grep { trim($form->{$_}) } qw(transdatefrom transdateto)) {
     $form->{"l_transdate"} = 1;
     push @select_tokens, 'transdate';
     for (qw(transdatefrom transdateto)) {
-      next unless $form->{$_};
+      my $value = trim($form->{$_});
+      next unless $value;
       push @where_tokens, sprintf "transdate %s ?", /from$/ ? '>=' : '<=';
-      push @bind_vars,    $form->{$_};
+      push @bind_vars,    $value;
     }
   }
 
+  # special case smart search
+  if ($form->{all}) {
+    $form->{"l_$_"} = 1 for qw(partnumber description unit sellprice lastcost cvar_packaging linetotal);
+    push @where_tokens, "p.partnumber ILIKE ? OR p.description ILIKE ?";
+    push @bind_vars,    (like($form->{all})) x 2;
+  }
+
   # special case insertdate
-  if (grep { $form->{$_} } qw(insertdatefrom insertdateto)) {
+  if (grep { trim($form->{$_}) } qw(insertdatefrom insertdateto)) {
     $form->{"l_insertdate"} = 1;
     push @select_tokens, 'insertdate';
 
@@ -877,9 +855,10 @@ sub all_parts {
     my $token = $token_builder->('insertdate');
 
     for (qw(insertdatefrom insertdateto)) {
-      next unless $form->{$_};
+      my $value = trim($form->{$_});
+      next unless $value;
       push @where_tokens, sprintf "$token %s ?", /from$/ ? '>=' : '<=';
-      push @bind_vars,    $form->{$_};
+      push @bind_vars,    $value;
     }
   }
 
@@ -903,7 +882,7 @@ sub all_parts {
     next unless $form->{$_};
     $form->{"l_$_"} = '1'; # show the column
     push @where_tokens, "$table_prefix{$_}$_ ILIKE ?";
-    push @bind_vars,    "%$form->{$_}%";
+    push @bind_vars,    like($form->{$_});
   }
 
   foreach (@simple_l_switches) {
@@ -912,10 +891,9 @@ sub all_parts {
   }
 
   for ($form->{searchitems}) {
-    push @where_tokens, 'p.inventory_accno_id > 0'     if /part/;
-    push @where_tokens, 'p.inventory_accno_id IS NULL' if /service/;
-    push @where_tokens, 'NOT p.assembly'               if /service/;
-    push @where_tokens, '    p.assembly'               if /assembly/;
+    push @where_tokens, "p.part_type = 'part'"     if /part/;
+    push @where_tokens, "p.part_type = 'service'"  if /service/;
+    push @where_tokens, "p.part_type = 'assembly'" if /assembly/;
   }
 
   for ($form->{itemstatus}) {
@@ -944,11 +922,11 @@ sub all_parts {
   # fortunately makemodel doesn't need to be displayed later, so adding a special clause to where_token is sufficient.
   if ($form->{make}) {
     push @where_tokens, 'mv.name ILIKE ?';
-    push @bind_vars, "%$form->{make}%";
+    push @bind_vars, like($form->{make});
   }
   if ($form->{model}) {
     push @where_tokens, 'mm.model ILIKE ?';
-    push @bind_vars, "%$form->{model}%";
+    push @bind_vars, like($form->{model});
   }
 
   # special case: sorting by partnumber
@@ -1142,14 +1120,14 @@ sub _create_filter_for_priceupdate {
     next unless ($form->{$column});
 
     $where .= qq| AND $item ILIKE ?|;
-    push(@where_values, '%' . $form->{$column} . '%');
+    push(@where_values, like($form->{$column}));
   }
 
   foreach my $item (qw(description serialnumber)) {
     next unless ($form->{$item});
 
     $where .= qq| AND (${item} ILIKE ?)|;
-    push(@where_values, '%' . $form->{$item} . '%');
+    push(@where_values, like($form->{$item}));
   }
 
 
@@ -1183,7 +1161,7 @@ sub _create_filter_for_priceupdate {
   foreach my $column (qw(make model)) {
     next unless ($form->{$column});
     $where .= qq| AND p.id IN (SELECT DISTINCT parts_id FROM makemodel WHERE $column ILIKE ?|;
-    push(@where_values, '%' . $form->{$column} . '%');
+    push(@where_values, like($form->{$column}));
   }
 
   $main::lxdebug->leave_sub();
@@ -1245,15 +1223,23 @@ sub get_num_matches_for_priceupdate {
 }
 
 sub update_prices {
+  my ($self, $myconfig, $form) = @_;
   $main::lxdebug->enter_sub();
 
+  my $num_updated = SL::DB->client->with_transaction(\&_update_prices, $self, $myconfig, $form);
+
+  $main::lxdebug->leave_sub();
+  return $num_updated;
+}
+
+sub _update_prices {
   my ($self, $myconfig, $form) = @_;
 
   my ($where, @where_values) = $self->_create_filter_for_priceupdate();
   my $num_updated = 0;
 
   # connect to database
-  my $dbh = $form->get_standard_dbh;
+  my $dbh = SL::DB->client->dbh;
 
   for my $column (qw(sellprice listprice)) {
     next if ($form->{$column} eq "");
@@ -1313,10 +1299,6 @@ sub update_prices {
   $sth_add->finish();
   $sth_multiply->finish();
 
-  my $rc= $dbh->commit;
-
-  $main::lxdebug->leave_sub();
-
   return $num_updated;
 }
 
@@ -1328,7 +1310,7 @@ sub create_links {
   # connect to database
   my $dbh = $form->get_standard_dbh;
 
-  my @values = ('%' . $module . '%');
+  my @values = like($module);
   my $query;
 
   if ($form->{id}) {
@@ -1397,15 +1379,15 @@ sub get_parts {
 
   if ($sortorder eq "all") {
     $where .= qq| AND (partnumber ILIKE ?) AND (description ILIKE ?)|;
-    push(@values, '%' . $form->{partnumber} . '%', '%' . $form->{description} . '%');
+    push(@values, like($form->{partnumber}), like($form->{description}));
 
   } elsif ($sortorder eq "partnumber") {
     $where .= qq| AND (partnumber ILIKE ?)|;
-    push(@values, '%' . $form->{partnumber} . '%');
+    push(@values, like($form->{partnumber}));
 
   } elsif ($sortorder eq "description") {
     $where .= qq| AND (description ILIKE ?)|;
-    push(@values, '%' . $form->{description} . '%');
+    push(@values, like($form->{description}));
     $order = "description";
 
   }
@@ -1581,7 +1563,7 @@ sub retrieve_accounts {
   my %accno_by_part = map { $_->{id} => $_ }
     selectall_hashref_query($form, $dbh, <<SQL, @part_ids);
     SELECT
-      p.id, p.inventory_accno_id AS is_part,
+      p.id, p.part_type,
       bg.inventory_accno_id,
       tc.income_accno_id AS income_accno_id,
       tc.expense_accno_id AS expense_accno_id,
@@ -1614,7 +1596,7 @@ SQL
   while (my ($index => $part_id) = each %args) {
     my $ref = $accno_by_part{$part_id} or next;
 
-    $ref->{"inventory_accno_id"} = undef unless $ref->{"is_part"};
+    $ref->{"inventory_accno_id"} = undef unless $ref->{"part_type"} eq 'part';
 
     my %accounts;
     for my $type (qw(inventory income expense)) {