1 #=====================================================================
4 # Based on SQL-Ledger Version 2.1.9
5 # Web http://www.lx-office.org
7 #=====================================================================
8 # SQL-Ledger, Accounting
11 # Author: Dieter Simader
12 # Email: dsimader@sql-ledger.org
13 # Web: http://www.sql-ledger.org
16 # This program is free software; you can redistribute it and/or modify
17 # it under the terms of the GNU General Public License as published by
18 # the Free Software Foundation; either version 2 of the License, or
19 # (at your option) any later version.
21 # This program is distributed in the hope that it will be useful,
22 # but WITHOUT ANY WARRANTY; without even the implied warranty of
23 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 # GNU General Public License for more details.
25 # You should have received a copy of the GNU General Public License
26 # along with this program; if not, write to the Free Software
27 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #======================================================================
30 # Inventory Control module
32 #======================================================================
34 use POSIX qw(strftime);
35 use List::Util qw(max);
36 use List::MoreUtils qw(any);
41 use SL::ReportGenerator;
49 our ($form, $locale, %myconfig, $lxdebug, $auth);
51 require "bin/mozilla/io.pl";
52 require "bin/mozilla/invoice_io.pl";
53 require "bin/mozilla/common.pl";
54 require "bin/mozilla/reportgenerator.pl";
59 # type=submit $locale->text('Add Part')
60 # type=submit $locale->text('Add Service')
61 # type=submit $locale->text('Add Assembly')
62 # type=submit $locale->text('Edit Part')
63 # type=submit $locale->text('Edit Service')
64 # type=submit $locale->text('Edit Assembly')
65 # $locale->text('Parts')
66 # $locale->text('Services')
67 # $locale->text('Inventory quantity must be zero before you can set this part obsolete!')
68 # $locale->text('Inventory quantity must be zero before you can set this assembly obsolete!')
69 # $locale->text('Part Number missing!')
70 # $locale->text('Service Number missing!')
71 # $locale->text('Assembly Number missing!')
72 # $locale->text('ea');
77 $lxdebug->enter_sub();
79 $auth->assert('part_service_assembly_edit');
81 $form->{title} = $locale->text('Add ' . ucfirst $form->{item});
82 $form->{callback} = "$form->{script}?action=add&item=$form->{item}" unless $form->{callback};
83 $form->{unit_changeable} = 1;
85 IC->get_pricegroups(\%myconfig, \%$form);
89 $lxdebug->leave_sub();
93 $lxdebug->enter_sub();
95 $auth->assert('part_service_assembly_edit');
97 $form->{revers} = 0; # switch for backward sorting
98 $form->{lastsort} = ""; # memory for which table was sort at last time
99 $form->{ndxs_counter} = 0; # counter for added entries to top100
101 my %is_xyz = map { +"is_$_" => ($form->{searchitems} eq $_) } qw(part service assembly);
103 $form->{title} = (ucfirst $form->{searchitems}) . "s";
104 $form->{title} = $locale->text($form->{title});
105 $form->{title} = $locale->text('Assemblies') if ($is_xyz{is_assembly});
107 $form->{jsscript} = 1;
109 $form->{CUSTOM_VARIABLES} = CVar->get_configs('module' => 'IC');
110 ($form->{CUSTOM_VARIABLES_FILTER_CODE},
111 $form->{CUSTOM_VARIABLES_INCLUSION_CODE}) = CVar->render_search_options('variables' => $form->{CUSTOM_VARIABLES},
112 'include_prefix' => 'l_',
113 'include_value' => 'Y');
117 print $form->parse_html_template('ic/search', { %is_xyz,
118 dateformat => $myconfig{dateformat}, });
120 $lxdebug->leave_sub();
123 sub search_update_prices {
124 $lxdebug->enter_sub();
126 $auth->assert('part_service_assembly_edit');
128 my $pricegroups = IC->get_pricegroups(\%myconfig, \%$form);
132 print $form->parse_html_template('ic/search_update_prices', { PRICE_ROWS => $pricegroups });
134 $lxdebug->leave_sub();
137 sub confirm_price_update {
138 $lxdebug->enter_sub();
140 $auth->assert('part_service_assembly_edit');
143 my $value_found = undef;
145 foreach my $idx (qw(sellprice listprice), (1..$form->{price_rows})) {
146 my $name = $idx =~ m/\d/ ? $form->{"pricegroup_${idx}"} : $idx eq 'sellprice' ? $locale->text('Sell Price') : $locale->text('List Price');
147 my $type = $idx =~ m/\d/ ? $form->{"pricegroup_type_${idx}"} : $form->{"${idx}_type"};
148 my $value_idx = $idx =~ m/\d/ ? "price_${idx}" : $idx;
149 my $value = $form->parse_amount(\%myconfig, $form->{$value_idx});
151 if ((0 > $value) && ($type eq 'percent')) {
152 push @errors, $locale->text('You cannot adjust the price for pricegroup "#1" by a negative percentage.', $name);
154 } elsif (!$value && ($form->{$value_idx} ne '')) {
155 push @errors, $locale->text('No valid number entered for pricegroup "#1".', $name);
157 } elsif (0 < $value) {
162 push @errors, $locale->text('No prices will be updated because no prices have been entered.') if (!$value_found);
164 my $num_matches = IC->get_num_matches_for_priceupdate();
169 $form->show_generic_error(join('<br>', @errors), 'back_button' => 1);
172 $form->{nextsub} = "update_prices";
174 map { delete $form->{$_} } qw(action header);
176 print $form->parse_html_template('ic/confirm_price_update', { HIDDENS => [ map { name => $_, value => $form->{$_} }, keys %$form ],
177 num_matches => $num_matches });
179 $lxdebug->leave_sub();
183 $lxdebug->enter_sub();
185 $auth->assert('part_service_assembly_edit');
187 my $num_updated = IC->update_prices(\%myconfig, \%$form);
189 if (-1 != $num_updated) {
190 $form->redirect($locale->text('#1 prices were updated.', $num_updated));
192 $form->error($locale->text('Could not update prices!'));
195 $lxdebug->leave_sub();
199 # $lxdebug->enter_sub();
201 # $auth->assert('part_service_assembly_edit');
203 # our ($j, $lastndx);
206 # $form->{title} = $locale->text('Top 100 hinzufuegen');
210 # push @custom_hiddens, qw(searchitems title bom titel revers lastsort sort ndxs_counter extras);
211 # push @custom_hiddens, qw(itemstatus l_linetotal l_partnumber l_description l_onhand l_unit l_sellprice l_linetotalsellprice);
213 # +{ name => 'row', value => $j },
214 # +{ name => 'nextsub', value => 'item_selected' },
215 # +{ name => 'test', value => 'item_selected' },
216 # +{ name => 'lastndx', value => $lastndx },
217 # map(+{ name => $_, value => $form->{$_} }, @custom_hiddens),
220 # my ($partnumber, $description, $unit, $sellprice, $soldtotal);
221 # # if choice set data
222 ## if ($form->{ndx}) {
223 ## for my $i (0 .. $form->{ndxs_counter}) {
225 ## # insert data into top100
226 ## push @{ $form->{parts} },
228 ## partnumber => $form->{"totop100_partnumber_$j"},
229 ## description => $form->{"totop100_description_$j"},
230 ## unit => $form->{"totop100_unit_$j"},
231 ## sellprice => $form->{"totop100_sellprice_$j"},
232 ## soldtotal => $form->{"totop100_soldtotal_$j"},
239 # # set data for next page
240 # for my $i (1 .. $form->{ndxs_counter}) {
241 # $partnumber = $form->{"totop100_partnumber_$i"};
242 # $description = $form->{"totop100_description_$i"};
243 # $unit = $form->{"totop100_unit_$i"};
244 # $sellprice = $form->{"totop100_sellprice_$i"};
245 # $soldtotal = $form->{"totop100_soldtotal_$i"};
248 # totop100_partnumber => $form->{"totop100_partnumber_$i"},
249 # totop100_description => $form->{"totop100_description_$i"},
250 # totop100_unit => $form->{"totop100_unit_$i"},
251 # totop100_sellprice => $form->{"totop100_sellprice_$i"},
252 # totop100_soldtotal => $form->{"totop100_soldtotal_$i"},
256 ##<input type=hidden name=totop100_partnumber_$i value=$form->{"totop100_partnumber_$i"}>
257 ##<input type=hidden name=totop100_description_$i value=$form->{"totop100_description_$i"}>
258 ##<input type=hidden name=totop100_unit_$i value=$form->{"totop100_unit_$i"}>
259 ##<input type=hidden name=totop100_sellprice_$i value=$form->{"totop100_sellprice_$i"}>
260 ##<input type=hidden name=totop100_soldtotal_$i value=$form->{"totop100_soldtotal_$i"}>
264 # print $form->parse_html_template('ic/choice', +{ HIDDENS => \@HIDDENS, PARTS => \@PARTS });
266 # $lxdebug->leave_sub();
270 # $lxdebug->enter_sub();
272 # $auth->assert('part_service_assembly_edit');
275 # our ($partnumber, $description, $unit, $sellprice, $soldtotal);
277 # my @sortorders = ("", "partnumber", "description", "all");
278 # my $sortorder = $sortorders[($form->{description} ? 2 : 0) + ($form->{partnumber} ? 1 : 0)];
279 # IC->get_parts(\%myconfig, \%$form, $sortorder);
281 # $form->{title} = $locale->text('Top 100 hinzufuegen');
287 # <form method=post action=ic.pl>
290 # <th class=listtop colspan=6>| . $locale->text('choice part') . qq|</th>
292 # <tr height="5"></tr>
293 # <tr class=listheading>
295 # <th class=listheading>| . $locale->text('Part Number') . qq|</th>
296 # <th class=listheading>| . $locale->text('Part Description') . qq|</th>
297 # <th class=listheading>| . $locale->text('Unit of measure') . qq|</th>
298 # <th class=listheading>| . $locale->text('Sell Price') . qq|</th>
299 # <th class=listheading>| . $locale->text('soldtotal') . qq|</th>
303 # my $i = $form->{rows};
305 # for ($j = 1; $j <= $i; $j++) {
308 # <tr class=listrow| . ($j % 2) . qq|>|;
311 # <td><input name=ndx class=radio type=radio value=$j checked></td>|;
314 # <td><input name=ndx class=radio type=radio value=$j></td>|;
317 # <td><input name="new_partnumber_$j" type=hidden value="$form->{"partnumber_$j"}">$form->{"partnumber_$j"}</td>
318 # <td><input name="new_description_$j" type=hidden value="$form->{"description_$j"}">$form->{"description_$j"}</td>
319 # <td><input name="new_unit_$j" type=hidden value="$form->{"unit_$j"}">$form->{"unit_$j"}</td>
320 # <td><input name="new_sellprice_$j" type=hidden value="$form->{"sellprice_$j"}">$form->{"sellprice_$j"}</td>
321 # <td><input name="new_soldtotal_$j" type=hidden value="$form->{"soldtotal_$j"}">$form->{"soldtotal_$j"}</td>
324 # <input name="new_id_$j" type=hidden value="$form->{"id_$j"}">|;
334 #<input type=hidden name=itemstatus value="$form->{itemstatus}">
335 #<input type=hidden name=l_linetotal value="$form->{l_linetotal}">
336 #<input type=hidden name=l_partnumber value="$form->{l_partnumber}">
337 #<input type=hidden name=l_description value="$form->{l_description}">
338 #<input type=hidden name=l_onhand value="$form->{l_onhand}">
339 #<input type=hidden name=l_unit value="$form->{l_unit}">
340 #<input type=hidden name=l_sellprice value="$form->{l_sellprice}">
341 #<input type=hidden name=l_linetotalsellprice value="$form->{l_linetotalsellprice}">
342 #<input type=hidden name=sort value="$form->{sort}">
343 #<input type=hidden name=revers value="$form->{revers}">
344 #<input type=hidden name=lastsort value="$form->{lastsort}">
346 #<input type=hidden name=bom value="$form->{bom}">
347 #<input type=hidden name=titel value="$form->{titel}">
348 #<input type=hidden name=searchitems value="$form->{searchitems}">
350 #<input type=hidden name=row value=$j>
352 #<input type=hidden name=nextsub value=item_selected>
354 #<input name=lastndx type=hidden value=$lastndx>
356 #<input name=ndxs_counter type=hidden value=$form->{ndxs_counter}>|;
360 # if (($form->{ndxs_counter}) > 0) {
361 # for ($i = 1; ($i < $form->{ndxs_counter} + 1); $i++) {
363 # $partnumber = $form->{"totop100_partnumber_$i"};
364 # $description = $form->{"totop100_description_$i"};
365 # $unit = $form->{"totop100_unit_$i"};
366 # $sellprice = $form->{"totop100_sellprice_$i"};
367 # $soldtotal = $form->{"totop100_soldtotal_$i"};
370 #<input type=hidden name=totop100_partnumber_$i value=$form->{"totop100_partnumber_$i"}>
371 #<input type=hidden name=totop100_description_$i value=$form->{"totop100_description_$i"}>
372 #<input type=hidden name=totop100_unit_$i value=$form->{"totop100_unit_$i"}>
373 #<input type=hidden name=totop100_sellprice_$i value=$form->{"totop100_sellprice_$i"}>
374 #<input type=hidden name=totop100_soldtotal_$i value=$form->{"totop100_soldtotal_$i"}>
382 #<input class=submit type=submit name=action value="|
383 # . $locale->text('TOP100') . qq|">
389 # $lxdebug->leave_sub();
393 $lxdebug->enter_sub();
395 $auth->assert('part_service_assembly_edit');
398 $form->{ndxs_counter}++;
400 if ($form->{ndxs_counter} > 0) {
402 my $index = $form->{ndx};
404 $form->{"totop100_partnumber_$form->{ndxs_counter}"} = $form->{"new_partnumber_$index"};
405 $form->{"totop100_description_$form->{ndxs_counter}"} = $form->{"new_description_$index"};
406 $form->{"totop100_unit_$form->{ndxs_counter}"} = $form->{"new_unit_$index"};
407 $form->{"totop100_sellprice_$form->{ndxs_counter}"} = $form->{"new_sellprice_$index"};
408 $form->{"totop100_soldtotal_$form->{ndxs_counter}"} = $form->{"new_soldtotal_$index"};
412 $lxdebug->leave_sub();
416 $lxdebug->enter_sub();
418 $auth->assert('part_service_assembly_edit');
420 my ($revers, $lastsort, $callback, $option, $description, $sameitem,
421 $partnumber, $unit, $sellprice, $soldtotal, $totop100, $onhand, $align);
422 my (@column_index, %column_header, %column_data);
423 my ($totalsellprice, $totallastcost, $totallistprice, $subtotalonhand, $subtotalsellprice, $subtotallastcost, $subtotallistprice);
425 $form->{top100} = "top100";
426 $form->{l_soldtotal} = "Y";
427 $form->{soldtotal} = "soldtotal";
428 $form->{sort} = "soldtotal";
429 $form->{l_qty} = "N";
430 $form->{l_linetotal} = "";
432 $form->{number} = "position";
433 $form->{l_number} = "Y";
437 $form->{title} = $locale->text('Top 100');
439 $revers = $form->{revers};
440 $lastsort = $form->{lastsort};
442 if (($form->{lastsort} eq "") && ($form->{sort} eq undef)) {
444 $form->{lastsort} = "partnumber";
445 $form->{sort} = "partnumber";
449 "$form->{script}?action=top100&searchitems=$form->{searchitems}&itemstatus=$form->{itemstatus}&bom=$form->{bom}&l_linetotal=$form->{l_linetotal}&title="
450 . $form->escape($form->{title}, 1);
452 # if we have a serialnumber limit search
453 if ($form->{serialnumber} || $form->{l_serialnumber}) {
454 $form->{l_serialnumber} = "Y";
455 unless ( $form->{bought}
458 || $form->{quoted}) {
459 $form->{bought} = $form->{sold} = 1;
462 IC->all_parts(\%myconfig, \%$form);
464 if ($form->{itemstatus} eq 'active') {
465 $option .= $locale->text('Active') . " : ";
467 if ($form->{itemstatus} eq 'obsolete') {
468 $option .= $locale->text('Obsolete') . " : ";
470 if ($form->{itemstatus} eq 'orphaned') {
471 $option .= $locale->text('Orphaned') . " : ";
473 if ($form->{itemstatus} eq 'onhand') {
474 $option .= $locale->text('On Hand') . " : ";
475 $form->{l_onhand} = "Y";
477 if ($form->{itemstatus} eq 'short') {
478 $option .= $locale->text('Short') . " : ";
479 $form->{l_onhand} = "Y";
481 if ($form->{onorder}) {
482 $form->{l_ordnumber} = "Y";
483 $callback .= "&onorder=$form->{onorder}";
484 $option .= $locale->text('On Order') . " : ";
486 if ($form->{ordered}) {
487 $form->{l_ordnumber} = "Y";
488 $callback .= "&ordered=$form->{ordered}";
489 $option .= $locale->text('Ordered') . " : ";
492 $form->{l_quonumber} = "Y";
493 $callback .= "&rfq=$form->{rfq}";
494 $option .= $locale->text('RFQ') . " : ";
496 if ($form->{quoted}) {
497 $form->{l_quonumber} = "Y";
498 $callback .= ""ed=$form->{quoted}";
499 $option .= $locale->text('Quoted') . " : ";
501 if ($form->{bought}) {
502 $form->{l_invnumber} = "Y";
503 $callback .= "&bought=$form->{bought}";
504 $option .= $locale->text('Bought') . " : ";
507 $form->{l_invnumber} = "Y";
508 $callback .= "&sold=$form->{sold}";
509 $option .= $locale->text('Sold') . " : ";
516 || $form->{quoted}) {
518 $form->{l_lastcost} = "";
519 $form->{l_name} = "Y";
520 if ($form->{transdatefrom}) {
521 $callback .= "&transdatefrom=$form->{transdatefrom}";
523 . $locale->text('From')
525 . $locale->date(\%myconfig, $form->{transdatefrom}, 1);
527 if ($form->{transdateto}) {
528 $callback .= "&transdateto=$form->{transdateto}";
530 . $locale->text('To')
532 . $locale->date(\%myconfig, $form->{transdateto}, 1);
538 if ($form->{partnumber}) {
539 $callback .= "&partnumber=$form->{partnumber}";
540 $option .= $locale->text('Part Number') . qq| : $form->{partnumber}<br>|;
543 $callback .= "&partnumber=$form->{ean}";
544 $option .= $locale->text('EAN') . qq| : $form->{ean}<br>|;
546 if ($form->{partsgroup}) {
547 $callback .= "&partsgroup=$form->{partsgroup}";
548 $option .= $locale->text('Group') . qq| : $form->{partsgroup}<br>|;
550 if ($form->{serialnumber}) {
551 $callback .= "&serialnumber=$form->{serialnumber}";
552 $option .= $locale->text('Serial Number') . qq| : $form->{serialnumber}<br>|;
554 if ($form->{description}) {
555 $callback .= "&description=$form->{description}";
556 $description = $form->{description};
557 $description =~ s/\n/<br>/g;
558 $option .= $locale->text('Part Description') . qq| : $form->{description}<br>|;
561 $callback .= "&make=$form->{make}";
562 $option .= $locale->text('Make') . qq| : $form->{make}<br>|;
564 if ($form->{model}) {
565 $callback .= "&model=$form->{model}";
566 $option .= $locale->text('Model') . qq| : $form->{model}<br>|;
568 if ($form->{drawing}) {
569 $callback .= "&drawing=$form->{drawing}";
570 $option .= $locale->text('Drawing') . qq| : $form->{drawing}<br>|;
572 if ($form->{microfiche}) {
573 $callback .= "µfiche=$form->{microfiche}";
574 $option .= $locale->text('Microfiche') . qq| : $form->{microfiche}<br>|;
576 if ($form->{l_soldtotal}) {
577 $callback .= "&soldtotal=$form->{soldtotal}";
578 $option .= $locale->text('soldtotal') . qq| : $form->{soldtotal}<br>|;
581 my @columns = $form->sort_columns(
582 qw(number partnumber ean description partsgroup bin onhand rop unit listprice linetotallistprice sellprice linetotalsellprice lastcost linetotallastcost priceupdate weight image drawing microfiche invnumber ordnumber quonumber name serialnumber soldtotal)
585 if ($form->{l_linetotal}) {
586 $form->{l_onhand} = "Y";
587 $form->{l_linetotalsellprice} = "Y" if $form->{l_sellprice};
588 if ($form->{l_lastcost}) {
589 $form->{l_linetotallastcost} = "Y";
590 if (($form->{searchitems} eq 'assembly') && !$form->{bom}) {
591 $form->{l_linetotallastcost} = "";
594 $form->{l_linetotallistprice} = "Y" if $form->{l_listprice};
597 if ($form->{searchitems} eq 'service') {
599 # remove bin, weight and rop from list
600 map { $form->{"l_$_"} = "" } qw(bin weight rop);
602 $form->{l_onhand} = "";
604 # qty is irrelevant unless bought or sold
610 || $form->{quoted}) {
611 $form->{l_onhand} = "Y";
613 $form->{l_linetotalsellprice} = "";
614 $form->{l_linetotallastcost} = "";
618 foreach my $item (@columns) {
619 if ($form->{"l_$item"} eq "Y") {
620 push @column_index, $item;
622 # add column to callback
623 $callback .= "&l_$item=Y";
627 if ($form->{l_subtotal} eq 'Y') {
628 $callback .= "&l_subtotal=Y";
631 $column_header{number} =
632 qq|<th class=listheading nowrap>| . $locale->text('number') . qq|</th>|;
633 $column_header{partnumber} =
634 qq|<th nowrap><a class=listheading href=$callback&sort=partnumber&revers=$form->{revers}&lastsort=$form->{lastsort}>|
635 . $locale->text('Part Number')
637 $column_header{description} =
638 qq|<th nowrap><a class=listheading href=$callback&sort=description&revers=$form->{revers}&lastsort=$form->{lastsort}>|
639 . $locale->text('Part Description')
641 $column_header{partsgroup} =
642 qq|<th nowrap><a class=listheading href=$callback&sort=partsgroup>|
643 . $locale->text('Group')
645 $column_header{bin} =
646 qq|<th><a class=listheading href=$callback&sort=bin>|
647 . $locale->text('Bin')
649 $column_header{priceupdate} =
650 qq|<th nowrap><a class=listheading href=$callback&sort=priceupdate>|
651 . $locale->text('Updated')
653 $column_header{onhand} =
654 qq|<th nowrap><a class=listheading href=$callback&sort=onhand&revers=$form->{revers}&lastsort=$form->{lastsort}>|
655 . $locale->text('Qty')
657 $column_header{unit} =
658 qq|<th class=listheading nowrap>| . $locale->text('Unit') . qq|</th>|;
659 $column_header{listprice} =
660 qq|<th class=listheading nowrap>|
661 . $locale->text('List Price')
663 $column_header{lastcost} =
664 qq|<th class=listheading nowrap>| . $locale->text('Last Cost') . qq|</th>|;
665 $column_header{rop} =
666 qq|<th class=listheading nowrap>| . $locale->text('ROP') . qq|</th>|;
667 $column_header{weight} =
668 qq|<th class=listheading nowrap>| . $locale->text('Weight') . qq|</th>|;
670 $column_header{invnumber} =
671 qq|<th nowrap><a class=listheading href=$callback&sort=invnumber>|
672 . $locale->text('Invoice Number')
674 $column_header{ordnumber} =
675 qq|<th nowrap><a class=listheading href=$callback&sort=ordnumber>|
676 . $locale->text('Order Number')
678 $column_header{quonumber} =
679 qq|<th nowrap><a class=listheading href=$callback&sort=quonumber>|
680 . $locale->text('Quotation')
683 $column_header{name} =
684 qq|<th nowrap><a class=listheading href=$callback&sort=name>|
685 . $locale->text('Name')
688 $column_header{sellprice} =
689 qq|<th class=listheading nowrap>|
690 . $locale->text('Sell Price')
692 $column_header{linetotalsellprice} =
693 qq|<th class=listheading nowrap>| . $locale->text('Extended') . qq|</th>|;
694 $column_header{linetotallastcost} =
695 qq|<th class=listheading nowrap>| . $locale->text('Extended') . qq|</th>|;
696 $column_header{linetotallistprice} =
697 qq|<th class=listheading nowrap>| . $locale->text('Extended') . qq|</th>|;
699 $column_header{image} =
700 qq|<th class=listheading nowrap>| . $locale->text('Image') . qq|</a></th>|;
701 $column_header{drawing} =
702 qq|<th nowrap><a class=listheading href=$callback&sort=drawing>|
703 . $locale->text('Drawing')
705 $column_header{microfiche} =
706 qq|<th nowrap><a class=listheading href=$callback&sort=microfiche>|
707 . $locale->text('Microfiche')
710 $column_header{serialnumber} =
711 qq|<th nowrap><a class=listheading href=$callback&sort=serialnumber>|
712 . $locale->text('Serial Number')
714 $column_header{soldtotal} =
715 qq|<th nowrap><a class=listheading href=$callback&sort=soldtotal&revers=$form->{revers}&lastsort=$form->{lastsort}>|
716 . $locale->text('soldtotal')
720 my $colspan = $#column_index + 1;
727 <th class=listtop colspan=$colspan>$form->{title}</th>
731 <tr><td colspan=$colspan>$option</td></tr>
733 <tr class=listheading>
736 map { print "\n$column_header{$_}" } @column_index;
742 # add order to callback
743 $form->{callback} = $callback .= "&sort=$form->{sort}";
745 # escape callback for href
746 $callback = $form->escape($callback);
748 if (@{ $form->{parts} }) {
749 $sameitem = $form->{parts}->[0]->{ $form->{sort} };
752 # insert numbers for top100
754 foreach my $ref (@{ $form->{parts} }) {
759 # if avaible -> insert choice here
760 if (($form->{ndxs_counter}) > 0) {
761 for (my $i = 1; ($i < $form->{ndxs_counter} + 1); $i++) {
762 $partnumber = $form->{"totop100_partnumber_$i"};
763 $description = $form->{"totop100_description_$i"};
764 $unit = $form->{"totop100_unit_$i"};
765 $sellprice = $form->{"totop100_sellprice_$i"};
766 $soldtotal = $form->{"totop100_soldtotal_$i"};
769 <input type=hidden name=totop100_partnumber_$i value=$form->{"totop100_partnumber_$i"}>
770 <input type=hidden name=totop100_description_$i value=$form->{"totop100_description_$i"}>
771 <input type=hidden name=totop100_unit_$i value=$form->{"totop100_unit_$i"}>
772 <input type=hidden name=totop100_sellprice_$i value=$form->{"totop100_sellprice_$i"}>
773 <input type=hidden name=totop100_soldtotal_$i value=$form->{"totop100_soldtotal_$i"}>
777 push @{ $form->{parts} },
779 partnumber => "$partnumber",
780 description => "$description",
782 sellprice => "$sellprice",
783 soldtotal => "$soldtotal" };
786 # build data for columns
788 foreach my $ref (@{ $form->{parts} }) {
790 if ($form->{l_subtotal} eq 'Y' && !$ref->{assemblyitem}) {
791 if ($sameitem ne $ref->{ $form->{sort} }) {
793 $sameitem = $ref->{ $form->{sort} };
797 $ref->{exchangerate} = 1 unless $ref->{exchangerate};
798 $ref->{sellprice} *= $ref->{exchangerate};
799 $ref->{listprice} *= $ref->{exchangerate};
800 $ref->{lastcost} *= $ref->{exchangerate};
802 # use this for assemblies
803 $onhand = $ref->{onhand};
806 if ($ref->{assemblyitem}) {
808 $onhand = 0 if ($form->{sold});
811 $ref->{description} =~ s/\n/<br>/g;
813 $column_data{number} =
815 . $form->format_amount(\%myconfig, $ref->{number})
817 $column_data{partnumber} =
818 "<td align=$align>$ref->{partnumber} </a></td>";
819 $column_data{description} = "<td>$ref->{description} </td>";
820 $column_data{partsgroup} = "<td>$ref->{partsgroup} </td>";
822 $column_data{onhand} =
824 . $form->format_amount(\%myconfig, $ref->{onhand})
826 $column_data{sellprice} =
828 . $form->format_amount(\%myconfig, $ref->{sellprice})
830 $column_data{listprice} =
832 . $form->format_amount(\%myconfig, $ref->{listprice})
834 $column_data{lastcost} =
836 . $form->format_amount(\%myconfig, $ref->{lastcost})
839 $column_data{linetotalsellprice} = "<td align=right>"
840 . $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{sellprice}, 2)
842 $column_data{linetotallastcost} = "<td align=right>"
843 . $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{lastcost}, 2)
845 $column_data{linetotallistprice} = "<td align=right>"
846 . $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{listprice}, 2)
849 if (!$ref->{assemblyitem}) {
850 $totalsellprice += $onhand * $ref->{sellprice};
851 $totallastcost += $onhand * $ref->{lastcost};
852 $totallistprice += $onhand * $ref->{listprice};
854 $subtotalonhand += $onhand;
855 $subtotalsellprice += $onhand * $ref->{sellprice};
856 $subtotallastcost += $onhand * $ref->{lastcost};
857 $subtotallistprice += $onhand * $ref->{listprice};
862 . $form->format_amount(\%myconfig, $ref->{rop}) . "</td>";
863 $column_data{weight} =
865 . $form->format_amount(\%myconfig, $ref->{weight})
867 $column_data{unit} = "<td>$ref->{unit} </td>";
868 $column_data{bin} = "<td>$ref->{bin} </td>";
869 $column_data{priceupdate} = "<td>$ref->{priceupdate} </td>";
871 $column_data{invnumber} =
872 ($ref->{module} ne 'oe')
873 ? "<td><a href=$ref->{module}.pl?action=edit&type=invoice&id=$ref->{trans_id}&callback=$callback>$ref->{invnumber}</a></td>"
874 : "<td>$ref->{invnumber}</td>";
875 $column_data{ordnumber} =
876 ($ref->{module} eq 'oe')
877 ? "<td><a href=$ref->{module}.pl?action=edit&type=$ref->{type}&id=$ref->{trans_id}&callback=$callback>$ref->{ordnumber}</a></td>"
878 : "<td>$ref->{ordnumber}</td>";
879 $column_data{quonumber} =
880 ($ref->{module} eq 'oe' && !$ref->{ordnumber})
881 ? "<td><a href=$ref->{module}.pl?action=edit&type=$ref->{type}&id=$ref->{trans_id}&callback=$callback>$ref->{quonumber}</a></td>"
882 : "<td>$ref->{quonumber}</td>";
884 $column_data{name} = "<td>$ref->{name}</td>";
886 $column_data{image} =
888 ? "<td><a href=$ref->{image}><img src=$ref->{image} height=32 border=0></a></td>"
890 $column_data{drawing} =
892 ? "<td><a href=$ref->{drawing}>$ref->{drawing}</a></td>"
894 $column_data{microfiche} =
896 ? "<td><a href=$ref->{microfiche}>$ref->{microfiche}</a></td>"
899 $column_data{serialnumber} = "<td>$ref->{serialnumber}</td>";
901 $column_data{soldtotal} = "<td align=right>$ref->{soldtotal}</td>";
905 print "<tr class=listrow$i>";
907 map { print "\n$column_data{$_}" } @column_index;
914 if ($form->{l_subtotal} eq 'Y') {
918 if ($form->{"l_linetotal"}) {
919 map { $column_data{$_} = "<td> </td>" } @column_index;
920 $column_data{linetotalsellprice} =
921 "<th class=listtotal align=right>"
922 . $form->format_amount(\%myconfig, $totalsellprice, 2)
924 $column_data{linetotallastcost} =
925 "<th class=listtotal align=right>"
926 . $form->format_amount(\%myconfig, $totallastcost, 2)
928 $column_data{linetotallistprice} =
929 "<th class=listtotal align=right>"
930 . $form->format_amount(\%myconfig, $totallistprice, 2)
933 print "<tr class=listtotal>";
935 map { print "\n$column_data{$_}" } @column_index;
942 <tr><td colspan=$colspan><hr size=3 noshade></td></tr>
951 <form method=post action=$form->{script}>
953 <input type=hidden name=itemstatus value="$form->{itemstatus}">
954 <input type=hidden name=l_linetotal value="$form->{l_linetotal}">
955 <input type=hidden name=l_partnumber value="$form->{l_partnumber}">
956 <input type=hidden name=l_description value="$form->{l_description}">
957 <input type=hidden name=l_onhand value="$form->{l_onhand}">
958 <input type=hidden name=l_unit value="$form->{l_unit}">
959 <input type=hidden name=l_sellprice value="$form->{l_sellprice}">
960 <input type=hidden name=l_linetotalsellprice value="$form->{l_linetotalsellprice}">
961 <input type=hidden name=sort value="$form->{sort}">
962 <input type=hidden name=revers value="$form->{revers}">
963 <input type=hidden name=lastsort value="$form->{lastsort}">
964 <input type=hidden name=parts value="$form->{parts}">
966 <input type=hidden name=bom value="$form->{bom}">
967 <input type=hidden name=titel value="$form->{titel}">
968 <input type=hidden name=searchitems value="$form->{searchitems}">|;
973 <!-- <input type=hidden name=ndxs_counter value="$form->{ndxs_counter}">-->
975 <input class=submit type=submit name=action value="|
976 . $locale->text('choice') . qq|">
984 $lxdebug->leave_sub();
989 # Warning, deep magic ahead.
990 # This function parses the requested details, sanity checks them, and converts them into a format thats usable for IC->all_parts
992 # flags coming from the form:
994 # searchitems=part revers=0 lastsort=''
997 # partnumber ean description partsgroup serialnumber make model drawing microfiche
998 # transdatefrom transdateto
1001 # itemstatus = active | onhand | short | obsolete | orphaned
1002 # action = continue | top100
1005 # bought sold onorder ordered rfq quoted
1006 # l_partnumber l_description l_serialnumber l_unit l_listprice l_sellprice l_lastcost
1007 # l_linetotal l_priceupdate l_bin l_rop l_weight l_image l_drawing l_microfiche
1008 # l_partsgroup l_subtotal l_soldtotal l_deliverydate
1011 # nextsub revers lastsort sort ndxs_counter
1013 sub generate_report {
1014 $lxdebug->enter_sub();
1016 $auth->assert('part_service_assembly_edit');
1018 my ($revers, $lastsort, $description);
1020 my $cvar_configs = CVar->get_configs('module' => 'IC');
1022 $form->{title} = (ucfirst $form->{searchitems}) . "s";
1023 $form->{title} =~ s/ys$/ies/;
1024 $form->{title} = $locale->text($form->{title});
1027 'bin' => { 'text' => $locale->text('Bin'), },
1028 'deliverydate' => { 'text' => $locale->text('deliverydate'), },
1029 'description' => { 'text' => $locale->text('Part Description'), },
1030 'drawing' => { 'text' => $locale->text('Drawing'), },
1031 'image' => { 'text' => $locale->text('Image'), },
1032 'invnumber' => { 'text' => $locale->text('Invoice Number'), },
1033 'lastcost' => { 'text' => $locale->text('Last Cost'), },
1034 'linetotallastcost' => { 'text' => $locale->text('Extended'), },
1035 'linetotallistprice' => { 'text' => $locale->text('Extended'), },
1036 'linetotalsellprice' => { 'text' => $locale->text('Extended'), },
1037 'listprice' => { 'text' => $locale->text('List Price'), },
1038 'microfiche' => { 'text' => $locale->text('Microfiche'), },
1039 'name' => { 'text' => $locale->text('Name'), },
1040 'onhand' => { 'text' => $locale->text('Qty'), },
1041 'ordnumber' => { 'text' => $locale->text('Order Number'), },
1042 'partnumber' => { 'text' => $locale->text('Part Number'), },
1043 'partsgroup' => { 'text' => $locale->text('Group'), },
1044 'priceupdate' => { 'text' => $locale->text('Updated'), },
1045 'quonumber' => { 'text' => $locale->text('Quotation'), },
1046 'rop' => { 'text' => $locale->text('ROP'), },
1047 'sellprice' => { 'text' => $locale->text('Sell Price'), },
1048 'serialnumber' => { 'text' => $locale->text('Serial Number'), },
1049 'soldtotal' => { 'text' => $locale->text('soldtotal'), },
1050 'transdate' => { 'text' => $locale->text('Transdate'), },
1051 'unit' => { 'text' => $locale->text('Unit'), },
1052 'weight' => { 'text' => $locale->text('Weight'), },
1055 $revers = $form->{revers};
1056 $lastsort = $form->{lastsort};
1058 # sorting and direction of sorting
1059 # ToDO: change this to the simpler field+direction method
1060 if (($form->{lastsort} eq "") && ($form->{sort} eq undef)) {
1061 $form->{revers} = 0;
1062 $form->{lastsort} = "partnumber";
1063 $form->{sort} = "partnumber";
1065 if ($form->{lastsort} eq $form->{sort}) {
1066 $form->{revers} = 1 - $form->{revers};
1068 $form->{revers} = 0;
1069 $form->{lastsort} = $form->{sort};
1073 # special case if we have a serialnumber limit search
1074 # serialnumbers are only given in invoices and orders,
1075 # so they can only pop up in bought, sold, rfq, and quoted stuff
1076 $form->{no_sn_joins} = 'Y' if ( !$form->{bought} && !$form->{sold}
1077 && !$form->{rfq} && !$form->{quoted}
1078 && ($form->{l_serialnumber} || $form->{serialnumber}));
1080 # special case for any checkbox of bought | sold | onorder | ordered | rfq | quoted.
1081 # if any of these are ticked the behavior changes slightly for lastcost
1082 # since all those are aggregation checks for the legder tables this is an internal switch
1083 # refered to as ledgerchecks
1084 $form->{ledgerchecks} = 'Y' if ( $form->{bought} || $form->{sold} || $form->{onorder}
1085 || $form->{ordered} || $form->{rfq} || $form->{quoted});
1087 # if something should be activated if something else is active, enter it here
1088 my %dependencies = (
1089 onhand => [ qw(l_onhand) ],
1090 short => [ qw(l_onhand) ],
1091 onorder => [ qw(l_ordnumber) ],
1092 ordered => [ qw(l_ordnumber) ],
1093 rfq => [ qw(l_quonumber) ],
1094 quoted => [ qw(l_quonumber) ],
1095 bought => [ qw(l_invnumber) ],
1096 sold => [ qw(l_invnumber) ],
1097 ledgerchecks => [ qw(l_name) ],
1098 serialnumber => [ qw(l_serialnumber) ],
1099 no_sn_joins => [ qw(bought sold) ],
1102 # these strings get displayed at the top of the results to indicate the user which switches were used
1104 active => $locale->text('Active'),
1105 obsolete => $locale->text('Obsolete'),
1106 orphaned => $locale->text('Orphaned'),
1107 onhand => $locale->text('On Hand'),
1108 short => $locale->text('Short'),
1109 onorder => $locale->text('On Order'),
1110 ordered => $locale->text('Ordered'),
1111 rfq => $locale->text('RFQ'),
1112 quoted => $locale->text('Quoted'),
1113 bought => $locale->text('Bought'),
1114 sold => $locale->text('Sold'),
1115 transdatefrom => $locale->text('From') . " " . $locale->date(\%myconfig, $form->{transdatefrom}, 1),
1116 transdateto => $locale->text('To (time)') . " " . $locale->date(\%myconfig, $form->{transdateto}, 1),
1117 partnumber => $locale->text('Part Number') . ": '$form->{partnumber}'",
1118 partsgroup => $locale->text('Group') . ": '$form->{partsgroup}'",
1119 serialnumber => $locale->text('Serial Number') . ": '$form->{serialnumber}'",
1120 description => $locale->text('Part Description') . ": '$form->{description}'",
1121 make => $locale->text('Make') . ": '$form->{make}'",
1122 model => $locale->text('Model') . ": '$form->{model}'",
1123 drawing => $locale->text('Drawing') . ": '$form->{drawing}'",
1124 microfiche => $locale->text('Microfiche') . ": '$form->{microfiche}'",
1125 l_soldtotal => $locale->text('soldtotal'),
1126 ean => $locale->text('EAN') . ": '$form->{ean}'",
1129 my @itemstatus_keys = qw(active obsolete orphaned onhand short);
1130 my @callback_keys = qw(onorder ordered rfq quoted bought sold partnumber partsgroup serialnumber description make model
1131 drawing microfiche l_soldtotal l_deliverydate transdatefrom transdateto ean);
1133 # calculate dependencies
1134 for (@itemstatus_keys, @callback_keys) {
1135 next if ($form->{itemstatus} ne $_ && !$form->{$_});
1136 map { $form->{$_} = 'Y' } @{ $dependencies{$_} } if $dependencies{$_};
1139 # generate callback and optionstrings
1141 for my $key (@itemstatus_keys, @callback_keys) {
1142 next if ($form->{itemstatus} ne $key && !$form->{$key});
1143 push @options, $optiontexts{$key};
1146 # special case for lastcost
1147 if ($form->{ledgerchecks}){
1148 # ledgerchecks don't know about sellprice or lastcost. they just return a
1149 # price. so rename sellprice to price, and drop lastcost.
1150 $column_defs{sellprice}{text} = $locale->text('Price');
1151 $form->{l_lastcost} = ""
1154 if ($form->{description}) {
1155 $description = $form->{description};
1156 $description =~ s/\n/<br>/g;
1159 if ($form->{l_linetotal}) {
1160 $form->{l_onhand} = "Y";
1161 $form->{l_linetotalsellprice} = "Y" if $form->{l_sellprice};
1162 $form->{l_linetotallastcost} = $form->{searchitems} eq 'assembly' && !$form->{bom} ? "" : 'Y' if $form->{l_lastcost};
1163 $form->{l_linetotallistprice} = "Y" if $form->{l_listprice};
1166 if ($form->{searchitems} eq 'service') {
1168 # remove bin, weight and rop from list
1169 map { $form->{"l_$_"} = "" } qw(bin weight rop);
1171 $form->{l_onhand} = "";
1173 # qty is irrelevant unless bought or sold
1174 if ( $form->{bought}
1179 || $form->{quoted}) {
1180 $form->{l_onhand} = "Y";
1182 $form->{l_linetotalsellprice} = "";
1183 $form->{l_linetotallastcost} = "";
1187 IC->all_parts(\%myconfig, \%$form);
1190 partnumber description partsgroup bin onhand rop unit listprice
1191 linetotallistprice sellprice linetotalsellprice lastcost linetotallastcost
1192 priceupdate weight image drawing microfiche invnumber ordnumber quonumber
1193 transdate name serialnumber soldtotal deliverydate ean
1196 my @includeable_custom_variables = grep { $_->{includeable} } @{ $cvar_configs };
1197 my @searchable_custom_variables = grep { $_->{searchable} } @{ $cvar_configs };
1198 my %column_defs_cvars = map { +"cvar_$_->{name}" => { 'text' => $_->{description} } } @includeable_custom_variables;
1200 push @columns, map { "cvar_$_->{name}" } @includeable_custom_variables;
1202 %column_defs = (%column_defs,%column_defs_cvars); # nochmal die cvars als überschrift hinzufügen
1203 map { $column_defs{$_}->{visible} = $form->{"l_$_"} ? 1 : 0 } @columns;
1204 map { $column_defs{$_}->{align} = 'right' } qw(onhand sellprice listprice lastcost linetotalsellprice linetotallastcost linetotallistprice rop weight soldtotal);
1206 my @hidden_variables = (qw(l_subtotal l_linetotal searchitems itemstatus bom), @itemstatus_keys, @callback_keys, @searchable_custom_variables, map { "l_$_" } @columns);
1207 my $callback = build_std_url('action=generate_report', grep { $form->{$_} } @hidden_variables);
1209 my @sort_full = qw(partnumber description onhand soldtotal deliverydate);
1210 my @sort_no_revers = qw(partsgroup bin priceupdate invnumber ordnumber quonumber name image drawing serialnumber);
1212 foreach my $col (@sort_full) {
1213 $column_defs{$col}->{link} = join '&', $callback, "sort=$col", map { "$_=" . E($form->{$_}) } qw(revers lastsort);
1215 map { $column_defs{$_}->{link} = "${callback}&sort=$_" } @sort_no_revers;
1217 # add order to callback
1218 $form->{callback} = join '&', ($callback, map { "${_}=" . E($form->{$_}) } qw(sort revers));
1220 my $report = SL::ReportGenerator->new(\%myconfig, $form);
1222 my %attachment_basenames = (
1223 'part' => $locale->text('part_list'),
1224 'service' => $locale->text('service_list'),
1225 'assembly' => $locale->text('assembly_list'),
1228 $report->set_options('top_info_text' => $locale->text('Options') . ': ' . join(', ', grep $_, @options),
1229 'raw_bottom_info_text' => $form->parse_html_template('ic/generate_report_bottom'),
1230 'output_format' => 'HTML',
1231 'title' => $form->{title},
1232 'attachment_basename' => $attachment_basenames{$form->{searchitems}} . strftime('_%Y%m%d', localtime time),
1234 $report->set_options_from_form();
1236 $report->set_columns(%column_defs);
1237 $report->set_column_order(@columns);
1239 $report->set_export_options('generate_report', @hidden_variables, qw(sort revers));
1241 $report->set_sort_indicator($form->{sort}, $form->{revers} ? 0 : 1);
1243 CVar->add_custom_variables_to_report('module' => 'IC',
1244 'trans_id_field' => 'id',
1245 'configs' => $cvar_configs,
1246 'column_defs' => \%column_defs,
1247 'data' => $form->{parts});
1249 CVar->add_custom_variables_to_report('module' => 'IC',
1250 'sub_module' => sub { $_[0]->{ioi} },
1251 'trans_id_field' => 'ioi_id',
1252 'configs' => $cvar_configs,
1253 'column_defs' => \%column_defs,
1254 'data' => $form->{parts});
1256 my @subtotal_columns = qw(sellprice listprice lastcost);
1257 my %subtotals = map { $_ => 0 } ('onhand', @subtotal_columns);
1258 my %totals = map { $_ => 0 } @subtotal_columns;
1260 my $same_item = $form->{parts}[0]{ $form->{sort} } if (scalar @{ $form->{parts} });
1262 my $defaults = AM->get_defaults();
1265 foreach my $ref (@{ $form->{parts} }) {
1267 # fresh row, for inserting later
1268 my $row = { map { $_ => { 'data' => $ref->{$_} } } @columns };
1270 $ref->{exchangerate} ||= 1;
1271 $ref->{price_factor} ||= 1;
1272 $ref->{sellprice} *= $ref->{exchangerate} / $ref->{price_factor};
1273 $ref->{listprice} *= $ref->{exchangerate} / $ref->{price_factor};
1274 $ref->{lastcost} *= $ref->{exchangerate} / $ref->{price_factor};
1276 # use this for assemblies
1277 my $onhand = $ref->{onhand};
1279 if ($ref->{assemblyitem}) {
1280 $row->{partnumber}{align} = 'right';
1281 $row->{onhand}{data} = 0;
1282 $onhand = 0 if ($form->{sold});
1285 my $edit_link = build_std_url('action=edit', 'id=' . E($ref->{id}), 'callback');
1286 $row->{partnumber}->{link} = $edit_link;
1287 $row->{description}->{link} = $edit_link;
1289 foreach (qw(sellprice listprice lastcost)) {
1290 $row->{$_}{data} = $form->format_amount(\%myconfig, $ref->{$_}, -2);
1291 $row->{"linetotal$_"}{data} = $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{$_}, 2);
1294 map { $row->{$_}{data} = $form->format_amount(\%myconfig, $ref->{$_}); } qw(onhand rop weight soldtotal);
1296 $row->{weight}->{data} .= ' ' . $defaults->{weightunit};
1298 if (!$ref->{assemblyitem}) {
1299 foreach my $col (@subtotal_columns) {
1300 $totals{$col} += $onhand * $ref->{$col};
1301 $subtotals{$col} += $onhand * $ref->{$col};
1304 $subtotals{onhand} += $onhand;
1308 if ($ref->{module} eq 'oe') {
1309 my $edit_oe_link = build_std_url("script=oe.pl", 'action=edit', 'type=' . E($ref->{cv} eq 'vendor' ? 'purchase_order' : 'sales_order'), 'id=' . E($ref->{trans_id}), 'callback');
1310 $row->{ordnumber}{link} = $edit_oe_link;
1311 $row->{quonumber}{link} = $edit_oe_link if (!$ref->{ordnumber});
1314 $row->{invnumber}{link} = build_std_url("script=$ref->{module}.pl", 'action=edit', 'type=invoice', 'id=' . E($ref->{trans_id}), 'callback');
1317 # set properties of images
1318 if ($ref->{image} && (lc $report->{options}->{output_format} eq 'html')) {
1319 $row->{image}{data} = '';
1320 $row->{image}{raw_data} = '<a href="' . H($ref->{image}) . '"><img src="' . H($ref->{image}) . '" height="32" border="0"></a>';
1322 map { $row->{$_}{link} = $ref->{$_} } qw(drawing microfiche);
1324 $report->add_data($row);
1326 my $next_ref = $form->{parts}[$idx + 1];
1328 # insert subtotal rows
1329 if (($form->{l_subtotal} eq 'Y') &&
1331 (!$next_ref->{assemblyitem} && ($same_item ne $next_ref->{ $form->{sort} })))) {
1332 my $row = { map { $_ => { 'class' => 'listsubtotal', } } @columns };
1334 if (($form->{searchitems} ne 'assembly') || !$form->{bom}) {
1335 $row->{onhand}->{data} = $form->format_amount(\%myconfig, $subtotals{onhand});
1338 map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $subtotals{$_}, 2) } @subtotal_columns;
1339 map { $subtotals{$_} = 0 } ('onhand', @subtotal_columns);
1341 $report->add_data($row);
1343 $same_item = $next_ref->{ $form->{sort} };
1349 if ($form->{"l_linetotal"}) {
1350 my $row = { map { $_ => { 'class' => 'listtotal', } } @columns };
1352 map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $totals{$_}, 2) } @subtotal_columns;
1354 $report->add_separator();
1355 $report->add_data($row);
1358 $report->generate_with_headers();
1360 $lxdebug->leave_sub();
1361 } #end generate_report
1363 sub parts_subtotal {
1364 $lxdebug->enter_sub();
1366 $auth->assert('part_service_assembly_edit');
1369 our (%column_data, @column_index);
1370 our ($subtotalonhand, $totalsellprice, $totallastcost, $totallistprice, $subtotalsellprice, $subtotallastcost, $subtotallistprice);
1372 map { $column_data{$_} = "<td> </td>" } @column_index;
1373 $subtotalonhand = 0 if ($form->{searchitems} eq 'assembly' && $form->{bom});
1375 $column_data{onhand} =
1376 "<th class=listsubtotal align=right>"
1377 . $form->format_amount(\%myconfig, $subtotalonhand)
1380 $column_data{linetotalsellprice} =
1381 "<th class=listsubtotal align=right>"
1382 . $form->format_amount(\%myconfig, $subtotalsellprice, 2)
1384 $column_data{linetotallistprice} =
1385 "<th class=listsubtotal align=right>"
1386 . $form->format_amount(\%myconfig, $subtotallistprice, 2)
1388 $column_data{linetotallastcost} =
1389 "<th class=listsubtotal align=right>"
1390 . $form->format_amount(\%myconfig, $subtotallastcost, 2)
1393 $subtotalonhand = 0;
1394 $subtotalsellprice = 0;
1395 $subtotallistprice = 0;
1396 $subtotallastcost = 0;
1398 print "<tr class=listsubtotal>";
1400 map { print "\n$column_data{$_}" } @column_index;
1406 $lxdebug->leave_sub();
1410 $lxdebug->enter_sub();
1412 $auth->assert('part_service_assembly_edit');
1414 # show history button
1415 $form->{javascript} = qq|<script type="text/javascript" src="js/show_history.js"></script>|;
1416 #/show hhistory button
1417 IC->get_part(\%myconfig, \%$form);
1419 $form->{"original_partnumber"} = $form->{"partnumber"};
1421 $form->{title} = $locale->text('Edit ' . ucfirst $form->{item});
1426 $lxdebug->leave_sub();
1430 $lxdebug->enter_sub();
1432 $auth->assert('part_service_assembly_edit');
1434 IC->create_links("IC", \%myconfig, \%$form);
1437 map({ $form->{selectcurrency} .= "<option>$_\n" }
1438 split(/:/, $form->{currencies}));
1440 # parts and assemblies have the same links
1441 my $item = $form->{item};
1442 if ($form->{item} eq 'assembly') {
1446 # build the popup menus
1447 $form->{taxaccounts} = "";
1448 foreach my $key (keys %{ $form->{IC_links} }) {
1449 foreach my $ref (@{ $form->{IC_links}{$key} }) {
1451 # if this is a tax field
1452 if ($key =~ /IC_tax/) {
1453 if ($key =~ /\Q$item\E/) {
1454 $form->{taxaccounts} .= "$ref->{accno} ";
1455 $form->{"IC_tax_$ref->{accno}_description"} =
1456 "$ref->{accno}--$ref->{description}";
1459 if ($form->{amount}{ $ref->{accno} }) {
1460 $form->{"IC_tax_$ref->{accno}"} = "checked";
1463 $form->{"IC_tax_$ref->{accno}"} = "checked";
1468 $form->{"select$key"} .=
1469 "<option $ref->{selected}>$ref->{accno}--$ref->{description}\n";
1470 if ($form->{amount}{$key} eq $ref->{accno}) {
1471 $form->{$key} = "$ref->{accno}--$ref->{description}";
1477 chop $form->{taxaccounts};
1479 if (($form->{item} eq "part") || ($form->{item} eq "assembly")) {
1480 $form->{selectIC_income} = $form->{selectIC_sale};
1481 $form->{selectIC_expense} = $form->{selectIC_cogs};
1482 $form->{IC_income} = $form->{IC_sale};
1483 $form->{IC_expense} = $form->{IC_cogs};
1486 delete $form->{IC_links};
1487 delete $form->{amount};
1489 $form->get_partsgroup(\%myconfig, { all => 1 });
1491 $form->{partsgroup} = "$form->{partsgroup}--$form->{partsgroup_id}";
1493 if (@{ $form->{all_partsgroup} }) {
1494 $form->{selectpartsgroup} = qq|<option>\n|;
1495 map { $form->{selectpartsgroup} .= qq|<option value="$_->{partsgroup}--$_->{id}">$_->{partsgroup}\n| } @{ $form->{all_partsgroup} };
1498 if ($form->{item} eq 'assembly') {
1500 foreach my $i (1 .. $form->{assembly_rows}) {
1501 if ($form->{"partsgroup_id_$i"}) {
1502 $form->{"partsgroup_$i"} =
1503 qq|$form->{"partsgroup_$i"}--$form->{"partsgroup_id_$i"}|;
1506 $form->get_partsgroup(\%myconfig);
1508 if (@{ $form->{all_partsgroup} }) {
1509 $form->{selectassemblypartsgroup} = qq|<option>\n|;
1512 $form->{selectassemblypartsgroup} .=
1513 qq|<option value="$_->{partsgroup}--$_->{id}">$_->{partsgroup}\n|
1514 } @{ $form->{all_partsgroup} };
1517 $lxdebug->leave_sub();
1521 $lxdebug->enter_sub();
1523 $auth->assert('part_service_assembly_edit');
1525 $form->{eur} = $main::eur; # config dumps into namespace - yuck
1526 $form->{pg_keys} = sub { "$_[0]->{partsgroup}--$_[0]->{id}" };
1527 $form->{description_area} = ($form->{rows} = $form->numtextrows($form->{description}, 40)) > 1;
1528 $form->{notes_rows} = max 4, $form->numtextrows($form->{notes}, 40), $form->numtextrows($form->{formel}, 40);
1530 map { $form->{"is_$_"} = ($form->{item} eq $_) } qw(part service assembly);
1531 map { $form->{$_} =~ s/"/"/g; } qw(unit);
1533 $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS',
1534 'partsgroup' => 'all_partsgroup',
1535 'vendors' => 'ALL_VENDORS',);
1538 IC->retrieve_buchungsgruppen(\%myconfig, $form);
1539 @{ $form->{BUCHUNGSGRUPPEN} } = grep { $_->{id} eq $form->{buchungsgruppen_id} || ($form->{id} && $form->{orphaned}) || !$form->{id} } @{ $form->{BUCHUNGSGRUPPEN} };
1541 # use JavaScript Calendar or not (yes!)
1542 $form->{jsscript} = 1;
1544 my $units = AM->retrieve_units(\%myconfig, $form);
1545 $form->{ALL_UNITS} = [ map +{ name => $_ }, sort { $units->{$a}{sortkey} <=> $units->{$b}{sortkey} } keys %$units ];
1547 $form->{defaults} = AM->get_defaults();
1549 $form->{fokus} = "ic.partnumber";
1551 $form->{CUSTOM_VARIABLES} = CVar->get_custom_variables('module' => 'IC', 'trans_id' => $form->{id});
1553 CVar->render_inputs('variables' => $form->{CUSTOM_VARIABLES}, show_disabled_message => 1)
1554 if (scalar @{ $form->{CUSTOM_VARIABLES} });
1557 #print $form->parse_html_template('ic/form_header', { ALL_PRICE_FACTORS => $form->{ALL_PRICE_FACTORS},
1558 # ALL_UNITS => $form->{ALL_UNITS},
1559 # BUCHUNGSGRUPPEN => $form->{BUCHUNGSGRUPPEN},
1560 # payment_terms => $form->{payment_terms},
1561 # all_partsgroup => $form->{all_partsgroup}});
1562 print $form->parse_html_template('ic/form_header');
1563 $lxdebug->leave_sub();
1567 $lxdebug->enter_sub();
1569 $auth->assert('part_service_assembly_edit');
1571 print $form->parse_html_template('ic/form_footer');
1573 $lxdebug->leave_sub();
1577 $lxdebug->enter_sub();
1580 my @mm_data = grep { any { $_ ne '' } @$_{qw(make model)} } map +{ make => $form->{"make_$_"}, model => $form->{"model_$_"} }, 1 .. $numrows;
1581 delete @{$form}{grep { m/^make_\d+/ || m/^model_\d+/ } keys %{ $form }};
1582 print $form->parse_html_template('ic/makemodel', { MM_DATA => [ @mm_data, {} ], mm_rows => scalar @mm_data + 1 });
1584 $lxdebug->leave_sub();
1588 $lxdebug->enter_sub();
1591 my ($nochange, $callback, $previousform, $linetotal, $line_purchase_price, $href);
1593 our ($deliverydate); # ToDO: check if this indeed comes from global context
1595 @column_index = qw(runningnumber qty unit bom partnumber description partsgroup lastcost total);
1597 if ($form->{previousform}) {
1599 @column_index = qw(qty unit bom partnumber description partsgroup total);
1603 $form->{old_callback} = $form->{callback};
1604 $callback = $form->{callback};
1605 $form->{callback} = "$form->{script}?action=display_form";
1608 map { delete $form->{$_} } qw(action header);
1610 # save form variables in a previousform variable
1611 $previousform = $form->escape($form->escape(join '&', map {
1612 sprintf "%s=%s", Q($_), /^listprice|lastcost|sellprice$/ ? $form->format_amount(\%myconfig, $form->{$_}) : $form->{$_}
1613 } grep { ref $form->{$_} eq '' && $form->{$_} } grep { !/^select/ } sort keys %$form ));
1615 $form->{callback} = $callback;
1616 $form->{assemblytotal} = 0;
1617 $form->{assembly_purchase_price_total} = 0;
1618 $form->{weight} = 0;
1622 runningnumber => { text => $locale->text('No.'), nowrap => 1, width => '5%' },
1623 qty => { text => $locale->text('Qty'), nowrap => 1, width => '10%' },
1624 unit => { text => $locale->text('Unit'), nowrap => 1, width => '5%' },
1625 partnumber => { text => $locale->text('Part Number'), nowrap => 1, width => '20%' },
1626 description => { text => $locale->text('Part Description'), nowrap => 1, width => '50%' },
1627 lastcost => { text => $locale->text('Purchase Prices'), nowrap => 1, width => '50%' },
1628 total => { text => $locale->text('Sale Prices'), nowrap => 1, },
1629 bom => { text => $locale->text('BOM'), },
1630 partsgroup => { text => $locale->text('Group'), },
1635 for my $i (1 .. $numrows) {
1636 my (%row, @row_hiddens);
1638 $form->{"partnumber_$i"} =~ s/\"/"/g;
1640 $linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"} / ($form->{"price_factor_$i"} || 1), 4);
1641 $line_purchase_price = $form->round_amount($form->{"lastcost_$i"} * $form->{"qty_$i"} / ($form->{"price_factor_$i"} || 1), 4);
1642 $form->{assemblytotal} += $linetotal;
1643 $form->{assembly_purchase_price_total} += $line_purchase_price;
1644 $form->{"qty_$i"} = $form->format_amount(\%myconfig, $form->{"qty_$i"});
1645 $linetotal = $form->format_amount(\%myconfig, $linetotal, 2);
1646 $line_purchase_price = $form->format_amount(\%myconfig, $line_purchase_price, 2);
1647 $href = qq|$form->{script}?action=edit&id=$form->{"id_$i"}&rowcount=$i&previousform=$previousform|;
1648 map { $row{$_}{data} = "" } qw(qty unit partnumber description bom partsgroup runningnumber);
1651 if (($i >= 1) && ($i == $numrows)) {
1652 if (!$form->{previousform}) {
1653 $row{partnumber}{data} = qq|<input name="partnumber_$i" size=15 value="$form->{"partnumber_$i"}">|;
1654 $row{qty}{data} = qq|<input name="qty_$i" size=5 value="$form->{"qty_$i"}">|;
1655 $row{description}{data} = qq|<input name="description_$i" size=40 value="$form->{"description_$i"}">|;
1656 $row{partsgroup}{data} = qq|<input name="partsgroup_$i" size=10 value="$form->{"partsgroup_$i"}">|;
1660 if ($form->{previousform}) {
1661 push @row_hiddens, qw(qty bom);
1662 $row{partnumber}{data} = $form->{"partnumber_$i"};
1663 $row{qty}{data} = $form->{"qty_$i"};
1664 $row{bom}{data} = $form->{"bom_$i"} ? "x" : " ";
1665 $row{qty}{align} = 'right';
1667 $row{partnumber}{data} = qq|<a href=$href>$form->{"partnumber_$i"}</a>|;
1668 $row{qty}{data} = qq|<input name="qty_$i" size=5 value="$form->{"qty_$i"}">|;
1669 $row{runningnumber}{data} = qq|<input name="runningnumber_$i" size=3 value="$i">|;
1670 $row{bom}{data} = sprintf qq|<input name="bom_$i" type=checkbox class=checkbox value=1 %s>|,
1671 $form->{"bom_$i"} ? 'checked' : '';
1673 push @row_hiddens, qw(unit description partnumber partsgroup);
1674 $row{unit}{data} = $form->{"unit_$i"};
1675 $row{description}{data} = $form->{"description_$i"};
1676 $row{partsgroup}{data} = $form->{"partsgroup_$i"};
1677 $row{bom}{align} = 'center';
1680 $row{lastcost}{data} = $line_purchase_price;
1681 $row{total}{data} = $linetotal;
1682 $row{deliverydate}{data} = $deliverydate;
1683 $row{lastcost}{align} = 'right';
1684 $row{total}{align} = 'right';
1685 $row{deliverydate}{align} = 'right';
1687 push @row_hiddens, qw(id sellprice lastcost weight price_factor_id price_factor);
1688 $row{hiddens} = [ map +{ name => "${_}_$i", value => $form->{"${_}_$i"} }, @row_hiddens ];
1693 print $form->parse_html_template('ic/assembly_row', { COLUMNS => \@column_index, ROWS => \@ROWS, HEADER => \%header });
1695 $lxdebug->leave_sub();
1699 $lxdebug->enter_sub();
1701 # parse pricegroups. and no, don't rely on check_form for this...
1702 map { $form->{"price_$_"} = $form->parse_amount(\%myconfig, $form->{"price_$_"}) } 1 .. $form->{price_rows};
1704 if ($form->{item} eq "assembly") {
1705 my $i = $form->{assembly_rows};
1707 # if last row is empty check the form otherwise retrieve item
1708 if ( ($form->{"partnumber_$i"} eq "")
1709 && ($form->{"description_$i"} eq "")
1710 && ($form->{"partsgroup_$i"} eq "")) {
1716 IC->assembly_item(\%myconfig, \%$form);
1718 my $rows = scalar @{ $form->{item_list} };
1721 $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
1724 $form->{makemodel_rows}--;
1728 map { $form->{item_list}[$i]{$_} =~ s/\"/"/g }
1729 qw(partnumber description unit partsgroup);
1730 map { $form->{"${_}_$i"} = $form->{item_list}[0]{$_} }
1731 keys %{ $form->{item_list}[0] };
1732 $form->{"runningnumber_$i"} = $form->{assembly_rows};
1733 $form->{assembly_rows}++;
1741 $form->{rowcount} = $i;
1742 $form->{assembly_rows}++;
1749 } elsif (($form->{item} eq 'part') || ($form->{item} eq 'service')) {
1753 $lxdebug->leave_sub();
1757 $lxdebug->enter_sub();
1759 $auth->assert('part_service_assembly_edit');
1761 my ($parts_id, %newform, $previousform, $amount, $callback);
1763 # check if there is a part number - commented out, cause there is an automatic allocation of numbers
1764 # $form->isblank("partnumber", $locale->text(ucfirst $form->{item}." Part Number missing!"));
1766 # check if there is a description
1767 $form->isblank("description", $locale->text("Part Description missing!"));
1769 $form->error($locale->text("Inventory quantity must be zero before you can set this $form->{item} obsolete!"))
1770 if $form->{obsolete} && $form->{onhand} * 1 && $form->{item} ne 'service';
1772 if (!$form->{buchungsgruppen_id}) {
1773 $form->error($locale->text("Parts must have an entry type.") . " " .
1774 $locale->text("If you see this message, you most likely just setup your LX-Office and haven't added any entry types. If this is the case, the option is accessible for administrators in the System menu.")
1778 $form->error($locale->text('Description must not be empty!')) unless $form->{description};
1779 $form->error($locale->text('Partnumber must not be set to empty!')) if $form->{id} && !$form->{partnumber};
1782 $lxdebug->message($LXDebug::DEBUG1, "ic.pl: sellprice in save = $form->{sellprice}\n");
1783 if (IC->save(\%myconfig, \%$form) == 3) {
1784 $form->error($locale->text('Partnumber not unique!'));
1786 # saving the history
1787 if(!exists $form->{addition}) {
1788 $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
1789 $form->{addition} = "SAVED";
1790 $form->save_history($form->dbconnect(\%myconfig));
1792 # /saving the history
1793 $parts_id = $form->{id};
1796 # load previous variables
1797 if ($form->{previousform}) {
1799 # save the new form variables before splitting previousform
1800 map { $newform{$_} = $form->{$_} } keys %$form;
1802 $previousform = $form->unescape($form->{previousform});
1804 # don't trample on previous variables
1805 map { delete $form->{$_} } keys %newform;
1807 my $ic_cvar_configs = CVar->get_configs(module => 'IC');
1808 my @ic_cvar_fields = map { "cvar_$_->{name}" } @{ $ic_cvar_configs };
1810 # now take it apart and restore original values
1811 foreach my $item (split /&/, $previousform) {
1812 my ($key, $value) = split m/=/, $item, 2;
1813 $value =~ s/%26/&/g;
1814 $form->{$key} = $value;
1816 $form->{taxaccounts} = $newform{taxaccount2};
1818 if ($form->{item} eq 'assembly') {
1820 # undo number formatting
1821 map { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) }
1822 qw(weight listprice sellprice rop);
1824 $form->{assembly_rows}--;
1825 $i = $newform{rowcount};
1826 $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
1828 $form->{sellprice} -= $form->{"sellprice_$i"} * $form->{"qty_$i"};
1829 $form->{weight} -= $form->{"weight_$i"} * $form->{"qty_$i"};
1831 # change/add values for assembly item
1832 map { $form->{"${_}_$i"} = $newform{$_} } qw(partnumber description bin unit weight listprice sellprice inventory_accno income_accno expense_accno price_factor_id);
1833 map { $form->{"ic_${_}_$i"} = $newform{$_} } @ic_cvar_fields;
1835 # das ist __voll__ bekloppt, dass so auszurechnen jb 22.5.09
1836 #$form->{sellprice} += $form->{"sellprice_$i"} * $form->{"qty_$i"};
1837 $form->{weight} += $form->{"weight_$i"} * $form->{"qty_$i"};
1841 # set values for last invoice/order item
1842 $i = $form->{rowcount};
1843 $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
1845 map { $form->{"${_}_$i"} = $newform{$_} } qw(partnumber description bin unit listprice inventory_accno income_accno expense_accno sellprice lastcost price_factor_id);
1846 map { $form->{"ic_${_}_$i"} = $newform{$_} } @ic_cvar_fields;
1848 $form->{"longdescription_$i"} = $newform{notes};
1850 $form->{"sellprice_$i"} = $newform{lastcost} if ($form->{vendor_id});
1852 if ($form->{exchangerate} != 0) {
1853 $form->{"sellprice_$i"} /= $form->{exchangerate};
1856 $lxdebug->message($LXDebug::DEBUG1, qq|sellprice_$i in previousform 2 = | . $form->{"sellprice_$i"} . qq|\n|);
1858 map { $form->{"taxaccounts_$i"} .= "$_ " } split / /, $newform{taxaccount};
1859 chop $form->{"taxaccounts_$i"};
1860 foreach my $item (qw(description rate taxnumber)) {
1861 my $index = $form->{"taxaccounts_$i"} . "_$item";
1862 $form->{$index} = $newform{$index};
1865 # credit remaining calculation
1866 $amount = $form->{"sellprice_$i"} * (1 - $form->{"discount_$i"} / 100) * $form->{"qty_$i"};
1868 map { $form->{"${_}_base"} += $amount } (split / /, $form->{"taxaccounts_$i"});
1869 map { $amount += ($form->{"${_}_base"} * $form->{"${_}_rate"}) } split / /, $form->{"taxaccounts_$i"} if !$form->{taxincluded};
1871 $form->{creditremaining} -= $amount;
1873 # redo number formatting, because invoice parse them!
1874 map { $form->{"${_}_$i"} = $form->format_amount(\%myconfig, $form->{"${_}_$i"}) } qw(weight listprice sellprice rop);
1877 $form->{"id_$i"} = $parts_id;
1879 # Get the actual price factor (not just the ID) for the marge calculation.
1880 $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS');
1881 foreach my $pfac (@{ $form->{ALL_PRICE_FACTORS} }) {
1882 next if ($pfac->{id} != $newform{price_factor_id});
1883 $form->{"marge_price_factor_$i"} = $pfac->{factor};
1886 delete $form->{ALL_PRICE_FACTORS};
1888 delete $form->{action};
1890 # restore original callback
1891 $callback = $form->unescape($form->{callback});
1892 $form->{callback} = $form->unescape($form->{old_callback});
1893 delete $form->{old_callback};
1895 $form->{makemodel_rows}--;
1897 # put callback together
1898 foreach my $key (keys %$form) {
1900 # do single escape for Apache 2.0
1901 my $value = $form->escape($form->{$key}, 1);
1902 $callback .= qq|&$key=$value|;
1904 $form->{callback} = $callback;
1906 $lxdebug->message($LXDebug::DEBUG1, qq|ic.pl: sellprice_$i nach sub save = | . $form->{"sellprice_$i"} . qq|\n|);
1911 $lxdebug->leave_sub();
1915 $lxdebug->enter_sub();
1917 $auth->assert('part_service_assembly_edit');
1919 # saving the history
1920 if(!exists $form->{addition}) {
1921 $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
1922 $form->{addition} = "SAVED AS NEW";
1923 $form->save_history($form->dbconnect(\%myconfig));
1925 # /saving the history
1927 if ($form->{"original_partnumber"} &&
1928 ($form->{"partnumber"} eq $form->{"original_partnumber"})) {
1929 $form->{partnumber} = "";
1932 $lxdebug->leave_sub();
1936 $lxdebug->enter_sub();
1938 $auth->assert('part_service_assembly_edit');
1940 # saving the history
1941 if(!exists $form->{addition}) {
1942 $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
1943 $form->{addition} = "DELETED";
1944 $form->save_history($form->dbconnect(\%myconfig));
1946 # /saving the history
1947 my $rc = IC->delete(\%myconfig, \%$form);
1950 $form->redirect($locale->text('Item deleted!')) if ($rc > 0);
1951 $form->error($locale->text('Cannot delete item!'));
1953 $lxdebug->leave_sub();
1957 $lxdebug->enter_sub();
1959 $auth->assert('part_service_assembly_edit');
1964 pricegroup => $form->{"pricegroup_$_"},
1965 pricegroup_id => $form->{"pricegroup_id_$_"},
1966 price => $form->{"price_$_"},
1969 print $form->parse_html_template('ic/price_row', { PRICES => \@PRICES });
1971 $lxdebug->leave_sub();
1974 sub parts_language_selection {
1975 $lxdebug->enter_sub();
1977 $auth->assert('part_service_assembly_edit');
1979 our ($onload, $callback);
1981 my $languages = IC->retrieve_languages(\%myconfig, $form);
1983 if ($form->{language_values} ne "") {
1984 foreach my $item (split(/---\+\+\+---/, $form->{language_values})) {
1985 my ($language_id, $translation, $longdescription) = split(/--\+\+--/, $item);
1987 foreach my $language (@{ $languages }) {
1988 next unless ($language->{id} == $language_id);
1990 $language->{translation} = $translation;
1991 $language->{longdescription} = $longdescription;
1997 my @header_sort = qw(name longdescription);
1998 my %header_title = ( "name" => $locale->text("Name"),
1999 "longdescription" => $locale->text("Long Description"),
2003 map(+{ "column_title" => $header_title{$_},
2005 "callback" => $callback,
2009 $form->{"title"} = $locale->text("Language Values");
2011 print $form->parse_html_template("ic/parts_language_selection", { "HEADER" => \@header,
2012 "LANGUAGES" => $languages,
2013 "onload" => $onload });
2015 $lxdebug->leave_sub();
2018 sub ajax_autocomplete {
2019 $main::lxdebug->enter_sub();
2021 my $form = $main::form;
2022 my %myconfig = %main::myconfig;
2024 $form->{column} = 'description' unless $form->{column} =~ /^partnumber|description$/;
2025 $form->{$form->{column}} = $form->{q} || '';
2026 $form->{limit} = ($form->{limit} * 1) || 10;
2027 $form->{searchitems} ||= '';
2029 my @results = IC->all_parts(\%myconfig, $form);
2031 print $form->ajax_response_header(),
2032 $form->parse_html_template('ic/ajax_autocomplete');
2034 $main::lxdebug->leave_sub();
2037 sub continue { call_sub($form->{"nextsub"}); }