1 #====================================================================
4 # Based on SQL-Ledger Version 2.1.9
5 # Web http://www.lx-office.org
7 #=====================================================================
8 # SQL-Ledger Accounting
9 # Copyright (C) 1999-2003
11 # Author: Dieter Simader
12 # Email: dsimader@sql-ledger.org
13 # Web: http://www.sql-ledger.org
17 # This program is free software; you can redistribute it and/or modify
18 # it under the terms of the GNU General Public License as published by
19 # the Free Software Foundation; either version 2 of the License, or
20 # (at your option) any later version.
22 # This program is distributed in the hope that it will be useful,
23 # but WITHOUT ANY WARRANTY; without even the implied warranty of
24 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 # GNU General Public License for more details.
26 # You should have received a copy of the GNU General Public License
27 # along with this program; if not, write to the Free Software
28 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #======================================================================
33 #======================================================================
37 use List::Util qw(max first);
46 OE.pm - Order entry module
50 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>.
59 $main::lxdebug->enter_sub();
61 my ($self, $myconfig, $form) = @_;
64 my $dbh = $form->dbconnect($myconfig);
67 my $ordnumber = 'ordnumber';
73 my $rate = ($form->{vc} eq 'customer') ? 'buy' : 'sell';
75 if ($form->{type} =~ /_quotation$/) {
77 $ordnumber = 'quonumber';
80 my $vc = $form->{vc} eq "customer" ? "customer" : "vendor";
83 qq|SELECT o.id, o.ordnumber, o.transdate, o.reqdate, | .
84 qq| o.amount, ct.name, o.netamount, o.${vc}_id, o.globalproject_id, | .
85 qq| o.closed, o.delivered, o.quonumber, o.shippingpoint, o.shipvia, | .
86 qq| o.transaction_description, | .
87 qq| o.marge_total, o.marge_percent, | .
88 qq| ex.$rate AS exchangerate, | .
89 qq| pr.projectnumber AS globalprojectnumber, | .
90 qq| e.name AS employee, s.name AS salesman, | .
91 qq| ct.country, ct.ustid | .
93 qq|JOIN $vc ct ON (o.${vc}_id = ct.id) | .
94 qq|LEFT JOIN employee e ON (o.employee_id = e.id) | .
95 qq|LEFT JOIN employee s ON (o.salesman_id = s.id) | .
96 qq|LEFT JOIN exchangerate ex ON (ex.curr = o.curr | .
97 qq| AND ex.transdate = o.transdate) | .
98 qq|LEFT JOIN project pr ON (o.globalproject_id = pr.id) | .
99 qq|WHERE (o.quotation = ?) |;
100 push(@values, $quotation);
102 my ($null, $split_department_id) = split /--/, $form->{department};
103 my $department_id = $form->{department_id} || $split_department_id;
104 if ($department_id) {
105 $query .= qq| AND o.department_id = ?|;
106 push(@values, $department_id);
109 if ($form->{"project_id"}) {
111 qq|AND ((globalproject_id = ?) OR EXISTS | .
112 qq| (SELECT * FROM orderitems oi | .
113 qq| WHERE oi.project_id = ? AND oi.trans_id = o.id))|;
114 push(@values, conv_i($form->{"project_id"}), conv_i($form->{"project_id"}));
117 if ($form->{"projectnumber"}) {
119 AND (pr.projectnumber ILIKE ?) OR EXISTS (
120 SELECT * FROM orderitems oi
121 LEFT JOIN project proi ON proi.id = oi.project_id
122 WHERE proi.projectnumber ILIKE ? AND oi.trans_id = o.id
125 push @values, "%" . $form->{"projectnumber"} . "%", "%" . $form->{"projectnumber"} . "%" ;
128 if ($form->{"${vc}_id"}) {
129 $query .= " AND o.${vc}_id = ?";
130 push(@values, $form->{"${vc}_id"});
132 } elsif ($form->{$vc}) {
133 $query .= " AND ct.name ILIKE ?";
134 push(@values, '%' . $form->{$vc} . '%');
137 if ($form->{employee_id}) {
138 $query .= " AND o.employee_id = ?";
139 push @values, conv_i($form->{employee_id});
142 if ($form->{salesman_id}) {
143 $query .= " AND o.salesman_id = ?";
144 push @values, conv_i($form->{salesman_id});
147 if (!$form->{open} && !$form->{closed}) {
148 $query .= " AND o.id = 0";
149 } elsif (!($form->{open} && $form->{closed})) {
150 $query .= ($form->{open}) ? " AND o.closed = '0'" : " AND o.closed = '1'";
153 if (($form->{"notdelivered"} || $form->{"delivered"}) &&
154 ($form->{"notdelivered"} ne $form->{"delivered"})) {
155 $query .= $form->{"delivered"} ?
156 " AND o.delivered " : " AND NOT o.delivered";
159 if ($form->{$ordnumber}) {
160 $query .= qq| AND o.$ordnumber ILIKE ?|;
161 push(@values, '%' . $form->{$ordnumber} . '%');
164 if($form->{transdatefrom}) {
165 $query .= qq| AND o.transdate >= ?|;
166 push(@values, conv_date($form->{transdatefrom}));
169 if($form->{transdateto}) {
170 $query .= qq| AND o.transdate <= ?|;
171 push(@values, conv_date($form->{transdateto}));
174 if($form->{reqdatefrom}) {
175 $query .= qq| AND o.reqdate >= ?|;
176 push(@values, conv_date($form->{reqdatefrom}));
179 if($form->{reqdateto}) {
180 $query .= qq| AND o.reqdate <= ?|;
181 push(@values, conv_date($form->{reqdateto}));
184 if ($form->{transaction_description}) {
185 $query .= qq| AND o.transaction_description ILIKE ?|;
186 push(@values, '%' . $form->{transaction_description} . '%');
189 my $sortdir = !defined $form->{sortdir} ? 'ASC' : $form->{sortdir} ? 'ASC' : 'DESC';
190 my $sortorder = join(', ', map { "${_} ${sortdir} " } ("o.id", $form->sort_columns("transdate", $ordnumber, "name")));
191 my %allowed_sort_columns = (
192 "transdate" => "o.transdate",
193 "reqdate" => "o.reqdate",
195 "ordnumber" => "o.ordnumber",
196 "quonumber" => "o.quonumber",
198 "employee" => "e.name",
199 "salesman" => "e.name",
200 "shipvia" => "o.shipvia",
201 "transaction_description" => "o.transaction_description"
203 if ($form->{sort} && grep($form->{sort}, keys(%allowed_sort_columns))) {
204 $sortorder = $allowed_sort_columns{$form->{sort}} . " ${sortdir}";
206 $query .= qq| ORDER by | . $sortorder;
208 my $sth = $dbh->prepare($query);
209 $sth->execute(@values) ||
210 $form->dberror($query . " (" . join(", ", @values) . ")");
214 while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
215 $ref->{exchangerate} = 1 unless $ref->{exchangerate};
216 push @{ $form->{OE} }, $ref if $ref->{id} != $id{ $ref->{id} };
217 $id{ $ref->{id} } = $ref->{id};
223 $main::lxdebug->leave_sub();
226 sub transactions_for_todo_list {
227 $main::lxdebug->enter_sub();
232 my $myconfig = \%main::myconfig;
233 my $form = $main::form;
235 my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig);
237 my $query = qq|SELECT id FROM employee WHERE login = ?|;
238 my ($e_id) = selectrow_query($form, $dbh, $query, $form->{login});
241 qq|SELECT oe.id, oe.transdate, oe.reqdate, oe.quonumber, oe.transaction_description, oe.amount,
242 CASE WHEN (COALESCE(oe.customer_id, 0) = 0) THEN 'vendor' ELSE 'customer' END AS vc,
247 LEFT JOIN customer c ON (oe.customer_id = c.id)
248 LEFT JOIN vendor v ON (oe.vendor_id = v.id)
249 LEFT JOIN employee e ON (oe.employee_id = e.id)
250 WHERE (COALESCE(quotation, FALSE) = TRUE)
251 AND (COALESCE(closed, FALSE) = FALSE)
252 AND ((oe.employee_id = ?) OR (oe.salesman_id = ?))
253 AND NOT (oe.reqdate ISNULL)
254 AND (oe.reqdate < current_date)
257 my $quotations = selectall_hashref_query($form, $dbh, $query, $e_id, $e_id);
259 $main::lxdebug->leave_sub();
265 $main::lxdebug->enter_sub();
267 my ($self, $myconfig, $form) = @_;
269 # connect to database, turn off autocommit
270 my $dbh = $form->dbconnect_noauto($myconfig);
272 my ($query, @values, $sth, $null);
273 my $exchangerate = 0;
275 my $all_units = AM->retrieve_units($myconfig, $form);
276 $form->{all_units} = $all_units;
278 my $ic_cvar_configs = CVar->get_configs(module => 'IC',
281 $form->{employee_id} = (split /--/, $form->{employee})[1] if !$form->{employee_id};
282 unless ($form->{employee_id}) {
283 $form->get_employee($dbh);
286 my $ml = ($form->{type} eq 'sales_order') ? 1 : -1;
289 $query = qq|DELETE FROM custom_variables
290 WHERE (config_id IN (SELECT id FROM custom_variable_configs WHERE module = 'IC'))
291 AND (sub_module = 'orderitems')
292 AND (trans_id IN (SELECT id FROM orderitems WHERE trans_id = ?))|;
293 do_query($form, $dbh, $query, $form->{id});
295 $query = qq|DELETE FROM orderitems WHERE trans_id = ?|;
296 do_query($form, $dbh, $query, $form->{id});
298 $query = qq|DELETE FROM shipto | .
299 qq|WHERE trans_id = ? AND module = 'OE'|;
300 do_query($form, $dbh, $query, $form->{id});
304 $query = qq|SELECT nextval('id')|;
305 ($form->{id}) = selectrow_query($form, $dbh, $query);
307 $query = qq|INSERT INTO oe (id, ordnumber, employee_id) VALUES (?, '', ?)|;
308 do_query($form, $dbh, $query, $form->{id}, $form->{employee_id});
326 $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS');
327 my %price_factors = map { $_->{id} => $_->{factor} } @{ $form->{ALL_PRICE_FACTORS} };
330 for my $i (1 .. $form->{rowcount}) {
332 map({ $form->{"${_}_$i"} = $form->parse_amount($myconfig, $form->{"${_}_$i"}) } qw(qty ship));
334 if ($form->{"id_$i"}) {
337 $query = qq|SELECT unit FROM parts WHERE id = ?|;
338 my ($item_unit) = selectrow_query($form, $dbh, $query, $form->{"id_$i"});
341 if (defined($all_units->{$item_unit}->{factor}) &&
342 (($all_units->{$item_unit}->{factor} * 1) != 0)) {
343 $basefactor = $all_units->{$form->{"unit_$i"}}->{factor} / $all_units->{$item_unit}->{factor};
345 my $baseqty = $form->{"qty_$i"} * $basefactor;
347 $form->{"marge_percent_$i"} = $form->parse_amount($myconfig, $form->{"marge_percent_$i"}) * 1;
348 $form->{"marge_total_$i"} = $form->parse_amount($myconfig, $form->{"marge_total_$i"}) * 1;
349 $form->{"lastcost_$i"} = $form->{"lastcost_$i"} * 1;
351 # set values to 0 if nothing entered
352 $form->{"discount_$i"} = $form->parse_amount($myconfig, $form->{"discount_$i"}) / 100;
354 $form->{"sellprice_$i"} = $form->parse_amount($myconfig, $form->{"sellprice_$i"});
355 $fxsellprice = $form->{"sellprice_$i"};
357 my ($dec) = ($form->{"sellprice_$i"} =~ /\.(\d+)/);
359 my $decimalplaces = ($dec > 2) ? $dec : 2;
361 $discount = $form->round_amount($form->{"sellprice_$i"} * $form->{"discount_$i"}, $decimalplaces);
362 $form->{"sellprice_$i"} = $form->round_amount($form->{"sellprice_$i"} - $discount, $decimalplaces);
364 $form->{"inventory_accno_$i"} *= 1;
365 $form->{"expense_accno_$i"} *= 1;
367 $price_factor = $price_factors{ $form->{"price_factor_id_$i"} } || 1;
368 $linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"} / $price_factor, 2);
370 @taxaccounts = split(/ /, $form->{"taxaccounts_$i"});
374 map { $taxrate += $form->{"${_}_rate"} } @taxaccounts;
376 if ($form->{taxincluded}) {
377 $taxamount = $linetotal * $taxrate / (1 + $taxrate);
378 $taxbase = $linetotal - $taxamount;
380 # we are not keeping a natural price, do not round
381 $form->{"sellprice_$i"} =
382 $form->{"sellprice_$i"} * (1 / (1 + $taxrate));
384 $taxamount = $linetotal * $taxrate;
385 $taxbase = $linetotal;
388 if ($form->round_amount($taxrate, 7) == 0) {
389 if ($form->{taxincluded}) {
390 foreach my $item (@taxaccounts) {
391 $taxamount = $form->round_amount($linetotal * $form->{"${item}_rate"} / (1 + abs($form->{"${item}_rate"})), 2);
392 $taxaccounts{$item} += $taxamount;
393 $taxdiff += $taxamount;
394 $taxbase{$item} += $taxbase;
396 $taxaccounts{ $taxaccounts[0] } += $taxdiff;
398 foreach my $item (@taxaccounts) {
399 $taxaccounts{$item} += $linetotal * $form->{"${item}_rate"};
400 $taxbase{$item} += $taxbase;
404 foreach my $item (@taxaccounts) {
405 $taxaccounts{$item} += $taxamount * $form->{"${item}_rate"} / $taxrate;
406 $taxbase{$item} += $taxbase;
410 $netamount += $form->{"sellprice_$i"} * $form->{"qty_$i"} / $price_factor;
412 $reqdate = ($form->{"reqdate_$i"}) ? $form->{"reqdate_$i"} : undef;
414 # get pricegroup_id and save ist
415 ($null, my $pricegroup_id) = split(/--/, $form->{"sellprice_pg_$i"});
418 # save detail record in orderitems table
419 my $orderitems_id = $form->{"orderitems_id_$i"};
420 ($orderitems_id) = selectfirst_array_query($form, $dbh, qq|SELECT nextval('orderitemsid')|) if (!$orderitems_id);
423 $query = qq|INSERT INTO orderitems (
424 id, trans_id, parts_id, description, longdescription, qty, base_qty,
425 sellprice, discount, unit, reqdate, project_id, serialnumber, ship,
426 pricegroup_id, ordnumber, transdate, cusordnumber, subtotal,
427 marge_percent, marge_total, lastcost, price_factor_id, price_factor, marge_price_factor)
428 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
429 (SELECT factor FROM price_factors WHERE id = ?), ?)|;
431 conv_i($orderitems_id), conv_i($form->{id}), conv_i($form->{"id_$i"}),
432 $form->{"description_$i"}, $form->{"longdescription_$i"},
433 $form->{"qty_$i"}, $baseqty,
434 $fxsellprice, $form->{"discount_$i"},
435 $form->{"unit_$i"}, conv_date($reqdate), conv_i($form->{"project_id_$i"}),
436 $form->{"serialnumber_$i"}, $form->{"ship_$i"}, conv_i($pricegroup_id),
437 $form->{"ordnumber_$i"}, conv_date($form->{"transdate_$i"}),
438 $form->{"cusordnumber_$i"}, $form->{"subtotal_$i"} ? 't' : 'f',
439 $form->{"marge_percent_$i"}, $form->{"marge_total_$i"},
440 $form->{"lastcost_$i"},
441 conv_i($form->{"price_factor_id_$i"}), conv_i($form->{"price_factor_id_$i"}),
442 conv_i($form->{"marge_price_factor_$i"}));
443 do_query($form, $dbh, $query, @values);
445 $form->{"sellprice_$i"} = $fxsellprice;
446 $form->{"discount_$i"} *= 100;
448 CVar->save_custom_variables(module => 'IC',
449 sub_module => 'orderitems',
450 trans_id => $orderitems_id,
451 configs => $ic_cvar_configs,
453 name_prefix => 'ic_',
454 name_postfix => "_$i",
459 $reqdate = ($form->{reqdate}) ? $form->{reqdate} : undef;
463 map { $tax += $form->round_amount($taxaccounts{$_}, 2) } keys %taxaccounts;
465 $amount = $form->round_amount($netamount + $tax, 2);
466 $netamount = $form->round_amount($netamount, 2);
468 if ($form->{currency} eq $form->{defaultcurrency}) {
469 $form->{exchangerate} = 1;
471 $exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{transdate}, ($form->{vc} eq 'customer') ? 'buy' : 'sell');
474 $form->{exchangerate} = $exchangerate || $form->parse_amount($myconfig, $form->{exchangerate});
476 my $quotation = $form->{type} =~ /_order$/ ? 'f' : 't';
478 ($null, $form->{department_id}) = split(/--/, $form->{department}) if $form->{department};
483 ordnumber = ?, quonumber = ?, cusordnumber = ?, transdate = ?, vendor_id = ?,
484 customer_id = ?, amount = ?, netamount = ?, reqdate = ?, taxincluded = ?,
485 shippingpoint = ?, shipvia = ?, notes = ?, intnotes = ?, curr = ?, closed = ?,
486 delivered = ?, proforma = ?, quotation = ?, department_id = ?, language_id = ?,
487 taxzone_id = ?, shipto_id = ?, payment_id = ?, delivery_vendor_id = ?, delivery_customer_id = ?,
488 globalproject_id = ?, employee_id = ?, salesman_id = ?, cp_id = ?, transaction_description = ?, marge_total = ?, marge_percent = ?
491 @values = ($form->{ordnumber} || '', $form->{quonumber},
492 $form->{cusordnumber}, conv_date($form->{transdate}),
493 conv_i($form->{vendor_id}), conv_i($form->{customer_id}),
494 $amount, $netamount, conv_date($reqdate),
495 $form->{taxincluded} ? 't' : 'f', $form->{shippingpoint},
496 $form->{shipvia}, $form->{notes}, $form->{intnotes},
497 substr($form->{currency}, 0, 3), $form->{closed} ? 't' : 'f',
498 $form->{delivered} ? "t" : "f", $form->{proforma} ? 't' : 'f',
499 $quotation, conv_i($form->{department_id}),
500 conv_i($form->{language_id}), conv_i($form->{taxzone_id}),
501 conv_i($form->{shipto_id}), conv_i($form->{payment_id}),
502 conv_i($form->{delivery_vendor_id}),
503 conv_i($form->{delivery_customer_id}),
504 conv_i($form->{globalproject_id}), conv_i($form->{employee_id}),
505 conv_i($form->{salesman_id}), conv_i($form->{cp_id}),
506 $form->{transaction_description},
507 $form->{marge_total} * 1, $form->{marge_percent} * 1,
508 conv_i($form->{id}));
509 do_query($form, $dbh, $query, @values);
511 $form->{ordtotal} = $amount;
514 $form->{name} = $form->{ $form->{vc} };
515 $form->{name} =~ s/--\Q$form->{"$form->{vc}_id"}\E//;
517 if (!$form->{shipto_id}) {
518 $form->add_shipto($dbh, $form->{id}, "OE");
521 # save printed, emailed, queued
522 $form->save_status($dbh);
524 # Link this record to the records it was created from.
525 $form->{convert_from_oe_ids} =~ s/^\s+//;
526 $form->{convert_from_oe_ids} =~ s/\s+$//;
527 my @convert_from_oe_ids = split m/\s+/, $form->{convert_from_oe_ids};
528 delete $form->{convert_from_oe_ids};
530 if (scalar @convert_from_oe_ids) {
531 RecordLinks->create_links('dbh' => $dbh,
533 'from_table' => 'oe',
534 'from_ids' => \@convert_from_oe_ids,
536 'to_id' => $form->{id},
539 $self->_close_quotations_rfqs('dbh' => $dbh,
540 'from_id' => \@convert_from_oe_ids,
541 'to_id' => $form->{id});
544 if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
545 if ($form->{vc} eq 'customer') {
546 $form->update_exchangerate($dbh, $form->{currency}, $form->{transdate}, $form->{exchangerate}, 0);
548 if ($form->{vc} eq 'vendor') {
549 $form->update_exchangerate($dbh, $form->{currency}, $form->{transdate}, 0, $form->{exchangerate});
553 $form->{saved_xyznumber} = $form->{$form->{type} =~ /_quotation$/ ?
554 "quonumber" : "ordnumber"};
556 Common::webdav_folder($form) if ($main::webdav);
558 my $rc = $dbh->commit;
561 $main::lxdebug->leave_sub();
566 sub _close_quotations_rfqs {
567 $main::lxdebug->enter_sub();
572 Common::check_params(\%params, qw(from_id to_id));
574 my $myconfig = \%main::myconfig;
575 my $form = $main::form;
577 my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig);
579 my $query = qq|SELECT quotation FROM oe WHERE id = ?|;
580 my $sth = prepare_query($form, $dbh, $query);
582 do_statement($form, $sth, $query, conv_i($params{to_id}));
584 my ($quotation) = $sth->fetchrow_array();
587 $main::lxdebug->leave_sub();
593 foreach my $from_id (@{ $params{from_id} }) {
594 $from_id = conv_i($from_id);
595 do_statement($form, $sth, $query, $from_id);
596 ($quotation) = $sth->fetchrow_array();
597 push @close_ids, $from_id if ($quotation);
602 if (scalar @close_ids) {
603 $query = qq|UPDATE oe SET closed = TRUE WHERE id IN (| . join(', ', ('?') x scalar @close_ids) . qq|)|;
604 do_query($form, $dbh, $query, @close_ids);
606 $dbh->commit() unless ($params{dbh});
609 $main::lxdebug->leave_sub();
613 $main::lxdebug->enter_sub();
615 my ($self, $myconfig, $form, $spool) = @_;
617 # connect to database
618 my $dbh = $form->dbconnect_noauto($myconfig);
621 my $query = qq|SELECT s.spoolfile FROM status s | .
622 qq|WHERE s.trans_id = ?|;
623 my @values = (conv_i($form->{id}));
624 my $sth = $dbh->prepare($query);
625 $sth->execute(@values) || $self->dberror($query);
630 while (($spoolfile) = $sth->fetchrow_array) {
631 push @spoolfiles, $spoolfile;
636 @values = (conv_i($form->{id}));
638 # delete status entries
639 $query = qq|DELETE FROM status | .
640 qq|WHERE trans_id = ?|;
641 do_query($form, $dbh, $query, @values);
644 $query = qq|DELETE FROM oe | .
646 do_query($form, $dbh, $query, @values);
648 # delete individual entries
649 $query = qq|DELETE FROM orderitems | .
650 qq|WHERE trans_id = ?|;
651 do_query($form, $dbh, $query, @values);
653 $query = qq|DELETE FROM shipto | .
654 qq|WHERE trans_id = ? AND module = 'OE'|;
655 do_query($form, $dbh, $query, @values);
657 my $rc = $dbh->commit;
661 foreach $spoolfile (@spoolfiles) {
662 unlink "$spool/$spoolfile" if $spoolfile;
666 $main::lxdebug->leave_sub();
672 $main::lxdebug->enter_sub();
674 my ($self, $myconfig, $form) = @_;
676 # connect to database
677 my $dbh = $form->dbconnect_noauto($myconfig);
679 my ($query, $query_add, @values, @ids, $sth);
681 my $ic_cvar_configs = CVar->get_configs(module => 'IC',
684 # translate the ids (given by id_# and trans_id_#) into one array of ids, so we can join them later
686 push @ids, $form->{"trans_id_$_"}
687 if ($form->{"multi_id_$_"} and $form->{"trans_id_$_"})
688 } (1 .. $form->{"rowcount"});
690 if ($form->{rowcount} && scalar @ids) {
691 $form->{convert_from_oe_ids} = join ' ', @ids;
694 # if called in multi id mode, and still only got one id, switch back to single id
695 if ($form->{"rowcount"} and $#ids == 0) {
696 $form->{"id"} = $ids[0];
700 # and remember for the rest of the function
701 my $is_collective_order = scalar @ids;
704 my $wday = (localtime(time))[6];
705 my $next_workday = $wday == 5 ? 3 : $wday == 6 ? 2 : 1;
706 $query_add = qq|, current_date AS transdate, date(current_date + interval '${next_workday} days') AS reqdate|;
709 # get default accounts
710 $query = qq|SELECT (SELECT c.accno FROM chart c WHERE d.inventory_accno_id = c.id) AS inventory_accno,
711 (SELECT c.accno FROM chart c WHERE d.income_accno_id = c.id) AS income_accno,
712 (SELECT c.accno FROM chart c WHERE d.expense_accno_id = c.id) AS expense_accno,
713 (SELECT c.accno FROM chart c WHERE d.fxgain_accno_id = c.id) AS fxgain_accno,
714 (SELECT c.accno FROM chart c WHERE d.fxloss_accno_id = c.id) AS fxloss_accno,
718 my $ref = selectfirst_hashref_query($form, $dbh, $query);
719 map { $form->{$_} = $ref->{$_} } keys %$ref;
721 ($form->{currency}) = split(/:/, $form->{currencies}) unless ($form->{currency});
723 # set reqdate if this is an invoice->order conversion. If someone knows a better check to ensure
724 # we come from invoices, feel free.
725 $form->{reqdate} = $form->{deliverydate}
726 if ( $form->{deliverydate}
727 and $form->{callback} =~ /action=ar_transactions/);
729 my $vc = $form->{vc} eq "customer" ? "customer" : "vendor";
731 if ($form->{id} or @ids) {
733 # retrieve order for single id
734 # NOTE: this query is intended to fetch all information only ONCE.
735 # so if any of these infos is important (or even different) for any item,
736 # it will be killed out and then has to be fetched from the item scope query further down
738 qq|SELECT o.cp_id, o.ordnumber, o.transdate, o.reqdate,
739 o.taxincluded, o.shippingpoint, o.shipvia, o.notes, o.intnotes,
740 o.curr AS currency, e.name AS employee, o.employee_id, o.salesman_id,
741 o.${vc}_id, cv.name AS ${vc}, o.amount AS invtotal,
742 o.closed, o.reqdate, o.quonumber, o.department_id, o.cusordnumber,
743 d.description AS department, o.payment_id, o.language_id, o.taxzone_id,
744 o.delivery_customer_id, o.delivery_vendor_id, o.proforma, o.shipto_id,
745 o.globalproject_id, o.delivered, o.transaction_description
747 JOIN ${vc} cv ON (o.${vc}_id = cv.id)
748 LEFT JOIN employee e ON (o.employee_id = e.id)
749 LEFT JOIN department d ON (o.department_id = d.id) | .
752 : "WHERE o.id IN (" . join(', ', map("? ", @ids)) . ")"
754 @values = $form->{id} ? ($form->{id}) : @ids;
755 $sth = prepare_execute_query($form, $dbh, $query, @values);
757 $ref = $sth->fetchrow_hashref("NAME_lc");
758 map { $form->{$_} = $ref->{$_} } keys %$ref;
760 $form->{saved_xyznumber} = $form->{$form->{type} =~ /_quotation$/ ?
761 "quonumber" : "ordnumber"};
763 # set all entries for multiple ids blank that yield different information
764 while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
765 map { $form->{$_} = '' if ($ref->{$_} ne $form->{$_}) } keys %$ref;
768 # if not given, fill transdate with current_date
769 $form->{transdate} = $form->current_date($myconfig)
770 unless $form->{transdate};
774 if ($form->{delivery_customer_id}) {
775 $query = qq|SELECT name FROM customer WHERE id = ?|;
776 ($form->{delivery_customer_string}) = selectrow_query($form, $dbh, $query, $form->{delivery_customer_id});
779 if ($form->{delivery_vendor_id}) {
780 $query = qq|SELECT name FROM customer WHERE id = ?|;
781 ($form->{delivery_vendor_string}) = selectrow_query($form, $dbh, $query, $form->{delivery_vendor_id});
784 # shipto and pinted/mailed/queued status makes only sense for single id retrieve
786 $query = qq|SELECT s.* FROM shipto s WHERE s.trans_id = ? AND s.module = 'OE'|;
787 $sth = prepare_execute_query($form, $dbh, $query, $form->{id});
789 $ref = $sth->fetchrow_hashref("NAME_lc");
791 map { $form->{$_} = $ref->{$_} } keys %$ref;
794 # get printed, emailed and queued
795 $query = qq|SELECT s.printed, s.emailed, s.spoolfile, s.formname FROM status s WHERE s.trans_id = ?|;
796 $sth = prepare_execute_query($form, $dbh, $query, $form->{id});
798 while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
799 $form->{printed} .= "$ref->{formname} " if $ref->{printed};
800 $form->{emailed} .= "$ref->{formname} " if $ref->{emailed};
801 $form->{queued} .= "$ref->{formname} $ref->{spoolfile} " if $ref->{spoolfile};
804 map { $form->{$_} =~ s/ +$//g } qw(printed emailed queued);
807 my %oid = ('Pg' => 'oid',
808 'Oracle' => 'rowid');
810 my $transdate = $form->{transdate} ? $dbh->quote($form->{transdate}) : "current_date";
812 $form->{taxzone_id} = 0 unless ($form->{taxzone_id});
814 # retrieve individual items
815 # this query looks up all information about the items
816 # stuff different from the whole will not be overwritten, but saved with a suffix.
818 qq|SELECT o.id AS orderitems_id,
819 c1.accno AS inventory_accno, c1.new_chart_id AS inventory_new_chart, date($transdate) - c1.valid_from as inventory_valid,
820 c2.accno AS income_accno, c2.new_chart_id AS income_new_chart, date($transdate) - c2.valid_from as income_valid,
821 c3.accno AS expense_accno, c3.new_chart_id AS expense_new_chart, date($transdate) - c3.valid_from as expense_valid,
822 oe.ordnumber AS ordnumber_oe, oe.transdate AS transdate_oe, oe.cusordnumber AS cusordnumber_oe,
823 p.partnumber, p.assembly, o.description, o.qty,
824 o.sellprice, o.parts_id AS id, o.unit, o.discount, p.bin, p.notes AS partnotes, p.inventory_accno_id AS part_inventory_accno_id,
825 o.reqdate, o.project_id, o.serialnumber, o.ship, o.lastcost,
826 o.ordnumber, o.transdate, o.cusordnumber, o.subtotal, o.longdescription,
827 o.price_factor_id, o.price_factor, o.marge_price_factor,
828 pr.projectnumber, p.formel,
829 pg.partsgroup, o.pricegroup_id, (SELECT pricegroup FROM pricegroup WHERE id=o.pricegroup_id) as pricegroup
831 JOIN parts p ON (o.parts_id = p.id)
832 JOIN oe ON (o.trans_id = oe.id)
833 LEFT JOIN chart c1 ON ((SELECT inventory_accno_id FROM buchungsgruppen WHERE id=p.buchungsgruppen_id) = c1.id)
834 LEFT JOIN chart c2 ON ((SELECT income_accno_id_$form->{taxzone_id} FROM buchungsgruppen WHERE id=p.buchungsgruppen_id) = c2.id)
835 LEFT JOIN chart c3 ON ((SELECT expense_accno_id_$form->{taxzone_id} FROM buchungsgruppen WHERE id=p.buchungsgruppen_id) = c3.id)
836 LEFT JOIN project pr ON (o.project_id = pr.id)
837 LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) | .
839 ? qq|WHERE o.trans_id = ?|
840 : qq|WHERE o.trans_id IN (| . join(", ", map("?", @ids)) . qq|)|) .
841 qq|ORDER BY o.$oid{$myconfig->{dbdriver}}|;
843 @ids = $form->{id} ? ($form->{id}) : @ids;
844 $sth = prepare_execute_query($form, $dbh, $query, @values);
846 while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
847 # Retrieve custom variables.
848 my $cvars = CVar->get_custom_variables(dbh => $dbh,
850 sub_module => 'orderitems',
851 trans_id => $ref->{orderitems_id},
853 map { $ref->{"ic_cvar_$_->{name}"} = $_->{value} } @{ $cvars };
856 if (!$ref->{"part_inventory_accno_id"}) {
857 map({ delete($ref->{$_}); } qw(inventory_accno inventory_new_chart inventory_valid));
859 delete($ref->{"part_inventory_accno_id"});
861 # in collective order, copy global ordnumber, transdate, cusordnumber into item scope
862 # unless already present there
863 # remove _oe entries afterwards
864 map { $ref->{$_} = $ref->{"${_}_oe"} if ($ref->{$_} eq '') }
865 qw|ordnumber transdate cusordnumber|
867 map { delete $ref->{$_} } qw|ordnumber_oe transdate_oe cusordnumber_oe|;
871 while ($ref->{inventory_new_chart} && ($ref->{inventory_valid} >= 0)) {
873 qq|SELECT accno AS inventory_accno, | .
874 qq| new_chart_id AS inventory_new_chart, | .
875 qq| date($transdate) - valid_from AS inventory_valid | .
876 qq|FROM chart WHERE id = $ref->{inventory_new_chart}|;
877 ($ref->{inventory_accno}, $ref->{inventory_new_chart},
878 $ref->{inventory_valid}) = selectrow_query($form, $dbh, $query);
881 while ($ref->{income_new_chart} && ($ref->{income_valid} >= 0)) {
883 qq|SELECT accno AS income_accno, | .
884 qq| new_chart_id AS income_new_chart, | .
885 qq| date($transdate) - valid_from AS income_valid | .
886 qq|FROM chart WHERE id = $ref->{income_new_chart}|;
887 ($ref->{income_accno}, $ref->{income_new_chart},
888 $ref->{income_valid}) = selectrow_query($form, $dbh, $query);
891 while ($ref->{expense_new_chart} && ($ref->{expense_valid} >= 0)) {
893 qq|SELECT accno AS expense_accno, | .
894 qq| new_chart_id AS expense_new_chart, | .
895 qq| date($transdate) - valid_from AS expense_valid | .
896 qq|FROM chart WHERE id = $ref->{expense_new_chart}|;
897 ($ref->{expense_accno}, $ref->{expense_new_chart},
898 $ref->{expense_valid}) = selectrow_query($form, $dbh, $query);
901 # delete orderitems_id in collective orders, so that they get cloned no matter what
902 delete $ref->{orderitems_id} if (@ids);
904 # get tax rates and description
905 my $accno_id = ($form->{vc} eq "customer") ? $ref->{income_accno} : $ref->{expense_accno};
907 qq|SELECT c.accno, t.taxdescription, t.rate, t.taxnumber | .
908 qq|FROM tax t LEFT JOIN chart c on (c.id = t.chart_id) | .
909 qq|WHERE t.id IN (SELECT tk.tax_id FROM taxkeys tk | .
910 qq| WHERE tk.chart_id = (SELECT id FROM chart WHERE accno = ?) | .
911 qq| AND startdate <= $transdate ORDER BY startdate DESC LIMIT 1) | .
912 qq|ORDER BY c.accno|;
913 my $stw = prepare_execute_query($form, $dbh, $query, $accno_id);
914 $ref->{taxaccounts} = "";
916 while (my $ptr = $stw->fetchrow_hashref("NAME_lc")) {
917 if (($ptr->{accno} eq "") && ($ptr->{rate} == 0)) {
921 $ref->{taxaccounts} .= "$ptr->{accno} ";
922 if (!($form->{taxaccounts} =~ /\Q$ptr->{accno}\E/)) {
923 $form->{"$ptr->{accno}_rate"} = $ptr->{rate};
924 $form->{"$ptr->{accno}_description"} = $ptr->{taxdescription};
925 $form->{"$ptr->{accno}_taxnumber"} = $ptr->{taxnumber};
926 $form->{taxaccounts} .= "$ptr->{accno} ";
931 chop $ref->{taxaccounts};
933 push @{ $form->{form_details} }, $ref;
941 $form->lastname_used($dbh, $myconfig, $form->{vc})
942 unless $form->{"$form->{vc}_id"};
946 $form->{exchangerate} = $form->get_exchangerate($dbh, $form->{currency}, $form->{transdate}, ($form->{vc} eq 'customer') ? "buy" : "sell");
948 Common::webdav_folder($form) if ($main::webdav);
950 my $rc = $dbh->commit;
953 $main::lxdebug->leave_sub();
958 =item retrieve_simple PARAMS
960 simple OE retrieval by id. does not look up customer, vendor, units or any other stuff. only oe and orderitems.
962 my $order = retrieve_simple(id => 2);
974 sub retrieve_simple {
975 $main::lxdebug->enter_sub();
980 Common::check_params(\%params, qw(id));
982 my $myconfig = \%main::myconfig;
983 my $form = $main::form;
985 my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig);
987 my $oe_query = qq|SELECT * FROM oe WHERE id = ?|;
988 my $oi_query = qq|SELECT * FROM orderitems WHERE trans_id = ?|;
990 my $order = selectfirst_hashref_query($form, $dbh, $oe_query, conv_i($params{id}));
991 $order->{orderitems} = selectall_hashref_query( $form, $dbh, $oi_query, conv_i($params{id}));
993 $main::lxdebug->leave_sub();
999 $main::lxdebug->enter_sub();
1001 my ($self, $myconfig, $form) = @_;
1003 # connect to database
1004 my $dbh = $form->dbconnect($myconfig);
1010 my $nodiscount_subtotal = 0;
1011 my $discount_subtotal = 0;
1014 my @partsgroup = ();
1017 my $subtotal_header = 0;
1018 my $subposition = 0;
1025 my %oid = ('Pg' => 'oid',
1026 'Oracle' => 'rowid');
1028 my (@project_ids, %projectnumbers);
1030 push(@project_ids, $form->{"globalproject_id"}) if ($form->{"globalproject_id"});
1032 $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS',
1033 'departments' => 'ALL_DEPARTMENTS');
1036 foreach my $pfac (@{ $form->{ALL_PRICE_FACTORS} }) {
1037 $price_factors{$pfac->{id}} = $pfac;
1038 $pfac->{factor} *= 1;
1039 $pfac->{formatted_factor} = $form->format_amount($myconfig, $pfac->{factor});
1043 foreach my $dept (@{ $form->{ALL_DEPARTMENTS} }) {
1044 next unless $dept->{id} eq $form->{department_id};
1045 $form->{department} = $dept->{description};
1049 # sort items by partsgroup
1050 for $i (1 .. $form->{rowcount}) {
1052 if ($form->{"partsgroup_$i"} && $form->{groupitems}) {
1053 $partsgroup = $form->{"partsgroup_$i"};
1055 push @partsgroup, [$i, $partsgroup];
1056 push(@project_ids, $form->{"project_id_$i"}) if ($form->{"project_id_$i"});
1060 $query = "SELECT id, projectnumber FROM project WHERE id IN (" .
1061 join(", ", map("?", @project_ids)) . ")";
1062 $sth = prepare_execute_query($form, $dbh, $query, @project_ids);
1063 while (my $ref = $sth->fetchrow_hashref()) {
1064 $projectnumbers{$ref->{id}} = $ref->{projectnumber};
1069 $form->{"globalprojectnumber"} = $projectnumbers{$form->{"globalproject_id"}};
1071 $form->{discount} = [];
1073 $form->{TEMPLATE_ARRAYS} = { };
1074 IC->prepare_parts_for_printing();
1076 my $ic_cvar_configs = CVar->get_configs(module => 'IC');
1079 qw(runningnumber number description longdescription qty ship unit bin
1080 partnotes serialnumber reqdate sellprice listprice netprice
1081 discount p_discount discount_sub nodiscount_sub
1082 linetotal nodiscount_linetotal tax_rate projectnumber
1083 price_factor price_factor_name partsgroup);
1085 push @arrays, map { "ic_cvar_$_->{name}" } @{ $ic_cvar_configs };
1087 my @tax_arrays = qw(taxbase tax taxdescription taxrate taxnumber);
1089 map { $form->{TEMPLATE_ARRAYS}->{$_} = [] } (@arrays, @tax_arrays);
1092 foreach $item (sort { $a->[1] cmp $b->[1] } @partsgroup) {
1095 if ($item->[1] ne $sameitem) {
1096 push(@{ $form->{TEMPLATE_ARRAYS}->{description} }, qq|$item->[1]|);
1097 $sameitem = $item->[1];
1099 map({ push(@{ $form->{TEMPLATE_ARRAYS}->{$_} }, "") } grep({ $_ ne "description" } @arrays));
1102 $form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
1104 if ($form->{"id_$i"} != 0) {
1106 # add number, description and qty to $form->{number}, ....
1108 if ($form->{"subtotal_$i"} && !$subtotal_header) {
1109 $subtotal_header = $i;
1110 $position = int($position);
1113 } elsif ($subtotal_header) {
1115 $position = int($position);
1116 $position = $position.".".$subposition;
1118 $position = int($position);
1122 my $price_factor = $price_factors{$form->{"price_factor_id_$i"}} || { 'factor' => 1 };
1124 push @{ $form->{TEMPLATE_ARRAYS}->{runningnumber} }, $position;
1125 push @{ $form->{TEMPLATE_ARRAYS}->{number} }, $form->{"partnumber_$i"};
1126 push @{ $form->{TEMPLATE_ARRAYS}->{description} }, $form->{"description_$i"};
1127 push @{ $form->{TEMPLATE_ARRAYS}->{longdescription} }, $form->{"longdescription_$i"};
1128 push @{ $form->{TEMPLATE_ARRAYS}->{qty} }, $form->format_amount($myconfig, $form->{"qty_$i"});
1129 push @{ $form->{TEMPLATE_ARRAYS}->{ship} }, $form->format_amount($myconfig, $form->{"ship_$i"});
1130 push @{ $form->{TEMPLATE_ARRAYS}->{unit} }, $form->{"unit_$i"};
1131 push @{ $form->{TEMPLATE_ARRAYS}->{bin} }, $form->{"bin_$i"};
1132 push @{ $form->{TEMPLATE_ARRAYS}->{partnotes} }, $form->{"partnotes_$i"};
1133 push @{ $form->{TEMPLATE_ARRAYS}->{serialnumber} }, $form->{"serialnumber_$i"};
1134 push @{ $form->{TEMPLATE_ARRAYS}->{reqdate} }, $form->{"reqdate_$i"};
1135 push @{ $form->{TEMPLATE_ARRAYS}->{sellprice} }, $form->{"sellprice_$i"};
1136 push @{ $form->{TEMPLATE_ARRAYS}->{listprice} }, $form->{"listprice_$i"};
1137 push @{ $form->{TEMPLATE_ARRAYS}->{price_factor} }, $price_factor->{formatted_factor};
1138 push @{ $form->{TEMPLATE_ARRAYS}->{price_factor_name} }, $price_factor->{description};
1139 push @{ $form->{TEMPLATE_ARRAYS}->{partsgroup} }, $form->{"partsgroup_$i"};
1141 my $sellprice = $form->parse_amount($myconfig, $form->{"sellprice_$i"});
1142 my ($dec) = ($sellprice =~ /\.(\d+)/);
1143 my $decimalplaces = max 2, length($dec);
1145 my $parsed_discount = $form->parse_amount($myconfig, $form->{"discount_$i"});
1146 my $linetotal_exact = $form->{"qty_$i"} * $sellprice * (100 - $parsed_discount) / 100 / $price_factor->{factor};
1147 my $linetotal = $form->round_amount($linetotal_exact, 2);
1148 my $discount = $form->round_amount($form->{"qty_$i"} * $sellprice * $parsed_discount / 100 / $price_factor->{factor} - ($linetotal - $linetotal_exact),
1150 my $nodiscount_linetotal = $form->round_amount($form->{"qty_$i"} * $sellprice / $price_factor->{factor}, 2);
1151 $form->{"netprice_$i"} = $form->round_amount($form->{"qty_$i"} ? ($linetotal / $form->{"qty_$i"}) : 0, 2);
1153 push @{ $form->{TEMPLATE_ARRAYS}->{netprice} }, ($form->{"netprice_$i"} != 0) ? $form->format_amount($myconfig, $form->{"netprice_$i"}, $decimalplaces) : '';
1155 $linetotal = ($linetotal != 0) ? $linetotal : '';
1157 push @{ $form->{TEMPLATE_ARRAYS}->{discount} }, ($discount != 0) ? $form->format_amount($myconfig, $discount * -1, 2) : '';
1158 push @{ $form->{TEMPLATE_ARRAYS}->{p_discount} }, $form->{"discount_$i"};
1160 $form->{ordtotal} += $linetotal;
1161 $form->{nodiscount_total} += $nodiscount_linetotal;
1162 $form->{discount_total} += $discount;
1164 if ($subtotal_header) {
1165 $discount_subtotal += $linetotal;
1166 $nodiscount_subtotal += $nodiscount_linetotal;
1169 if ($form->{"subtotal_$i"} && $subtotal_header && ($subtotal_header != $i)) {
1170 push @{ $form->{TEMPLATE_ARRAYS}->{discount_sub} }, $form->format_amount($myconfig, $discount_subtotal, 2);
1171 push @{ $form->{TEMPLATE_ARRAYS}->{nodiscount_sub} }, $form->format_amount($myconfig, $nodiscount_subtotal, 2);
1173 $discount_subtotal = 0;
1174 $nodiscount_subtotal = 0;
1175 $subtotal_header = 0;
1178 push @{ $form->{TEMPLATE_ARRAYS}->{discount_sub} }, "";
1179 push @{ $form->{TEMPLATE_ARRAYS}->{nodiscount_sub} }, "";
1182 if (!$form->{"discount_$i"}) {
1183 $nodiscount += $linetotal;
1186 push @{ $form->{TEMPLATE_ARRAYS}->{linetotal} }, $form->format_amount($myconfig, $linetotal, 2);
1187 push @{ $form->{TEMPLATE_ARRAYS}->{nodiscount_linetotal} }, $form->format_amount($myconfig, $nodiscount_linetotal, 2);
1189 push(@{ $form->{TEMPLATE_ARRAYS}->{projectnumber} }, $projectnumbers{$form->{"project_id_$i"}});
1191 my ($taxamount, $taxbase);
1194 map { $taxrate += $form->{"${_}_rate"} } split(/ /, $form->{"taxaccounts_$i"});
1196 if ($form->{taxincluded}) {
1199 $taxamount = $linetotal * $taxrate / (1 + $taxrate);
1200 $taxbase = $linetotal / (1 + $taxrate);
1202 $taxamount = $linetotal * $taxrate;
1203 $taxbase = $linetotal;
1206 if ($taxamount != 0) {
1207 foreach my $accno (split / /, $form->{"taxaccounts_$i"}) {
1208 $taxaccounts{$accno} += $taxamount * $form->{"${accno}_rate"} / $taxrate;
1209 $taxbase{$accno} += $taxbase;
1213 $tax_rate = $taxrate * 100;
1214 push(@{ $form->{TEMPLATE_ARRAYS}->{tax_rate} }, qq|$tax_rate|);
1216 if ($form->{"assembly_$i"}) {
1219 # get parts and push them onto the stack
1221 if ($form->{groupitems}) {
1222 $sortorder = qq|ORDER BY pg.partsgroup, a.$oid{$myconfig->{dbdriver}}|;
1224 $sortorder = qq|ORDER BY a.$oid{$myconfig->{dbdriver}}|;
1227 $query = qq|SELECT p.partnumber, p.description, p.unit, a.qty, | .
1228 qq|pg.partsgroup | .
1229 qq|FROM assembly a | .
1230 qq| JOIN parts p ON (a.parts_id = p.id) | .
1231 qq| LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) | .
1232 qq| WHERE a.bom = '1' | .
1233 qq| AND a.id = ? | . $sortorder;
1234 @values = ($form->{"id_$i"});
1235 $sth = $dbh->prepare($query);
1236 $sth->execute(@values) || $form->dberror($query);
1238 while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
1239 if ($form->{groupitems} && $ref->{partsgroup} ne $sameitem) {
1240 map({ push(@{ $form->{TEMPLATE_ARRAYS}->{$_} }, "") } grep({ $_ ne "description" } @arrays));
1241 $sameitem = ($ref->{partsgroup}) ? $ref->{partsgroup} : "--";
1242 push(@{ $form->{TEMPLATE_ARRAYS}->{description} }, $sameitem);
1245 push(@{ $form->{TEMPLATE_ARRAYS}->{description} }, $form->format_amount($myconfig, $ref->{qty} * $form->{"qty_$i"}) . qq|, $ref->{partnumber}, $ref->{description}|);
1246 map({ push(@{ $form->{TEMPLATE_ARRAYS}->{$_} }, "") } grep({ $_ ne "description" } @arrays));
1251 map { push @{ $form->{TEMPLATE_ARRAYS}->{"ic_cvar_$_->{name}"} }, $form->{"ic_cvar_$_->{name}_$i"} } @{ $ic_cvar_configs };
1256 foreach $item (sort keys %taxaccounts) {
1257 $tax += $taxamount = $form->round_amount($taxaccounts{$item}, 2);
1259 push(@{ $form->{TEMPLATE_ARRAYS}->{taxbase} }, $form->format_amount($myconfig, $taxbase{$item}, 2));
1260 push(@{ $form->{TEMPLATE_ARRAYS}->{tax} }, $form->format_amount($myconfig, $taxamount, 2));
1261 push(@{ $form->{TEMPLATE_ARRAYS}->{taxrate} }, $form->format_amount($myconfig, $form->{"${item}_rate"} * 100));
1262 push(@{ $form->{TEMPLATE_ARRAYS}->{taxdescription} }, $form->{"${item}_description"} . q{ } . 100 * $form->{"${item}_rate"} . q{%});
1263 push(@{ $form->{TEMPLATE_ARRAYS}->{taxnumber} }, $form->{"${item}_taxnumber"});
1266 $form->{nodiscount_subtotal} = $form->format_amount($myconfig, $form->{nodiscount_total}, 2);
1267 $form->{discount_total} = $form->format_amount($myconfig, $form->{discount_total}, 2);
1268 $form->{nodiscount} = $form->format_amount($myconfig, $nodiscount, 2);
1269 $form->{yesdiscount} = $form->format_amount($myconfig, $form->{nodiscount_total} - $nodiscount, 2);
1271 if($form->{taxincluded}) {
1272 $form->{subtotal} = $form->format_amount($myconfig, $form->{ordtotal} - $tax, 2);
1274 $form->{subtotal} = $form->format_amount($myconfig, $form->{ordtotal}, 2);
1277 $form->{ordtotal} = ($form->{taxincluded}) ? $form->{ordtotal} : $form->{ordtotal} + $tax;
1280 $form->{quototal} = $form->{ordtotal} = $form->format_amount($myconfig, $form->{ordtotal}, 2);
1282 if ($form->{type} =~ /_quotation/) {
1283 $form->set_payment_options($myconfig, $form->{quodate});
1285 $form->set_payment_options($myconfig, $form->{orddate});
1288 $form->{username} = $myconfig->{name};
1292 $main::lxdebug->leave_sub();
1295 sub project_description {
1296 $main::lxdebug->enter_sub();
1298 my ($self, $dbh, $id) = @_;
1300 my $query = qq|SELECT description FROM project WHERE id = ?|;
1301 my ($value) = selectrow_query($main::form, $dbh, $query, $id);
1303 $main::lxdebug->leave_sub();