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_total_$i"} = $form->parse_amount($myconfig, $form->{"marge_total_$i"}) * 1;
341 $form->{"lastcost_$i"} = $form->{"lastcost_$i"} * 1;
343 # set values to 0 if nothing entered
344 $form->{"discount_$i"} = $form->parse_amount($myconfig, $form->{"discount_$i"}) / 100;
346 $form->{"sellprice_$i"} = $form->parse_amount($myconfig, $form->{"sellprice_$i"});
347 $fxsellprice = $form->{"sellprice_$i"};
349 my ($dec) = ($form->{"sellprice_$i"} =~ /\.(\d+)/);
351 my $decimalplaces = ($dec > 2) ? $dec : 2;
353 $discount = $form->round_amount($form->{"sellprice_$i"} * $form->{"discount_$i"}, $decimalplaces);
354 $form->{"sellprice_$i"} = $form->round_amount($form->{"sellprice_$i"} - $discount, $decimalplaces);
356 $form->{"inventory_accno_$i"} *= 1;
357 $form->{"expense_accno_$i"} *= 1;
359 $price_factor = $price_factors{ $form->{"price_factor_id_$i"} } || 1;
360 $linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"} / $price_factor, 2);
362 @taxaccounts = split(/ /, $form->{"taxaccounts_$i"});
366 map { $taxrate += $form->{"${_}_rate"} } @taxaccounts;
368 if ($form->{taxincluded}) {
369 $taxamount = $linetotal * $taxrate / (1 + $taxrate);
370 $taxbase = $linetotal - $taxamount;
372 # we are not keeping a natural price, do not round
373 $form->{"sellprice_$i"} =
374 $form->{"sellprice_$i"} * (1 / (1 + $taxrate));
376 $taxamount = $linetotal * $taxrate;
377 $taxbase = $linetotal;
380 if ($form->round_amount($taxrate, 7) == 0) {
381 if ($form->{taxincluded}) {
382 foreach my $item (@taxaccounts) {
383 $taxamount = $form->round_amount($linetotal * $form->{"${item}_rate"} / (1 + abs($form->{"${item}_rate"})), 2);
384 $taxaccounts{$item} += $taxamount;
385 $taxdiff += $taxamount;
386 $taxbase{$item} += $taxbase;
388 $taxaccounts{ $taxaccounts[0] } += $taxdiff;
390 foreach my $item (@taxaccounts) {
391 $taxaccounts{$item} += $linetotal * $form->{"${item}_rate"};
392 $taxbase{$item} += $taxbase;
396 foreach my $item (@taxaccounts) {
397 $taxaccounts{$item} += $taxamount * $form->{"${item}_rate"} / $taxrate;
398 $taxbase{$item} += $taxbase;
402 $netamount += $form->{"sellprice_$i"} * $form->{"qty_$i"} / $price_factor;
404 $reqdate = ($form->{"reqdate_$i"}) ? $form->{"reqdate_$i"} : undef;
406 # get pricegroup_id and save ist
407 ($null, my $pricegroup_id) = split(/--/, $form->{"sellprice_pg_$i"});
410 # save detail record in orderitems table
411 my $orderitems_id = $form->{"orderitems_id_$i"};
412 ($orderitems_id) = selectfirst_array_query($form, $dbh, qq|SELECT nextval('orderitemsid')|) if (!$orderitems_id);
415 $query = qq|INSERT INTO orderitems (
416 id, trans_id, parts_id, description, longdescription, qty, base_qty,
417 sellprice, discount, unit, reqdate, project_id, serialnumber, ship,
418 pricegroup_id, ordnumber, transdate, cusordnumber, subtotal,
419 marge_percent, marge_total, lastcost, price_factor_id, price_factor, marge_price_factor)
420 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
421 (SELECT factor FROM price_factors WHERE id = ?), ?)|;
423 conv_i($orderitems_id), conv_i($form->{id}), conv_i($form->{"id_$i"}),
424 $form->{"description_$i"}, $form->{"longdescription_$i"},
425 $form->{"qty_$i"}, $baseqty,
426 $fxsellprice, $form->{"discount_$i"},
427 $form->{"unit_$i"}, conv_date($reqdate), conv_i($form->{"project_id_$i"}),
428 $form->{"serialnumber_$i"}, $form->{"ship_$i"}, conv_i($pricegroup_id),
429 $form->{"ordnumber_$i"}, conv_date($form->{"transdate_$i"}),
430 $form->{"cusordnumber_$i"}, $form->{"subtotal_$i"} ? 't' : 'f',
431 $form->{"marge_percent_$i"}, $form->{"marge_total_$i"},
432 $form->{"lastcost_$i"},
433 conv_i($form->{"price_factor_id_$i"}), conv_i($form->{"price_factor_id_$i"}),
434 conv_i($form->{"marge_price_factor_$i"}));
435 do_query($form, $dbh, $query, @values);
437 $form->{"sellprice_$i"} = $fxsellprice;
438 $form->{"discount_$i"} *= 100;
440 CVar->save_custom_variables(module => 'IC',
441 sub_module => 'orderitems',
442 trans_id => $orderitems_id,
443 configs => $ic_cvar_configs,
445 name_prefix => 'ic_',
446 name_postfix => "_$i",
451 $reqdate = ($form->{reqdate}) ? $form->{reqdate} : undef;
455 map { $tax += $form->round_amount($taxaccounts{$_}, 2) } keys %taxaccounts;
457 $amount = $form->round_amount($netamount + $tax, 2);
458 $netamount = $form->round_amount($netamount, 2);
460 if ($form->{currency} eq $form->{defaultcurrency}) {
461 $form->{exchangerate} = 1;
463 $exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{transdate}, ($form->{vc} eq 'customer') ? 'buy' : 'sell');
466 $form->{exchangerate} = $exchangerate || $form->parse_amount($myconfig, $form->{exchangerate});
468 my $quotation = $form->{type} =~ /_order$/ ? 'f' : 't';
470 ($null, $form->{department_id}) = split(/--/, $form->{department}) if $form->{department};
475 ordnumber = ?, quonumber = ?, cusordnumber = ?, transdate = ?, vendor_id = ?,
476 customer_id = ?, amount = ?, netamount = ?, reqdate = ?, taxincluded = ?,
477 shippingpoint = ?, shipvia = ?, notes = ?, intnotes = ?, curr = ?, closed = ?,
478 delivered = ?, proforma = ?, quotation = ?, department_id = ?, language_id = ?,
479 taxzone_id = ?, shipto_id = ?, payment_id = ?, delivery_vendor_id = ?, delivery_customer_id = ?,
480 globalproject_id = ?, employee_id = ?, salesman_id = ?, cp_id = ?, transaction_description = ?, marge_total = ?, marge_percent = ?
483 @values = ($form->{ordnumber} || '', $form->{quonumber},
484 $form->{cusordnumber}, conv_date($form->{transdate}),
485 conv_i($form->{vendor_id}), conv_i($form->{customer_id}),
486 $amount, $netamount, conv_date($reqdate),
487 $form->{taxincluded} ? 't' : 'f', $form->{shippingpoint},
488 $form->{shipvia}, $form->{notes}, $form->{intnotes},
489 substr($form->{currency}, 0, 3), $form->{closed} ? 't' : 'f',
490 $form->{delivered} ? "t" : "f", $form->{proforma} ? 't' : 'f',
491 $quotation, conv_i($form->{department_id}),
492 conv_i($form->{language_id}), conv_i($form->{taxzone_id}),
493 conv_i($form->{shipto_id}), conv_i($form->{payment_id}),
494 conv_i($form->{delivery_vendor_id}),
495 conv_i($form->{delivery_customer_id}),
496 conv_i($form->{globalproject_id}), conv_i($form->{employee_id}),
497 conv_i($form->{salesman_id}), conv_i($form->{cp_id}),
498 $form->{transaction_description},
499 $form->{marge_total} * 1, $form->{marge_percent} * 1,
500 conv_i($form->{id}));
501 do_query($form, $dbh, $query, @values);
503 $form->{ordtotal} = $amount;
506 $form->{name} = $form->{ $form->{vc} };
507 $form->{name} =~ s/--\Q$form->{"$form->{vc}_id"}\E//;
509 if (!$form->{shipto_id}) {
510 $form->add_shipto($dbh, $form->{id}, "OE");
513 # save printed, emailed, queued
514 $form->save_status($dbh);
516 # Link this record to the records it was created from.
517 $form->{convert_from_oe_ids} =~ s/^\s+//;
518 $form->{convert_from_oe_ids} =~ s/\s+$//;
519 my @convert_from_oe_ids = split m/\s+/, $form->{convert_from_oe_ids};
520 delete $form->{convert_from_oe_ids};
522 if (scalar @convert_from_oe_ids) {
523 RecordLinks->create_links('dbh' => $dbh,
525 'from_table' => 'oe',
526 'from_ids' => \@convert_from_oe_ids,
528 'to_id' => $form->{id},
531 $self->_close_quotations_rfqs('dbh' => $dbh,
532 'from_id' => \@convert_from_oe_ids,
533 'to_id' => $form->{id});
536 if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
537 if ($form->{vc} eq 'customer') {
538 $form->update_exchangerate($dbh, $form->{currency}, $form->{transdate}, $form->{exchangerate}, 0);
540 if ($form->{vc} eq 'vendor') {
541 $form->update_exchangerate($dbh, $form->{currency}, $form->{transdate}, 0, $form->{exchangerate});
545 $form->{saved_xyznumber} = $form->{$form->{type} =~ /_quotation$/ ?
546 "quonumber" : "ordnumber"};
548 Common::webdav_folder($form) if ($main::webdav);
550 my $rc = $dbh->commit;
553 $main::lxdebug->leave_sub();
558 sub _close_quotations_rfqs {
559 $main::lxdebug->enter_sub();
564 Common::check_params(\%params, qw(from_id to_id));
566 my $myconfig = \%main::myconfig;
567 my $form = $main::form;
569 my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig);
571 my $query = qq|SELECT quotation FROM oe WHERE id = ?|;
572 my $sth = prepare_query($form, $dbh, $query);
574 do_statement($form, $sth, $query, conv_i($params{to_id}));
576 my ($quotation) = $sth->fetchrow_array();
579 $main::lxdebug->leave_sub();
585 foreach my $from_id (@{ $params{from_id} }) {
586 $from_id = conv_i($from_id);
587 do_statement($form, $sth, $query, $from_id);
588 ($quotation) = $sth->fetchrow_array();
589 push @close_ids, $from_id if ($quotation);
594 if (scalar @close_ids) {
595 $query = qq|UPDATE oe SET closed = TRUE WHERE id IN (| . join(', ', ('?') x scalar @close_ids) . qq|)|;
596 do_query($form, $dbh, $query, @close_ids);
598 $dbh->commit() unless ($params{dbh});
601 $main::lxdebug->leave_sub();
605 $main::lxdebug->enter_sub();
607 my ($self, $myconfig, $form, $spool) = @_;
609 # connect to database
610 my $dbh = $form->dbconnect_noauto($myconfig);
613 my $query = qq|SELECT s.spoolfile FROM status s | .
614 qq|WHERE s.trans_id = ?|;
615 my @values = (conv_i($form->{id}));
616 my $sth = $dbh->prepare($query);
617 $sth->execute(@values) || $self->dberror($query);
622 while (($spoolfile) = $sth->fetchrow_array) {
623 push @spoolfiles, $spoolfile;
628 @values = (conv_i($form->{id}));
630 # delete status entries
631 $query = qq|DELETE FROM status | .
632 qq|WHERE trans_id = ?|;
633 do_query($form, $dbh, $query, @values);
636 $query = qq|DELETE FROM oe | .
638 do_query($form, $dbh, $query, @values);
640 # delete individual entries
641 $query = qq|DELETE FROM orderitems | .
642 qq|WHERE trans_id = ?|;
643 do_query($form, $dbh, $query, @values);
645 $query = qq|DELETE FROM shipto | .
646 qq|WHERE trans_id = ? AND module = 'OE'|;
647 do_query($form, $dbh, $query, @values);
649 my $rc = $dbh->commit;
653 foreach $spoolfile (@spoolfiles) {
654 unlink "$spool/$spoolfile" if $spoolfile;
658 $main::lxdebug->leave_sub();
664 $main::lxdebug->enter_sub();
666 my ($self, $myconfig, $form) = @_;
668 # connect to database
669 my $dbh = $form->dbconnect_noauto($myconfig);
671 my ($query, $query_add, @values, @ids, $sth);
673 my $ic_cvar_configs = CVar->get_configs(module => 'IC',
676 # translate the ids (given by id_# and trans_id_#) into one array of ids, so we can join them later
678 push @ids, $form->{"trans_id_$_"}
679 if ($form->{"multi_id_$_"} and $form->{"trans_id_$_"})
680 } (1 .. $form->{"rowcount"});
682 if ($form->{rowcount} && scalar @ids) {
683 $form->{convert_from_oe_ids} = join ' ', @ids;
686 # if called in multi id mode, and still only got one id, switch back to single id
687 if ($form->{"rowcount"} and $#ids == 0) {
688 $form->{"id"} = $ids[0];
692 # and remember for the rest of the function
693 my $is_collective_order = scalar @ids;
696 my $wday = (localtime(time))[6];
697 my $next_workday = $wday == 5 ? 3 : $wday == 6 ? 2 : 1;
698 $query_add = qq|, current_date AS transdate, date(current_date + interval '${next_workday} days') AS reqdate|;
701 # get default accounts
702 $query = qq|SELECT (SELECT c.accno FROM chart c WHERE d.inventory_accno_id = c.id) AS inventory_accno,
703 (SELECT c.accno FROM chart c WHERE d.income_accno_id = c.id) AS income_accno,
704 (SELECT c.accno FROM chart c WHERE d.expense_accno_id = c.id) AS expense_accno,
705 (SELECT c.accno FROM chart c WHERE d.fxgain_accno_id = c.id) AS fxgain_accno,
706 (SELECT c.accno FROM chart c WHERE d.fxloss_accno_id = c.id) AS fxloss_accno,
710 my $ref = selectfirst_hashref_query($form, $dbh, $query);
711 map { $form->{$_} = $ref->{$_} } keys %$ref;
713 ($form->{currency}) = split(/:/, $form->{currencies}) unless ($form->{currency});
715 # set reqdate if this is an invoice->order conversion. If someone knows a better check to ensure
716 # we come from invoices, feel free.
717 $form->{reqdate} = $form->{deliverydate}
718 if ( $form->{deliverydate}
719 and $form->{callback} =~ /action=ar_transactions/);
721 my $vc = $form->{vc} eq "customer" ? "customer" : "vendor";
723 if ($form->{id} or @ids) {
725 # retrieve order for single id
726 # NOTE: this query is intended to fetch all information only ONCE.
727 # so if any of these infos is important (or even different) for any item,
728 # it will be killed out and then has to be fetched from the item scope query further down
730 qq|SELECT o.cp_id, o.ordnumber, o.transdate, o.reqdate,
731 o.taxincluded, o.shippingpoint, o.shipvia, o.notes, o.intnotes,
732 o.curr AS currency, e.name AS employee, o.employee_id, o.salesman_id,
733 o.${vc}_id, cv.name AS ${vc}, o.amount AS invtotal,
734 o.closed, o.reqdate, o.quonumber, o.department_id, o.cusordnumber,
735 d.description AS department, o.payment_id, o.language_id, o.taxzone_id,
736 o.delivery_customer_id, o.delivery_vendor_id, o.proforma, o.shipto_id,
737 o.globalproject_id, o.delivered, o.transaction_description
739 JOIN ${vc} cv ON (o.${vc}_id = cv.id)
740 LEFT JOIN employee e ON (o.employee_id = e.id)
741 LEFT JOIN department d ON (o.department_id = d.id) | .
744 : "WHERE o.id IN (" . join(', ', map("? ", @ids)) . ")"
746 @values = $form->{id} ? ($form->{id}) : @ids;
747 $sth = prepare_execute_query($form, $dbh, $query, @values);
749 $ref = $sth->fetchrow_hashref("NAME_lc");
750 map { $form->{$_} = $ref->{$_} } keys %$ref;
752 $form->{saved_xyznumber} = $form->{$form->{type} =~ /_quotation$/ ?
753 "quonumber" : "ordnumber"};
755 # set all entries for multiple ids blank that yield different information
756 while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
757 map { $form->{$_} = '' if ($ref->{$_} ne $form->{$_}) } keys %$ref;
760 # if not given, fill transdate with current_date
761 $form->{transdate} = $form->current_date($myconfig)
762 unless $form->{transdate};
766 if ($form->{delivery_customer_id}) {
767 $query = qq|SELECT name FROM customer WHERE id = ?|;
768 ($form->{delivery_customer_string}) = selectrow_query($form, $dbh, $query, $form->{delivery_customer_id});
771 if ($form->{delivery_vendor_id}) {
772 $query = qq|SELECT name FROM customer WHERE id = ?|;
773 ($form->{delivery_vendor_string}) = selectrow_query($form, $dbh, $query, $form->{delivery_vendor_id});
776 # shipto and pinted/mailed/queued status makes only sense for single id retrieve
778 $query = qq|SELECT s.* FROM shipto s WHERE s.trans_id = ? AND s.module = 'OE'|;
779 $sth = prepare_execute_query($form, $dbh, $query, $form->{id});
781 $ref = $sth->fetchrow_hashref("NAME_lc");
783 map { $form->{$_} = $ref->{$_} } keys %$ref;
786 # get printed, emailed and queued
787 $query = qq|SELECT s.printed, s.emailed, s.spoolfile, s.formname FROM status s WHERE s.trans_id = ?|;
788 $sth = prepare_execute_query($form, $dbh, $query, $form->{id});
790 while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
791 $form->{printed} .= "$ref->{formname} " if $ref->{printed};
792 $form->{emailed} .= "$ref->{formname} " if $ref->{emailed};
793 $form->{queued} .= "$ref->{formname} $ref->{spoolfile} " if $ref->{spoolfile};
796 map { $form->{$_} =~ s/ +$//g } qw(printed emailed queued);
799 my %oid = ('Pg' => 'oid',
800 'Oracle' => 'rowid');
802 my $transdate = $form->{transdate} ? $dbh->quote($form->{transdate}) : "current_date";
804 $form->{taxzone_id} = 0 unless ($form->{taxzone_id});
806 # retrieve individual items
807 # this query looks up all information about the items
808 # stuff different from the whole will not be overwritten, but saved with a suffix.
810 qq|SELECT o.id AS orderitems_id,
811 c1.accno AS inventory_accno, c1.new_chart_id AS inventory_new_chart, date($transdate) - c1.valid_from as inventory_valid,
812 c2.accno AS income_accno, c2.new_chart_id AS income_new_chart, date($transdate) - c2.valid_from as income_valid,
813 c3.accno AS expense_accno, c3.new_chart_id AS expense_new_chart, date($transdate) - c3.valid_from as expense_valid,
814 oe.ordnumber AS ordnumber_oe, oe.transdate AS transdate_oe, oe.cusordnumber AS cusordnumber_oe,
815 p.partnumber, p.assembly, o.description, o.qty,
816 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,
817 o.reqdate, o.project_id, o.serialnumber, o.ship, o.lastcost,
818 o.ordnumber, o.transdate, o.cusordnumber, o.subtotal, o.longdescription,
819 o.price_factor_id, o.price_factor, o.marge_price_factor,
820 pr.projectnumber, p.formel,
821 pg.partsgroup, o.pricegroup_id, (SELECT pricegroup FROM pricegroup WHERE id=o.pricegroup_id) as pricegroup
823 JOIN parts p ON (o.parts_id = p.id)
824 JOIN oe ON (o.trans_id = oe.id)
825 LEFT JOIN chart c1 ON ((SELECT inventory_accno_id FROM buchungsgruppen WHERE id=p.buchungsgruppen_id) = c1.id)
826 LEFT JOIN chart c2 ON ((SELECT income_accno_id_$form->{taxzone_id} FROM buchungsgruppen WHERE id=p.buchungsgruppen_id) = c2.id)
827 LEFT JOIN chart c3 ON ((SELECT expense_accno_id_$form->{taxzone_id} FROM buchungsgruppen WHERE id=p.buchungsgruppen_id) = c3.id)
828 LEFT JOIN project pr ON (o.project_id = pr.id)
829 LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) | .
831 ? qq|WHERE o.trans_id = ?|
832 : qq|WHERE o.trans_id IN (| . join(", ", map("?", @ids)) . qq|)|) .
833 qq|ORDER BY o.$oid{$myconfig->{dbdriver}}|;
835 @ids = $form->{id} ? ($form->{id}) : @ids;
836 $sth = prepare_execute_query($form, $dbh, $query, @values);
838 while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
839 # Retrieve custom variables.
840 my $cvars = CVar->get_custom_variables(dbh => $dbh,
842 sub_module => 'orderitems',
843 trans_id => $ref->{orderitems_id},
845 map { $ref->{"ic_cvar_$_->{name}"} = $_->{value} } @{ $cvars };
848 if (!$ref->{"part_inventory_accno_id"}) {
849 map({ delete($ref->{$_}); } qw(inventory_accno inventory_new_chart inventory_valid));
851 delete($ref->{"part_inventory_accno_id"});
853 # in collective order, copy global ordnumber, transdate, cusordnumber into item scope
854 # unless already present there
855 # remove _oe entries afterwards
856 map { $ref->{$_} = $ref->{"${_}_oe"} if ($ref->{$_} eq '') }
857 qw|ordnumber transdate cusordnumber|
859 map { delete $ref->{$_} } qw|ordnumber_oe transdate_oe cusordnumber_oe|;
863 while ($ref->{inventory_new_chart} && ($ref->{inventory_valid} >= 0)) {
865 qq|SELECT accno AS inventory_accno, | .
866 qq| new_chart_id AS inventory_new_chart, | .
867 qq| date($transdate) - valid_from AS inventory_valid | .
868 qq|FROM chart WHERE id = $ref->{inventory_new_chart}|;
869 ($ref->{inventory_accno}, $ref->{inventory_new_chart},
870 $ref->{inventory_valid}) = selectrow_query($form, $dbh, $query);
873 while ($ref->{income_new_chart} && ($ref->{income_valid} >= 0)) {
875 qq|SELECT accno AS income_accno, | .
876 qq| new_chart_id AS income_new_chart, | .
877 qq| date($transdate) - valid_from AS income_valid | .
878 qq|FROM chart WHERE id = $ref->{income_new_chart}|;
879 ($ref->{income_accno}, $ref->{income_new_chart},
880 $ref->{income_valid}) = selectrow_query($form, $dbh, $query);
883 while ($ref->{expense_new_chart} && ($ref->{expense_valid} >= 0)) {
885 qq|SELECT accno AS expense_accno, | .
886 qq| new_chart_id AS expense_new_chart, | .
887 qq| date($transdate) - valid_from AS expense_valid | .
888 qq|FROM chart WHERE id = $ref->{expense_new_chart}|;
889 ($ref->{expense_accno}, $ref->{expense_new_chart},
890 $ref->{expense_valid}) = selectrow_query($form, $dbh, $query);
893 # delete orderitems_id in collective orders, so that they get cloned no matter what
894 delete $ref->{orderitems_id} if (@ids);
896 # get tax rates and description
897 my $accno_id = ($form->{vc} eq "customer") ? $ref->{income_accno} : $ref->{expense_accno};
899 qq|SELECT c.accno, t.taxdescription, t.rate, t.taxnumber | .
900 qq|FROM tax t LEFT JOIN chart c on (c.id = t.chart_id) | .
901 qq|WHERE t.id IN (SELECT tk.tax_id FROM taxkeys tk | .
902 qq| WHERE tk.chart_id = (SELECT id FROM chart WHERE accno = ?) | .
903 qq| AND startdate <= $transdate ORDER BY startdate DESC LIMIT 1) | .
904 qq|ORDER BY c.accno|;
905 my $stw = prepare_execute_query($form, $dbh, $query, $accno_id);
906 $ref->{taxaccounts} = "";
908 while (my $ptr = $stw->fetchrow_hashref("NAME_lc")) {
909 if (($ptr->{accno} eq "") && ($ptr->{rate} == 0)) {
913 $ref->{taxaccounts} .= "$ptr->{accno} ";
914 if (!($form->{taxaccounts} =~ /\Q$ptr->{accno}\E/)) {
915 $form->{"$ptr->{accno}_rate"} = $ptr->{rate};
916 $form->{"$ptr->{accno}_description"} = $ptr->{taxdescription};
917 $form->{"$ptr->{accno}_taxnumber"} = $ptr->{taxnumber};
918 $form->{taxaccounts} .= "$ptr->{accno} ";
923 chop $ref->{taxaccounts};
925 push @{ $form->{form_details} }, $ref;
933 $form->lastname_used($dbh, $myconfig, $form->{vc})
934 unless $form->{"$form->{vc}_id"};
938 $form->{exchangerate} = $form->get_exchangerate($dbh, $form->{currency}, $form->{transdate}, ($form->{vc} eq 'customer') ? "buy" : "sell");
940 Common::webdav_folder($form) if ($main::webdav);
942 my $rc = $dbh->commit;
945 $main::lxdebug->leave_sub();
950 sub retrieve_simple {
951 $main::lxdebug->enter_sub();
956 Common::check_params(\%params, qw(id));
958 my $myconfig = \%main::myconfig;
959 my $form = $main::form;
961 my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig);
963 my $oe_query = qq|SELECT * FROM oe WHERE id = ?|;
964 my $oi_query = qq|SELECT * FROM orderitems WHERE trans_id = ?|;
966 my $order = selectfirst_hashref_query($form, $dbh, $oe_query, conv_i($params{id}));
967 $order->{orderitems} = selectall_hashref_query( $form, $dbh, $oi_query, conv_i($params{id}));
969 $main::lxdebug->leave_sub();
975 $main::lxdebug->enter_sub();
977 my ($self, $myconfig, $form) = @_;
979 # connect to database
980 my $dbh = $form->dbconnect($myconfig);
986 my $nodiscount_subtotal = 0;
987 my $discount_subtotal = 0;
993 my $subtotal_header = 0;
1001 my %oid = ('Pg' => 'oid',
1002 'Oracle' => 'rowid');
1004 my (@project_ids, %projectnumbers, %projectdescriptions);
1006 push(@project_ids, $form->{"globalproject_id"}) if ($form->{"globalproject_id"});
1008 $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS',
1009 'departments' => 'ALL_DEPARTMENTS');
1012 foreach my $pfac (@{ $form->{ALL_PRICE_FACTORS} }) {
1013 $price_factors{$pfac->{id}} = $pfac;
1014 $pfac->{factor} *= 1;
1015 $pfac->{formatted_factor} = $form->format_amount($myconfig, $pfac->{factor});
1019 foreach my $dept (@{ $form->{ALL_DEPARTMENTS} }) {
1020 next unless $dept->{id} eq $form->{department_id};
1021 $form->{department} = $dept->{description};
1025 # sort items by partsgroup
1026 for $i (1 .. $form->{rowcount}) {
1028 if ($form->{"partsgroup_$i"} && $form->{groupitems}) {
1029 $partsgroup = $form->{"partsgroup_$i"};
1031 push @partsgroup, [$i, $partsgroup];
1032 push(@project_ids, $form->{"project_id_$i"}) if ($form->{"project_id_$i"});
1036 $query = "SELECT id, projectnumber, description FROM project WHERE id IN (" .
1037 join(", ", map("?", @project_ids)) . ")";
1038 $sth = prepare_execute_query($form, $dbh, $query, @project_ids);
1039 while (my $ref = $sth->fetchrow_hashref()) {
1040 $projectnumbers{$ref->{id}} = $ref->{projectnumber};
1041 $projectdescriptions{$ref->{id}} = $ref->{description};
1046 $form->{"globalprojectnumber"} = $projectnumbers{$form->{"globalproject_id"}};
1047 $form->{"globalprojectdescription"} = $projectdescriptions{$form->{"globalproject_id"}};
1049 $form->{discount} = [];
1051 $form->{TEMPLATE_ARRAYS} = { };
1052 IC->prepare_parts_for_printing();
1054 my $ic_cvar_configs = CVar->get_configs(module => 'IC');
1057 qw(runningnumber number description longdescription qty ship unit bin
1058 partnotes serialnumber reqdate sellprice listprice netprice
1059 discount p_discount discount_sub nodiscount_sub
1060 linetotal nodiscount_linetotal tax_rate projectnumber projectdescription
1061 price_factor price_factor_name partsgroup);
1063 push @arrays, map { "ic_cvar_$_->{name}" } @{ $ic_cvar_configs };
1065 my @tax_arrays = qw(taxbase tax taxdescription taxrate taxnumber);
1067 map { $form->{TEMPLATE_ARRAYS}->{$_} = [] } (@arrays, @tax_arrays);
1070 foreach $item (sort { $a->[1] cmp $b->[1] } @partsgroup) {
1073 if ($item->[1] ne $sameitem) {
1074 push(@{ $form->{TEMPLATE_ARRAYS}->{description} }, qq|$item->[1]|);
1075 $sameitem = $item->[1];
1077 map({ push(@{ $form->{TEMPLATE_ARRAYS}->{$_} }, "") } grep({ $_ ne "description" } @arrays));
1080 $form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
1082 if ($form->{"id_$i"} != 0) {
1084 # add number, description and qty to $form->{number}, ....
1086 if ($form->{"subtotal_$i"} && !$subtotal_header) {
1087 $subtotal_header = $i;
1088 $position = int($position);
1091 } elsif ($subtotal_header) {
1093 $position = int($position);
1094 $position = $position.".".$subposition;
1096 $position = int($position);
1100 my $price_factor = $price_factors{$form->{"price_factor_id_$i"}} || { 'factor' => 1 };
1102 push @{ $form->{TEMPLATE_ARRAYS}->{runningnumber} }, $position;
1103 push @{ $form->{TEMPLATE_ARRAYS}->{number} }, $form->{"partnumber_$i"};
1104 push @{ $form->{TEMPLATE_ARRAYS}->{description} }, $form->{"description_$i"};
1105 push @{ $form->{TEMPLATE_ARRAYS}->{longdescription} }, $form->{"longdescription_$i"};
1106 push @{ $form->{TEMPLATE_ARRAYS}->{qty} }, $form->format_amount($myconfig, $form->{"qty_$i"});
1107 push @{ $form->{TEMPLATE_ARRAYS}->{ship} }, $form->format_amount($myconfig, $form->{"ship_$i"});
1108 push @{ $form->{TEMPLATE_ARRAYS}->{unit} }, $form->{"unit_$i"};
1109 push @{ $form->{TEMPLATE_ARRAYS}->{bin} }, $form->{"bin_$i"};
1110 push @{ $form->{TEMPLATE_ARRAYS}->{partnotes} }, $form->{"partnotes_$i"};
1111 push @{ $form->{TEMPLATE_ARRAYS}->{serialnumber} }, $form->{"serialnumber_$i"};
1112 push @{ $form->{TEMPLATE_ARRAYS}->{reqdate} }, $form->{"reqdate_$i"};
1113 push @{ $form->{TEMPLATE_ARRAYS}->{sellprice} }, $form->{"sellprice_$i"};
1114 push @{ $form->{TEMPLATE_ARRAYS}->{listprice} }, $form->{"listprice_$i"};
1115 push @{ $form->{TEMPLATE_ARRAYS}->{price_factor} }, $price_factor->{formatted_factor};
1116 push @{ $form->{TEMPLATE_ARRAYS}->{price_factor_name} }, $price_factor->{description};
1117 push @{ $form->{TEMPLATE_ARRAYS}->{partsgroup} }, $form->{"partsgroup_$i"};
1119 my $sellprice = $form->parse_amount($myconfig, $form->{"sellprice_$i"});
1120 my ($dec) = ($sellprice =~ /\.(\d+)/);
1121 my $decimalplaces = max 2, length($dec);
1123 my $parsed_discount = $form->parse_amount($myconfig, $form->{"discount_$i"});
1124 my $linetotal_exact = $form->{"qty_$i"} * $sellprice * (100 - $parsed_discount) / 100 / $price_factor->{factor};
1125 my $linetotal = $form->round_amount($linetotal_exact, 2);
1126 my $discount = $form->round_amount($form->{"qty_$i"} * $sellprice * $parsed_discount / 100 / $price_factor->{factor} - ($linetotal - $linetotal_exact),
1128 my $nodiscount_linetotal = $form->round_amount($form->{"qty_$i"} * $sellprice / $price_factor->{factor}, 2);
1129 $form->{"netprice_$i"} = $form->round_amount($form->{"qty_$i"} ? ($linetotal / $form->{"qty_$i"}) : 0, 2);
1131 push @{ $form->{TEMPLATE_ARRAYS}->{netprice} }, ($form->{"netprice_$i"} != 0) ? $form->format_amount($myconfig, $form->{"netprice_$i"}, $decimalplaces) : '';
1133 $linetotal = ($linetotal != 0) ? $linetotal : '';
1135 push @{ $form->{TEMPLATE_ARRAYS}->{discount} }, ($discount != 0) ? $form->format_amount($myconfig, $discount * -1, 2) : '';
1136 push @{ $form->{TEMPLATE_ARRAYS}->{p_discount} }, $form->{"discount_$i"};
1138 $form->{ordtotal} += $linetotal;
1139 $form->{nodiscount_total} += $nodiscount_linetotal;
1140 $form->{discount_total} += $discount;
1142 if ($subtotal_header) {
1143 $discount_subtotal += $linetotal;
1144 $nodiscount_subtotal += $nodiscount_linetotal;
1147 if ($form->{"subtotal_$i"} && $subtotal_header && ($subtotal_header != $i)) {
1148 push @{ $form->{TEMPLATE_ARRAYS}->{discount_sub} }, $form->format_amount($myconfig, $discount_subtotal, 2);
1149 push @{ $form->{TEMPLATE_ARRAYS}->{nodiscount_sub} }, $form->format_amount($myconfig, $nodiscount_subtotal, 2);
1151 $discount_subtotal = 0;
1152 $nodiscount_subtotal = 0;
1153 $subtotal_header = 0;
1156 push @{ $form->{TEMPLATE_ARRAYS}->{discount_sub} }, "";
1157 push @{ $form->{TEMPLATE_ARRAYS}->{nodiscount_sub} }, "";
1160 if (!$form->{"discount_$i"}) {
1161 $nodiscount += $linetotal;
1164 push @{ $form->{TEMPLATE_ARRAYS}->{linetotal} }, $form->format_amount($myconfig, $linetotal, 2);
1165 push @{ $form->{TEMPLATE_ARRAYS}->{nodiscount_linetotal} }, $form->format_amount($myconfig, $nodiscount_linetotal, 2);
1167 push(@{ $form->{TEMPLATE_ARRAYS}->{projectnumber} }, $projectnumbers{$form->{"project_id_$i"}});
1168 push(@{ $form->{TEMPLATE_ARRAYS}->{projectdescription} }, $projectdescriptions{$form->{"project_id_$i"}});
1170 my ($taxamount, $taxbase);
1173 map { $taxrate += $form->{"${_}_rate"} } split(/ /, $form->{"taxaccounts_$i"});
1175 if ($form->{taxincluded}) {
1178 $taxamount = $linetotal * $taxrate / (1 + $taxrate);
1179 $taxbase = $linetotal / (1 + $taxrate);
1181 $taxamount = $linetotal * $taxrate;
1182 $taxbase = $linetotal;
1185 if ($taxamount != 0) {
1186 foreach my $accno (split / /, $form->{"taxaccounts_$i"}) {
1187 $taxaccounts{$accno} += $taxamount * $form->{"${accno}_rate"} / $taxrate;
1188 $taxbase{$accno} += $taxbase;
1192 $tax_rate = $taxrate * 100;
1193 push(@{ $form->{TEMPLATE_ARRAYS}->{tax_rate} }, qq|$tax_rate|);
1195 if ($form->{"assembly_$i"}) {
1198 # get parts and push them onto the stack
1200 if ($form->{groupitems}) {
1201 $sortorder = qq|ORDER BY pg.partsgroup, a.$oid{$myconfig->{dbdriver}}|;
1203 $sortorder = qq|ORDER BY a.$oid{$myconfig->{dbdriver}}|;
1206 $query = qq|SELECT p.partnumber, p.description, p.unit, a.qty, | .
1207 qq|pg.partsgroup | .
1208 qq|FROM assembly a | .
1209 qq| JOIN parts p ON (a.parts_id = p.id) | .
1210 qq| LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) | .
1211 qq| WHERE a.bom = '1' | .
1212 qq| AND a.id = ? | . $sortorder;
1213 @values = ($form->{"id_$i"});
1214 $sth = $dbh->prepare($query);
1215 $sth->execute(@values) || $form->dberror($query);
1217 while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
1218 if ($form->{groupitems} && $ref->{partsgroup} ne $sameitem) {
1219 map({ push(@{ $form->{TEMPLATE_ARRAYS}->{$_} }, "") } grep({ $_ ne "description" } @arrays));
1220 $sameitem = ($ref->{partsgroup}) ? $ref->{partsgroup} : "--";
1221 push(@{ $form->{TEMPLATE_ARRAYS}->{description} }, $sameitem);
1224 push(@{ $form->{TEMPLATE_ARRAYS}->{description} }, $form->format_amount($myconfig, $ref->{qty} * $form->{"qty_$i"}) . qq|, $ref->{partnumber}, $ref->{description}|);
1225 map({ push(@{ $form->{TEMPLATE_ARRAYS}->{$_} }, "") } grep({ $_ ne "description" } @arrays));
1230 map { push @{ $form->{TEMPLATE_ARRAYS}->{"ic_cvar_$_->{name}"} }, $form->{"ic_cvar_$_->{name}_$i"} } @{ $ic_cvar_configs };
1235 foreach $item (sort keys %taxaccounts) {
1236 $tax += $taxamount = $form->round_amount($taxaccounts{$item}, 2);
1238 push(@{ $form->{TEMPLATE_ARRAYS}->{taxbase} }, $form->format_amount($myconfig, $taxbase{$item}, 2));
1239 push(@{ $form->{TEMPLATE_ARRAYS}->{tax} }, $form->format_amount($myconfig, $taxamount, 2));
1240 push(@{ $form->{TEMPLATE_ARRAYS}->{taxrate} }, $form->format_amount($myconfig, $form->{"${item}_rate"} * 100));
1241 push(@{ $form->{TEMPLATE_ARRAYS}->{taxdescription} }, $form->{"${item}_description"} . q{ } . 100 * $form->{"${item}_rate"} . q{%});
1242 push(@{ $form->{TEMPLATE_ARRAYS}->{taxnumber} }, $form->{"${item}_taxnumber"});
1245 $form->{nodiscount_subtotal} = $form->format_amount($myconfig, $form->{nodiscount_total}, 2);
1246 $form->{discount_total} = $form->format_amount($myconfig, $form->{discount_total}, 2);
1247 $form->{nodiscount} = $form->format_amount($myconfig, $nodiscount, 2);
1248 $form->{yesdiscount} = $form->format_amount($myconfig, $form->{nodiscount_total} - $nodiscount, 2);
1250 if($form->{taxincluded}) {
1251 $form->{subtotal} = $form->format_amount($myconfig, $form->{ordtotal} - $tax, 2);
1253 $form->{subtotal} = $form->format_amount($myconfig, $form->{ordtotal}, 2);
1256 $form->{ordtotal} = ($form->{taxincluded}) ? $form->{ordtotal} : $form->{ordtotal} + $tax;
1259 $form->{quototal} = $form->{ordtotal} = $form->format_amount($myconfig, $form->{ordtotal}, 2);
1261 if ($form->{type} =~ /_quotation/) {
1262 $form->set_payment_options($myconfig, $form->{quodate});
1264 $form->set_payment_options($myconfig, $form->{orddate});
1267 $form->{username} = $myconfig->{name};
1271 $main::lxdebug->leave_sub();
1274 sub project_description {
1275 $main::lxdebug->enter_sub();
1277 my ($self, $dbh, $id) = @_;
1279 my $query = qq|SELECT description FROM project WHERE id = ?|;
1280 my ($value) = selectrow_query($main::form, $dbh, $query, $id);
1282 $main::lxdebug->leave_sub();
1287 ##########################
1288 # Get data for the submitted order id
1291 sub get_order_data_by_ordnumber {
1292 $main::lxdebug->enter_sub();
1297 Common::check_params(\%params, qw(ordnumber));
1299 my $form = $main::form;
1300 my %myconfig = %main::myconfig;
1301 my $dbh = $form->get_standard_dbh();
1303 my @values = ($params{ordnumber});
1305 # We query the database for the fields we need using the submitted "ordnumber"
1307 SELECT o.payment_id, o.salesman_id, o.transdate AS orddate, o.taxzone_id, o.quonumber
1309 WHERE o.ordnumber = ?;
1312 # Do the actual query and return the results for later processing by our "frontend"
1313 my $result = selectfirst_hashref_query($form, $dbh, $query, @values);
1315 $main::lxdebug->leave_sub();
1326 OE.pm - Order entry module
1330 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>.
1336 =item retrieve_simple PARAMS
1338 simple OE retrieval by id. does not look up customer, vendor, units or any other stuff. only oe and orderitems.
1340 my $order = retrieve_simple(id => 2);