X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FIC.pm;h=880502b9d11057061a5b06af36de3aca1fa1073d;hb=f373f98d676d433b7db20e3e74435a34029cac0f;hp=62af112ef465a640d5d109b95fcbbe642e7dada5;hpb=d0779d015d862645b9f63140f7e7af2596238c8e;p=kivitendo-erp.git diff --git a/SL/IC.pm b/SL/IC.pm index 62af112ef..880502b9d 100644 --- a/SL/IC.pm +++ b/SL/IC.pm @@ -33,7 +33,12 @@ #====================================================================== package IC; + use Data::Dumper; +use List::MoreUtils qw(all); +use YAML; + +use SL::CVar; use SL::DBUtils; sub get_part { @@ -63,6 +68,8 @@ sub get_part { # copy to $form variables map { $form->{$_} = $ref->{$_} } (keys %{$ref}); + $form->{onhand} *= 1; + my %oid = ('Pg' => 'a.oid', 'Oracle' => 'a.rowid'); @@ -74,11 +81,12 @@ sub get_part { # retrieve assembly items $query = qq|SELECT p.id, p.partnumber, p.description, - p.sellprice, p.weight, a.qty, a.bom, p.unit, - pg.partsgroup + p.sellprice, p.lastcost, p.weight, a.qty, a.bom, p.unit, + pg.partsgroup, p.price_factor_id, pfac.factor AS price_factor FROM parts p JOIN assembly a ON (a.parts_id = p.id) LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) + LEFT JOIN price_factors pfac ON pfac.id = p.price_factor_id WHERE (a.id = ?) ORDER BY $oid{$myconfig->{dbdriver}}|; $sth = prepare_execute_query($form, $dbh, $query, conv_i($form->{id})); @@ -120,8 +128,6 @@ sub get_part { while (($form->{"klass_$i"}, $form->{"pricegroup_id_$i"}, $form->{"price_$i"}, $form->{"pricegroup_$i"}) = $sth->fetchrow_array()) { - $form->{"price_$i"} = $form->round_amount($form->{"price_$i"}, 5); - $form->{"price_$i"} = $form->format_amount($myconfig, $form->{"price_$i"}, -2); push @pricegroups, $form->{"pricegroup_id_$i"}; $i++; } @@ -149,8 +155,6 @@ sub get_part { foreach $name (@pricegroups_not_used) { $form->{"klass_$i"} = "$name->{id}"; - $form->{"price_$i"} = $form->round_amount($form->{sellprice}, 5); - $form->{"price_$i"} = $form->format_amount($myconfig, $form->{"price_$i"}, -2); $form->{"pricegroup_id_$i"} = "$name->{id}"; $form->{"pricegroup_$i"} = "$name->{pricegroup}"; $i++; @@ -183,10 +187,12 @@ sub get_part { # get translations $form->{language_values} = ""; - $query = qq|SELECT language_id, translation FROM translation WHERE parts_id = ?|; + $query = qq|SELECT language_id, translation, longdescription + FROM translation + WHERE parts_id = ?|; my $trq = prepare_execute_query($form, $dbh, $query, conv_i($form->{id})); - while ($tr = $trq->fetchrow_hashref(NAME_lc)) { - $form->{language_values} .= "---+++---".$tr->{language_id}."--++--".$tr->{translation}; + while (my $tr = $trq->fetchrow_hashref(NAME_lc)) { + $form->{language_values} .= "---+++---" . join('--++--', @{$tr}{qw(language_id translation longdescription)}); } $trq->finish; @@ -203,7 +209,7 @@ sub get_part { $sth->finish; # is it an orphan - my @referencing_tables = qw(invoice orderitems invoice inventory rmaitems); + my @referencing_tables = qw(invoice orderitems inventory rmaitems); my %column_map = ( ); my $parts_id = conv_i($form->{id}); @@ -253,6 +259,8 @@ sub get_pricegroups { $dbh->disconnect; $main::lxdebug->leave_sub(); + + return $pricegroups; } sub retrieve_buchungsgruppen { @@ -290,7 +298,7 @@ sub save { # undo amount formatting map { $form->{$_} = $form->parse_amount($myconfig, $form->{$_}) } - qw(rop weight listprice sellprice gv lastcost stock); + qw(rop weight listprice sellprice gv lastcost); my $makemodel = (($form->{make_1}) || ($form->{model_1})) ? 1 : 0; @@ -298,6 +306,8 @@ sub save { my ($query, $sth); + my $priceupdate = ', priceupdate = current_date'; + if ($form->{id}) { # get old price @@ -318,14 +328,8 @@ sub save { } if ($form->{item} eq 'assembly') { - if ($form->{onhand} != 0) { - &adjust_inventory($dbh, $form, $form->{id}, $form->{onhand} * -1); - } - # delete assembly records do_query($form, $dbh, qq|DELETE FROM assembly WHERE id = ?|, conv_i($form->{id})); - - $form->{onhand} += $form->{stock}; } # delete tax records @@ -334,6 +338,11 @@ sub save { # delete translations do_query($form, $dbh, qq|DELETE FROM translation WHERE parts_id = ?|, conv_i($form->{id})); + # Check whether or not the prices have changed. If they haven't + # then 'priceupdate' should not be updated. + my $previous_values = selectfirst_hashref_query($form, $dbh, qq|SELECT * FROM parts WHERE id = ?|, conv_i($form->{id})) || {}; + $priceupdate = '' if (all { $previous_values->{$_} == $form->{$_} } qw(sellprice lastcost listprice)); + } else { my ($count) = selectrow_query($form, $dbh, qq|SELECT COUNT(*) FROM parts WHERE partnumber = ?|, $form->{partnumber}); if ($count) { @@ -345,7 +354,6 @@ sub save { do_query($form, $dbh, qq|INSERT INTO parts (id, partnumber) VALUES (?, '')|, $form->{id}); $form->{orphaned} = 1; - $form->{onhand} = $form->{stock} if $form->{item} eq 'assembly'; if ($form->{partnumber} eq "" && $form->{"item"} eq "service") { $form->{partnumber} = $form->update_defaults($myconfig, "servicenumber"); } @@ -390,7 +398,6 @@ sub save { sellprice = ?, lastcost = ?, weight = ?, - priceupdate = ?, unit = ?, notes = ?, formel = ?, @@ -412,6 +419,7 @@ sub save { microfiche = ?, partsgroup_id = ?, price_factor_id = ? + $priceupdate WHERE id = ?|; @values = ($form->{partnumber}, $form->{description}, @@ -421,7 +429,6 @@ sub save { $form->{sellprice}, $form->{lastcost}, $form->{weight}, - conv_date($form->{priceupdate}), $form->{unit}, $form->{notes}, $form->{formel}, @@ -465,22 +472,20 @@ sub save { # insert price records only if different to sellprice for my $i (1 .. $form->{price_rows}) { - if ($form->{"price_$i"} eq "0") { + my $price = $form->parse_amount($myconfig, $form->{"price_$i"}); + if ($price == 0) { $form->{"price_$i"} = $form->{sellprice}; } if ( - ( $form->{"price_$i"} + ( $price || $form->{"klass_$i"} || $form->{"pricegroup_id_$i"}) - and $form->{"price_$i"} != $form->{sellprice} + and $price != $form->{sellprice} ) { #$klass = $form->parse_amount($myconfig, $form->{"klass_$i"}); - $price = $form->parse_amount($myconfig, $form->{"price_$i"}); - $pricegroup_id = - $form->parse_amount($myconfig, $form->{"pricegroup_id_$i"}); $query = qq|INSERT INTO prices (parts_id, pricegroup_id, price) | . qq|VALUES(?, ?, ?)|; - @values = (conv_i($form->{id}), conv_i($pricegroup_id), $price); + @values = (conv_i($form->{id}), conv_i($form->{"pricegroup_id_$i"}), $price); do_query($form, $dbh, $query, @values); } } @@ -489,11 +494,11 @@ sub save { unless ($form->{item} eq 'service') { for my $i (1 .. $form->{makemodel_rows}) { if (($form->{"make_$i"}) || ($form->{"model_$i"})) { - map { $form->{"${_}_$i"} =~ s/\'/\'\'/g } qw(make model); $query = qq|INSERT INTO makemodel (parts_id, make, model) | . qq|VALUES (?, ?, ?)|; - @values = (conv_i($form->{id}), $form->{"make_$i"}, $form->{"model_$i"}); + @values = (conv_i($form->{id}), conv_i($form->{"make_$i"}), $form->{"model_$i"}); + do_query($form, $dbh, $query, @values); } } @@ -525,11 +530,6 @@ sub save { } } - # adjust onhand for the parts - if ($form->{onhand} != 0) { - &adjust_inventory($dbh, $form, $form->{id}, $form->{onhand}); - } - @a = localtime; $a[5] += 1900; $a[4]++; @@ -537,13 +537,6 @@ sub save { $form->get_employee($dbh); - # add inventory record - $query = - qq|INSERT INTO inventory (warehouse_id, parts_id, qty, shippingdate, employee_id) - VALUES (0, ?, ?, '$shippingdate', ?)|; - @values = (conv_i($form->{id}), $form->{stock}, conv_i($form->{employee_id})); - do_query($form, $dbh, $query, @values); - } #set expense_accno=inventory_accno if they are different => bilanz @@ -573,6 +566,11 @@ sub save { } } + CVar->save_custom_variables('dbh' => $dbh, + 'module' => 'IC', + 'trans_id' => $form->{id}, + 'variables' => $form); + # commit my $rc = $dbh->commit; $dbh->disconnect; @@ -643,67 +641,6 @@ sub retrieve_assemblies { $main::lxdebug->leave_sub(); } -sub restock_assemblies { - $main::lxdebug->enter_sub(); - - my ($self, $myconfig, $form) = @_; - - # connect to database - my $dbh = $form->dbconnect_noauto($myconfig); - - for my $i (1 .. $form->{rowcount}) { - - $form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"}); - - if ($form->{"qty_$i"} != 0) { - &adjust_inventory($dbh, $form, $form->{"id_$i"}, $form->{"qty_$i"}); - } - - } - - my $rc = $dbh->commit; - $dbh->disconnect; - - $main::lxdebug->leave_sub(); - - return $rc; -} - -sub adjust_inventory { - $main::lxdebug->enter_sub(); - - my ($dbh, $form, $id, $qty) = @_; - - my $query = - qq|SELECT p.id, p.inventory_accno_id, p.assembly, a.qty - FROM parts p, assembly a - WHERE (a.parts_id = p.id) AND (a.id = ?)|; - my $sth = prepare_execute_query($form, $dbh, $query, conv_i($id)); - - while (my $ref = $sth->fetchrow_hashref(NAME_lc)) { - - my $allocate = $qty * $ref->{qty}; - - # is it a service item, then loop - $ref->{inventory_accno_id} *= 1; - next if (($ref->{inventory_accno_id} == 0) && !$ref->{assembly}); - - # adjust parts onhand - $form->update_balance($dbh, "parts", "onhand", - qq|id = $ref->{id}|, - $allocate * -1); - } - - $sth->finish; - - # update assembly - my $rc = $form->update_balance($dbh, "parts", "onhand", qq|id = ?|, $qty, $id); - - $main::lxdebug->leave_sub(); - - return $rc; -} - sub delete { $main::lxdebug->enter_sub(); @@ -761,9 +698,12 @@ sub assembly_item { my $dbh = $form->dbconnect($myconfig); my $query = - qq|SELECT p.id, p.partnumber, p.description, p.sellprice, p.weight, p.onhand, p.unit, pg.partsgroup + 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 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); @@ -803,9 +743,9 @@ sub assembly_item { # short - NOT IMPLEMENTED as form filter, only as itemstatus option # l_serialnumber - belonges to serialnumber filter # l_deliverydate - displays deliverydate is sold etc. flags are active +# l_soldtotal - aggreg join to display total of sold quantity, works as long as there's no bullshit in soldtotal # # not working: -# l_soldtotal - aggreg join to display total of sold quantity # onhand - as above, but masking the simple itemstatus results (doh!) # masking of onhand in bsooqr mode - ToDO: fixme # @@ -825,7 +765,8 @@ sub all_parts { my ($self, $myconfig, $form) = @_; my $dbh = $form->get_standard_dbh($myconfig); - $form->{parts} = +{ }; + $form->{parts} = +{ }; + $form->{soldtotal} = undef if $form->{l_soldtotal}; # security fix. top100 insists on putting strings in there... my @simple_filters = qw(partnumber ean description partsgroup microfiche drawing onhand); my @makemodel_filters = qw(make model); @@ -850,10 +791,10 @@ sub all_parts { ) AS ioi ON ioi.parts_id = p.id|, apoe => q|LEFT JOIN ( - SELECT id, transdate, 'ir' AS module, ordnumber, quonumber, invnumber, FALSE AS quotation, NULL AS customer_id, vendor_id, NULL AS deliverydate FROM ap UNION - SELECT id, transdate, 'is' AS module, ordnumber, quonumber, invnumber, FALSE AS quotation, customer_id, NULL AS vendor_id, deliverydate FROM ar UNION - SELECT id, transdate, 'oe' AS module, ordnumber, quonumber, NULL AS invnumber, quotation, customer_id, vendor_id, NULL AS deliverydate FROM oe - ) AS apoe ON ioi.trans_id = apoe.id|, + SELECT id, transdate, 'ir' AS module, ordnumber, quonumber, invnumber, FALSE AS quotation, NULL AS customer_id, vendor_id, NULL AS deliverydate, 'invoice' AS ioi FROM ap UNION + SELECT id, transdate, 'is' AS module, ordnumber, quonumber, invnumber, FALSE AS quotation, customer_id, NULL AS vendor_id, deliverydate, 'invoice' AS ioi FROM ar UNION + SELECT id, transdate, 'oe' AS module, ordnumber, quonumber, NULL AS invnumber, quotation, customer_id, vendor_id, NULL AS deliverydate, 'orderitems' AS ioi FROM oe + ) AS apoe ON ((ioi.trans_id = apoe.id) AND (ioi.ioi = apoe.ioi))|, cv => q|LEFT JOIN ( SELECT id, name, 'customer' AS cv FROM customer UNION @@ -863,6 +804,10 @@ sub all_parts { my @join_order = qw(partsgroup makemodel invoice_oi apoe cv pfac); my %joins_needed; + if (($form->{searchitems} eq 'assembly') && $form->{l_lastcost}) { + @simple_l_switches = grep { $_ ne 'lastcost' } @simple_l_switches; + } + #===== switches and simple filters ========# my @select_tokens = qw(id factor); @@ -915,20 +860,30 @@ sub all_parts { push @where_tokens, 'p.onhand < p.rop', if /short/; } + my $q_assembly_lastcost = + qq|(SELECT SUM(a_lc.qty * p_lc.lastcost / COALESCE(pfac_lc.factor, 1)) + FROM assembly a_lc + LEFT JOIN parts p_lc ON (a_lc.parts_id = p_lc.id) + LEFT JOIN price_factors pfac_lc ON (p_lc.price_factor_id = pfac_lc.id) + WHERE (a_lc.id = p.id)) AS lastcost|; my @sort_cols = (@simple_filters, qw(id bin priceupdate onhand invnumber ordnumber quonumber name serialnumber soldtotal deliverydate)); $form->{sort} = 'id' unless grep { $form->{"l_$_"} } grep { $form->{sort} eq $_ } @sort_cols; my $sort_order = ($form->{revers} ? ' DESC' : ' ASC'); + my $order_clause = " ORDER BY $form->{sort} " . ($form->{revers} ? 'DESC' : 'ASC'); + # special case: sorting by partnumber # since partnumbers are expected to be prefixed integers, a special sorting is implemented sorting first lexically by prefix and then by suffix. # and yes, that expression is designed to hold that array of regexes only once, so the map is kinda messy, sorry about that. # ToDO: implement proper functional sorting - $form->{sort} = join ', ', map { push @select_tokens, $_; ($table_prefix{$_} = "substring(partnumber,'[") . $_ } qw|^[:digit:]]+') [:digit:]]+')::INTEGER| - if $form->{sort} eq 'partnumber'; + # Nette Idee von Sven, gibt aber Probleme wenn die Artikelnummern groesser als 32bit sind. Korrekt waere es, dass Sort-Natural-Modul zu nehmen + # Ich lass das mal hier drin, damit die Idee erhalten bleibt jb 28.5.2009 bug 1018 + #$form->{sort} = join ', ', map { push @select_tokens, $_; ($table_prefix{$_} = "substring(partnumber,'[") . $_ } qw|^[:digit:]]+') [:digit:]]+')::INTEGER| + # if $form->{sort} eq 'partnumber'; - my $order_clause = " ORDER BY $form->{sort} $sort_order"; + #my $order_clause = " ORDER BY $form->{sort} $sort_order"; my $limit_clause = " LIMIT 100" if $form->{top100}; @@ -941,6 +896,7 @@ sub all_parts { my @bsooqr; push @select_tokens, @qsooqr_flags if $bsooqr; push @select_tokens, @deliverydate_flags if $bsooqr && $form->{l_deliverydate}; + push @select_tokens, $q_assembly_lastcost if ($form->{searchitems} eq 'assembly') && $form->{l_lastcost}; push @bsooqr_tokens, q|module = 'ir' AND NOT ioi.assemblyitem| if $form->{bought}; push @bsooqr_tokens, q|module = 'is' AND NOT ioi.assemblyitem| if $form->{sold}; push @bsooqr_tokens, q|module = 'oe' AND NOT quotation AND cv = 'customer'| if $form->{ordered}; @@ -973,6 +929,7 @@ sub all_parts { if ($form->{l_soldtotal}) { push @where_tokens, 'ioi.qty >= 0'; push @group_tokens, @select_tokens; + map { s/.*\sAS\s+//si } @group_tokens; push @select_tokens, 'SUM(ioi.qty)'; } @@ -986,10 +943,13 @@ sub all_parts { ordnumber => 'apoe.', make => 'mm.', quonumber => 'apoe.', model => 'mm.', invnumber => 'apoe.', partsgroup => 'pg.', + lastcost => ' ', factor => 'pfac.', 'SUM(ioi.qty)' => ' ', ); + $table_prefix{$q_assembly_lastcost} = ' '; + my %renamed_columns = ( 'factor' => 'price_factor', 'SUM(ioi.qty)' => 'soldtotal', @@ -1003,365 +963,36 @@ sub all_parts { my $where_clause = join ' AND ', map { "($_)" } @where_tokens; my $group_clause = ' GROUP BY ' . join ', ', map { ($table_prefix{$_} || "p.") . $_ } @group_tokens if scalar @group_tokens; + my ($cvar_where, @cvar_values) = CVar->build_filter_query('module' => 'IC', + 'trans_id_field' => 'p.id', + 'filter' => $form); + + if ($cvar_where) { + $where_clause .= qq| AND ($cvar_where)|; + push @bind_vars, @cvar_values; + } + my $query = qq|SELECT DISTINCT $select_clause FROM parts p $join_clause WHERE $where_clause $group_clause $order_clause $limit_clause|; $form->{parts} = selectall_hashref_query($form, $dbh, $query, @bind_vars); -## my $where = qq|1 = 1|; -## my (@values, $var, $flds, $group, $limit); -## -## foreach my $item (qw(partnumber drawing microfiche ean pg.partsgroup)) { -## my $column = $item; -## $column =~ s/.*\.//; # get rid of table prefixes -## if ($form->{$column}) { -## $where .= qq| AND ($item ILIKE ?)|; -## push(@values, "%$form->{$column}%"); -## } -## } -## -## # special case for description -## if ($form->{description} -## && !( $form->{bought} || $form->{sold} || $form->{onorder} -## || $form->{ordered} || $form->{rfq} || $form->{quoted})) { -## $where .= qq| AND (p.description ILIKE ?)|; -## push(@values, "%$form->{description}%"); -## } -## -## # special case for serialnumber -## if ($form->{l_serialnumber} && $form->{serialnumber}) { -## $where .= qq| AND (serialnumber ILIKE ?)|; -## push(@values, "%$form->{serialnumber}%"); -## } -## -## if ($form->{searchitems} eq 'part') { -## $where .= qq| AND (p.inventory_accno_id > 0) |; -## } -## -## if ($form->{searchitems} eq 'assembly') { -## $form->{bought} = ""; -## $where .= qq| AND p.assembly|; -## } -## -## if ($form->{searchitems} eq 'service') { -## $where .= qq| AND (p.inventory_accno_id IS NULL) AND NOT (p.assembly = '1')|; -## # irrelevant for services -## map { $form->{$_} = '' } qw(make model); -## } -## -## # items which were never bought, sold or on an order -## if ($form->{itemstatus} eq 'orphaned') { -## map { $form->{$_} = 0 } qw(onhand short bought sold onorder ordered rfq quoted); -## map { $form->{$_} = '' } qw(transdatefrom transdateto); -## -## $where .= -## qq| AND (p.onhand = 0) -## AND p.id NOT IN -## ( -## SELECT DISTINCT parts_id FROM invoice -## UNION -## SELECT DISTINCT parts_id FROM assembly -## UNION -## SELECT DISTINCT parts_id FROM orderitems -## )|; -## } -## -## my %status2condition = ( -## active => " AND (p.obsolete = '0')", -## obsolete => " AND (p.obsolete = '1')", -## onhand => " AND (p.onhand > 0)", -## short => " AND (p.onhand < p.rop)", -## ); -## $where .= $status2condition{$form->{itemstatus}}; -## -## $form->{onhand} = $form->{short} = 0 if ($form->{itemstatus} eq 'obsolete'); -## -## my @subcolumns; -## foreach my $column (qw(make model)) { -## push @subcolumns, $column if $form->{$column}; -## } -## if (@subcolumns) { -## $where .= qq| AND p.id IN (SELECT DISTINCT parts_id FROM makemodel WHERE | . (join " AND ", map { "($_ ILIKE ?)"; } @subcolumns) . ")"; -## push @values, map { '%' . $form->{$_} . '%' } @subcolumns; -## } -## -## if ($form->{l_soldtotal}) { -## $where .= qq| AND (p.id = i.parts_id) AND (i.qty >= 0)|; -## $group = qq| GROUP BY p.id, p.partnumber, p.description, p.onhand, p.unit, p.bin, p.sellprice, p.listprice, p.lastcost, p.priceupdate, pg.partsgroup|; -## } -## -## $limit = qq| LIMIT 100| if ($form->{top100}); -## -## # connect to database -## my $dbh = $form->dbconnect($myconfig); -## -## my @sort_cols = qw(id partnumber description partsgroup bin priceupdate onhand -## invnumber ordnumber quonumber name drawing microfiche -## serialnumber soldtotal deliverydate); -## -## my $sortorder = "partnumber"; -## $sortorder = $form->{sort} if ($form->{sort} && grep({ $_ eq $form->{sort} } @sort_cols)); -## $sortorder .= " DESC" if ($form->{revers}); -## -## my $query = ""; -## -## if ($form->{l_soldtotal}) { -## $form->{soldtotal} = 'soldtotal'; -## $query = -## qq|SELECT p.id, p.partnumber, p.description, p.onhand, p.unit, -## p.bin, p.sellprice, p.listprice, p.lastcost, -## p.priceupdate, pg.partsgroup,sum(i.qty) AS soldtotal -## FROM parts p -## LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id), invoice i -## WHERE $where -## $group -## ORDER BY $sortorder $limit|; -## } else { -## $query = -## qq|SELECT p.id, p.partnumber, p.description, p.onhand, p.unit, -## p.bin, p.sellprice, p.listprice, p.lastcost, p.rop, p.weight, -## p.priceupdate, p.image, p.drawing, p.microfiche, -## pg.partsgroup -## FROM parts p -## LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) -## WHERE $where -## $group -## ORDER BY $sortorder $limit|; -## } -## -## my @all_values = @values; -## -## # rebuild query for bought and sold items -## if ( $form->{bought} -## || $form->{sold} -## || $form->{onorder} -## || $form->{ordered} -## || $form->{rfq} -## || $form->{quoted}) { -## my $union = ""; -## $query = ""; -## @all_values = (); -## -## if ($form->{bought} || $form->{sold}) { -## -## my @invvalues = @values; -## my $invwhere = "$where"; -# $invwhere .= qq| AND i.assemblyitem = '0'|; -## -## if ($form->{transdatefrom}) { -## $invwhere .= qq| AND a.transdate >= ?|; -## push(@invvalues, $form->{transdatefrom}); -## } -## -## if ($form->{transdateto}) { -## $invwhere .= qq| AND a.transdate <= ?|; -## push(@invvalues, $form->{transdateto}); -## } -## -## if ($form->{description}) { -## $invwhere .= qq| AND i.description ILIKE ?|; -## push(@invvalues, '%' . $form->{description} . '%'); -## } -## -## $flds = -## qq|p.id, p.partnumber, i.description, i.serialnumber, -# i.qty AS onhand, i.unit, p.bin, i.sellprice, -## p.listprice, p.lastcost, p.rop, p.weight, -## p.priceupdate, p.image, p.drawing, p.microfiche, -## pg.partsgroup, -## a.invnumber, a.ordnumber, a.quonumber, i.trans_id, -## ct.name, i.deliverydate|; -## -## if ($form->{bought}) { -## $query = -## qq|SELECT $flds, 'ir' AS module, '' AS type, 1 AS exchangerate -## FROM invoice i -## JOIN parts p ON (p.id = i.parts_id) -## JOIN ap a ON (a.id = i.trans_id) -## JOIN vendor ct ON (a.vendor_id = ct.id) -## LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) -## WHERE $invwhere|; -## -## $union = qq| UNION |; -## -## push(@all_values, @invvalues); -## } -## -## if ($form->{sold}) { -## $query .= -## qq|$union -## -## SELECT $flds, 'is' AS module, '' AS type, 1 As exchangerate -## FROM invoice i -## JOIN parts p ON (p.id = i.parts_id) -## JOIN ar a ON (a.id = i.trans_id) -## JOIN customer ct ON (a.customer_id = ct.id) -## LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) -## WHERE $invwhere|; -## $union = qq| UNION |; -## -## push(@all_values, @invvalues); -## } -## } -## -## if ($form->{onorder} || $form->{ordered}) { -## my @ordvalues = @values; -## my $ordwhere = $where . qq| AND o.quotation = '0'|; -## -## if ($form->{transdatefrom}) { -## $ordwhere .= qq| AND o.transdate >= ?|; -## push(@ordvalues, $form->{transdatefrom}); -## } -## -## if ($form->{transdateto}) { -## $ordwhere .= qq| AND o.transdate <= ?|; -## push(@ordvalues, $form->{transdateto}); -## } -## -## if ($form->{description}) { -## $ordwhere .= qq| AND oi.description ILIKE ?|; -## push(@ordvalues, '%' . $form->{description} . '%'); -## } -## -## if ($form->{ordered}) { -## $query .= -## qq|$union -## -## SELECT p.id, p.partnumber, oi.description, oi.serialnumber AS serialnumber, -## oi.qty AS onhand, oi.unit, p.bin, oi.sellprice, -## p.listprice, p.lastcost, p.rop, p.weight, -## p.priceupdate, p.image, p.drawing, p.microfiche, -## pg.partsgroup, -## '' AS invnumber, o.ordnumber, o.quonumber, oi.trans_id, -## ct.name, NULL AS deliverydate, -## 'oe' AS module, 'sales_order' AS type, -## (SELECT buy FROM exchangerate ex -## WHERE ex.curr = o.curr AND ex.transdate = o.transdate) AS exchangerate -## FROM orderitems oi -## JOIN parts p ON (oi.parts_id = p.id) -## JOIN oe o ON (oi.trans_id = o.id) -## JOIN customer ct ON (o.customer_id = ct.id) -## LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) -## WHERE $ordwhere AND (o.customer_id > 0)|; -## $union = qq| UNION |; -## -## push(@all_values, @ordvalues); -## } -## -## if ($form->{onorder}) { -## $query .= -## qq|$union -## -## SELECT p.id, p.partnumber, oi.description, oi.serialnumber AS serialnumber, -## oi.qty * -1 AS onhand, oi.unit, p.bin, oi.sellprice, -## p.listprice, p.lastcost, p.rop, p.weight, -## p.priceupdate, p.image, p.drawing, p.microfiche, -## pg.partsgroup, -## '' AS invnumber, o.ordnumber, o.quonumber, oi.trans_id, -## ct.name, NULL AS deliverydate, -## 'oe' AS module, 'purchase_order' AS type, -## (SELECT sell FROM exchangerate ex -## WHERE ex.curr = o.curr AND (ex.transdate = o.transdate)) AS exchangerate -## FROM orderitems oi -## JOIN parts p ON (oi.parts_id = p.id) -## JOIN oe o ON (oi.trans_id = o.id) -## JOIN vendor ct ON (o.vendor_id = ct.id) -## LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) -## WHERE $ordwhere AND (o.vendor_id > 0)|; -## $union = qq| UNION |; -## -## push(@all_values, @ordvalues); -## } -## -## } -## -## if ($form->{rfq} || $form->{quoted}) { -## my $quowhere = $where . qq| AND o.quotation = '1'|; -## my @quovalues = @values; -## -## if ($form->{transdatefrom}) { -## $quowhere .= qq| AND o.transdate >= ?|; -## push(@quovalues, $form->{transdatefrom}); -## } -## -## if ($form->{transdateto}) { -## $quowhere .= qq| AND o.transdate <= ?|; -## push(@quovalues, $form->{transdateto}); -## } -## -## if ($form->{description}) { -## $quowhere .= qq| AND oi.description ILIKE ?|; -## push(@quovalues, '%' . $form->{description} . '%'); -## } -## -## if ($form->{quoted}) { -## $query .= -## qq|$union -## -## SELECT -## p.id, p.partnumber, oi.description, oi.serialnumber AS serialnumber, -## oi.qty AS onhand, oi.unit, p.bin, oi.sellprice, -## p.listprice, p.lastcost, p.rop, p.weight, -## p.priceupdate, p.image, p.drawing, p.microfiche, -## pg.partsgroup, -## '' AS invnumber, o.ordnumber, o.quonumber, oi.trans_id, -## ct.name, NULL AS deliverydate, 'oe' AS module, 'sales_quotation' AS type, -## (SELECT buy FROM exchangerate ex -## WHERE (ex.curr = o.curr) AND (ex.transdate = o.transdate)) AS exchangerate -## FROM orderitems oi -## JOIN parts p ON (oi.parts_id = p.id) -## JOIN oe o ON (oi.trans_id = o.id) -## JOIN customer ct ON (o.customer_id = ct.id) -## LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) -## WHERE $quowhere -## AND o.customer_id > 0|; -## $union = qq| UNION |; -## -## push(@all_values, @quovalues); -## } -## -## if ($form->{rfq}) { -## $query .= -## qq|$union -## -## SELECT p.id, p.partnumber, oi.description, oi.serialnumber AS serialnumber, -## oi.qty * -1 AS onhand, oi.unit, p.bin, oi.sellprice, -## p.listprice, p.lastcost, p.rop, p.weight, -## p.priceupdate, p.image, p.drawing, p.microfiche, -## pg.partsgroup, -## '' AS invnumber, o.ordnumber, o.quonumber, oi.trans_id, -## ct.name, NULL AS deliverydate, -## 'oe' AS module, 'request_quotation' AS type, -## (SELECT sell FROM exchangerate ex -## WHERE (ex.curr = o.curr) AND (ex.transdate = o.transdate)) AS exchangerate -## FROM orderitems oi -## JOIN parts p ON (oi.parts_id = p.id) -## JOIN oe o ON (oi.trans_id = o.id) -## JOIN vendor ct ON (o.vendor_id = ct.id) -## LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) -## WHERE $quowhere -## AND o.vendor_id > 0|; -## -## push(@all_values, @quovalues); -## } -## -## } -## $query .= qq| ORDER BY | . $sortorder; -## -## } -## -## $form->{parts} = selectall_hashref_query($form, $dbh, $query, @all_values); -# + map { $_->{onhand} *= 1 } @{ $form->{parts} }; + + # post processing for assembly parts lists (bom) + # for each part get the assembly parts and add them into the partlist. my @assemblies; - # include individual items for assemblies if ($form->{searchitems} eq 'assembly' && $form->{bom}) { $query = qq|SELECT p.id, p.partnumber, p.description, a.qty AS onhand, p.unit, p.bin, p.sellprice, p.listprice, p.lastcost, p.rop, p.weight, p.priceupdate, - p.image, p.drawing, p.microfiche - FROM parts p, assembly a - WHERE (p.id = a.parts_id) AND (a.id = ?)|; + p.image, p.drawing, p.microfiche, + pfac.factor + FROM parts p + INNER JOIN assembly a ON (p.id = a.parts_id) + $joins{pfac} + WHERE a.id = ?|; $sth = prepare_query($form, $dbh, $query); foreach $item (@{ $form->{parts} }) { @@ -1370,6 +1001,7 @@ sub all_parts { while ($ref = $sth->fetchrow_hashref(NAME_lc)) { $ref->{assemblyitem} = 1; + map { $ref->{$_} /= $ref->{factor} || 1 } qw(sellprice listprice lastcost); push(@assemblies, $ref); } $sth->finish; @@ -1379,55 +1011,38 @@ sub all_parts { $form->{parts} = \@assemblies; } - $dbh->disconnect; $main::lxdebug->leave_sub(); } -sub update_prices { +sub _create_filter_for_priceupdate { $main::lxdebug->enter_sub(); - my ($self, $myconfig, $form) = @_; + my $self = shift; + my $myconfig = \%main::myconfig; + my $form = $main::form; + my @where_values; my $where = '1 = 1'; - my $var; - my $group; - my $limit; + foreach my $item (qw(partnumber drawing microfiche make model pg.partsgroup)) { + my $column = $item; + $column =~ s/.*\.//; + next unless ($form->{$column}); - if ($item ne 'make') { - foreach my $item (qw(partnumber drawing microfiche make model pg.partsgroup)) { - my $column = $item; - $column =~ s/.*\.//; - next unless ($form->{$column}); - $where .= qq| AND $item ILIKE ?|; - push(@where_values, '%' . $form->{$column} . '%'); - } + $where .= qq| AND $item ILIKE ?|; + push(@where_values, '%' . $form->{$column} . '%'); } - # special case for description - if ($form->{description} - && !( $form->{bought} || $form->{sold} || $form->{onorder} - || $form->{ordered} || $form->{rfq} || $form->{quoted})) { - $where .= qq| AND (p.description ILIKE ?)|; - push(@where_values, '%' . $form->{description} . '%'); - } + foreach my $item (qw(description serialnumber)) { + next unless ($form->{$item}); - # special case for serialnumber - if ($form->{l_serialnumber} && $form->{serialnumber}) { - $where .= qq| AND serialnumber ILIKE ?|; - push(@where_values, '%' . $form->{serialnumber} . '%'); + $where .= qq| AND (${item} ILIKE ?)|; + push(@where_values, '%' . $form->{$item} . '%'); } # items which were never bought, sold or on an order if ($form->{itemstatus} eq 'orphaned') { - $form->{onhand} = $form->{short} = 0; - $form->{bought} = $form->{sold} = 0; - $form->{onorder} = $form->{ordered} = 0; - $form->{rfq} = $form->{quoted} = 0; - - $form->{transdatefrom} = $form->{transdateto} = ""; - $where .= qq| AND (p.onhand = 0) AND p.id NOT IN @@ -1438,23 +1053,19 @@ sub update_prices { UNION SELECT DISTINCT parts_id FROM orderitems )|; - } - if ($form->{itemstatus} eq 'active') { + } elsif ($form->{itemstatus} eq 'active') { $where .= qq| AND p.obsolete = '0'|; - } - if ($form->{itemstatus} eq 'obsolete') { + } elsif ($form->{itemstatus} eq 'obsolete') { $where .= qq| AND p.obsolete = '1'|; - $form->{onhand} = $form->{short} = 0; - } - if ($form->{itemstatus} eq 'onhand') { + } elsif ($form->{itemstatus} eq 'onhand') { $where .= qq| AND p.onhand > 0|; - } - if ($form->{itemstatus} eq 'short') { + } elsif ($form->{itemstatus} eq 'short') { $where .= qq| AND p.onhand < p.rop|; + } foreach my $column (qw(make model)) { @@ -1463,6 +1074,72 @@ sub update_prices { push(@where_values, '%' . $form->{$column} . '%'); } + $main::lxdebug->leave_sub(); + + return ($where, @where_values); +} + +sub get_num_matches_for_priceupdate { + $main::lxdebug->enter_sub(); + + my $self = shift; + + my $myconfig = \%main::myconfig; + my $form = $main::form; + + my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig); + + my ($where, @where_values) = $self->_create_filter_for_priceupdate(); + + my $num_updated = 0; + my $query; + + for my $column (qw(sellprice listprice)) { + next if ($form->{$column} eq ""); + + $query = + qq|SELECT COUNT(*) + FROM parts + WHERE id IN + (SELECT p.id + FROM parts p + LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) + WHERE $where)|; + my ($result) = selectfirst_array_query($from, $dbh, $query, @where_values); + $num_updated += $result if (0 <= $result); + } + + $query = + qq|SELECT COUNT(*) + FROM prices + WHERE parts_id IN + (SELECT p.id + FROM parts p + LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) + WHERE $where) AND (pricegroup_id = ?)|; + my $sth = prepare_query($form, $dbh, $query); + + for my $i (1 .. $form->{price_rows}) { + next if ($form->{"price_$i"} eq ""); + + my ($result) = do_statement($form, $sth, $query, @where_values, conv_i($form->{"pricegroup_id_$i"})); + $num_updated += $result if (0 <= $result); + } + $sth->finish(); + + $main::lxdebug->leave_sub(); + + return $num_updated; +} + +sub update_prices { + $main::lxdebug->enter_sub(); + + my ($self, $myconfig, $form) = @_; + + my ($where, @where_values) = $self->_create_filter_for_priceupdate(); + my $num_updated = 0; + # connect to database my $dbh = $form->dbconnect_noauto($myconfig); @@ -1484,7 +1161,8 @@ sub update_prices { FROM parts p LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) WHERE $where)|; - do_query($from, $dbh, $query, $value, @where_values); + my $result = do_query($from, $dbh, $query, $value, @where_values); + $num_updated += $result if (0 <= $result); } my $q_add = @@ -1509,12 +1187,15 @@ sub update_prices { next if ($form->{"price_$i"} eq ""); my $value = $form->parse_amount($myconfig, $form->{"price_$i"}); + my $result; if ($form->{"pricegroup_type_$i"} eq "percent") { - do_statement($form, $sth_multiply, $q_multiply, ($value / 100) + 1, @where_values, conv_i($form->{"pricegroup_id_$i"})); + $result = do_statement($form, $sth_multiply, $q_multiply, ($value / 100) + 1, @where_values, conv_i($form->{"pricegroup_id_$i"})); } else { - do_statement($form, $sth_add, $q_add, $value, @where_values, conv_i($form->{"pricegroup_id_$i"})); + $result = do_statement($form, $sth_add, $q_add, $value, @where_values, conv_i($form->{"pricegroup_id_$i"})); } + + $num_updated += $result if (0 <= $result); } $sth_add->finish(); @@ -1525,7 +1206,7 @@ sub update_prices { $main::lxdebug->leave_sub(); - return $rc; + return $num_updated; } sub create_links { @@ -1827,4 +1508,113 @@ sub retrieve_accounts { $main::lxdebug->leave_sub(2); } +sub get_basic_part_info { + $main::lxdebug->enter_sub(); + + my $self = shift; + my %params = @_; + + Common::check_params(\%params, qw(id)); + + my @ids = 'ARRAY' eq ref $params{id} ? @{ $params{id} } : ($params{id}); + + if (!scalar @ids) { + $main::lxdebug->leave_sub(); + return (); + } + + my $myconfig = \%main::myconfig; + my $form = $main::form; + + my $dbh = $form->get_standard_dbh($myconfig); + + my $query = qq|SELECT id, partnumber, description, unit FROM parts WHERE id IN (| . join(', ', ('?') x scalar(@ids)) . qq|)|; + + my $info = selectall_hashref_query($form, $dbh, $query, map { conv_i($_) } @ids); + + if ('' eq ref $params{id}) { + $info = $info->[0] || { }; + + $main::lxdebug->leave_sub(); + return $info; + } + + my %info_map = map { $_->{id} => $_ } @{ $info }; + + $main::lxdebug->leave_sub(); + + return %info_map; +} + +sub prepare_parts_for_printing { + $main::lxdebug->enter_sub(); + + my $self = shift; + my %params = @_; + + my $myconfig = \%main::myconfig; + my $form = $main::form; + + my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig); + + my $prefix = $params{prefix} || 'id_'; + my $rowcount = defined $params{rowcount} ? $params{rowcount} : $form->{rowcount}; + + my @part_ids = keys %{ { map { $_ => 1 } grep { $_ } map { $form->{"${prefix}${_}"} } (1 .. $rowcount) } }; + + if (!@part_ids) { + $main::lxdebug->leave_sub(); + return; + } + + my $placeholders = join ', ', ('?') x scalar(@part_ids); + my $query = qq|SELECT mm.parts_id, mm.model, v.name AS make + FROM makemodel mm + LEFT JOIN vendor v ON (mm.make = cast (v.id as text)) + WHERE mm.parts_id IN ($placeholders)|; + + my %makemodel = (); + + my $sth = prepare_execute_query($form, $dbh, $query, @part_ids); + + while (my $ref = $sth->fetchrow_hashref()) { + $makemodel{$ref->{parts_id}} ||= []; + push @{ $makemodel{$ref->{parts_id}} }, $ref; + } + + $sth->finish(); + + my @columns = qw(ean image microfiche drawing weight); + + $query = qq|SELECT id, | . join(', ', @columns) . qq| + FROM parts + WHERE id IN ($placeholders)|; + + my %data = selectall_as_map($form, $dbh, $query, 'id', \@columns, @part_ids); + + map { $form->{TEMPLATE_ARRAYS}{$_} = [] } (qw(make model), @columns); + + foreach my $i (1 .. $rowcount) { + my $id = $form->{"${prefix}${i}"}; + + next if (!$id); + + foreach (@columns) { + push @{ $form->{TEMPLATE_ARRAYS}{$_} }, $data{$id}->{$_}; + } + + push @{ $form->{TEMPLATE_ARRAYS}{make} }, []; + push @{ $form->{TEMPLATE_ARRAYS}{model} }, []; + + next if (!$makemodel{$id}); + + foreach my $ref (@{ $makemodel{$id} }) { + map { push @{ $form->{TEMPLATE_ARRAYS}{$_}->[-1] }, $ref->{$_} } qw(make model); + } + } + + $main::lxdebug->leave_sub(); +} + + 1;