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'),
1128 my @itemstatus_keys = qw(active obsolete orphaned onhand short);
1129 my @callback_keys = qw(onorder ordered rfq quoted bought sold partnumber partsgroup serialnumber description make model
1130 drawing microfiche l_soldtotal l_deliverydate transdatefrom transdateto ean);
1132 # calculate dependencies
1133 for (@itemstatus_keys, @callback_keys) {
1134 next if ($form->{itemstatus} ne $_ && !$form->{$_});
1135 map { $form->{$_} = 'Y' } @{ $dependencies{$_} } if $dependencies{$_};
1138 # generate callback and optionstrings
1140 for my $key (@itemstatus_keys, @callback_keys) {
1141 next if ($form->{itemstatus} ne $key && !$form->{$key});
1142 push @options, $optiontexts{$key};
1145 # special case for lastcost
1146 if ($form->{ledgerchecks}){
1147 # zumindestens für den haken 'gekauft' muss das verhalten
1148 # so sein, das der Verkaufspreis nicht angezeigt
1149 # wird. In der Backend-Funktion all_parts wird nur mit
1151 $column_defs{sellprice}{text} = $locale->text('Price');
1152 $form->{l_lastcost} = ""
1155 if ($form->{description}) {
1156 $description = $form->{description};
1157 $description =~ s/\n/<br>/g;
1160 if ($form->{l_linetotal}) {
1161 $form->{l_onhand} = "Y";
1162 $form->{l_linetotalsellprice} = "Y" if $form->{l_sellprice};
1163 $form->{l_linetotallastcost} = $form->{searchitems} eq 'assembly' && !$form->{bom} ? "" : 'Y' if $form->{l_lastcost};
1164 $form->{l_linetotallistprice} = "Y" if $form->{l_listprice};
1167 if ($form->{searchitems} eq 'service') {
1169 # remove bin, weight and rop from list
1170 map { $form->{"l_$_"} = "" } qw(bin weight rop);
1172 $form->{l_onhand} = "";
1174 # qty is irrelevant unless bought or sold
1175 if ( $form->{bought}
1180 || $form->{quoted}) {
1181 $form->{l_onhand} = "Y";
1183 $form->{l_linetotalsellprice} = "";
1184 $form->{l_linetotallastcost} = "";
1188 IC->all_parts(\%myconfig, \%$form);
1191 partnumber description partsgroup bin onhand rop unit listprice
1192 linetotallistprice sellprice linetotalsellprice lastcost linetotallastcost
1193 priceupdate weight image drawing microfiche invnumber ordnumber quonumber
1194 transdate name serialnumber soldtotal deliverydate
1197 my @includeable_custom_variables = grep { $_->{includeable} } @{ $cvar_configs };
1198 my @searchable_custom_variables = grep { $_->{searchable} } @{ $cvar_configs };
1199 my %column_defs_cvars = map { +"cvar_$_->{name}" => { 'text' => $_->{description} } } @includeable_custom_variables;
1201 push @columns, map { "cvar_$_->{name}" } @includeable_custom_variables;
1203 %column_defs = (%column_defs,%column_defs_cvars); # nochmal die cvars als überschrift hinzufügen
1205 map { $column_defs{$_}->{visible} = $form->{"l_$_"} ? 1 : 0 } @columns;
1206 map { $column_defs{$_}->{align} = 'right' } qw(onhand sellprice listprice lastcost linetotalsellprice linetotallastcost linetotallistprice rop weight soldtotal);
1208 my @hidden_variables = (qw(l_subtotal l_linetotal searchitems itemstatus bom), @itemstatus_keys, @callback_keys, @searchable_custom_variables, map { "l_$_" } @columns);
1209 my $callback = build_std_url('action=generate_report', grep { $form->{$_} } @hidden_variables);
1211 my @sort_full = qw(partnumber description onhand soldtotal deliverydate);
1212 my @sort_no_revers = qw(partsgroup bin priceupdate invnumber ordnumber quonumber name image drawing serialnumber);
1214 foreach my $col (@sort_full) {
1215 $column_defs{$col}->{link} = join '&', $callback, "sort=$col", map { "$_=" . E($form->{$_}) } qw(revers lastsort);
1217 map { $column_defs{$_}->{link} = "${callback}&sort=$_" } @sort_no_revers;
1219 # add order to callback
1220 $form->{callback} = join '&', ($callback, map { "${_}=" . E($form->{$_}) } qw(sort revers));
1222 my $report = SL::ReportGenerator->new(\%myconfig, $form);
1224 my %attachment_basenames = (
1225 'part' => $locale->text('part_list'),
1226 'service' => $locale->text('service_list'),
1227 'assembly' => $locale->text('assembly_list'),
1230 $report->set_options('top_info_text' => $locale->text('Options') . ': ' . join(', ', grep $_, @options),
1231 'raw_bottom_info_text' => $form->parse_html_template('ic/generate_report_bottom'),
1232 'output_format' => 'HTML',
1233 'title' => $form->{title},
1234 'attachment_basename' => $attachment_basenames{$form->{searchitems}} . strftime('_%Y%m%d', localtime time),
1236 $report->set_options_from_form();
1238 $report->set_columns(%column_defs);
1239 $report->set_column_order(@columns);
1241 $report->set_export_options('generate_report', @hidden_variables, qw(sort revers));
1243 $report->set_sort_indicator($form->{sort}, $form->{revers} ? 0 : 1);
1245 CVar->add_custom_variables_to_report('module' => 'IC',
1246 'trans_id_field' => 'id',
1247 'configs' => $cvar_configs,
1248 'column_defs' => \%column_defs,
1249 'data' => $form->{parts});
1251 CVar->add_custom_variables_to_report('module' => 'IC',
1252 'sub_module' => sub { $_[0]->{ioi} },
1253 'trans_id_field' => 'ioi_id',
1254 'configs' => $cvar_configs,
1255 'column_defs' => \%column_defs,
1256 'data' => $form->{parts});
1258 my @subtotal_columns = qw(sellprice listprice lastcost);
1259 my %subtotals = map { $_ => 0 } ('onhand', @subtotal_columns);
1260 my %totals = map { $_ => 0 } @subtotal_columns;
1262 my $same_item = $form->{parts}[0]{ $form->{sort} } if (scalar @{ $form->{parts} });
1264 my $defaults = AM->get_defaults();
1267 foreach my $ref (@{ $form->{parts} }) {
1269 # fresh row, for inserting later
1270 my $row = { map { $_ => { 'data' => $ref->{$_} } } @columns };
1272 $ref->{exchangerate} ||= 1;
1273 $ref->{price_factor} ||= 1;
1274 $ref->{sellprice} *= $ref->{exchangerate} / $ref->{price_factor};
1275 $ref->{listprice} *= $ref->{exchangerate} / $ref->{price_factor};
1276 $ref->{lastcost} *= $ref->{exchangerate} / $ref->{price_factor};
1278 # use this for assemblies
1279 my $onhand = $ref->{onhand};
1281 if ($ref->{assemblyitem}) {
1282 $row->{partnumber}{align} = 'right';
1283 $row->{onhand}{data} = 0;
1284 $onhand = 0 if ($form->{sold});
1287 my $edit_link = build_std_url('action=edit', 'id=' . E($ref->{id}), 'callback');
1288 $row->{partnumber}->{link} = $edit_link;
1289 $row->{description}->{link} = $edit_link;
1291 foreach (qw(sellprice listprice lastcost)) {
1292 $row->{$_}{data} = $form->format_amount(\%myconfig, $ref->{$_}, -2);
1293 $row->{"linetotal$_"}{data} = $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{$_}, 2);
1296 map { $row->{$_}{data} = $form->format_amount(\%myconfig, $ref->{$_}); } qw(onhand rop weight soldtotal);
1298 $row->{weight}->{data} .= ' ' . $defaults->{weightunit};
1300 if (!$ref->{assemblyitem}) {
1301 foreach my $col (@subtotal_columns) {
1302 $totals{$col} += $onhand * $ref->{$col};
1303 $subtotals{$col} += $onhand * $ref->{$col};
1306 $subtotals{onhand} += $onhand;
1310 if ($ref->{module} eq 'oe') {
1311 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');
1312 $row->{ordnumber}{link} = $edit_oe_link;
1313 $row->{quonumber}{link} = $edit_oe_link if (!$ref->{ordnumber});
1316 $row->{invnumber}{link} = build_std_url("script=$ref->{module}.pl", 'action=edit', 'type=invoice', 'id=' . E($ref->{trans_id}), 'callback');
1319 # set properties of images
1320 if ($ref->{image} && (lc $report->{options}->{output_format} eq 'html')) {
1321 $row->{image}{data} = '';
1322 $row->{image}{raw_data} = '<a href="' . H($ref->{image}) . '"><img src="' . H($ref->{image}) . '" height="32" border="0"></a>';
1324 map { $row->{$_}{link} = $ref->{$_} } qw(drawing microfiche);
1326 $report->add_data($row);
1328 my $next_ref = $form->{parts}[$idx + 1];
1330 # insert subtotal rows
1331 if (($form->{l_subtotal} eq 'Y') &&
1333 (!$next_ref->{assemblyitem} && ($same_item ne $next_ref->{ $form->{sort} })))) {
1334 my $row = { map { $_ => { 'class' => 'listsubtotal', } } @columns };
1336 if (($form->{searchitems} ne 'assembly') || !$form->{bom}) {
1337 $row->{onhand}->{data} = $form->format_amount(\%myconfig, $subtotals{onhand});
1340 map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $subtotals{$_}, 2) } @subtotal_columns;
1341 map { $subtotals{$_} = 0 } ('onhand', @subtotal_columns);
1343 $report->add_data($row);
1345 $same_item = $next_ref->{ $form->{sort} };
1351 if ($form->{"l_linetotal"}) {
1352 my $row = { map { $_ => { 'class' => 'listtotal', } } @columns };
1354 map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $totals{$_}, 2) } @subtotal_columns;
1356 $report->add_separator();
1357 $report->add_data($row);
1360 $report->generate_with_headers();
1362 $lxdebug->leave_sub();
1363 } #end generate_report
1365 sub parts_subtotal {
1366 $lxdebug->enter_sub();
1368 $auth->assert('part_service_assembly_edit');
1371 our (%column_data, @column_index);
1372 our ($subtotalonhand, $totalsellprice, $totallastcost, $totallistprice, $subtotalsellprice, $subtotallastcost, $subtotallistprice);
1374 map { $column_data{$_} = "<td> </td>" } @column_index;
1375 $subtotalonhand = 0 if ($form->{searchitems} eq 'assembly' && $form->{bom});
1377 $column_data{onhand} =
1378 "<th class=listsubtotal align=right>"
1379 . $form->format_amount(\%myconfig, $subtotalonhand)
1382 $column_data{linetotalsellprice} =
1383 "<th class=listsubtotal align=right>"
1384 . $form->format_amount(\%myconfig, $subtotalsellprice, 2)
1386 $column_data{linetotallistprice} =
1387 "<th class=listsubtotal align=right>"
1388 . $form->format_amount(\%myconfig, $subtotallistprice, 2)
1390 $column_data{linetotallastcost} =
1391 "<th class=listsubtotal align=right>"
1392 . $form->format_amount(\%myconfig, $subtotallastcost, 2)
1395 $subtotalonhand = 0;
1396 $subtotalsellprice = 0;
1397 $subtotallistprice = 0;
1398 $subtotallastcost = 0;
1400 print "<tr class=listsubtotal>";
1402 map { print "\n$column_data{$_}" } @column_index;
1408 $lxdebug->leave_sub();
1412 $lxdebug->enter_sub();
1414 $auth->assert('part_service_assembly_edit');
1416 # show history button
1417 $form->{javascript} = qq|<script type="text/javascript" src="js/show_history.js"></script>|;
1418 #/show hhistory button
1419 IC->get_part(\%myconfig, \%$form);
1421 $form->{"original_partnumber"} = $form->{"partnumber"};
1423 $form->{title} = $locale->text('Edit ' . ucfirst $form->{item});
1428 $lxdebug->leave_sub();
1432 $lxdebug->enter_sub();
1434 $auth->assert('part_service_assembly_edit');
1436 IC->create_links("IC", \%myconfig, \%$form);
1439 map({ $form->{selectcurrency} .= "<option>$_\n" }
1440 split(/:/, $form->{currencies}));
1442 # parts and assemblies have the same links
1443 my $item = $form->{item};
1444 if ($form->{item} eq 'assembly') {
1448 # build the popup menus
1449 $form->{taxaccounts} = "";
1450 foreach my $key (keys %{ $form->{IC_links} }) {
1451 foreach my $ref (@{ $form->{IC_links}{$key} }) {
1453 # if this is a tax field
1454 if ($key =~ /IC_tax/) {
1455 if ($key =~ /\Q$item\E/) {
1456 $form->{taxaccounts} .= "$ref->{accno} ";
1457 $form->{"IC_tax_$ref->{accno}_description"} =
1458 "$ref->{accno}--$ref->{description}";
1461 if ($form->{amount}{ $ref->{accno} }) {
1462 $form->{"IC_tax_$ref->{accno}"} = "checked";
1465 $form->{"IC_tax_$ref->{accno}"} = "checked";
1470 $form->{"select$key"} .=
1471 "<option $ref->{selected}>$ref->{accno}--$ref->{description}\n";
1472 if ($form->{amount}{$key} eq $ref->{accno}) {
1473 $form->{$key} = "$ref->{accno}--$ref->{description}";
1479 chop $form->{taxaccounts};
1481 if (($form->{item} eq "part") || ($form->{item} eq "assembly")) {
1482 $form->{selectIC_income} = $form->{selectIC_sale};
1483 $form->{selectIC_expense} = $form->{selectIC_cogs};
1484 $form->{IC_income} = $form->{IC_sale};
1485 $form->{IC_expense} = $form->{IC_cogs};
1488 delete $form->{IC_links};
1489 delete $form->{amount};
1491 $form->get_partsgroup(\%myconfig, { all => 1 });
1493 $form->{partsgroup} = "$form->{partsgroup}--$form->{partsgroup_id}";
1495 if (@{ $form->{all_partsgroup} }) {
1496 $form->{selectpartsgroup} = qq|<option>\n|;
1497 map { $form->{selectpartsgroup} .= qq|<option value="$_->{partsgroup}--$_->{id}">$_->{partsgroup}\n| } @{ $form->{all_partsgroup} };
1500 if ($form->{item} eq 'assembly') {
1502 foreach my $i (1 .. $form->{assembly_rows}) {
1503 if ($form->{"partsgroup_id_$i"}) {
1504 $form->{"partsgroup_$i"} =
1505 qq|$form->{"partsgroup_$i"}--$form->{"partsgroup_id_$i"}|;
1508 $form->get_partsgroup(\%myconfig);
1510 if (@{ $form->{all_partsgroup} }) {
1511 $form->{selectassemblypartsgroup} = qq|<option>\n|;
1514 $form->{selectassemblypartsgroup} .=
1515 qq|<option value="$_->{partsgroup}--$_->{id}">$_->{partsgroup}\n|
1516 } @{ $form->{all_partsgroup} };
1519 $lxdebug->leave_sub();
1523 $lxdebug->enter_sub();
1525 $auth->assert('part_service_assembly_edit');
1527 $form->{eur} = $main::eur; # config dumps into namespace - yuck
1528 $form->{pg_keys} = sub { "$_[0]->{partsgroup}--$_[0]->{id}" };
1529 $form->{description_area} = ($form->{rows} = $form->numtextrows($form->{description}, 40)) > 1;
1530 $form->{notes_rows} = max 4, $form->numtextrows($form->{notes}, 40), $form->numtextrows($form->{formel}, 40);
1532 map { $form->{"is_$_"} = ($form->{item} eq $_) } qw(part service assembly);
1533 map { $form->{$_} =~ s/"/"/g; } qw(unit);
1535 $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS',
1536 'partsgroup' => 'all_partsgroup',
1537 'vendors' => 'ALL_VENDORS',);
1540 IC->retrieve_buchungsgruppen(\%myconfig, $form);
1541 @{ $form->{BUCHUNGSGRUPPEN} } = grep { $_->{id} eq $form->{buchungsgruppen_id} || ($form->{id} && $form->{orphaned}) || !$form->{id} } @{ $form->{BUCHUNGSGRUPPEN} };
1543 # use JavaScript Calendar or not (yes!)
1544 $form->{jsscript} = 1;
1546 my $units = AM->retrieve_units(\%myconfig, $form);
1547 $form->{ALL_UNITS} = [ map +{ name => $_ }, sort { $units->{$a}{sortkey} <=> $units->{$b}{sortkey} } keys %$units ];
1549 $form->{defaults} = AM->get_defaults();
1551 $form->{fokus} = "ic.partnumber";
1553 $form->{CUSTOM_VARIABLES} = CVar->get_custom_variables('module' => 'IC', 'trans_id' => $form->{id});
1555 CVar->render_inputs('variables' => $form->{CUSTOM_VARIABLES}, show_disabled_message => 1)
1556 if (scalar @{ $form->{CUSTOM_VARIABLES} });
1559 #print $form->parse_html_template('ic/form_header', { ALL_PRICE_FACTORS => $form->{ALL_PRICE_FACTORS},
1560 # ALL_UNITS => $form->{ALL_UNITS},
1561 # BUCHUNGSGRUPPEN => $form->{BUCHUNGSGRUPPEN},
1562 # payment_terms => $form->{payment_terms},
1563 # all_partsgroup => $form->{all_partsgroup}});
1564 print $form->parse_html_template('ic/form_header');
1565 $lxdebug->leave_sub();
1569 $lxdebug->enter_sub();
1571 $auth->assert('part_service_assembly_edit');
1573 print $form->parse_html_template('ic/form_footer');
1575 $lxdebug->leave_sub();
1579 $lxdebug->enter_sub();
1582 my @mm_data = grep { any { $_ ne '' } @$_{qw(make model)} } map +{ make => $form->{"make_$_"}, model => $form->{"model_$_"} }, 1 .. $numrows;
1583 delete @{$form}{grep { m/^make_\d+/ || m/^model_\d+/ } keys %{ $form }};
1584 print $form->parse_html_template('ic/makemodel', { MM_DATA => [ @mm_data, {} ], mm_rows => scalar @mm_data + 1 });
1586 $lxdebug->leave_sub();
1590 $lxdebug->enter_sub();
1593 my ($nochange, $callback, $previousform, $linetotal, $line_purchase_price, $href);
1595 our ($deliverydate); # ToDO: check if this indeed comes from global context
1597 @column_index = qw(runningnumber qty unit bom partnumber description partsgroup lastcost total);
1599 if ($form->{previousform}) {
1601 @column_index = qw(qty unit bom partnumber description partsgroup total);
1605 $form->{old_callback} = $form->{callback};
1606 $callback = $form->{callback};
1607 $form->{callback} = "$form->{script}?action=display_form";
1610 map { delete $form->{$_} } qw(action header);
1612 # save form variables in a previousform variable
1613 $previousform = $form->escape($form->escape(join '&', map {
1614 sprintf "%s=%s", Q($_), /^listprice|lastcost|sellprice$/ ? $form->format_amount(\%myconfig, $form->{$_}) : $form->{$_}
1615 } grep { ref $form->{$_} eq '' && $form->{$_} } grep { !/^select/ } sort keys %$form ));
1617 $form->{callback} = $callback;
1618 $form->{assemblytotal} = 0;
1619 $form->{assembly_purchase_price_total} = 0;
1620 $form->{weight} = 0;
1624 runningnumber => { text => $locale->text('No.'), nowrap => 1, width => '5%' },
1625 qty => { text => $locale->text('Qty'), nowrap => 1, width => '10%' },
1626 unit => { text => $locale->text('Unit'), nowrap => 1, width => '5%' },
1627 partnumber => { text => $locale->text('Part Number'), nowrap => 1, width => '20%' },
1628 description => { text => $locale->text('Part Description'), nowrap => 1, width => '50%' },
1629 lastcost => { text => $locale->text('Purchase Prices'), nowrap => 1, width => '50%' },
1630 total => { text => $locale->text('Sale Prices'), nowrap => 1, },
1631 bom => { text => $locale->text('BOM'), },
1632 partsgroup => { text => $locale->text('Group'), },
1637 for my $i (1 .. $numrows) {
1638 my (%row, @row_hiddens);
1640 $form->{"partnumber_$i"} =~ s/\"/"/g;
1642 $linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"} / ($form->{"price_factor_$i"} || 1), 4);
1643 $line_purchase_price = $form->round_amount($form->{"lastcost_$i"} * $form->{"qty_$i"} / ($form->{"price_factor_$i"} || 1), 4);
1644 $form->{assemblytotal} += $linetotal;
1645 $form->{assembly_purchase_price_total} += $line_purchase_price;
1646 $form->{"qty_$i"} = $form->format_amount(\%myconfig, $form->{"qty_$i"});
1647 $linetotal = $form->format_amount(\%myconfig, $linetotal, 2);
1648 $line_purchase_price = $form->format_amount(\%myconfig, $line_purchase_price, 2);
1649 $href = qq|$form->{script}?action=edit&id=$form->{"id_$i"}&rowcount=$i&previousform=$previousform|;
1650 map { $row{$_}{data} = "" } qw(qty unit partnumber description bom partsgroup runningnumber);
1653 if (($i >= 1) && ($i == $numrows)) {
1654 if (!$form->{previousform}) {
1655 $row{partnumber}{data} = qq|<input name="partnumber_$i" size=15 value="$form->{"partnumber_$i"}">|;
1656 $row{qty}{data} = qq|<input name="qty_$i" size=5 value="$form->{"qty_$i"}">|;
1657 $row{description}{data} = qq|<input name="description_$i" size=40 value="$form->{"description_$i"}">|;
1658 $row{partsgroup}{data} = qq|<input name="partsgroup_$i" size=10 value="$form->{"partsgroup_$i"}">|;
1662 if ($form->{previousform}) {
1663 push @row_hiddens, qw(qty bom);
1664 $row{partnumber}{data} = $form->{"partnumber_$i"};
1665 $row{qty}{data} = $form->{"qty_$i"};
1666 $row{bom}{data} = $form->{"bom_$i"} ? "x" : " ";
1667 $row{qty}{align} = 'right';
1669 $row{partnumber}{data} = qq|<a href=$href>$form->{"partnumber_$i"}</a>|;
1670 $row{qty}{data} = qq|<input name="qty_$i" size=5 value="$form->{"qty_$i"}">|;
1671 $row{runningnumber}{data} = qq|<input name="runningnumber_$i" size=3 value="$i">|;
1672 $row{bom}{data} = sprintf qq|<input name="bom_$i" type=checkbox class=checkbox value=1 %s>|,
1673 $form->{"bom_$i"} ? 'checked' : '';
1675 push @row_hiddens, qw(unit description partnumber partsgroup);
1676 $row{unit}{data} = $form->{"unit_$i"};
1677 $row{description}{data} = $form->{"description_$i"};
1678 $row{partsgroup}{data} = $form->{"partsgroup_$i"};
1679 $row{bom}{align} = 'center';
1682 $row{lastcost}{data} = $line_purchase_price;
1683 $row{total}{data} = $linetotal;
1684 $row{deliverydate}{data} = $deliverydate;
1685 $row{lastcost}{align} = 'right';
1686 $row{total}{align} = 'right';
1687 $row{deliverydate}{align} = 'right';
1689 push @row_hiddens, qw(id sellprice lastcost weight price_factor_id price_factor);
1690 $row{hiddens} = [ map +{ name => "${_}_$i", value => $form->{"${_}_$i"} }, @row_hiddens ];
1695 print $form->parse_html_template('ic/assembly_row', { COLUMNS => \@column_index, ROWS => \@ROWS, HEADER => \%header });
1697 $lxdebug->leave_sub();
1701 $lxdebug->enter_sub();
1703 # parse pricegroups. and no, don't rely on check_form for this...
1704 map { $form->{"price_$_"} = $form->parse_amount(\%myconfig, $form->{"price_$_"}) } 1 .. $form->{price_rows};
1706 if ($form->{item} eq "assembly") {
1707 my $i = $form->{assembly_rows};
1709 # if last row is empty check the form otherwise retrieve item
1710 if ( ($form->{"partnumber_$i"} eq "")
1711 && ($form->{"description_$i"} eq "")
1712 && ($form->{"partsgroup_$i"} eq "")) {
1718 IC->assembly_item(\%myconfig, \%$form);
1720 my $rows = scalar @{ $form->{item_list} };
1723 $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
1726 $form->{makemodel_rows}--;
1730 map { $form->{item_list}[$i]{$_} =~ s/\"/"/g }
1731 qw(partnumber description unit partsgroup);
1732 map { $form->{"${_}_$i"} = $form->{item_list}[0]{$_} }
1733 keys %{ $form->{item_list}[0] };
1734 $form->{"runningnumber_$i"} = $form->{assembly_rows};
1735 $form->{assembly_rows}++;
1743 $form->{rowcount} = $i;
1744 $form->{assembly_rows}++;
1751 } elsif (($form->{item} eq 'part') || ($form->{item} eq 'service')) {
1755 $lxdebug->leave_sub();
1759 $lxdebug->enter_sub();
1761 $auth->assert('part_service_assembly_edit');
1763 my ($parts_id, %newform, $previousform, $amount, $callback);
1765 # check if there is a part number - commented out, cause there is an automatic allocation of numbers
1766 # $form->isblank("partnumber", $locale->text(ucfirst $form->{item}." Part Number missing!"));
1768 # check if there is a description
1769 $form->isblank("description", $locale->text("Part Description missing!"));
1771 $form->error($locale->text("Inventory quantity must be zero before you can set this $form->{item} obsolete!"))
1772 if $form->{obsolete} && $form->{onhand} * 1 && $form->{item} ne 'service';
1774 if (!$form->{buchungsgruppen_id}) {
1775 $form->error($locale->text("Parts must have an entry type.") . " " .
1776 $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.")
1780 $form->error($locale->text('Description must not be empty!')) unless $form->{description};
1781 $form->error($locale->text('Partnumber must not be set to empty!')) if $form->{id} && !$form->{partnumber};
1784 $lxdebug->message($LXDebug::DEBUG1, "ic.pl: sellprice in save = $form->{sellprice}\n");
1785 if (IC->save(\%myconfig, \%$form) == 3) {
1786 $form->error($locale->text('Partnumber not unique!'));
1788 # saving the history
1789 if(!exists $form->{addition}) {
1790 $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
1791 $form->{addition} = "SAVED";
1792 $form->save_history($form->dbconnect(\%myconfig));
1794 # /saving the history
1795 $parts_id = $form->{id};
1798 # load previous variables
1799 if ($form->{previousform}) {
1801 # save the new form variables before splitting previousform
1802 map { $newform{$_} = $form->{$_} } keys %$form;
1804 $previousform = $form->unescape($form->{previousform});
1806 # don't trample on previous variables
1807 map { delete $form->{$_} } keys %newform;
1809 my $ic_cvar_configs = CVar->get_configs(module => 'IC');
1810 my @ic_cvar_fields = map { "cvar_$_->{name}" } @{ $ic_cvar_configs };
1812 # now take it apart and restore original values
1813 foreach my $item (split /&/, $previousform) {
1814 my ($key, $value) = split m/=/, $item, 2;
1815 $value =~ s/%26/&/g;
1816 $form->{$key} = $value;
1818 $form->{taxaccounts} = $newform{taxaccount2};
1820 if ($form->{item} eq 'assembly') {
1822 # undo number formatting
1823 map { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) }
1824 qw(weight listprice sellprice rop);
1826 $form->{assembly_rows}--;
1827 $i = $newform{rowcount};
1828 $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
1830 $form->{sellprice} -= $form->{"sellprice_$i"} * $form->{"qty_$i"};
1831 $form->{weight} -= $form->{"weight_$i"} * $form->{"qty_$i"};
1833 # change/add values for assembly item
1834 map { $form->{"${_}_$i"} = $newform{$_} } qw(partnumber description bin unit weight listprice sellprice inventory_accno income_accno expense_accno price_factor_id);
1835 map { $form->{"ic_${_}_$i"} = $newform{$_} } @ic_cvar_fields;
1837 # das ist __voll__ bekloppt, dass so auszurechnen jb 22.5.09
1838 #$form->{sellprice} += $form->{"sellprice_$i"} * $form->{"qty_$i"};
1839 $form->{weight} += $form->{"weight_$i"} * $form->{"qty_$i"};
1843 # set values for last invoice/order item
1844 $i = $form->{rowcount};
1845 $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
1847 map { $form->{"${_}_$i"} = $newform{$_} } qw(partnumber description bin unit listprice inventory_accno income_accno expense_accno sellprice lastcost price_factor_id);
1848 map { $form->{"ic_${_}_$i"} = $newform{$_} } @ic_cvar_fields;
1850 $form->{"longdescription_$i"} = $newform{notes};
1852 $form->{"sellprice_$i"} = $newform{lastcost} if ($form->{vendor_id});
1854 if ($form->{exchangerate} != 0) {
1855 $form->{"sellprice_$i"} /= $form->{exchangerate};
1858 $lxdebug->message($LXDebug::DEBUG1, qq|sellprice_$i in previousform 2 = | . $form->{"sellprice_$i"} . qq|\n|);
1860 map { $form->{"taxaccounts_$i"} .= "$_ " } split / /, $newform{taxaccount};
1861 chop $form->{"taxaccounts_$i"};
1862 foreach my $item (qw(description rate taxnumber)) {
1863 my $index = $form->{"taxaccounts_$i"} . "_$item";
1864 $form->{$index} = $newform{$index};
1867 # credit remaining calculation
1868 $amount = $form->{"sellprice_$i"} * (1 - $form->{"discount_$i"} / 100) * $form->{"qty_$i"};
1870 map { $form->{"${_}_base"} += $amount } (split / /, $form->{"taxaccounts_$i"});
1871 map { $amount += ($form->{"${_}_base"} * $form->{"${_}_rate"}) } split / /, $form->{"taxaccounts_$i"} if !$form->{taxincluded};
1873 $form->{creditremaining} -= $amount;
1875 # redo number formatting, because invoice parse them!
1876 map { $form->{"${_}_$i"} = $form->format_amount(\%myconfig, $form->{"${_}_$i"}) } qw(weight listprice sellprice rop);
1879 $form->{"id_$i"} = $parts_id;
1881 # Get the actual price factor (not just the ID) for the marge calculation.
1882 $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS');
1883 foreach my $pfac (@{ $form->{ALL_PRICE_FACTORS} }) {
1884 next if ($pfac->{id} != $newform{price_factor_id});
1885 $form->{"marge_price_factor_$i"} = $pfac->{factor};
1888 delete $form->{ALL_PRICE_FACTORS};
1890 delete $form->{action};
1892 # restore original callback
1893 $callback = $form->unescape($form->{callback});
1894 $form->{callback} = $form->unescape($form->{old_callback});
1895 delete $form->{old_callback};
1897 $form->{makemodel_rows}--;
1899 # put callback together
1900 foreach my $key (keys %$form) {
1902 # do single escape for Apache 2.0
1903 my $value = $form->escape($form->{$key}, 1);
1904 $callback .= qq|&$key=$value|;
1906 $form->{callback} = $callback;
1908 $lxdebug->message($LXDebug::DEBUG1, qq|ic.pl: sellprice_$i nach sub save = | . $form->{"sellprice_$i"} . qq|\n|);
1913 $lxdebug->leave_sub();
1917 $lxdebug->enter_sub();
1919 $auth->assert('part_service_assembly_edit');
1921 # saving the history
1922 if(!exists $form->{addition}) {
1923 $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
1924 $form->{addition} = "SAVED AS NEW";
1925 $form->save_history($form->dbconnect(\%myconfig));
1927 # /saving the history
1929 if ($form->{"original_partnumber"} &&
1930 ($form->{"partnumber"} eq $form->{"original_partnumber"})) {
1931 $form->{partnumber} = "";
1934 $lxdebug->leave_sub();
1938 $lxdebug->enter_sub();
1940 $auth->assert('part_service_assembly_edit');
1942 # saving the history
1943 if(!exists $form->{addition}) {
1944 $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
1945 $form->{addition} = "DELETED";
1946 $form->save_history($form->dbconnect(\%myconfig));
1948 # /saving the history
1949 my $rc = IC->delete(\%myconfig, \%$form);
1952 $form->redirect($locale->text('Item deleted!')) if ($rc > 0);
1953 $form->error($locale->text('Cannot delete item!'));
1955 $lxdebug->leave_sub();
1959 $lxdebug->enter_sub();
1961 $auth->assert('part_service_assembly_edit');
1966 pricegroup => $form->{"pricegroup_$_"},
1967 pricegroup_id => $form->{"pricegroup_id_$_"},
1968 price => $form->{"price_$_"},
1971 print $form->parse_html_template('ic/price_row', { PRICES => \@PRICES });
1973 $lxdebug->leave_sub();
1976 sub parts_language_selection {
1977 $lxdebug->enter_sub();
1979 $auth->assert('part_service_assembly_edit');
1981 our ($onload, $callback);
1983 my $languages = IC->retrieve_languages(\%myconfig, $form);
1985 if ($form->{language_values} ne "") {
1986 foreach my $item (split(/---\+\+\+---/, $form->{language_values})) {
1987 my ($language_id, $translation, $longdescription) = split(/--\+\+--/, $item);
1989 foreach my $language (@{ $languages }) {
1990 next unless ($language->{id} == $language_id);
1992 $language->{translation} = $translation;
1993 $language->{longdescription} = $longdescription;
1999 my @header_sort = qw(name longdescription);
2000 my %header_title = ( "name" => $locale->text("Name"),
2001 "longdescription" => $locale->text("Long Description"),
2005 map(+{ "column_title" => $header_title{$_},
2007 "callback" => $callback,
2011 $form->{"title"} = $locale->text("Language Values");
2013 print $form->parse_html_template("ic/parts_language_selection", { "HEADER" => \@header,
2014 "LANGUAGES" => $languages,
2015 "onload" => $onload });
2017 $lxdebug->leave_sub();
2020 sub ajax_autocomplete {
2021 $main::lxdebug->enter_sub();
2023 my $form = $main::form;
2024 my %myconfig = %main::myconfig;
2026 $form->{column} = 'description' unless $form->{column} =~ /^partnumber|description$/;
2027 $form->{$form->{column}} = $form->{q} || '';
2028 $form->{limit} = ($form->{limit} * 1) || 10;
2029 $form->{searchitems} ||= '';
2031 my @results = IC->all_parts(\%myconfig, $form);
2033 print $form->ajax_response_header(),
2034 $form->parse_html_template('ic/ajax_autocomplete');
2036 $main::lxdebug->leave_sub();
2039 sub continue { call_sub($form->{"nextsub"}); }