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);
47 $main::lxdebug->enter_sub();
49 my ($self, $myconfig, $form) = @_;
52 my $dbh = $form->dbconnect($myconfig);
55 my $ordnumber = 'ordnumber';
61 my $rate = ($form->{vc} eq 'customer') ? 'buy' : 'sell';
63 if ($form->{type} =~ /_quotation$/) {
65 $ordnumber = 'quonumber';
68 my $vc = $form->{vc} eq "customer" ? "customer" : "vendor";
71 qq|SELECT o.id, o.ordnumber, o.transdate, o.reqdate, | .
72 qq| o.amount, ct.name, o.netamount, o.${vc}_id, o.globalproject_id, | .
73 qq| o.closed, o.delivered, o.quonumber, o.shippingpoint, o.shipvia, | .
74 qq| o.transaction_description, | .
75 qq| o.marge_total, o.marge_percent, | .
76 qq| ex.$rate AS exchangerate, | .
77 qq| pr.projectnumber AS globalprojectnumber, | .
78 qq| e.name AS employee, s.name AS salesman, | .
79 qq| ct.${vc}number AS vcnumber, ct.country, ct.ustid | .
81 qq|JOIN $vc ct ON (o.${vc}_id = ct.id) | .
82 qq|LEFT JOIN employee e ON (o.employee_id = e.id) | .
83 qq|LEFT JOIN employee s ON (o.salesman_id = s.id) | .
84 qq|LEFT JOIN exchangerate ex ON (ex.curr = o.curr | .
85 qq| AND ex.transdate = o.transdate) | .
86 qq|LEFT JOIN project pr ON (o.globalproject_id = pr.id) | .
87 qq|WHERE (o.quotation = ?) |;
88 push(@values, $quotation);
90 my ($null, $split_department_id) = split /--/, $form->{department};
91 my $department_id = $form->{department_id} || $split_department_id;
93 $query .= qq| AND o.department_id = ?|;
94 push(@values, $department_id);
97 if ($form->{"project_id"}) {
99 qq|AND ((globalproject_id = ?) OR EXISTS | .
100 qq| (SELECT * FROM orderitems oi | .
101 qq| WHERE oi.project_id = ? AND oi.trans_id = o.id))|;
102 push(@values, conv_i($form->{"project_id"}), conv_i($form->{"project_id"}));
105 if ($form->{"projectnumber"}) {
107 AND (pr.projectnumber ILIKE ?) OR EXISTS (
108 SELECT * FROM orderitems oi
109 LEFT JOIN project proi ON proi.id = oi.project_id
110 WHERE proi.projectnumber ILIKE ? AND oi.trans_id = o.id
113 push @values, "%" . $form->{"projectnumber"} . "%", "%" . $form->{"projectnumber"} . "%" ;
116 if ($form->{"${vc}_id"}) {
117 $query .= " AND o.${vc}_id = ?";
118 push(@values, $form->{"${vc}_id"});
120 } elsif ($form->{$vc}) {
121 $query .= " AND ct.name ILIKE ?";
122 push(@values, '%' . $form->{$vc} . '%');
125 if (!$main::auth->assert('sales_all_edit', 1)) {
126 $query .= " AND o.employee_id = (select id from employee where login= ?)";
127 push @values, $form->{login};
129 if ($form->{employee_id}) {
130 $query .= " AND o.employee_id = ?";
131 push @values, conv_i($form->{employee_id});
134 if ($form->{salesman_id}) {
135 $query .= " AND o.salesman_id = ?";
136 push @values, conv_i($form->{salesman_id});
139 if (!$form->{open} && !$form->{closed}) {
140 $query .= " AND o.id = 0";
141 } elsif (!($form->{open} && $form->{closed})) {
142 $query .= ($form->{open}) ? " AND o.closed = '0'" : " AND o.closed = '1'";
145 if (($form->{"notdelivered"} || $form->{"delivered"}) &&
146 ($form->{"notdelivered"} ne $form->{"delivered"})) {
147 $query .= $form->{"delivered"} ?
148 " AND o.delivered " : " AND NOT o.delivered";
151 if ($form->{$ordnumber}) {
152 $query .= qq| AND o.$ordnumber ILIKE ?|;
153 push(@values, '%' . $form->{$ordnumber} . '%');
156 if($form->{transdatefrom}) {
157 $query .= qq| AND o.transdate >= ?|;
158 push(@values, conv_date($form->{transdatefrom}));
161 if($form->{transdateto}) {
162 $query .= qq| AND o.transdate <= ?|;
163 push(@values, conv_date($form->{transdateto}));
166 if($form->{reqdatefrom}) {
167 $query .= qq| AND o.reqdate >= ?|;
168 push(@values, conv_date($form->{reqdatefrom}));
171 if($form->{reqdateto}) {
172 $query .= qq| AND o.reqdate <= ?|;
173 push(@values, conv_date($form->{reqdateto}));
176 if ($form->{transaction_description}) {
177 $query .= qq| AND o.transaction_description ILIKE ?|;
178 push(@values, '%' . $form->{transaction_description} . '%');
181 my $sortdir = !defined $form->{sortdir} ? 'ASC' : $form->{sortdir} ? 'ASC' : 'DESC';
182 my $sortorder = join(', ', map { "${_} ${sortdir} " } ("o.id", $form->sort_columns("transdate", $ordnumber, "name")));
183 my %allowed_sort_columns = (
184 "transdate" => "o.transdate",
185 "reqdate" => "o.reqdate",
187 "ordnumber" => "o.ordnumber",
188 "quonumber" => "o.quonumber",
190 "employee" => "e.name",
191 "salesman" => "e.name",
192 "shipvia" => "o.shipvia",
193 "transaction_description" => "o.transaction_description"
195 if ($form->{sort} && grep($form->{sort}, keys(%allowed_sort_columns))) {
196 $sortorder = $allowed_sort_columns{$form->{sort}} . " ${sortdir}";
198 $query .= qq| ORDER by | . $sortorder;
200 my $sth = $dbh->prepare($query);
201 $sth->execute(@values) ||
202 $form->dberror($query . " (" . join(", ", @values) . ")");
206 while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
207 $ref->{exchangerate} = 1 unless $ref->{exchangerate};
208 push @{ $form->{OE} }, $ref if $ref->{id} != $id{ $ref->{id} };
209 $id{ $ref->{id} } = $ref->{id};
215 $main::lxdebug->leave_sub();
218 sub transactions_for_todo_list {
219 $main::lxdebug->enter_sub();
224 my $myconfig = \%main::myconfig;
225 my $form = $main::form;
227 my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig);
229 my $query = qq|SELECT id FROM employee WHERE login = ?|;
230 my ($e_id) = selectrow_query($form, $dbh, $query, $form->{login});
233 qq|SELECT oe.id, oe.transdate, oe.reqdate, oe.quonumber, oe.transaction_description, oe.amount,
234 CASE WHEN (COALESCE(oe.customer_id, 0) = 0) THEN 'vendor' ELSE 'customer' END AS vc,
239 LEFT JOIN customer c ON (oe.customer_id = c.id)
240 LEFT JOIN vendor v ON (oe.vendor_id = v.id)
241 LEFT JOIN employee e ON (oe.employee_id = e.id)
242 WHERE (COALESCE(quotation, FALSE) = TRUE)
243 AND (COALESCE(closed, FALSE) = FALSE)
244 AND ((oe.employee_id = ?) OR (oe.salesman_id = ?))
245 AND NOT (oe.reqdate ISNULL)
246 AND (oe.reqdate < current_date)
249 my $quotations = selectall_hashref_query($form, $dbh, $query, $e_id, $e_id);
251 $main::lxdebug->leave_sub();
257 $main::lxdebug->enter_sub();
259 my ($self, $myconfig, $form) = @_;
261 # connect to database, turn off autocommit
262 my $dbh = $form->dbconnect_noauto($myconfig);
264 my ($query, @values, $sth, $null);
265 my $exchangerate = 0;
267 my $all_units = AM->retrieve_units($myconfig, $form);
268 $form->{all_units} = $all_units;
270 my $ic_cvar_configs = CVar->get_configs(module => 'IC',
273 $form->{employee_id} = (split /--/, $form->{employee})[1] if !$form->{employee_id};
274 unless ($form->{employee_id}) {
275 $form->get_employee($dbh);
278 my $ml = ($form->{type} eq 'sales_order') ? 1 : -1;
281 $query = qq|DELETE FROM custom_variables
282 WHERE (config_id IN (SELECT id FROM custom_variable_configs WHERE module = 'IC'))
283 AND (sub_module = 'orderitems')
284 AND (trans_id IN (SELECT id FROM orderitems WHERE trans_id = ?))|;
285 do_query($form, $dbh, $query, $form->{id});
287 $query = qq|DELETE FROM orderitems WHERE trans_id = ?|;
288 do_query($form, $dbh, $query, $form->{id});
290 $query = qq|DELETE FROM shipto | .
291 qq|WHERE trans_id = ? AND module = 'OE'|;
292 do_query($form, $dbh, $query, $form->{id});
296 $query = qq|SELECT nextval('id')|;
297 ($form->{id}) = selectrow_query($form, $dbh, $query);
299 $query = qq|INSERT INTO oe (id, ordnumber, employee_id) VALUES (?, '', ?)|;
300 do_query($form, $dbh, $query, $form->{id}, $form->{employee_id});
318 $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS');
319 my %price_factors = map { $_->{id} => $_->{factor} } @{ $form->{ALL_PRICE_FACTORS} };
322 for my $i (1 .. $form->{rowcount}) {
324 map({ $form->{"${_}_$i"} = $form->parse_amount($myconfig, $form->{"${_}_$i"}) } qw(qty ship));
326 if ($form->{"id_$i"}) {
329 $query = qq|SELECT unit FROM parts WHERE id = ?|;
330 my ($item_unit) = selectrow_query($form, $dbh, $query, $form->{"id_$i"});
333 if (defined($all_units->{$item_unit}->{factor}) &&
334 (($all_units->{$item_unit}->{factor} * 1) != 0)) {
335 $basefactor = $all_units->{$form->{"unit_$i"}}->{factor} / $all_units->{$item_unit}->{factor};
337 my $baseqty = $form->{"qty_$i"} * $basefactor;
339 $form->{"marge_percent_$i"} = $form->parse_amount($myconfig, $form->{"marge_percent_$i"}) * 1;
340 $form->{"marge_absolut_$i"} = $form->parse_amount($myconfig, $form->{"marge_absolut_$i"}) * 1;
342 $form->{"lastcost_$i"} = $form->parse_amount($myconfig, $form->{"lastcost_$i"});
344 # set values to 0 if nothing entered
345 $form->{"discount_$i"} = $form->parse_amount($myconfig, $form->{"discount_$i"}) / 100;
347 $form->{"sellprice_$i"} = $form->parse_amount($myconfig, $form->{"sellprice_$i"});
348 $fxsellprice = $form->{"sellprice_$i"};
350 my ($dec) = ($form->{"sellprice_$i"} =~ /\.(\d+)/);
352 my $decimalplaces = ($dec > 2) ? $dec : 2;
354 $discount = $form->round_amount($form->{"sellprice_$i"} * $form->{"discount_$i"}, $decimalplaces);
355 $form->{"sellprice_$i"} = $form->round_amount($form->{"sellprice_$i"} - $discount, $decimalplaces);
357 $form->{"inventory_accno_$i"} *= 1;
358 $form->{"expense_accno_$i"} *= 1;
360 $price_factor = $price_factors{ $form->{"price_factor_id_$i"} } || 1;
361 $linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"} / $price_factor, 2);
363 @taxaccounts = split(/ /, $form->{"taxaccounts_$i"});
367 map { $taxrate += $form->{"${_}_rate"} } @taxaccounts;
369 if ($form->{taxincluded}) {
370 $taxamount = $linetotal * $taxrate / (1 + $taxrate);
371 $taxbase = $linetotal - $taxamount;
373 # we are not keeping a natural price, do not round
374 $form->{"sellprice_$i"} =
375 $form->{"sellprice_$i"} * (1 / (1 + $taxrate));
377 $taxamount = $linetotal * $taxrate;
378 $taxbase = $linetotal;
381 if ($form->round_amount($taxrate, 7) == 0) {
382 if ($form->{taxincluded}) {
383 foreach my $item (@taxaccounts) {
384 $taxamount = $form->round_amount($linetotal * $form->{"${item}_rate"} / (1 + abs($form->{"${item}_rate"})), 2);
385 $taxaccounts{$item} += $taxamount;
386 $taxdiff += $taxamount;
387 $taxbase{$item} += $taxbase;
389 $taxaccounts{ $taxaccounts[0] } += $taxdiff;
391 foreach my $item (@taxaccounts) {
392 $taxaccounts{$item} += $linetotal * $form->{"${item}_rate"};
393 $taxbase{$item} += $taxbase;
397 foreach my $item (@taxaccounts) {
398 $taxaccounts{$item} += $taxamount * $form->{"${item}_rate"} / $taxrate;
399 $taxbase{$item} += $taxbase;
403 $netamount += $form->{"sellprice_$i"} * $form->{"qty_$i"} / $price_factor;
405 $reqdate = ($form->{"reqdate_$i"}) ? $form->{"reqdate_$i"} : undef;
407 # get pricegroup_id and save ist
408 ($null, my $pricegroup_id) = split(/--/, $form->{"sellprice_pg_$i"});
411 # save detail record in orderitems table
412 my $orderitems_id = $form->{"orderitems_id_$i"};
413 ($orderitems_id) = selectfirst_array_query($form, $dbh, qq|SELECT nextval('orderitemsid')|) if (!$orderitems_id);
416 $query = qq|INSERT INTO orderitems (
417 id, trans_id, parts_id, description, longdescription, qty, base_qty,
418 sellprice, discount, unit, reqdate, project_id, serialnumber, ship,
419 pricegroup_id, ordnumber, transdate, cusordnumber, subtotal,
420 marge_percent, marge_total, lastcost, price_factor_id, price_factor, marge_price_factor)
421 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
422 (SELECT factor FROM price_factors WHERE id = ?), ?)|;
424 conv_i($orderitems_id), conv_i($form->{id}), conv_i($form->{"id_$i"}),
425 $form->{"description_$i"}, $form->{"longdescription_$i"},
426 $form->{"qty_$i"}, $baseqty,
427 $fxsellprice, $form->{"discount_$i"},
428 $form->{"unit_$i"}, conv_date($reqdate), conv_i($form->{"project_id_$i"}),
429 $form->{"serialnumber_$i"}, $form->{"ship_$i"}, conv_i($pricegroup_id),
430 $form->{"ordnumber_$i"}, conv_date($form->{"transdate_$i"}),
431 $form->{"cusordnumber_$i"}, $form->{"subtotal_$i"} ? 't' : 'f',
432 $form->{"marge_percent_$i"}, $form->{"marge_absolut_$i"},
433 $form->{"lastcost_$i"},
434 conv_i($form->{"price_factor_id_$i"}), conv_i($form->{"price_factor_id_$i"}),
435 conv_i($form->{"marge_price_factor_$i"}));
436 do_query($form, $dbh, $query, @values);
438 $form->{"sellprice_$i"} = $fxsellprice;
439 $form->{"discount_$i"} *= 100;
441 CVar->save_custom_variables(module => 'IC',
442 sub_module => 'orderitems',
443 trans_id => $orderitems_id,
444 configs => $ic_cvar_configs,
446 name_prefix => 'ic_',
447 name_postfix => "_$i",
452 $reqdate = ($form->{reqdate}) ? $form->{reqdate} : undef;
456 map { $tax += $form->round_amount($taxaccounts{$_}, 2) } keys %taxaccounts;
458 $amount = $form->round_amount($netamount + $tax, 2);
459 $netamount = $form->round_amount($netamount, 2);
461 if ($form->{currency} eq $form->{defaultcurrency}) {
462 $form->{exchangerate} = 1;
464 $exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{transdate}, ($form->{vc} eq 'customer') ? 'buy' : 'sell');
467 $form->{exchangerate} = $exchangerate || $form->parse_amount($myconfig, $form->{exchangerate});
469 my $quotation = $form->{type} =~ /_order$/ ? 'f' : 't';
471 ($null, $form->{department_id}) = split(/--/, $form->{department}) if $form->{department};
476 ordnumber = ?, quonumber = ?, cusordnumber = ?, transdate = ?, vendor_id = ?,
477 customer_id = ?, amount = ?, netamount = ?, reqdate = ?, taxincluded = ?,
478 shippingpoint = ?, shipvia = ?, notes = ?, intnotes = ?, curr = ?, closed = ?,
479 delivered = ?, proforma = ?, quotation = ?, department_id = ?, language_id = ?,
480 taxzone_id = ?, shipto_id = ?, payment_id = ?, delivery_vendor_id = ?, delivery_customer_id = ?,
481 globalproject_id = ?, employee_id = ?, salesman_id = ?, cp_id = ?, transaction_description = ?, marge_total = ?, marge_percent = ?
484 @values = ($form->{ordnumber} || '', $form->{quonumber},
485 $form->{cusordnumber}, conv_date($form->{transdate}),
486 conv_i($form->{vendor_id}), conv_i($form->{customer_id}),
487 $amount, $netamount, conv_date($reqdate),
488 $form->{taxincluded} ? 't' : 'f', $form->{shippingpoint},
489 $form->{shipvia}, $form->{notes}, $form->{intnotes},
490 substr($form->{currency}, 0, 3), $form->{closed} ? 't' : 'f',
491 $form->{delivered} ? "t" : "f", $form->{proforma} ? 't' : 'f',
492 $quotation, conv_i($form->{department_id}),
493 conv_i($form->{language_id}), conv_i($form->{taxzone_id}),
494 conv_i($form->{shipto_id}), conv_i($form->{payment_id}),
495 conv_i($form->{delivery_vendor_id}),
496 conv_i($form->{delivery_customer_id}),
497 conv_i($form->{globalproject_id}), conv_i($form->{employee_id}),
498 conv_i($form->{salesman_id}), conv_i($form->{cp_id}),
499 $form->{transaction_description},
500 $form->{marge_total} * 1, $form->{marge_percent} * 1,
501 conv_i($form->{id}));
502 do_query($form, $dbh, $query, @values);
504 $form->{ordtotal} = $amount;
507 $form->{name} = $form->{ $form->{vc} };
508 $form->{name} =~ s/--\Q$form->{"$form->{vc}_id"}\E//;
510 if (!$form->{shipto_id}) {
511 $form->add_shipto($dbh, $form->{id}, "OE");
514 # save printed, emailed, queued
515 $form->save_status($dbh);
517 # Link this record to the records it was created from.
518 $form->{convert_from_oe_ids} =~ s/^\s+//;
519 $form->{convert_from_oe_ids} =~ s/\s+$//;
520 my @convert_from_oe_ids = split m/\s+/, $form->{convert_from_oe_ids};
521 delete $form->{convert_from_oe_ids};
523 if (scalar @convert_from_oe_ids) {
524 RecordLinks->create_links('dbh' => $dbh,
526 'from_table' => 'oe',
527 'from_ids' => \@convert_from_oe_ids,
529 'to_id' => $form->{id},
532 $self->_close_quotations_rfqs('dbh' => $dbh,
533 'from_id' => \@convert_from_oe_ids,
534 'to_id' => $form->{id});
537 if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
538 if ($form->{vc} eq 'customer') {
539 $form->update_exchangerate($dbh, $form->{currency}, $form->{transdate}, $form->{exchangerate}, 0);
541 if ($form->{vc} eq 'vendor') {
542 $form->update_exchangerate($dbh, $form->{currency}, $form->{transdate}, 0, $form->{exchangerate});
546 $form->{saved_xyznumber} = $form->{$form->{type} =~ /_quotation$/ ?
547 "quonumber" : "ordnumber"};
549 Common::webdav_folder($form) if ($main::webdav);
551 my $rc = $dbh->commit;
554 $main::lxdebug->leave_sub();
559 sub _close_quotations_rfqs {
560 $main::lxdebug->enter_sub();
565 Common::check_params(\%params, qw(from_id to_id));
567 my $myconfig = \%main::myconfig;
568 my $form = $main::form;
570 my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig);
572 my $query = qq|SELECT quotation FROM oe WHERE id = ?|;
573 my $sth = prepare_query($form, $dbh, $query);
575 do_statement($form, $sth, $query, conv_i($params{to_id}));
577 my ($quotation) = $sth->fetchrow_array();
580 $main::lxdebug->leave_sub();
586 foreach my $from_id (@{ $params{from_id} }) {
587 $from_id = conv_i($from_id);
588 do_statement($form, $sth, $query, $from_id);
589 ($quotation) = $sth->fetchrow_array();
590 push @close_ids, $from_id if ($quotation);
595 if (scalar @close_ids) {
596 $query = qq|UPDATE oe SET closed = TRUE WHERE id IN (| . join(', ', ('?') x scalar @close_ids) . qq|)|;
597 do_query($form, $dbh, $query, @close_ids);
599 $dbh->commit() unless ($params{dbh});
602 $main::lxdebug->leave_sub();
606 $main::lxdebug->enter_sub();
608 my ($self, $myconfig, $form, $spool) = @_;
610 # connect to database
611 my $dbh = $form->dbconnect_noauto($myconfig);
614 my $query = qq|SELECT s.spoolfile FROM status s | .
615 qq|WHERE s.trans_id = ?|;
616 my @values = (conv_i($form->{id}));
617 my $sth = $dbh->prepare($query);
618 $sth->execute(@values) || $self->dberror($query);
623 while (($spoolfile) = $sth->fetchrow_array) {
624 push @spoolfiles, $spoolfile;
629 @values = (conv_i($form->{id}));
631 # delete status entries
632 $query = qq|DELETE FROM status | .
633 qq|WHERE trans_id = ?|;
634 do_query($form, $dbh, $query, @values);
637 $query = qq|DELETE FROM oe | .
639 do_query($form, $dbh, $query, @values);
641 # delete individual entries
642 $query = qq|DELETE FROM orderitems | .
643 qq|WHERE trans_id = ?|;
644 do_query($form, $dbh, $query, @values);
646 $query = qq|DELETE FROM shipto | .
647 qq|WHERE trans_id = ? AND module = 'OE'|;
648 do_query($form, $dbh, $query, @values);
650 my $rc = $dbh->commit;
654 foreach $spoolfile (@spoolfiles) {
655 unlink "$spool/$spoolfile" if $spoolfile;
659 $main::lxdebug->leave_sub();
665 $main::lxdebug->enter_sub();
667 my ($self, $myconfig, $form) = @_;
669 # connect to database
670 my $dbh = $form->get_standard_dbh;
672 my ($query, $query_add, @values, @ids, $sth);
674 my $ic_cvar_configs = CVar->get_configs(module => 'IC',
677 # translate the ids (given by id_# and trans_id_#) into one array of ids, so we can join them later
679 push @ids, $form->{"trans_id_$_"}
680 if ($form->{"multi_id_$_"} and $form->{"trans_id_$_"})
681 } (1 .. $form->{"rowcount"});
683 if ($form->{rowcount} && scalar @ids) {
684 $form->{convert_from_oe_ids} = join ' ', @ids;
687 # if called in multi id mode, and still only got one id, switch back to single id
688 if ($form->{"rowcount"} and $#ids == 0) {
689 $form->{"id"} = $ids[0];
693 # and remember for the rest of the function
694 my $is_collective_order = scalar @ids;
697 my $wday = (localtime(time))[6];
698 my $next_workday = $wday == 5 ? 3 : $wday == 6 ? 2 : 1;
699 $query_add = qq|, current_date AS transdate, date(current_date + interval '${next_workday} days') AS reqdate|;
702 # get default accounts
703 $query = qq|SELECT (SELECT c.accno FROM chart c WHERE d.inventory_accno_id = c.id) AS inventory_accno,
704 (SELECT c.accno FROM chart c WHERE d.income_accno_id = c.id) AS income_accno,
705 (SELECT c.accno FROM chart c WHERE d.expense_accno_id = c.id) AS expense_accno,
706 (SELECT c.accno FROM chart c WHERE d.fxgain_accno_id = c.id) AS fxgain_accno,
707 (SELECT c.accno FROM chart c WHERE d.fxloss_accno_id = c.id) AS fxloss_accno,
711 my $ref = selectfirst_hashref_query($form, $dbh, $query);
712 map { $form->{$_} = $ref->{$_} } keys %$ref;
714 ($form->{currency}) = split(/:/, $form->{currencies}) unless ($form->{currency});
716 # set reqdate if this is an invoice->order conversion. If someone knows a better check to ensure
717 # we come from invoices, feel free.
718 $form->{reqdate} = $form->{deliverydate}
719 if ( $form->{deliverydate}
720 and $form->{callback} =~ /action=ar_transactions/);
722 my $vc = $form->{vc} eq "customer" ? "customer" : "vendor";
724 if ($form->{id} or @ids) {
726 # retrieve order for single id
727 # NOTE: this query is intended to fetch all information only ONCE.
728 # so if any of these infos is important (or even different) for any item,
729 # it will be killed out and then has to be fetched from the item scope query further down
731 qq|SELECT o.cp_id, o.ordnumber, o.transdate, o.reqdate,
732 o.taxincluded, o.shippingpoint, o.shipvia, o.notes, o.intnotes,
733 o.curr AS currency, e.name AS employee, o.employee_id, o.salesman_id,
734 o.${vc}_id, cv.name AS ${vc}, o.amount AS invtotal,
735 o.closed, o.reqdate, o.quonumber, o.department_id, o.cusordnumber,
736 d.description AS department, o.payment_id, o.language_id, o.taxzone_id,
737 o.delivery_customer_id, o.delivery_vendor_id, o.proforma, o.shipto_id,
738 o.globalproject_id, o.delivered, o.transaction_description
740 JOIN ${vc} cv ON (o.${vc}_id = cv.id)
741 LEFT JOIN employee e ON (o.employee_id = e.id)
742 LEFT JOIN department d ON (o.department_id = d.id) | .
745 : "WHERE o.id IN (" . join(', ', map("? ", @ids)) . ")"
747 @values = $form->{id} ? ($form->{id}) : @ids;
748 $sth = prepare_execute_query($form, $dbh, $query, @values);
750 $ref = $sth->fetchrow_hashref("NAME_lc");
751 map { $form->{$_} = $ref->{$_} } keys %$ref;
753 $form->{saved_xyznumber} = $form->{$form->{type} =~ /_quotation$/ ?
754 "quonumber" : "ordnumber"};
756 # set all entries for multiple ids blank that yield different information
757 while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
758 map { $form->{$_} = '' if ($ref->{$_} ne $form->{$_}) } keys %$ref;
761 # if not given, fill transdate with current_date
762 $form->{transdate} = $form->current_date($myconfig)
763 unless $form->{transdate};
767 if ($form->{delivery_customer_id}) {
768 $query = qq|SELECT name FROM customer WHERE id = ?|;
769 ($form->{delivery_customer_string}) = selectrow_query($form, $dbh, $query, $form->{delivery_customer_id});
772 if ($form->{delivery_vendor_id}) {
773 $query = qq|SELECT name FROM customer WHERE id = ?|;
774 ($form->{delivery_vendor_string}) = selectrow_query($form, $dbh, $query, $form->{delivery_vendor_id});
777 # shipto and pinted/mailed/queued status makes only sense for single id retrieve
779 $query = qq|SELECT s.* FROM shipto s WHERE s.trans_id = ? AND s.module = 'OE'|;
780 $sth = prepare_execute_query($form, $dbh, $query, $form->{id});
782 $ref = $sth->fetchrow_hashref("NAME_lc");
784 map { $form->{$_} = $ref->{$_} } keys %$ref;
787 # get printed, emailed and queued
788 $query = qq|SELECT s.printed, s.emailed, s.spoolfile, s.formname FROM status s WHERE s.trans_id = ?|;
789 $sth = prepare_execute_query($form, $dbh, $query, $form->{id});
791 while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
792 $form->{printed} .= "$ref->{formname} " if $ref->{printed};
793 $form->{emailed} .= "$ref->{formname} " if $ref->{emailed};
794 $form->{queued} .= "$ref->{formname} $ref->{spoolfile} " if $ref->{spoolfile};
797 map { $form->{$_} =~ s/ +$//g } qw(printed emailed queued);
800 my %oid = ('Pg' => 'oid',
801 'Oracle' => 'rowid');
803 my $transdate = $form->{transdate} ? $dbh->quote($form->{transdate}) : "current_date";
805 $form->{taxzone_id} = 0 unless ($form->{taxzone_id});
807 # retrieve individual items
808 # this query looks up all information about the items
809 # stuff different from the whole will not be overwritten, but saved with a suffix.
811 qq|SELECT o.id AS orderitems_id,
812 c1.accno AS inventory_accno, c1.new_chart_id AS inventory_new_chart, date($transdate) - c1.valid_from as inventory_valid,
813 c2.accno AS income_accno, c2.new_chart_id AS income_new_chart, date($transdate) - c2.valid_from as income_valid,
814 c3.accno AS expense_accno, c3.new_chart_id AS expense_new_chart, date($transdate) - c3.valid_from as expense_valid,
815 oe.ordnumber AS ordnumber_oe, oe.transdate AS transdate_oe, oe.cusordnumber AS cusordnumber_oe,
816 p.partnumber, p.assembly, o.description, o.qty,
817 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,
818 o.reqdate, o.project_id, o.serialnumber, o.ship, o.lastcost,
819 o.ordnumber, o.transdate, o.cusordnumber, o.subtotal, o.longdescription,
820 o.price_factor_id, o.price_factor, o.marge_price_factor,
821 pr.projectnumber, p.formel,
822 pg.partsgroup, o.pricegroup_id, (SELECT pricegroup FROM pricegroup WHERE id=o.pricegroup_id) as pricegroup
824 JOIN parts p ON (o.parts_id = p.id)
825 JOIN oe ON (o.trans_id = oe.id)
826 LEFT JOIN chart c1 ON ((SELECT inventory_accno_id FROM buchungsgruppen WHERE id=p.buchungsgruppen_id) = c1.id)
827 LEFT JOIN chart c2 ON ((SELECT income_accno_id_$form->{taxzone_id} FROM buchungsgruppen WHERE id=p.buchungsgruppen_id) = c2.id)
828 LEFT JOIN chart c3 ON ((SELECT expense_accno_id_$form->{taxzone_id} FROM buchungsgruppen WHERE id=p.buchungsgruppen_id) = c3.id)
829 LEFT JOIN project pr ON (o.project_id = pr.id)
830 LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) | .
832 ? qq|WHERE o.trans_id = ?|
833 : qq|WHERE o.trans_id IN (| . join(", ", map("?", @ids)) . qq|)|) .
834 qq|ORDER BY o.$oid{$myconfig->{dbdriver}}|;
836 @ids = $form->{id} ? ($form->{id}) : @ids;
837 $sth = prepare_execute_query($form, $dbh, $query, @values);
839 while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
840 # Retrieve custom variables.
841 my $cvars = CVar->get_custom_variables(dbh => $dbh,
843 sub_module => 'orderitems',
844 trans_id => $ref->{orderitems_id},
846 map { $ref->{"ic_cvar_$_->{name}"} = $_->{value} } @{ $cvars };
849 if (!$ref->{"part_inventory_accno_id"}) {
850 map({ delete($ref->{$_}); } qw(inventory_accno inventory_new_chart inventory_valid));
852 delete($ref->{"part_inventory_accno_id"});
854 # in collective order, copy global ordnumber, transdate, cusordnumber into item scope
855 # unless already present there
856 # remove _oe entries afterwards
857 map { $ref->{$_} = $ref->{"${_}_oe"} if ($ref->{$_} eq '') }
858 qw|ordnumber transdate cusordnumber|
860 map { delete $ref->{$_} } qw|ordnumber_oe transdate_oe cusordnumber_oe|;
864 while ($ref->{inventory_new_chart} && ($ref->{inventory_valid} >= 0)) {
866 qq|SELECT accno AS inventory_accno, | .
867 qq| new_chart_id AS inventory_new_chart, | .
868 qq| date($transdate) - valid_from AS inventory_valid | .
869 qq|FROM chart WHERE id = $ref->{inventory_new_chart}|;
870 ($ref->{inventory_accno}, $ref->{inventory_new_chart},
871 $ref->{inventory_valid}) = selectrow_query($form, $dbh, $query);
874 while ($ref->{income_new_chart} && ($ref->{income_valid} >= 0)) {
876 qq|SELECT accno AS income_accno, | .
877 qq| new_chart_id AS income_new_chart, | .
878 qq| date($transdate) - valid_from AS income_valid | .
879 qq|FROM chart WHERE id = $ref->{income_new_chart}|;
880 ($ref->{income_accno}, $ref->{income_new_chart},
881 $ref->{income_valid}) = selectrow_query($form, $dbh, $query);
884 while ($ref->{expense_new_chart} && ($ref->{expense_valid} >= 0)) {
886 qq|SELECT accno AS expense_accno, | .
887 qq| new_chart_id AS expense_new_chart, | .
888 qq| date($transdate) - valid_from AS expense_valid | .
889 qq|FROM chart WHERE id = $ref->{expense_new_chart}|;
890 ($ref->{expense_accno}, $ref->{expense_new_chart},
891 $ref->{expense_valid}) = selectrow_query($form, $dbh, $query);
894 # delete orderitems_id in collective orders, so that they get cloned no matter what
895 delete $ref->{orderitems_id} if (@ids);
897 # get tax rates and description
898 my $accno_id = ($form->{vc} eq "customer") ? $ref->{income_accno} : $ref->{expense_accno};
900 qq|SELECT c.accno, t.taxdescription, t.rate, t.taxnumber | .
901 qq|FROM tax t LEFT JOIN chart c on (c.id = t.chart_id) | .
902 qq|WHERE t.id IN (SELECT tk.tax_id FROM taxkeys tk | .
903 qq| WHERE tk.chart_id = (SELECT id FROM chart WHERE accno = ?) | .
904 qq| AND startdate <= $transdate ORDER BY startdate DESC LIMIT 1) | .
905 qq|ORDER BY c.accno|;
906 my $stw = prepare_execute_query($form, $dbh, $query, $accno_id);
907 $ref->{taxaccounts} = "";
909 while (my $ptr = $stw->fetchrow_hashref("NAME_lc")) {
910 if (($ptr->{accno} eq "") && ($ptr->{rate} == 0)) {
914 $ref->{taxaccounts} .= "$ptr->{accno} ";
915 if (!($form->{taxaccounts} =~ /\Q$ptr->{accno}\E/)) {
916 $form->{"$ptr->{accno}_rate"} = $ptr->{rate};
917 $form->{"$ptr->{accno}_description"} = $ptr->{taxdescription};
918 $form->{"$ptr->{accno}_taxnumber"} = $ptr->{taxnumber};
919 $form->{taxaccounts} .= "$ptr->{accno} ";
924 chop $ref->{taxaccounts};
926 push @{ $form->{form_details} }, $ref;
934 $form->lastname_used($dbh, $myconfig, $form->{vc})
935 unless $form->{"$form->{vc}_id"};
939 $form->{exchangerate} = $form->get_exchangerate($dbh, $form->{currency}, $form->{transdate}, ($form->{vc} eq 'customer') ? "buy" : "sell");
941 Common::webdav_folder($form) if ($main::webdav);
943 my $rc = $dbh->commit;
946 $main::lxdebug->leave_sub();
951 sub retrieve_simple {
952 $main::lxdebug->enter_sub();
957 Common::check_params(\%params, qw(id));
959 my $myconfig = \%main::myconfig;
960 my $form = $main::form;
962 my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig);
964 my $oe_query = qq|SELECT * FROM oe WHERE id = ?|;
965 my $oi_query = qq|SELECT * FROM orderitems WHERE trans_id = ?|;
967 my $order = selectfirst_hashref_query($form, $dbh, $oe_query, conv_i($params{id}));
968 $order->{orderitems} = selectall_hashref_query( $form, $dbh, $oi_query, conv_i($params{id}));
970 $main::lxdebug->leave_sub();
976 $main::lxdebug->enter_sub();
978 my ($self, $myconfig, $form) = @_;
980 # connect to database
981 my $dbh = $form->dbconnect($myconfig);
987 my $nodiscount_subtotal = 0;
988 my $discount_subtotal = 0;
994 my $subtotal_header = 0;
1002 my %oid = ('Pg' => 'oid',
1003 'Oracle' => 'rowid');
1005 my (@project_ids, %projectnumbers, %projectdescriptions);
1007 push(@project_ids, $form->{"globalproject_id"}) if ($form->{"globalproject_id"});
1009 $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS',
1010 'departments' => 'ALL_DEPARTMENTS');
1013 foreach my $pfac (@{ $form->{ALL_PRICE_FACTORS} }) {
1014 $price_factors{$pfac->{id}} = $pfac;
1015 $pfac->{factor} *= 1;
1016 $pfac->{formatted_factor} = $form->format_amount($myconfig, $pfac->{factor});
1020 foreach my $dept (@{ $form->{ALL_DEPARTMENTS} }) {
1021 next unless $dept->{id} eq $form->{department_id};
1022 $form->{department} = $dept->{description};
1026 # sort items by partsgroup
1027 for $i (1 .. $form->{rowcount}) {
1029 if ($form->{"partsgroup_$i"} && $form->{groupitems}) {
1030 $partsgroup = $form->{"partsgroup_$i"};
1032 push @partsgroup, [$i, $partsgroup];
1033 push(@project_ids, $form->{"project_id_$i"}) if ($form->{"project_id_$i"});
1037 $query = "SELECT id, projectnumber, description FROM project WHERE id IN (" .
1038 join(", ", map("?", @project_ids)) . ")";
1039 $sth = prepare_execute_query($form, $dbh, $query, @project_ids);
1040 while (my $ref = $sth->fetchrow_hashref()) {
1041 $projectnumbers{$ref->{id}} = $ref->{projectnumber};
1042 $projectdescriptions{$ref->{id}} = $ref->{description};
1047 $form->{"globalprojectnumber"} = $projectnumbers{$form->{"globalproject_id"}};
1048 $form->{"globalprojectdescription"} = $projectdescriptions{$form->{"globalproject_id"}};
1050 $form->{discount} = [];
1052 $form->{TEMPLATE_ARRAYS} = { };
1053 IC->prepare_parts_for_printing();
1055 my $ic_cvar_configs = CVar->get_configs(module => 'IC');
1058 qw(runningnumber number description longdescription qty ship unit bin
1059 partnotes serialnumber reqdate sellprice listprice netprice
1060 discount p_discount discount_sub nodiscount_sub
1061 linetotal nodiscount_linetotal tax_rate projectnumber projectdescription
1062 price_factor price_factor_name partsgroup);
1064 push @arrays, map { "ic_cvar_$_->{name}" } @{ $ic_cvar_configs };
1066 my @tax_arrays = qw(taxbase tax taxdescription taxrate taxnumber);
1068 map { $form->{TEMPLATE_ARRAYS}->{$_} = [] } (@arrays, @tax_arrays);
1071 foreach $item (sort { $a->[1] cmp $b->[1] } @partsgroup) {
1074 if ($item->[1] ne $sameitem) {
1075 push(@{ $form->{TEMPLATE_ARRAYS}->{description} }, qq|$item->[1]|);
1076 $sameitem = $item->[1];
1078 map({ push(@{ $form->{TEMPLATE_ARRAYS}->{$_} }, "") } grep({ $_ ne "description" } @arrays));
1081 $form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
1083 if ($form->{"id_$i"} != 0) {
1085 # add number, description and qty to $form->{number}, ....
1087 if ($form->{"subtotal_$i"} && !$subtotal_header) {
1088 $subtotal_header = $i;
1089 $position = int($position);
1092 } elsif ($subtotal_header) {
1094 $position = int($position);
1095 $position = $position.".".$subposition;
1097 $position = int($position);
1101 my $price_factor = $price_factors{$form->{"price_factor_id_$i"}} || { 'factor' => 1 };
1103 push @{ $form->{TEMPLATE_ARRAYS}->{runningnumber} }, $position;
1104 push @{ $form->{TEMPLATE_ARRAYS}->{number} }, $form->{"partnumber_$i"};
1105 push @{ $form->{TEMPLATE_ARRAYS}->{description} }, $form->{"description_$i"};
1106 push @{ $form->{TEMPLATE_ARRAYS}->{longdescription} }, $form->{"longdescription_$i"};
1107 push @{ $form->{TEMPLATE_ARRAYS}->{qty} }, $form->format_amount($myconfig, $form->{"qty_$i"});
1108 push @{ $form->{TEMPLATE_ARRAYS}->{ship} }, $form->format_amount($myconfig, $form->{"ship_$i"});
1109 push @{ $form->{TEMPLATE_ARRAYS}->{unit} }, $form->{"unit_$i"};
1110 push @{ $form->{TEMPLATE_ARRAYS}->{bin} }, $form->{"bin_$i"};
1111 push @{ $form->{TEMPLATE_ARRAYS}->{partnotes} }, $form->{"partnotes_$i"};
1112 push @{ $form->{TEMPLATE_ARRAYS}->{serialnumber} }, $form->{"serialnumber_$i"};
1113 push @{ $form->{TEMPLATE_ARRAYS}->{reqdate} }, $form->{"reqdate_$i"};
1114 push @{ $form->{TEMPLATE_ARRAYS}->{sellprice} }, $form->{"sellprice_$i"};
1115 push @{ $form->{TEMPLATE_ARRAYS}->{listprice} }, $form->{"listprice_$i"};
1116 push @{ $form->{TEMPLATE_ARRAYS}->{price_factor} }, $price_factor->{formatted_factor};
1117 push @{ $form->{TEMPLATE_ARRAYS}->{price_factor_name} }, $price_factor->{description};
1118 push @{ $form->{TEMPLATE_ARRAYS}->{partsgroup} }, $form->{"partsgroup_$i"};
1120 my $sellprice = $form->parse_amount($myconfig, $form->{"sellprice_$i"});
1121 my ($dec) = ($sellprice =~ /\.(\d+)/);
1122 my $decimalplaces = max 2, length($dec);
1124 my $parsed_discount = $form->parse_amount($myconfig, $form->{"discount_$i"});
1125 my $linetotal_exact = $form->{"qty_$i"} * $sellprice * (100 - $parsed_discount) / 100 / $price_factor->{factor};
1126 my $linetotal = $form->round_amount($linetotal_exact, 2);
1127 my $discount = $form->round_amount($form->{"qty_$i"} * $sellprice * $parsed_discount / 100 / $price_factor->{factor} - ($linetotal - $linetotal_exact),
1129 my $nodiscount_linetotal = $form->round_amount($form->{"qty_$i"} * $sellprice / $price_factor->{factor}, 2);
1130 $form->{"netprice_$i"} = $form->round_amount($form->{"qty_$i"} ? ($linetotal / $form->{"qty_$i"}) : 0, 2);
1132 push @{ $form->{TEMPLATE_ARRAYS}->{netprice} }, ($form->{"netprice_$i"} != 0) ? $form->format_amount($myconfig, $form->{"netprice_$i"}, $decimalplaces) : '';
1134 $linetotal = ($linetotal != 0) ? $linetotal : '';
1136 push @{ $form->{TEMPLATE_ARRAYS}->{discount} }, ($discount != 0) ? $form->format_amount($myconfig, $discount * -1, 2) : '';
1137 push @{ $form->{TEMPLATE_ARRAYS}->{p_discount} }, $form->{"discount_$i"};
1139 $form->{ordtotal} += $linetotal;
1140 $form->{nodiscount_total} += $nodiscount_linetotal;
1141 $form->{discount_total} += $discount;
1143 if ($subtotal_header) {
1144 $discount_subtotal += $linetotal;
1145 $nodiscount_subtotal += $nodiscount_linetotal;
1148 if ($form->{"subtotal_$i"} && $subtotal_header && ($subtotal_header != $i)) {
1149 push @{ $form->{TEMPLATE_ARRAYS}->{discount_sub} }, $form->format_amount($myconfig, $discount_subtotal, 2);
1150 push @{ $form->{TEMPLATE_ARRAYS}->{nodiscount_sub} }, $form->format_amount($myconfig, $nodiscount_subtotal, 2);
1152 $discount_subtotal = 0;
1153 $nodiscount_subtotal = 0;
1154 $subtotal_header = 0;
1157 push @{ $form->{TEMPLATE_ARRAYS}->{discount_sub} }, "";
1158 push @{ $form->{TEMPLATE_ARRAYS}->{nodiscount_sub} }, "";
1161 if (!$form->{"discount_$i"}) {
1162 $nodiscount += $linetotal;
1165 push @{ $form->{TEMPLATE_ARRAYS}->{linetotal} }, $form->format_amount($myconfig, $linetotal, 2);
1166 push @{ $form->{TEMPLATE_ARRAYS}->{nodiscount_linetotal} }, $form->format_amount($myconfig, $nodiscount_linetotal, 2);
1168 push(@{ $form->{TEMPLATE_ARRAYS}->{projectnumber} }, $projectnumbers{$form->{"project_id_$i"}});
1169 push(@{ $form->{TEMPLATE_ARRAYS}->{projectdescription} }, $projectdescriptions{$form->{"project_id_$i"}});
1171 my ($taxamount, $taxbase);
1174 map { $taxrate += $form->{"${_}_rate"} } split(/ /, $form->{"taxaccounts_$i"});
1176 if ($form->{taxincluded}) {
1179 $taxamount = $linetotal * $taxrate / (1 + $taxrate);
1180 $taxbase = $linetotal / (1 + $taxrate);
1182 $taxamount = $linetotal * $taxrate;
1183 $taxbase = $linetotal;
1186 if ($taxamount != 0) {
1187 foreach my $accno (split / /, $form->{"taxaccounts_$i"}) {
1188 $taxaccounts{$accno} += $taxamount * $form->{"${accno}_rate"} / $taxrate;
1189 $taxbase{$accno} += $taxbase;
1193 $tax_rate = $taxrate * 100;
1194 push(@{ $form->{TEMPLATE_ARRAYS}->{tax_rate} }, qq|$tax_rate|);
1196 if ($form->{"assembly_$i"}) {
1199 # get parts and push them onto the stack
1201 if ($form->{groupitems}) {
1202 $sortorder = qq|ORDER BY pg.partsgroup, a.$oid{$myconfig->{dbdriver}}|;
1204 $sortorder = qq|ORDER BY a.$oid{$myconfig->{dbdriver}}|;
1207 $query = qq|SELECT p.partnumber, p.description, p.unit, a.qty, | .
1208 qq|pg.partsgroup | .
1209 qq|FROM assembly a | .
1210 qq| JOIN parts p ON (a.parts_id = p.id) | .
1211 qq| LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) | .
1212 qq| WHERE a.bom = '1' | .
1213 qq| AND a.id = ? | . $sortorder;
1214 @values = ($form->{"id_$i"});
1215 $sth = $dbh->prepare($query);
1216 $sth->execute(@values) || $form->dberror($query);
1218 while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
1219 if ($form->{groupitems} && $ref->{partsgroup} ne $sameitem) {
1220 map({ push(@{ $form->{TEMPLATE_ARRAYS}->{$_} }, "") } grep({ $_ ne "description" } @arrays));
1221 $sameitem = ($ref->{partsgroup}) ? $ref->{partsgroup} : "--";
1222 push(@{ $form->{TEMPLATE_ARRAYS}->{description} }, $sameitem);
1225 push(@{ $form->{TEMPLATE_ARRAYS}->{description} }, $form->format_amount($myconfig, $ref->{qty} * $form->{"qty_$i"}) . qq|, $ref->{partnumber}, $ref->{description}|);
1226 map({ push(@{ $form->{TEMPLATE_ARRAYS}->{$_} }, "") } grep({ $_ ne "description" } @arrays));
1231 map { push @{ $form->{TEMPLATE_ARRAYS}->{"ic_cvar_$_->{name}"} }, $form->{"ic_cvar_$_->{name}_$i"} } @{ $ic_cvar_configs };
1236 foreach $item (sort keys %taxaccounts) {
1237 $tax += $taxamount = $form->round_amount($taxaccounts{$item}, 2);
1239 push(@{ $form->{TEMPLATE_ARRAYS}->{taxbase} }, $form->format_amount($myconfig, $taxbase{$item}, 2));
1240 push(@{ $form->{TEMPLATE_ARRAYS}->{tax} }, $form->format_amount($myconfig, $taxamount, 2));
1241 push(@{ $form->{TEMPLATE_ARRAYS}->{taxrate} }, $form->format_amount($myconfig, $form->{"${item}_rate"} * 100));
1242 push(@{ $form->{TEMPLATE_ARRAYS}->{taxdescription} }, $form->{"${item}_description"} . q{ } . 100 * $form->{"${item}_rate"} . q{%});
1243 push(@{ $form->{TEMPLATE_ARRAYS}->{taxnumber} }, $form->{"${item}_taxnumber"});
1246 $form->{nodiscount_subtotal} = $form->format_amount($myconfig, $form->{nodiscount_total}, 2);
1247 $form->{discount_total} = $form->format_amount($myconfig, $form->{discount_total}, 2);
1248 $form->{nodiscount} = $form->format_amount($myconfig, $nodiscount, 2);
1249 $form->{yesdiscount} = $form->format_amount($myconfig, $form->{nodiscount_total} - $nodiscount, 2);
1251 if($form->{taxincluded}) {
1252 $form->{subtotal} = $form->format_amount($myconfig, $form->{ordtotal} - $tax, 2);
1254 $form->{subtotal} = $form->format_amount($myconfig, $form->{ordtotal}, 2);
1257 $form->{ordtotal} = ($form->{taxincluded}) ? $form->{ordtotal} : $form->{ordtotal} + $tax;
1260 $form->{quototal} = $form->{ordtotal} = $form->format_amount($myconfig, $form->{ordtotal}, 2);
1262 if ($form->{type} =~ /_quotation/) {
1263 $form->set_payment_options($myconfig, $form->{quodate});
1265 $form->set_payment_options($myconfig, $form->{orddate});
1268 $form->{username} = $myconfig->{name};
1272 $main::lxdebug->leave_sub();
1275 sub project_description {
1276 $main::lxdebug->enter_sub();
1278 my ($self, $dbh, $id) = @_;
1280 my $query = qq|SELECT description FROM project WHERE id = ?|;
1281 my ($value) = selectrow_query($main::form, $dbh, $query, $id);
1283 $main::lxdebug->leave_sub();
1288 ##########################
1289 # Get data for the submitted order id
1292 sub get_order_data_by_ordnumber {
1293 $main::lxdebug->enter_sub();
1298 Common::check_params(\%params, qw(ordnumber));
1300 my $form = $main::form;
1301 my %myconfig = %main::myconfig;
1302 my $dbh = $form->get_standard_dbh();
1304 my @values = ($params{ordnumber});
1306 # We query the database for the fields we need using the submitted "ordnumber"
1308 SELECT o.payment_id, o.salesman_id, o.transdate AS orddate, o.taxzone_id, o.quonumber
1310 WHERE o.ordnumber = ?;
1313 # Do the actual query and return the results for later processing by our "frontend"
1314 my $result = selectfirst_hashref_query($form, $dbh, $query, @values);
1316 $main::lxdebug->leave_sub();
1327 OE.pm - Order entry module
1331 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>.
1337 =item retrieve_simple PARAMS
1339 simple OE retrieval by id. does not look up customer, vendor, units or any other stuff. only oe and orderitems.
1341 my $order = retrieve_simple(id => 2);