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});
1026 $revers = $form->{revers};
1027 $lastsort = $form->{lastsort};
1029 # sorting and direction of sorting
1030 # ToDO: change this to the simpler field+direction method
1031 if (($form->{lastsort} eq "") && ($form->{sort} eq undef)) {
1032 $form->{revers} = 0;
1033 $form->{lastsort} = "partnumber";
1034 $form->{sort} = "partnumber";
1036 if ($form->{lastsort} eq $form->{sort}) {
1037 $form->{revers} = 1 - $form->{revers};
1039 $form->{revers} = 0;
1040 $form->{lastsort} = $form->{sort};
1044 # special case if we have a serialnumber limit search
1045 # serialnumbers are only given in invoices and orders,
1046 # so they can only pop up in bought, sold, rfq, and quoted stuff
1047 $form->{no_sn_joins} = 'Y' if ( !$form->{bought} && !$form->{sold}
1048 && !$form->{rfq} && !$form->{quoted}
1049 && ($form->{l_serialnumber} || $form->{serialnumber}));
1051 # special case for any checkbox of bought | sold | onorder | ordered | rfq | quoted.
1052 # if any of these are ticked the behavior changes slightly for lastcost
1053 # since all those are aggregation checks for the legder tables this is an internal switch
1054 # refered to as ledgerchecks
1055 $form->{ledgerchecks} = 'Y' if ( $form->{bought} || $form->{sold} || $form->{onorder}
1056 || $form->{ordered} || $form->{rfq} || $form->{quoted});
1058 # if something should be activated if something else is active, enter it here
1059 my %dependencies = (
1060 onhand => [ qw(l_onhand) ],
1061 short => [ qw(l_onhand) ],
1062 onorder => [ qw(l_ordnumber) ],
1063 ordered => [ qw(l_ordnumber) ],
1064 rfq => [ qw(l_quonumber) ],
1065 quoted => [ qw(l_quonumber) ],
1066 bought => [ qw(l_invnumber) ],
1067 sold => [ qw(l_invnumber) ],
1068 ledgerchecks => [ qw(l_name) ],
1069 serialnumber => [ qw(l_serialnumber) ],
1070 no_sn_joins => [ qw(bought sold) ],
1073 # these strings get displayed at the top of the results to indicate the user which switches were used
1075 active => $locale->text('Active'),
1076 obsolete => $locale->text('Obsolete'),
1077 orphaned => $locale->text('Orphaned'),
1078 onhand => $locale->text('On Hand'),
1079 short => $locale->text('Short'),
1080 onorder => $locale->text('On Order'),
1081 ordered => $locale->text('Ordered'),
1082 rfq => $locale->text('RFQ'),
1083 quoted => $locale->text('Quoted'),
1084 bought => $locale->text('Bought'),
1085 sold => $locale->text('Sold'),
1086 transdatefrom => $locale->text('From') . " " . $locale->date(\%myconfig, $form->{transdatefrom}, 1),
1087 transdateto => $locale->text('To (time)') . " " . $locale->date(\%myconfig, $form->{transdateto}, 1),
1088 partnumber => $locale->text('Part Number') . ": '$form->{partnumber}'",
1089 partsgroup => $locale->text('Group') . ": '$form->{partsgroup}'",
1090 serialnumber => $locale->text('Serial Number') . ": '$form->{serialnumber}'",
1091 description => $locale->text('Part Description') . ": '$form->{description}'",
1092 make => $locale->text('Make') . ": '$form->{make}'",
1093 model => $locale->text('Model') . ": '$form->{model}'",
1094 drawing => $locale->text('Drawing') . ": '$form->{drawing}'",
1095 microfiche => $locale->text('Microfiche') . ": '$form->{microfiche}'",
1096 l_soldtotal => $locale->text('soldtotal'),
1097 ean => $locale->text('EAN') . ": '$form->{ean}'",
1100 my @itemstatus_keys = qw(active obsolete orphaned onhand short);
1101 my @callback_keys = qw(onorder ordered rfq quoted bought sold partnumber partsgroup serialnumber description make model
1102 drawing microfiche l_soldtotal l_deliverydate transdatefrom transdateto ean);
1104 # calculate dependencies
1105 for (@itemstatus_keys, @callback_keys) {
1106 next if ($form->{itemstatus} ne $_ && !$form->{$_});
1107 map { $form->{$_} = 'Y' } @{ $dependencies{$_} } if $dependencies{$_};
1110 # generate callback and optionstrings
1112 for my $key (@itemstatus_keys, @callback_keys) {
1113 next if ($form->{itemstatus} ne $key && !$form->{$key});
1114 push @options, $optiontexts{$key};
1117 # special case for lastcost
1118 $form->{l_lastcost} = "" if $form->{ledgerchecks};
1120 if ($form->{description}) {
1121 $description = $form->{description};
1122 $description =~ s/\n/<br>/g;
1125 if ($form->{l_linetotal}) {
1126 $form->{l_onhand} = "Y";
1127 $form->{l_linetotalsellprice} = "Y" if $form->{l_sellprice};
1128 $form->{l_linetotallastcost} = $form->{searchitems} eq 'assembly' && !$form->{bom} ? "" : 'Y' if $form->{l_lastcost};
1129 $form->{l_linetotallistprice} = "Y" if $form->{l_listprice};
1132 if ($form->{searchitems} eq 'service') {
1134 # remove bin, weight and rop from list
1135 map { $form->{"l_$_"} = "" } qw(bin weight rop);
1137 $form->{l_onhand} = "";
1139 # qty is irrelevant unless bought or sold
1140 if ( $form->{bought}
1145 || $form->{quoted}) {
1146 $form->{l_onhand} = "Y";
1148 $form->{l_linetotalsellprice} = "";
1149 $form->{l_linetotallastcost} = "";
1153 IC->all_parts(\%myconfig, \%$form);
1156 partnumber description partsgroup bin onhand rop unit listprice
1157 linetotallistprice sellprice linetotalsellprice lastcost linetotallastcost
1158 priceupdate weight image drawing microfiche invnumber ordnumber quonumber
1159 transdate name serialnumber soldtotal deliverydate ean
1162 my @includeable_custom_variables = grep { $_->{includeable} } @{ $cvar_configs };
1163 my @searchable_custom_variables = grep { $_->{searchable} } @{ $cvar_configs };
1164 my %column_defs_cvars = map { +"cvar_$_->{name}" => { 'text' => $_->{description} } } @includeable_custom_variables;
1166 push @columns, map { "cvar_$_->{name}" } @includeable_custom_variables;
1169 'bin' => { 'text' => $locale->text('Bin'), },
1170 'deliverydate' => { 'text' => $locale->text('deliverydate'), },
1171 'description' => { 'text' => $locale->text('Part Description'), },
1172 'drawing' => { 'text' => $locale->text('Drawing'), },
1173 'image' => { 'text' => $locale->text('Image'), },
1174 'invnumber' => { 'text' => $locale->text('Invoice Number'), },
1175 'lastcost' => { 'text' => $locale->text('Last Cost'), },
1176 'linetotallastcost' => { 'text' => $locale->text('Extended'), },
1177 'linetotallistprice' => { 'text' => $locale->text('Extended'), },
1178 'linetotalsellprice' => { 'text' => $locale->text('Extended'), },
1179 'listprice' => { 'text' => $locale->text('List Price'), },
1180 'microfiche' => { 'text' => $locale->text('Microfiche'), },
1181 'name' => { 'text' => $locale->text('Name'), },
1182 'onhand' => { 'text' => $locale->text('Qty'), },
1183 'ordnumber' => { 'text' => $locale->text('Order Number'), },
1184 'partnumber' => { 'text' => $locale->text('Part Number'), },
1185 'partsgroup' => { 'text' => $locale->text('Group'), },
1186 'priceupdate' => { 'text' => $locale->text('Updated'), },
1187 'quonumber' => { 'text' => $locale->text('Quotation'), },
1188 'rop' => { 'text' => $locale->text('ROP'), },
1189 'sellprice' => { 'text' => $locale->text('Sell Price'), },
1190 'serialnumber' => { 'text' => $locale->text('Serial Number'), },
1191 'soldtotal' => { 'text' => $locale->text('soldtotal'), },
1192 'transdate' => { 'text' => $locale->text('Transdate'), },
1193 'unit' => { 'text' => $locale->text('Unit'), },
1194 'weight' => { 'text' => $locale->text('Weight'), },
1195 'ean' => { 'text' => $locale->text('EAN'), },
1199 map { $column_defs{$_}->{visible} = $form->{"l_$_"} ? 1 : 0 } @columns;
1200 map { $column_defs{$_}->{align} = 'right' } qw(onhand sellprice listprice lastcost linetotalsellprice linetotallastcost linetotallistprice rop weight soldtotal);
1202 my @hidden_variables = (qw(l_subtotal l_linetotal searchitems itemstatus bom), @itemstatus_keys, @callback_keys, @searchable_custom_variables, map { "l_$_" } @columns);
1203 my $callback = build_std_url('action=generate_report', grep { $form->{$_} } @hidden_variables);
1205 my @sort_full = qw(partnumber description onhand soldtotal deliverydate);
1206 my @sort_no_revers = qw(partsgroup bin priceupdate invnumber ordnumber quonumber name image drawing serialnumber);
1208 foreach my $col (@sort_full) {
1209 $column_defs{$col}->{link} = join '&', $callback, "sort=$col", map { "$_=" . E($form->{$_}) } qw(revers lastsort);
1211 map { $column_defs{$_}->{link} = "${callback}&sort=$_" } @sort_no_revers;
1213 # add order to callback
1214 $form->{callback} = join '&', ($callback, map { "${_}=" . E($form->{$_}) } qw(sort revers));
1216 my $report = SL::ReportGenerator->new(\%myconfig, $form);
1218 my %attachment_basenames = (
1219 'part' => $locale->text('part_list'),
1220 'service' => $locale->text('service_list'),
1221 'assembly' => $locale->text('assembly_list'),
1224 $report->set_options('top_info_text' => $locale->text('Options') . ': ' . join(', ', grep $_, @options),
1225 'raw_bottom_info_text' => $form->parse_html_template('ic/generate_report_bottom'),
1226 'output_format' => 'HTML',
1227 'title' => $form->{title},
1228 'attachment_basename' => $attachment_basenames{$form->{searchitems}} . strftime('_%Y%m%d', localtime time),
1230 $report->set_options_from_form();
1232 $report->set_columns(%column_defs);
1233 $report->set_column_order(@columns);
1235 $report->set_export_options('generate_report', @hidden_variables, qw(sort revers));
1237 $report->set_sort_indicator($form->{sort}, $form->{revers} ? 0 : 1);
1239 CVar->add_custom_variables_to_report('module' => 'IC',
1240 'trans_id_field' => 'id',
1241 'configs' => $cvar_configs,
1242 'column_defs' => \%column_defs,
1243 'data' => $form->{parts});
1245 CVar->add_custom_variables_to_report('module' => 'IC',
1246 'sub_module' => sub { $_[0]->{ioi} },
1247 'trans_id_field' => 'ioi_id',
1248 'configs' => $cvar_configs,
1249 'column_defs' => \%column_defs,
1250 'data' => $form->{parts});
1252 my @subtotal_columns = qw(sellprice listprice lastcost);
1253 my %subtotals = map { $_ => 0 } ('onhand', @subtotal_columns);
1254 my %totals = map { $_ => 0 } @subtotal_columns;
1256 my $same_item = $form->{parts}[0]{ $form->{sort} } if (scalar @{ $form->{parts} });
1258 my $defaults = AM->get_defaults();
1261 foreach my $ref (@{ $form->{parts} }) {
1263 # fresh row, for inserting later
1264 my $row = { map { $_ => { 'data' => $ref->{$_} } } @columns };
1266 $ref->{exchangerate} ||= 1;
1267 $ref->{price_factor} ||= 1;
1268 $ref->{sellprice} *= $ref->{exchangerate} / $ref->{price_factor};
1269 $ref->{listprice} *= $ref->{exchangerate} / $ref->{price_factor};
1270 $ref->{lastcost} *= $ref->{exchangerate} / $ref->{price_factor};
1272 # use this for assemblies
1273 my $onhand = $ref->{onhand};
1275 if ($ref->{assemblyitem}) {
1276 $row->{partnumber}{align} = 'right';
1277 $row->{onhand}{data} = 0;
1278 $onhand = 0 if ($form->{sold});
1281 my $edit_link = build_std_url('action=edit', 'id=' . E($ref->{id}), 'callback');
1282 $row->{partnumber}->{link} = $edit_link;
1283 $row->{description}->{link} = $edit_link;
1285 foreach (qw(sellprice listprice lastcost)) {
1286 $row->{$_}{data} = $form->format_amount(\%myconfig, $ref->{$_}, -2);
1287 $row->{"linetotal$_"}{data} = $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{$_}, 2);
1290 map { $row->{$_}{data} = $form->format_amount(\%myconfig, $ref->{$_}); } qw(onhand rop weight soldtotal);
1292 $row->{weight}->{data} .= ' ' . $defaults->{weightunit};
1294 if (!$ref->{assemblyitem}) {
1295 foreach my $col (@subtotal_columns) {
1296 $totals{$col} += $onhand * $ref->{$col};
1297 $subtotals{$col} += $onhand * $ref->{$col};
1300 $subtotals{onhand} += $onhand;
1304 if ($ref->{module} eq 'oe') {
1305 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');
1306 $row->{ordnumber}{link} = $edit_oe_link;
1307 $row->{quonumber}{link} = $edit_oe_link if (!$ref->{ordnumber});
1310 $row->{invnumber}{link} = build_std_url("script=$ref->{module}.pl", 'action=edit', 'type=invoice', 'id=' . E($ref->{trans_id}), 'callback');
1313 # set properties of images
1314 if ($ref->{image} && (lc $report->{options}->{output_format} eq 'html')) {
1315 $row->{image}{data} = '';
1316 $row->{image}{raw_data} = '<a href="' . H($ref->{image}) . '"><img src="' . H($ref->{image}) . '" height="32" border="0"></a>';
1318 map { $row->{$_}{link} = $ref->{$_} } qw(drawing microfiche);
1320 $report->add_data($row);
1322 my $next_ref = $form->{parts}[$idx + 1];
1324 # insert subtotal rows
1325 if (($form->{l_subtotal} eq 'Y') &&
1327 (!$next_ref->{assemblyitem} && ($same_item ne $next_ref->{ $form->{sort} })))) {
1328 my $row = { map { $_ => { 'class' => 'listsubtotal', } } @columns };
1330 if (($form->{searchitems} ne 'assembly') || !$form->{bom}) {
1331 $row->{onhand}->{data} = $form->format_amount(\%myconfig, $subtotals{onhand});
1334 map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $subtotals{$_}, 2) } @subtotal_columns;
1335 map { $subtotals{$_} = 0 } ('onhand', @subtotal_columns);
1337 $report->add_data($row);
1339 $same_item = $next_ref->{ $form->{sort} };
1345 if ($form->{"l_linetotal"}) {
1346 my $row = { map { $_ => { 'class' => 'listtotal', } } @columns };
1348 map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $totals{$_}, 2) } @subtotal_columns;
1350 $report->add_separator();
1351 $report->add_data($row);
1354 $report->generate_with_headers();
1356 $lxdebug->leave_sub();
1357 } #end generate_report
1359 sub parts_subtotal {
1360 $lxdebug->enter_sub();
1362 $auth->assert('part_service_assembly_edit');
1365 our (%column_data, @column_index);
1366 our ($subtotalonhand, $totalsellprice, $totallastcost, $totallistprice, $subtotalsellprice, $subtotallastcost, $subtotallistprice);
1368 map { $column_data{$_} = "<td> </td>" } @column_index;
1369 $subtotalonhand = 0 if ($form->{searchitems} eq 'assembly' && $form->{bom});
1371 $column_data{onhand} =
1372 "<th class=listsubtotal align=right>"
1373 . $form->format_amount(\%myconfig, $subtotalonhand)
1376 $column_data{linetotalsellprice} =
1377 "<th class=listsubtotal align=right>"
1378 . $form->format_amount(\%myconfig, $subtotalsellprice, 2)
1380 $column_data{linetotallistprice} =
1381 "<th class=listsubtotal align=right>"
1382 . $form->format_amount(\%myconfig, $subtotallistprice, 2)
1384 $column_data{linetotallastcost} =
1385 "<th class=listsubtotal align=right>"
1386 . $form->format_amount(\%myconfig, $subtotallastcost, 2)
1389 $subtotalonhand = 0;
1390 $subtotalsellprice = 0;
1391 $subtotallistprice = 0;
1392 $subtotallastcost = 0;
1394 print "<tr class=listsubtotal>";
1396 map { print "\n$column_data{$_}" } @column_index;
1402 $lxdebug->leave_sub();
1406 $lxdebug->enter_sub();
1408 $auth->assert('part_service_assembly_edit');
1410 # show history button
1411 $form->{javascript} = qq|<script type="text/javascript" src="js/show_history.js"></script>|;
1412 #/show hhistory button
1413 IC->get_part(\%myconfig, \%$form);
1415 $form->{"original_partnumber"} = $form->{"partnumber"};
1417 $form->{title} = $locale->text('Edit ' . ucfirst $form->{item});
1422 $lxdebug->leave_sub();
1426 $lxdebug->enter_sub();
1428 $auth->assert('part_service_assembly_edit');
1430 IC->create_links("IC", \%myconfig, \%$form);
1433 map({ $form->{selectcurrency} .= "<option>$_\n" }
1434 split(/:/, $form->{currencies}));
1436 # parts and assemblies have the same links
1437 my $item = $form->{item};
1438 if ($form->{item} eq 'assembly') {
1442 # build the popup menus
1443 $form->{taxaccounts} = "";
1444 foreach my $key (keys %{ $form->{IC_links} }) {
1445 foreach my $ref (@{ $form->{IC_links}{$key} }) {
1447 # if this is a tax field
1448 if ($key =~ /IC_tax/) {
1449 if ($key =~ /\Q$item\E/) {
1450 $form->{taxaccounts} .= "$ref->{accno} ";
1451 $form->{"IC_tax_$ref->{accno}_description"} =
1452 "$ref->{accno}--$ref->{description}";
1455 if ($form->{amount}{ $ref->{accno} }) {
1456 $form->{"IC_tax_$ref->{accno}"} = "checked";
1459 $form->{"IC_tax_$ref->{accno}"} = "checked";
1464 $form->{"select$key"} .=
1465 "<option $ref->{selected}>$ref->{accno}--$ref->{description}\n";
1466 if ($form->{amount}{$key} eq $ref->{accno}) {
1467 $form->{$key} = "$ref->{accno}--$ref->{description}";
1473 chop $form->{taxaccounts};
1475 if (($form->{item} eq "part") || ($form->{item} eq "assembly")) {
1476 $form->{selectIC_income} = $form->{selectIC_sale};
1477 $form->{selectIC_expense} = $form->{selectIC_cogs};
1478 $form->{IC_income} = $form->{IC_sale};
1479 $form->{IC_expense} = $form->{IC_cogs};
1482 delete $form->{IC_links};
1483 delete $form->{amount};
1485 $form->get_partsgroup(\%myconfig, { all => 1 });
1487 $form->{partsgroup} = "$form->{partsgroup}--$form->{partsgroup_id}";
1489 if (@{ $form->{all_partsgroup} }) {
1490 $form->{selectpartsgroup} = qq|<option>\n|;
1491 map { $form->{selectpartsgroup} .= qq|<option value="$_->{partsgroup}--$_->{id}">$_->{partsgroup}\n| } @{ $form->{all_partsgroup} };
1494 if ($form->{item} eq 'assembly') {
1496 foreach my $i (1 .. $form->{assembly_rows}) {
1497 if ($form->{"partsgroup_id_$i"}) {
1498 $form->{"partsgroup_$i"} =
1499 qq|$form->{"partsgroup_$i"}--$form->{"partsgroup_id_$i"}|;
1502 $form->get_partsgroup(\%myconfig);
1504 if (@{ $form->{all_partsgroup} }) {
1505 $form->{selectassemblypartsgroup} = qq|<option>\n|;
1508 $form->{selectassemblypartsgroup} .=
1509 qq|<option value="$_->{partsgroup}--$_->{id}">$_->{partsgroup}\n|
1510 } @{ $form->{all_partsgroup} };
1513 $lxdebug->leave_sub();
1517 $lxdebug->enter_sub();
1519 $auth->assert('part_service_assembly_edit');
1521 $form->{eur} = $main::eur; # config dumps into namespace - yuck
1522 $form->{pg_keys} = sub { "$_[0]->{partsgroup}--$_[0]->{id}" };
1523 $form->{description_area} = ($form->{rows} = $form->numtextrows($form->{description}, 40)) > 1;
1524 $form->{notes_rows} = max 4, $form->numtextrows($form->{notes}, 40), $form->numtextrows($form->{formel}, 40);
1526 map { $form->{"is_$_"} = ($form->{item} eq $_) } qw(part service assembly);
1527 map { $form->{$_} =~ s/"/"/g; } qw(unit);
1529 $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS',
1530 'partsgroup' => 'all_partsgroup',
1531 'vendors' => 'ALL_VENDORS',);
1534 IC->retrieve_buchungsgruppen(\%myconfig, $form);
1535 @{ $form->{BUCHUNGSGRUPPEN} } = grep { $_->{id} eq $form->{buchungsgruppen_id} || ($form->{id} && $form->{orphaned}) || !$form->{id} } @{ $form->{BUCHUNGSGRUPPEN} };
1537 # use JavaScript Calendar or not (yes!)
1538 $form->{jsscript} = 1;
1540 my $units = AM->retrieve_units(\%myconfig, $form);
1541 $form->{ALL_UNITS} = [ map +{ name => $_ }, sort { $units->{$a}{sortkey} <=> $units->{$b}{sortkey} } keys %$units ];
1543 $form->{defaults} = AM->get_defaults();
1545 $form->{fokus} = "ic.partnumber";
1547 $form->{CUSTOM_VARIABLES} = CVar->get_custom_variables('module' => 'IC', 'trans_id' => $form->{id});
1549 CVar->render_inputs('variables' => $form->{CUSTOM_VARIABLES}, show_disabled_message => 1)
1550 if (scalar @{ $form->{CUSTOM_VARIABLES} });
1553 #print $form->parse_html_template('ic/form_header', { ALL_PRICE_FACTORS => $form->{ALL_PRICE_FACTORS},
1554 # ALL_UNITS => $form->{ALL_UNITS},
1555 # BUCHUNGSGRUPPEN => $form->{BUCHUNGSGRUPPEN},
1556 # payment_terms => $form->{payment_terms},
1557 # all_partsgroup => $form->{all_partsgroup}});
1558 print $form->parse_html_template('ic/form_header');
1559 $lxdebug->leave_sub();
1563 $lxdebug->enter_sub();
1565 $auth->assert('part_service_assembly_edit');
1567 print $form->parse_html_template('ic/form_footer');
1569 $lxdebug->leave_sub();
1573 $lxdebug->enter_sub();
1576 my @mm_data = grep { any { $_ ne '' } @$_{qw(make model)} } map +{ make => $form->{"make_$_"}, model => $form->{"model_$_"} }, 1 .. $numrows;
1577 delete @{$form}{grep { m/^make_\d+/ || m/^model_\d+/ } keys %{ $form }};
1578 print $form->parse_html_template('ic/makemodel', { MM_DATA => [ @mm_data, {} ], mm_rows => scalar @mm_data + 1 });
1580 $lxdebug->leave_sub();
1584 $lxdebug->enter_sub();
1587 my ($nochange, $callback, $previousform, $linetotal, $line_purchase_price, $href);
1589 our ($deliverydate); # ToDO: check if this indeed comes from global context
1591 @column_index = qw(runningnumber qty unit bom partnumber description partsgroup lastcost total);
1593 if ($form->{previousform}) {
1595 @column_index = qw(qty unit bom partnumber description partsgroup total);
1599 $form->{old_callback} = $form->{callback};
1600 $callback = $form->{callback};
1601 $form->{callback} = "$form->{script}?action=display_form";
1604 map { delete $form->{$_} } qw(action header);
1606 # save form variables in a previousform variable
1607 $previousform = $form->escape($form->escape(join '&', map {
1608 sprintf "%s=%s", Q($_), /^listprice|lastcost|sellprice$/ ? $form->format_amount(\%myconfig, $form->{$_}) : $form->{$_}
1609 } grep { ref $form->{$_} eq '' && $form->{$_} } grep { !/^select/ } sort keys %$form ));
1611 $form->{callback} = $callback;
1612 $form->{assemblytotal} = 0;
1613 $form->{assembly_purchase_price_total} = 0;
1614 $form->{weight} = 0;
1618 runningnumber => { text => $locale->text('No.'), nowrap => 1, width => '5%' },
1619 qty => { text => $locale->text('Qty'), nowrap => 1, width => '10%' },
1620 unit => { text => $locale->text('Unit'), nowrap => 1, width => '5%' },
1621 partnumber => { text => $locale->text('Part Number'), nowrap => 1, width => '20%' },
1622 description => { text => $locale->text('Part Description'), nowrap => 1, width => '50%' },
1623 lastcost => { text => $locale->text('Purchase Prices'), nowrap => 1, width => '50%' },
1624 total => { text => $locale->text('Sale Prices'), nowrap => 1, },
1625 bom => { text => $locale->text('BOM'), },
1626 partsgroup => { text => $locale->text('Group'), },
1631 for my $i (1 .. $numrows) {
1632 my (%row, @row_hiddens);
1634 $form->{"partnumber_$i"} =~ s/\"/"/g;
1636 $linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"} / ($form->{"price_factor_$i"} || 1), 4);
1637 $line_purchase_price = $form->round_amount($form->{"lastcost_$i"} * $form->{"qty_$i"} / ($form->{"price_factor_$i"} || 1), 4);
1638 $form->{assemblytotal} += $linetotal;
1639 $form->{assembly_purchase_price_total} += $line_purchase_price;
1640 $form->{"qty_$i"} = $form->format_amount(\%myconfig, $form->{"qty_$i"});
1641 $linetotal = $form->format_amount(\%myconfig, $linetotal, 2);
1642 $line_purchase_price = $form->format_amount(\%myconfig, $line_purchase_price, 2);
1643 $href = qq|$form->{script}?action=edit&id=$form->{"id_$i"}&rowcount=$i&previousform=$previousform|;
1644 map { $row{$_}{data} = "" } qw(qty unit partnumber description bom partsgroup runningnumber);
1647 if (($i >= 1) && ($i == $numrows)) {
1648 if (!$form->{previousform}) {
1649 $row{partnumber}{data} = qq|<input name="partnumber_$i" size=15 value="$form->{"partnumber_$i"}">|;
1650 $row{qty}{data} = qq|<input name="qty_$i" size=5 value="$form->{"qty_$i"}">|;
1651 $row{description}{data} = qq|<input name="description_$i" size=40 value="$form->{"description_$i"}">|;
1652 $row{partsgroup}{data} = qq|<input name="partsgroup_$i" size=10 value="$form->{"partsgroup_$i"}">|;
1656 if ($form->{previousform}) {
1657 push @row_hiddens, qw(qty bom);
1658 $row{partnumber}{data} = $form->{"partnumber_$i"};
1659 $row{qty}{data} = $form->{"qty_$i"};
1660 $row{bom}{data} = $form->{"bom_$i"} ? "x" : " ";
1661 $row{qty}{align} = 'right';
1663 $row{partnumber}{data} = qq|<a href=$href>$form->{"partnumber_$i"}</a>|;
1664 $row{qty}{data} = qq|<input name="qty_$i" size=5 value="$form->{"qty_$i"}">|;
1665 $row{runningnumber}{data} = qq|<input name="runningnumber_$i" size=3 value="$i">|;
1666 $row{bom}{data} = sprintf qq|<input name="bom_$i" type=checkbox class=checkbox value=1 %s>|,
1667 $form->{"bom_$i"} ? 'checked' : '';
1669 push @row_hiddens, qw(unit description partnumber partsgroup);
1670 $row{unit}{data} = $form->{"unit_$i"};
1671 $row{description}{data} = $form->{"description_$i"};
1672 $row{partsgroup}{data} = $form->{"partsgroup_$i"};
1673 $row{bom}{align} = 'center';
1676 $row{lastcost}{data} = $line_purchase_price;
1677 $row{total}{data} = $linetotal;
1678 $row{deliverydate}{data} = $deliverydate;
1679 $row{lastcost}{align} = 'right';
1680 $row{total}{align} = 'right';
1681 $row{deliverydate}{align} = 'right';
1683 push @row_hiddens, qw(id sellprice lastcost weight price_factor_id price_factor);
1684 $row{hiddens} = [ map +{ name => "${_}_$i", value => $form->{"${_}_$i"} }, @row_hiddens ];
1689 print $form->parse_html_template('ic/assembly_row', { COLUMNS => \@column_index, ROWS => \@ROWS, HEADER => \%header });
1691 $lxdebug->leave_sub();
1695 $lxdebug->enter_sub();
1697 # parse pricegroups. and no, don't rely on check_form for this...
1698 map { $form->{"price_$_"} = $form->parse_amount(\%myconfig, $form->{"price_$_"}) } 1 .. $form->{price_rows};
1700 if ($form->{item} eq "assembly") {
1701 my $i = $form->{assembly_rows};
1703 # if last row is empty check the form otherwise retrieve item
1704 if ( ($form->{"partnumber_$i"} eq "")
1705 && ($form->{"description_$i"} eq "")
1706 && ($form->{"partsgroup_$i"} eq "")) {
1712 IC->assembly_item(\%myconfig, \%$form);
1714 my $rows = scalar @{ $form->{item_list} };
1717 $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
1720 $form->{makemodel_rows}--;
1724 map { $form->{item_list}[$i]{$_} =~ s/\"/"/g }
1725 qw(partnumber description unit partsgroup);
1726 map { $form->{"${_}_$i"} = $form->{item_list}[0]{$_} }
1727 keys %{ $form->{item_list}[0] };
1728 $form->{"runningnumber_$i"} = $form->{assembly_rows};
1729 $form->{assembly_rows}++;
1737 $form->{rowcount} = $i;
1738 $form->{assembly_rows}++;
1745 } elsif (($form->{item} eq 'part') || ($form->{item} eq 'service')) {
1749 $lxdebug->leave_sub();
1753 $lxdebug->enter_sub();
1755 $auth->assert('part_service_assembly_edit');
1757 my ($parts_id, %newform, $previousform, $amount, $callback);
1759 # check if there is a part number - commented out, cause there is an automatic allocation of numbers
1760 # $form->isblank("partnumber", $locale->text(ucfirst $form->{item}." Part Number missing!"));
1762 # check if there is a description
1763 $form->isblank("description", $locale->text("Part Description missing!"));
1765 $form->error($locale->text("Inventory quantity must be zero before you can set this $form->{item} obsolete!"))
1766 if $form->{obsolete} && $form->{onhand} * 1 && $form->{item} ne 'service';
1768 if (!$form->{buchungsgruppen_id}) {
1769 $form->error($locale->text("Parts must have an entry type.") . " " .
1770 $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.")
1774 $form->error($locale->text('Description must not be empty!')) unless $form->{description};
1775 $form->error($locale->text('Partnumber must not be set to empty!')) if $form->{id} && !$form->{partnumber};
1778 $lxdebug->message($LXDebug::DEBUG1, "ic.pl: sellprice in save = $form->{sellprice}\n");
1779 if (IC->save(\%myconfig, \%$form) == 3) {
1780 $form->error($locale->text('Partnumber not unique!'));
1782 # saving the history
1783 if(!exists $form->{addition}) {
1784 $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
1785 $form->{addition} = "SAVED";
1786 $form->save_history($form->dbconnect(\%myconfig));
1788 # /saving the history
1789 $parts_id = $form->{id};
1792 # load previous variables
1793 if ($form->{previousform}) {
1795 # save the new form variables before splitting previousform
1796 map { $newform{$_} = $form->{$_} } keys %$form;
1798 $previousform = $form->unescape($form->{previousform});
1800 # don't trample on previous variables
1801 map { delete $form->{$_} } keys %newform;
1803 my $ic_cvar_configs = CVar->get_configs(module => 'IC');
1804 my @ic_cvar_fields = map { "cvar_$_->{name}" } @{ $ic_cvar_configs };
1806 # now take it apart and restore original values
1807 foreach my $item (split /&/, $previousform) {
1808 my ($key, $value) = split m/=/, $item, 2;
1809 $value =~ s/%26/&/g;
1810 $form->{$key} = $value;
1812 $form->{taxaccounts} = $newform{taxaccount2};
1814 if ($form->{item} eq 'assembly') {
1816 # undo number formatting
1817 map { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) }
1818 qw(weight listprice sellprice rop);
1820 $form->{assembly_rows}--;
1821 $i = $newform{rowcount};
1822 $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
1824 $form->{sellprice} -= $form->{"sellprice_$i"} * $form->{"qty_$i"};
1825 $form->{weight} -= $form->{"weight_$i"} * $form->{"qty_$i"};
1827 # change/add values for assembly item
1828 map { $form->{"${_}_$i"} = $newform{$_} } qw(partnumber description bin unit weight listprice sellprice inventory_accno income_accno expense_accno price_factor_id);
1829 map { $form->{"ic_${_}_$i"} = $newform{$_} } @ic_cvar_fields;
1831 # das ist __voll__ bekloppt, dass so auszurechnen jb 22.5.09
1832 #$form->{sellprice} += $form->{"sellprice_$i"} * $form->{"qty_$i"};
1833 $form->{weight} += $form->{"weight_$i"} * $form->{"qty_$i"};
1837 # set values for last invoice/order item
1838 $i = $form->{rowcount};
1839 $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
1841 map { $form->{"${_}_$i"} = $newform{$_} } qw(partnumber description bin unit listprice inventory_accno income_accno expense_accno sellprice lastcost price_factor_id);
1842 map { $form->{"ic_${_}_$i"} = $newform{$_} } @ic_cvar_fields;
1844 $form->{"longdescription_$i"} = $newform{notes};
1846 $form->{"sellprice_$i"} = $newform{lastcost} if ($form->{vendor_id});
1848 if ($form->{exchangerate} != 0) {
1849 $form->{"sellprice_$i"} /= $form->{exchangerate};
1852 $lxdebug->message($LXDebug::DEBUG1, qq|sellprice_$i in previousform 2 = | . $form->{"sellprice_$i"} . qq|\n|);
1854 map { $form->{"taxaccounts_$i"} .= "$_ " } split / /, $newform{taxaccount};
1855 chop $form->{"taxaccounts_$i"};
1856 foreach my $item (qw(description rate taxnumber)) {
1857 my $index = $form->{"taxaccounts_$i"} . "_$item";
1858 $form->{$index} = $newform{$index};
1861 # credit remaining calculation
1862 $amount = $form->{"sellprice_$i"} * (1 - $form->{"discount_$i"} / 100) * $form->{"qty_$i"};
1864 map { $form->{"${_}_base"} += $amount } (split / /, $form->{"taxaccounts_$i"});
1865 map { $amount += ($form->{"${_}_base"} * $form->{"${_}_rate"}) } split / /, $form->{"taxaccounts_$i"} if !$form->{taxincluded};
1867 $form->{creditremaining} -= $amount;
1869 # redo number formatting, because invoice parse them!
1870 map { $form->{"${_}_$i"} = $form->format_amount(\%myconfig, $form->{"${_}_$i"}) } qw(weight listprice sellprice rop);
1873 $form->{"id_$i"} = $parts_id;
1875 # Get the actual price factor (not just the ID) for the marge calculation.
1876 $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS');
1877 foreach my $pfac (@{ $form->{ALL_PRICE_FACTORS} }) {
1878 next if ($pfac->{id} != $newform{price_factor_id});
1879 $form->{"marge_price_factor_$i"} = $pfac->{factor};
1882 delete $form->{ALL_PRICE_FACTORS};
1884 delete $form->{action};
1886 # restore original callback
1887 $callback = $form->unescape($form->{callback});
1888 $form->{callback} = $form->unescape($form->{old_callback});
1889 delete $form->{old_callback};
1891 $form->{makemodel_rows}--;
1893 # put callback together
1894 foreach my $key (keys %$form) {
1896 # do single escape for Apache 2.0
1897 my $value = $form->escape($form->{$key}, 1);
1898 $callback .= qq|&$key=$value|;
1900 $form->{callback} = $callback;
1902 $lxdebug->message($LXDebug::DEBUG1, qq|ic.pl: sellprice_$i nach sub save = | . $form->{"sellprice_$i"} . qq|\n|);
1907 $lxdebug->leave_sub();
1911 $lxdebug->enter_sub();
1913 $auth->assert('part_service_assembly_edit');
1915 # saving the history
1916 if(!exists $form->{addition}) {
1917 $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
1918 $form->{addition} = "SAVED AS NEW";
1919 $form->save_history($form->dbconnect(\%myconfig));
1921 # /saving the history
1923 if ($form->{"original_partnumber"} &&
1924 ($form->{"partnumber"} eq $form->{"original_partnumber"})) {
1925 $form->{partnumber} = "";
1928 $lxdebug->leave_sub();
1932 $lxdebug->enter_sub();
1934 $auth->assert('part_service_assembly_edit');
1936 # saving the history
1937 if(!exists $form->{addition}) {
1938 $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
1939 $form->{addition} = "DELETED";
1940 $form->save_history($form->dbconnect(\%myconfig));
1942 # /saving the history
1943 my $rc = IC->delete(\%myconfig, \%$form);
1946 $form->redirect($locale->text('Item deleted!')) if ($rc > 0);
1947 $form->error($locale->text('Cannot delete item!'));
1949 $lxdebug->leave_sub();
1953 $lxdebug->enter_sub();
1955 $auth->assert('part_service_assembly_edit');
1960 pricegroup => $form->{"pricegroup_$_"},
1961 pricegroup_id => $form->{"pricegroup_id_$_"},
1962 price => $form->{"price_$_"},
1965 print $form->parse_html_template('ic/price_row', { PRICES => \@PRICES });
1967 $lxdebug->leave_sub();
1970 sub parts_language_selection {
1971 $lxdebug->enter_sub();
1973 $auth->assert('part_service_assembly_edit');
1975 our ($onload, $callback);
1977 my $languages = IC->retrieve_languages(\%myconfig, $form);
1979 if ($form->{language_values} ne "") {
1980 foreach my $item (split(/---\+\+\+---/, $form->{language_values})) {
1981 my ($language_id, $translation, $longdescription) = split(/--\+\+--/, $item);
1983 foreach my $language (@{ $languages }) {
1984 next unless ($language->{id} == $language_id);
1986 $language->{translation} = $translation;
1987 $language->{longdescription} = $longdescription;
1993 my @header_sort = qw(name longdescription);
1994 my %header_title = ( "name" => $locale->text("Name"),
1995 "longdescription" => $locale->text("Long Description"),
1999 map(+{ "column_title" => $header_title{$_},
2001 "callback" => $callback,
2005 $form->{"title"} = $locale->text("Language Values");
2007 print $form->parse_html_template("ic/parts_language_selection", { "HEADER" => \@header,
2008 "LANGUAGES" => $languages,
2009 "onload" => $onload });
2011 $lxdebug->leave_sub();
2014 sub ajax_autocomplete {
2015 $main::lxdebug->enter_sub();
2017 my $form = $main::form;
2018 my %myconfig = %main::myconfig;
2020 $form->{column} = 'description' unless $form->{column} =~ /^partnumber|description$/;
2021 $form->{$form->{column}} = $form->{q} || '';
2022 $form->{limit} = ($form->{limit} * 1) || 10;
2023 $form->{searchitems} ||= '';
2025 my @results = IC->all_parts(\%myconfig, $form);
2027 print $form->ajax_response_header(),
2028 $form->parse_html_template('ic/ajax_autocomplete');
2030 $main::lxdebug->leave_sub();
2033 sub continue { call_sub($form->{"nextsub"}); }