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 my $title = 'Add ' . ucfirst $form->{item};
82 $form->{title} = $locale->text($title);
83 $form->{callback} = "$form->{script}?action=add&item=$form->{item}" unless $form->{callback};
84 $form->{unit_changeable} = 1;
86 IC->get_pricegroups(\%myconfig, \%$form);
90 $lxdebug->leave_sub();
94 $lxdebug->enter_sub();
96 $auth->assert('part_service_assembly_edit');
98 $form->{revers} = 0; # switch for backward sorting
99 $form->{lastsort} = ""; # memory for which table was sort at last time
100 $form->{ndxs_counter} = 0; # counter for added entries to top100
102 my %is_xyz = map { +"is_$_" => ($form->{searchitems} eq $_) } qw(part service assembly);
104 $form->{title} = (ucfirst $form->{searchitems}) . "s";
105 $form->{title} = $locale->text($form->{title});
106 $form->{title} = $locale->text('Assemblies') if ($is_xyz{is_assembly});
108 $form->{jsscript} = 1;
110 $form->{CUSTOM_VARIABLES} = CVar->get_configs('module' => 'IC');
111 ($form->{CUSTOM_VARIABLES_FILTER_CODE},
112 $form->{CUSTOM_VARIABLES_INCLUSION_CODE}) = CVar->render_search_options('variables' => $form->{CUSTOM_VARIABLES},
113 'include_prefix' => 'l_',
114 'include_value' => 'Y');
118 print $form->parse_html_template('ic/search', { %is_xyz,
119 dateformat => $myconfig{dateformat}, });
121 $lxdebug->leave_sub();
124 sub search_update_prices {
125 $lxdebug->enter_sub();
127 $auth->assert('part_service_assembly_edit');
129 my $pricegroups = IC->get_pricegroups(\%myconfig, \%$form);
131 $form->{title} = $locale->text('Update Prices');
135 print $form->parse_html_template('ic/search_update_prices', { PRICE_ROWS => $pricegroups });
137 $lxdebug->leave_sub();
140 sub confirm_price_update {
141 $lxdebug->enter_sub();
143 $auth->assert('part_service_assembly_edit');
146 my $value_found = undef;
148 foreach my $idx (qw(sellprice listprice), (1..$form->{price_rows})) {
149 my $name = $idx =~ m/\d/ ? $form->{"pricegroup_${idx}"} : $idx eq 'sellprice' ? $locale->text('Sell Price') : $locale->text('List Price');
150 my $type = $idx =~ m/\d/ ? $form->{"pricegroup_type_${idx}"} : $form->{"${idx}_type"};
151 my $value_idx = $idx =~ m/\d/ ? "price_${idx}" : $idx;
152 my $value = $form->parse_amount(\%myconfig, $form->{$value_idx});
154 if ((0 > $value) && ($type eq 'percent')) {
155 push @errors, $locale->text('You cannot adjust the price for pricegroup "#1" by a negative percentage.', $name);
157 } elsif (!$value && ($form->{$value_idx} ne '')) {
158 push @errors, $locale->text('No valid number entered for pricegroup "#1".', $name);
160 } elsif (0 < $value) {
165 push @errors, $locale->text('No prices will be updated because no prices have been entered.') if (!$value_found);
167 my $num_matches = IC->get_num_matches_for_priceupdate();
172 $form->show_generic_error(join('<br>', @errors), 'back_button' => 1);
175 $form->{nextsub} = "update_prices";
177 map { delete $form->{$_} } qw(action header);
179 print $form->parse_html_template('ic/confirm_price_update', { HIDDENS => [ map { name => $_, value => $form->{$_} }, keys %$form ],
180 num_matches => $num_matches });
182 $lxdebug->leave_sub();
186 $lxdebug->enter_sub();
188 $auth->assert('part_service_assembly_edit');
190 my $num_updated = IC->update_prices(\%myconfig, \%$form);
192 if (-1 != $num_updated) {
193 $form->redirect($locale->text('#1 prices were updated.', $num_updated));
195 $form->error($locale->text('Could not update prices!'));
198 $lxdebug->leave_sub();
202 # $lxdebug->enter_sub();
204 # $auth->assert('part_service_assembly_edit');
206 # our ($j, $lastndx);
209 # $form->{title} = $locale->text('Top 100 hinzufuegen');
213 # push @custom_hiddens, qw(searchitems title bom titel revers lastsort sort ndxs_counter extras);
214 # push @custom_hiddens, qw(itemstatus l_linetotal l_partnumber l_description l_onhand l_unit l_sellprice l_linetotalsellprice);
216 # +{ name => 'row', value => $j },
217 # +{ name => 'nextsub', value => 'item_selected' },
218 # +{ name => 'test', value => 'item_selected' },
219 # +{ name => 'lastndx', value => $lastndx },
220 # map(+{ name => $_, value => $form->{$_} }, @custom_hiddens),
223 # my ($partnumber, $description, $unit, $sellprice, $soldtotal);
224 # # if choice set data
225 ## if ($form->{ndx}) {
226 ## for my $i (0 .. $form->{ndxs_counter}) {
228 ## # insert data into top100
229 ## push @{ $form->{parts} },
231 ## partnumber => $form->{"totop100_partnumber_$j"},
232 ## description => $form->{"totop100_description_$j"},
233 ## unit => $form->{"totop100_unit_$j"},
234 ## sellprice => $form->{"totop100_sellprice_$j"},
235 ## soldtotal => $form->{"totop100_soldtotal_$j"},
242 # # set data for next page
243 # for my $i (1 .. $form->{ndxs_counter}) {
244 # $partnumber = $form->{"totop100_partnumber_$i"};
245 # $description = $form->{"totop100_description_$i"};
246 # $unit = $form->{"totop100_unit_$i"};
247 # $sellprice = $form->{"totop100_sellprice_$i"};
248 # $soldtotal = $form->{"totop100_soldtotal_$i"};
251 # totop100_partnumber => $form->{"totop100_partnumber_$i"},
252 # totop100_description => $form->{"totop100_description_$i"},
253 # totop100_unit => $form->{"totop100_unit_$i"},
254 # totop100_sellprice => $form->{"totop100_sellprice_$i"},
255 # totop100_soldtotal => $form->{"totop100_soldtotal_$i"},
259 ##<input type=hidden name=totop100_partnumber_$i value=$form->{"totop100_partnumber_$i"}>
260 ##<input type=hidden name=totop100_description_$i value=$form->{"totop100_description_$i"}>
261 ##<input type=hidden name=totop100_unit_$i value=$form->{"totop100_unit_$i"}>
262 ##<input type=hidden name=totop100_sellprice_$i value=$form->{"totop100_sellprice_$i"}>
263 ##<input type=hidden name=totop100_soldtotal_$i value=$form->{"totop100_soldtotal_$i"}>
267 # print $form->parse_html_template('ic/choice', +{ HIDDENS => \@HIDDENS, PARTS => \@PARTS });
269 # $lxdebug->leave_sub();
273 # $lxdebug->enter_sub();
275 # $auth->assert('part_service_assembly_edit');
278 # our ($partnumber, $description, $unit, $sellprice, $soldtotal);
280 # my @sortorders = ("", "partnumber", "description", "all");
281 # my $sortorder = $sortorders[($form->{description} ? 2 : 0) + ($form->{partnumber} ? 1 : 0)];
282 # IC->get_parts(\%myconfig, \%$form, $sortorder);
284 # $form->{title} = $locale->text('Top 100 hinzufuegen');
290 # <form method=post action=ic.pl>
293 # <th class=listtop colspan=6>| . $locale->text('choice part') . qq|</th>
295 # <tr height="5"></tr>
296 # <tr class=listheading>
298 # <th class=listheading>| . $locale->text('Part Number') . qq|</th>
299 # <th class=listheading>| . $locale->text('Part Description') . qq|</th>
300 # <th class=listheading>| . $locale->text('Unit of measure') . qq|</th>
301 # <th class=listheading>| . $locale->text('Sell Price') . qq|</th>
302 # <th class=listheading>| . $locale->text('soldtotal') . qq|</th>
306 # my $i = $form->{rows};
308 # for ($j = 1; $j <= $i; $j++) {
311 # <tr class=listrow| . ($j % 2) . qq|>|;
314 # <td><input name=ndx class=radio type=radio value=$j checked></td>|;
317 # <td><input name=ndx class=radio type=radio value=$j></td>|;
320 # <td><input name="new_partnumber_$j" type=hidden value="$form->{"partnumber_$j"}">$form->{"partnumber_$j"}</td>
321 # <td><input name="new_description_$j" type=hidden value="$form->{"description_$j"}">$form->{"description_$j"}</td>
322 # <td><input name="new_unit_$j" type=hidden value="$form->{"unit_$j"}">$form->{"unit_$j"}</td>
323 # <td><input name="new_sellprice_$j" type=hidden value="$form->{"sellprice_$j"}">$form->{"sellprice_$j"}</td>
324 # <td><input name="new_soldtotal_$j" type=hidden value="$form->{"soldtotal_$j"}">$form->{"soldtotal_$j"}</td>
327 # <input name="new_id_$j" type=hidden value="$form->{"id_$j"}">|;
337 #<input type=hidden name=itemstatus value="$form->{itemstatus}">
338 #<input type=hidden name=l_linetotal value="$form->{l_linetotal}">
339 #<input type=hidden name=l_partnumber value="$form->{l_partnumber}">
340 #<input type=hidden name=l_description value="$form->{l_description}">
341 #<input type=hidden name=l_onhand value="$form->{l_onhand}">
342 #<input type=hidden name=l_unit value="$form->{l_unit}">
343 #<input type=hidden name=l_sellprice value="$form->{l_sellprice}">
344 #<input type=hidden name=l_linetotalsellprice value="$form->{l_linetotalsellprice}">
345 #<input type=hidden name=sort value="$form->{sort}">
346 #<input type=hidden name=revers value="$form->{revers}">
347 #<input type=hidden name=lastsort value="$form->{lastsort}">
349 #<input type=hidden name=bom value="$form->{bom}">
350 #<input type=hidden name=titel value="$form->{titel}">
351 #<input type=hidden name=searchitems value="$form->{searchitems}">
353 #<input type=hidden name=row value=$j>
355 #<input type=hidden name=nextsub value=item_selected>
357 #<input name=lastndx type=hidden value=$lastndx>
359 #<input name=ndxs_counter type=hidden value=$form->{ndxs_counter}>|;
363 # if (($form->{ndxs_counter}) > 0) {
364 # for ($i = 1; ($i < $form->{ndxs_counter} + 1); $i++) {
366 # $partnumber = $form->{"totop100_partnumber_$i"};
367 # $description = $form->{"totop100_description_$i"};
368 # $unit = $form->{"totop100_unit_$i"};
369 # $sellprice = $form->{"totop100_sellprice_$i"};
370 # $soldtotal = $form->{"totop100_soldtotal_$i"};
373 #<input type=hidden name=totop100_partnumber_$i value=$form->{"totop100_partnumber_$i"}>
374 #<input type=hidden name=totop100_description_$i value=$form->{"totop100_description_$i"}>
375 #<input type=hidden name=totop100_unit_$i value=$form->{"totop100_unit_$i"}>
376 #<input type=hidden name=totop100_sellprice_$i value=$form->{"totop100_sellprice_$i"}>
377 #<input type=hidden name=totop100_soldtotal_$i value=$form->{"totop100_soldtotal_$i"}>
385 #<input class=submit type=submit name=action value="|
386 # . $locale->text('TOP100') . qq|">
392 # $lxdebug->leave_sub();
396 $lxdebug->enter_sub();
398 $auth->assert('part_service_assembly_edit');
401 $form->{ndxs_counter}++;
403 if ($form->{ndxs_counter} > 0) {
405 my $index = $form->{ndx};
407 $form->{"totop100_partnumber_$form->{ndxs_counter}"} = $form->{"new_partnumber_$index"};
408 $form->{"totop100_description_$form->{ndxs_counter}"} = $form->{"new_description_$index"};
409 $form->{"totop100_unit_$form->{ndxs_counter}"} = $form->{"new_unit_$index"};
410 $form->{"totop100_sellprice_$form->{ndxs_counter}"} = $form->{"new_sellprice_$index"};
411 $form->{"totop100_soldtotal_$form->{ndxs_counter}"} = $form->{"new_soldtotal_$index"};
415 $lxdebug->leave_sub();
419 $lxdebug->enter_sub();
421 $auth->assert('part_service_assembly_edit');
423 my ($revers, $lastsort, $callback, $option, $description, $sameitem,
424 $partnumber, $unit, $sellprice, $soldtotal, $totop100, $onhand, $align);
425 my (@column_index, %column_header, %column_data);
426 my ($totalsellprice, $totallastcost, $totallistprice, $subtotalonhand, $subtotalsellprice, $subtotallastcost, $subtotallistprice);
428 $form->{top100} = "top100";
429 $form->{l_soldtotal} = "Y";
430 $form->{soldtotal} = "soldtotal";
431 $form->{sort} = "soldtotal";
432 $form->{l_qty} = "N";
433 $form->{l_linetotal} = "";
435 $form->{number} = "position";
436 $form->{l_number} = "Y";
440 $form->{title} = $locale->text('Top 100');
442 $revers = $form->{revers};
443 $lastsort = $form->{lastsort};
445 if (($form->{lastsort} eq "") && ($form->{sort} eq undef)) {
447 $form->{lastsort} = "partnumber";
448 $form->{sort} = "partnumber";
452 "$form->{script}?action=top100&searchitems=$form->{searchitems}&itemstatus=$form->{itemstatus}&bom=$form->{bom}&l_linetotal=$form->{l_linetotal}&title="
453 . $form->escape($form->{title}, 1);
455 # if we have a serialnumber limit search
456 if ($form->{serialnumber} || $form->{l_serialnumber}) {
457 $form->{l_serialnumber} = "Y";
458 unless ( $form->{bought}
461 || $form->{quoted}) {
462 $form->{bought} = $form->{sold} = 1;
465 IC->all_parts(\%myconfig, \%$form);
467 if ($form->{itemstatus} eq 'active') {
468 $option .= $locale->text('Active') . " : ";
470 if ($form->{itemstatus} eq 'obsolete') {
471 $option .= $locale->text('Obsolete') . " : ";
473 if ($form->{itemstatus} eq 'orphaned') {
474 $option .= $locale->text('Orphaned') . " : ";
476 if ($form->{itemstatus} eq 'onhand') {
477 $option .= $locale->text('On Hand') . " : ";
478 $form->{l_onhand} = "Y";
480 if ($form->{itemstatus} eq 'short') {
481 $option .= $locale->text('Short') . " : ";
482 $form->{l_onhand} = "Y";
484 if ($form->{onorder}) {
485 $form->{l_ordnumber} = "Y";
486 $callback .= "&onorder=$form->{onorder}";
487 $option .= $locale->text('On Order') . " : ";
489 if ($form->{ordered}) {
490 $form->{l_ordnumber} = "Y";
491 $callback .= "&ordered=$form->{ordered}";
492 $option .= $locale->text('Ordered') . " : ";
495 $form->{l_quonumber} = "Y";
496 $callback .= "&rfq=$form->{rfq}";
497 $option .= $locale->text('RFQ') . " : ";
499 if ($form->{quoted}) {
500 $form->{l_quonumber} = "Y";
501 $callback .= ""ed=$form->{quoted}";
502 $option .= $locale->text('Quoted') . " : ";
504 if ($form->{bought}) {
505 $form->{l_invnumber} = "Y";
506 $callback .= "&bought=$form->{bought}";
507 $option .= $locale->text('Bought') . " : ";
510 $form->{l_invnumber} = "Y";
511 $callback .= "&sold=$form->{sold}";
512 $option .= $locale->text('Sold') . " : ";
519 || $form->{quoted}) {
521 $form->{l_lastcost} = "";
522 $form->{l_name} = "Y";
523 if ($form->{transdatefrom}) {
524 $callback .= "&transdatefrom=$form->{transdatefrom}";
526 . $locale->text('From')
528 . $locale->date(\%myconfig, $form->{transdatefrom}, 1);
530 if ($form->{transdateto}) {
531 $callback .= "&transdateto=$form->{transdateto}";
533 . $locale->text('To')
535 . $locale->date(\%myconfig, $form->{transdateto}, 1);
541 if ($form->{partnumber}) {
542 $callback .= "&partnumber=$form->{partnumber}";
543 $option .= $locale->text('Part Number') . qq| : $form->{partnumber}<br>|;
546 $callback .= "&partnumber=$form->{ean}";
547 $option .= $locale->text('EAN') . qq| : $form->{ean}<br>|;
549 if ($form->{partsgroup}) {
550 $callback .= "&partsgroup=$form->{partsgroup}";
551 $option .= $locale->text('Group') . qq| : $form->{partsgroup}<br>|;
553 if ($form->{serialnumber}) {
554 $callback .= "&serialnumber=$form->{serialnumber}";
555 $option .= $locale->text('Serial Number') . qq| : $form->{serialnumber}<br>|;
557 if ($form->{description}) {
558 $callback .= "&description=$form->{description}";
559 $description = $form->{description};
560 $description =~ s/\n/<br>/g;
561 $option .= $locale->text('Part Description') . qq| : $form->{description}<br>|;
564 $callback .= "&make=$form->{make}";
565 $option .= $locale->text('Make') . qq| : $form->{make}<br>|;
567 if ($form->{model}) {
568 $callback .= "&model=$form->{model}";
569 $option .= $locale->text('Model') . qq| : $form->{model}<br>|;
571 if ($form->{drawing}) {
572 $callback .= "&drawing=$form->{drawing}";
573 $option .= $locale->text('Drawing') . qq| : $form->{drawing}<br>|;
575 if ($form->{microfiche}) {
576 $callback .= "µfiche=$form->{microfiche}";
577 $option .= $locale->text('Microfiche') . qq| : $form->{microfiche}<br>|;
579 if ($form->{l_soldtotal}) {
580 $callback .= "&soldtotal=$form->{soldtotal}";
581 $option .= $locale->text('soldtotal') . qq| : $form->{soldtotal}<br>|;
584 my @columns = $form->sort_columns(
585 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)
588 if ($form->{l_linetotal}) {
589 $form->{l_onhand} = "Y";
590 $form->{l_linetotalsellprice} = "Y" if $form->{l_sellprice};
591 if ($form->{l_lastcost}) {
592 $form->{l_linetotallastcost} = "Y";
593 if (($form->{searchitems} eq 'assembly') && !$form->{bom}) {
594 $form->{l_linetotallastcost} = "";
597 $form->{l_linetotallistprice} = "Y" if $form->{l_listprice};
600 if ($form->{searchitems} eq 'service') {
602 # remove bin, weight and rop from list
603 map { $form->{"l_$_"} = "" } qw(bin weight rop);
605 $form->{l_onhand} = "";
607 # qty is irrelevant unless bought or sold
613 || $form->{quoted}) {
614 $form->{l_onhand} = "Y";
616 $form->{l_linetotalsellprice} = "";
617 $form->{l_linetotallastcost} = "";
621 foreach my $item (@columns) {
622 if ($form->{"l_$item"} eq "Y") {
623 push @column_index, $item;
625 # add column to callback
626 $callback .= "&l_$item=Y";
630 if ($form->{l_subtotal} eq 'Y') {
631 $callback .= "&l_subtotal=Y";
634 $column_header{number} =
635 qq|<th class=listheading nowrap>| . $locale->text('number') . qq|</th>|;
636 $column_header{partnumber} =
637 qq|<th nowrap><a class=listheading href=$callback&sort=partnumber&revers=$form->{revers}&lastsort=$form->{lastsort}>|
638 . $locale->text('Part Number')
640 $column_header{description} =
641 qq|<th nowrap><a class=listheading href=$callback&sort=description&revers=$form->{revers}&lastsort=$form->{lastsort}>|
642 . $locale->text('Part Description')
644 $column_header{partsgroup} =
645 qq|<th nowrap><a class=listheading href=$callback&sort=partsgroup>|
646 . $locale->text('Group')
648 $column_header{bin} =
649 qq|<th><a class=listheading href=$callback&sort=bin>|
650 . $locale->text('Bin')
652 $column_header{priceupdate} =
653 qq|<th nowrap><a class=listheading href=$callback&sort=priceupdate>|
654 . $locale->text('Updated')
656 $column_header{onhand} =
657 qq|<th nowrap><a class=listheading href=$callback&sort=onhand&revers=$form->{revers}&lastsort=$form->{lastsort}>|
658 . $locale->text('Qty')
660 $column_header{unit} =
661 qq|<th class=listheading nowrap>| . $locale->text('Unit') . qq|</th>|;
662 $column_header{listprice} =
663 qq|<th class=listheading nowrap>|
664 . $locale->text('List Price')
666 $column_header{lastcost} =
667 qq|<th class=listheading nowrap>| . $locale->text('Last Cost') . qq|</th>|;
668 $column_header{rop} =
669 qq|<th class=listheading nowrap>| . $locale->text('ROP') . qq|</th>|;
670 $column_header{weight} =
671 qq|<th class=listheading nowrap>| . $locale->text('Weight') . qq|</th>|;
673 $column_header{invnumber} =
674 qq|<th nowrap><a class=listheading href=$callback&sort=invnumber>|
675 . $locale->text('Invoice Number')
677 $column_header{ordnumber} =
678 qq|<th nowrap><a class=listheading href=$callback&sort=ordnumber>|
679 . $locale->text('Order Number')
681 $column_header{quonumber} =
682 qq|<th nowrap><a class=listheading href=$callback&sort=quonumber>|
683 . $locale->text('Quotation')
686 $column_header{name} =
687 qq|<th nowrap><a class=listheading href=$callback&sort=name>|
688 . $locale->text('Name')
691 $column_header{sellprice} =
692 qq|<th class=listheading nowrap>|
693 . $locale->text('Sell Price')
695 $column_header{linetotalsellprice} =
696 qq|<th class=listheading nowrap>| . $locale->text('Extended') . qq|</th>|;
697 $column_header{linetotallastcost} =
698 qq|<th class=listheading nowrap>| . $locale->text('Extended') . qq|</th>|;
699 $column_header{linetotallistprice} =
700 qq|<th class=listheading nowrap>| . $locale->text('Extended') . qq|</th>|;
702 $column_header{image} =
703 qq|<th class=listheading nowrap>| . $locale->text('Image') . qq|</a></th>|;
704 $column_header{drawing} =
705 qq|<th nowrap><a class=listheading href=$callback&sort=drawing>|
706 . $locale->text('Drawing')
708 $column_header{microfiche} =
709 qq|<th nowrap><a class=listheading href=$callback&sort=microfiche>|
710 . $locale->text('Microfiche')
713 $column_header{serialnumber} =
714 qq|<th nowrap><a class=listheading href=$callback&sort=serialnumber>|
715 . $locale->text('Serial Number')
717 $column_header{soldtotal} =
718 qq|<th nowrap><a class=listheading href=$callback&sort=soldtotal&revers=$form->{revers}&lastsort=$form->{lastsort}>|
719 . $locale->text('soldtotal')
723 my $colspan = $#column_index + 1;
730 <th class=listtop colspan=$colspan>$form->{title}</th>
734 <tr><td colspan=$colspan>$option</td></tr>
736 <tr class=listheading>
739 map { print "\n$column_header{$_}" } @column_index;
745 # add order to callback
746 $form->{callback} = $callback .= "&sort=$form->{sort}";
748 # escape callback for href
749 $callback = $form->escape($callback);
751 if (@{ $form->{parts} }) {
752 $sameitem = $form->{parts}->[0]->{ $form->{sort} };
755 # insert numbers for top100
757 foreach my $ref (@{ $form->{parts} }) {
762 # if avaible -> insert choice here
763 if (($form->{ndxs_counter}) > 0) {
764 for (my $i = 1; ($i < $form->{ndxs_counter} + 1); $i++) {
765 $partnumber = $form->{"totop100_partnumber_$i"};
766 $description = $form->{"totop100_description_$i"};
767 $unit = $form->{"totop100_unit_$i"};
768 $sellprice = $form->{"totop100_sellprice_$i"};
769 $soldtotal = $form->{"totop100_soldtotal_$i"};
772 <input type=hidden name=totop100_partnumber_$i value=$form->{"totop100_partnumber_$i"}>
773 <input type=hidden name=totop100_description_$i value=$form->{"totop100_description_$i"}>
774 <input type=hidden name=totop100_unit_$i value=$form->{"totop100_unit_$i"}>
775 <input type=hidden name=totop100_sellprice_$i value=$form->{"totop100_sellprice_$i"}>
776 <input type=hidden name=totop100_soldtotal_$i value=$form->{"totop100_soldtotal_$i"}>
780 push @{ $form->{parts} },
782 partnumber => "$partnumber",
783 description => "$description",
785 sellprice => "$sellprice",
786 soldtotal => "$soldtotal" };
789 # build data for columns
791 foreach my $ref (@{ $form->{parts} }) {
793 if ($form->{l_subtotal} eq 'Y' && !$ref->{assemblyitem}) {
794 if ($sameitem ne $ref->{ $form->{sort} }) {
795 parts_subtotal(\@column_index, \$subtotalonhand, \$subtotalsellprice, \$subtotallastcost, \$subtotallistprice);
796 $sameitem = $ref->{ $form->{sort} };
800 $ref->{exchangerate} = 1 unless $ref->{exchangerate};
801 $ref->{sellprice} *= $ref->{exchangerate};
802 $ref->{listprice} *= $ref->{exchangerate};
803 $ref->{lastcost} *= $ref->{exchangerate};
805 # use this for assemblies
806 $onhand = $ref->{onhand};
809 if ($ref->{assemblyitem}) {
811 $onhand = 0 if ($form->{sold});
814 $ref->{description} =~ s/\n/<br>/g;
816 $column_data{number} =
818 . $form->format_amount(\%myconfig, $ref->{number})
820 $column_data{partnumber} =
821 "<td align=$align>$ref->{partnumber} </a></td>";
822 $column_data{description} = "<td>$ref->{description} </td>";
823 $column_data{partsgroup} = "<td>$ref->{partsgroup} </td>";
825 $column_data{onhand} =
827 . $form->format_amount(\%myconfig, $ref->{onhand})
829 $column_data{sellprice} =
831 . $form->format_amount(\%myconfig, $ref->{sellprice})
833 $column_data{listprice} =
835 . $form->format_amount(\%myconfig, $ref->{listprice})
837 $column_data{lastcost} =
839 . $form->format_amount(\%myconfig, $ref->{lastcost})
842 $column_data{linetotalsellprice} = "<td align=right>"
843 . $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{sellprice}, 2)
845 $column_data{linetotallastcost} = "<td align=right>"
846 . $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{lastcost}, 2)
848 $column_data{linetotallistprice} = "<td align=right>"
849 . $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{listprice}, 2)
852 if (!$ref->{assemblyitem}) {
853 $totalsellprice += $onhand * $ref->{sellprice};
854 $totallastcost += $onhand * $ref->{lastcost};
855 $totallistprice += $onhand * $ref->{listprice};
857 $subtotalonhand += $onhand;
858 $subtotalsellprice += $onhand * $ref->{sellprice};
859 $subtotallastcost += $onhand * $ref->{lastcost};
860 $subtotallistprice += $onhand * $ref->{listprice};
865 . $form->format_amount(\%myconfig, $ref->{rop}) . "</td>";
866 $column_data{weight} =
868 . $form->format_amount(\%myconfig, $ref->{weight})
870 $column_data{unit} = "<td>$ref->{unit} </td>";
871 $column_data{bin} = "<td>$ref->{bin} </td>";
872 $column_data{priceupdate} = "<td>$ref->{priceupdate} </td>";
874 $column_data{invnumber} =
875 ($ref->{module} ne 'oe')
876 ? "<td><a href=$ref->{module}.pl?action=edit&type=invoice&id=$ref->{trans_id}&callback=$callback>$ref->{invnumber}</a></td>"
877 : "<td>$ref->{invnumber}</td>";
878 $column_data{ordnumber} =
879 ($ref->{module} eq 'oe')
880 ? "<td><a href=$ref->{module}.pl?action=edit&type=$ref->{type}&id=$ref->{trans_id}&callback=$callback>$ref->{ordnumber}</a></td>"
881 : "<td>$ref->{ordnumber}</td>";
882 $column_data{quonumber} =
883 ($ref->{module} eq 'oe' && !$ref->{ordnumber})
884 ? "<td><a href=$ref->{module}.pl?action=edit&type=$ref->{type}&id=$ref->{trans_id}&callback=$callback>$ref->{quonumber}</a></td>"
885 : "<td>$ref->{quonumber}</td>";
887 $column_data{name} = "<td>$ref->{name}</td>";
889 $column_data{image} =
891 ? "<td><a href=$ref->{image}><img src=$ref->{image} height=32 border=0></a></td>"
893 $column_data{drawing} =
895 ? "<td><a href=$ref->{drawing}>$ref->{drawing}</a></td>"
897 $column_data{microfiche} =
899 ? "<td><a href=$ref->{microfiche}>$ref->{microfiche}</a></td>"
902 $column_data{serialnumber} = "<td>$ref->{serialnumber}</td>";
904 $column_data{soldtotal} = "<td align=right>$ref->{soldtotal}</td>";
908 print "<tr class=listrow$i>";
910 map { print "\n$column_data{$_}" } @column_index;
917 if ($form->{l_subtotal} eq 'Y') {
918 parts_subtotal(\@column_index, \$subtotalonhand, \$subtotalsellprice, \$subtotallastcost, \$subtotallistprice);
921 if ($form->{"l_linetotal"}) {
922 map { $column_data{$_} = "<td> </td>" } @column_index;
923 $column_data{linetotalsellprice} =
924 "<th class=listtotal align=right>"
925 . $form->format_amount(\%myconfig, $totalsellprice, 2)
927 $column_data{linetotallastcost} =
928 "<th class=listtotal align=right>"
929 . $form->format_amount(\%myconfig, $totallastcost, 2)
931 $column_data{linetotallistprice} =
932 "<th class=listtotal align=right>"
933 . $form->format_amount(\%myconfig, $totallistprice, 2)
936 print "<tr class=listtotal>";
938 map { print "\n$column_data{$_}" } @column_index;
945 <tr><td colspan=$colspan><hr size=3 noshade></td></tr>
954 <form method=post action=$form->{script}>
956 <input type=hidden name=itemstatus value="$form->{itemstatus}">
957 <input type=hidden name=l_linetotal value="$form->{l_linetotal}">
958 <input type=hidden name=l_partnumber value="$form->{l_partnumber}">
959 <input type=hidden name=l_description value="$form->{l_description}">
960 <input type=hidden name=l_onhand value="$form->{l_onhand}">
961 <input type=hidden name=l_unit value="$form->{l_unit}">
962 <input type=hidden name=l_sellprice value="$form->{l_sellprice}">
963 <input type=hidden name=l_linetotalsellprice value="$form->{l_linetotalsellprice}">
964 <input type=hidden name=sort value="$form->{sort}">
965 <input type=hidden name=revers value="$form->{revers}">
966 <input type=hidden name=lastsort value="$form->{lastsort}">
967 <input type=hidden name=parts value="$form->{parts}">
969 <input type=hidden name=bom value="$form->{bom}">
970 <input type=hidden name=titel value="$form->{titel}">
971 <input type=hidden name=searchitems value="$form->{searchitems}">|;
976 <!-- <input type=hidden name=ndxs_counter value="$form->{ndxs_counter}">-->
978 <input class=submit type=submit name=action value="|
979 . $locale->text('choice') . qq|">
987 $lxdebug->leave_sub();
992 # Warning, deep magic ahead.
993 # This function parses the requested details, sanity checks them, and converts them into a format thats usable for IC->all_parts
995 # flags coming from the form:
997 # searchitems=part revers=0 lastsort=''
1000 # partnumber ean description partsgroup serialnumber make model drawing microfiche
1001 # transdatefrom transdateto
1004 # itemstatus = active | onhand | short | obsolete | orphaned
1005 # action = continue | top100
1008 # bought sold onorder ordered rfq quoted
1009 # l_partnumber l_description l_serialnumber l_unit l_listprice l_sellprice l_lastcost
1010 # l_linetotal l_priceupdate l_bin l_rop l_weight l_image l_drawing l_microfiche
1011 # l_partsgroup l_subtotal l_soldtotal l_deliverydate
1014 # nextsub revers lastsort sort ndxs_counter
1016 sub generate_report {
1017 $lxdebug->enter_sub();
1019 $auth->assert('part_service_assembly_edit');
1021 my ($revers, $lastsort, $description);
1023 my $cvar_configs = CVar->get_configs('module' => 'IC');
1025 $form->{title} = (ucfirst $form->{searchitems}) . "s";
1026 $form->{title} =~ s/ys$/ies/;
1027 $form->{title} = $locale->text($form->{title});
1030 'bin' => { 'text' => $locale->text('Bin'), },
1031 'deliverydate' => { 'text' => $locale->text('deliverydate'), },
1032 'description' => { 'text' => $locale->text('Part Description'), },
1033 'drawing' => { 'text' => $locale->text('Drawing'), },
1034 'ean' => { 'text' => $locale->text('EAN'), },
1035 'image' => { 'text' => $locale->text('Image'), },
1036 'invnumber' => { 'text' => $locale->text('Invoice Number'), },
1037 'lastcost' => { 'text' => $locale->text('Last Cost'), },
1038 'linetotallastcost' => { 'text' => $locale->text('Extended'), },
1039 'linetotallistprice' => { 'text' => $locale->text('Extended'), },
1040 'linetotalsellprice' => { 'text' => $locale->text('Extended'), },
1041 'listprice' => { 'text' => $locale->text('List Price'), },
1042 'microfiche' => { 'text' => $locale->text('Microfiche'), },
1043 'name' => { 'text' => $locale->text('Name'), },
1044 'onhand' => { 'text' => $locale->text('Qty'), },
1045 'ordnumber' => { 'text' => $locale->text('Order Number'), },
1046 'partnumber' => { 'text' => $locale->text('Part Number'), },
1047 'partsgroup' => { 'text' => $locale->text('Group'), },
1048 'priceupdate' => { 'text' => $locale->text('Updated'), },
1049 'quonumber' => { 'text' => $locale->text('Quotation'), },
1050 'rop' => { 'text' => $locale->text('ROP'), },
1051 'sellprice' => { 'text' => $locale->text('Sell Price'), },
1052 'serialnumber' => { 'text' => $locale->text('Serial Number'), },
1053 'soldtotal' => { 'text' => $locale->text('soldtotal'), },
1054 'transdate' => { 'text' => $locale->text('Transdate'), },
1055 'unit' => { 'text' => $locale->text('Unit'), },
1056 'weight' => { 'text' => $locale->text('Weight'), },
1059 $revers = $form->{revers};
1060 $lastsort = $form->{lastsort};
1062 # sorting and direction of sorting
1063 # ToDO: change this to the simpler field+direction method
1064 if (($form->{lastsort} eq "") && ($form->{sort} eq undef)) {
1065 $form->{revers} = 0;
1066 $form->{lastsort} = "partnumber";
1067 $form->{sort} = "partnumber";
1069 if ($form->{lastsort} eq $form->{sort}) {
1070 $form->{revers} = 1 - $form->{revers};
1072 $form->{revers} = 0;
1073 $form->{lastsort} = $form->{sort};
1077 # special case if we have a serialnumber limit search
1078 # serialnumbers are only given in invoices and orders,
1079 # so they can only pop up in bought, sold, rfq, and quoted stuff
1080 $form->{no_sn_joins} = 'Y' if ( !$form->{bought} && !$form->{sold}
1081 && !$form->{rfq} && !$form->{quoted}
1082 && ($form->{l_serialnumber} || $form->{serialnumber}));
1084 # special case for any checkbox of bought | sold | onorder | ordered | rfq | quoted.
1085 # if any of these are ticked the behavior changes slightly for lastcost
1086 # since all those are aggregation checks for the legder tables this is an internal switch
1087 # refered to as ledgerchecks
1088 $form->{ledgerchecks} = 'Y' if ( $form->{bought} || $form->{sold} || $form->{onorder}
1089 || $form->{ordered} || $form->{rfq} || $form->{quoted});
1091 # if something should be activated if something else is active, enter it here
1092 my %dependencies = (
1093 onhand => [ qw(l_onhand) ],
1094 short => [ qw(l_onhand) ],
1095 onorder => [ qw(l_ordnumber) ],
1096 ordered => [ qw(l_ordnumber) ],
1097 rfq => [ qw(l_quonumber) ],
1098 quoted => [ qw(l_quonumber) ],
1099 bought => [ qw(l_invnumber) ],
1100 sold => [ qw(l_invnumber) ],
1101 ledgerchecks => [ qw(l_name) ],
1102 serialnumber => [ qw(l_serialnumber) ],
1103 no_sn_joins => [ qw(bought sold) ],
1106 # these strings get displayed at the top of the results to indicate the user which switches were used
1108 active => $locale->text('Active'),
1109 obsolete => $locale->text('Obsolete'),
1110 orphaned => $locale->text('Orphaned'),
1111 onhand => $locale->text('On Hand'),
1112 short => $locale->text('Short'),
1113 onorder => $locale->text('On Order'),
1114 ordered => $locale->text('Ordered'),
1115 rfq => $locale->text('RFQ'),
1116 quoted => $locale->text('Quoted'),
1117 bought => $locale->text('Bought'),
1118 sold => $locale->text('Sold'),
1119 transdatefrom => $locale->text('From') . " " . $locale->date(\%myconfig, $form->{transdatefrom}, 1),
1120 transdateto => $locale->text('To (time)') . " " . $locale->date(\%myconfig, $form->{transdateto}, 1),
1121 partnumber => $locale->text('Part Number') . ": '$form->{partnumber}'",
1122 partsgroup => $locale->text('Group') . ": '$form->{partsgroup}'",
1123 serialnumber => $locale->text('Serial Number') . ": '$form->{serialnumber}'",
1124 description => $locale->text('Part Description') . ": '$form->{description}'",
1125 make => $locale->text('Make') . ": '$form->{make}'",
1126 model => $locale->text('Model') . ": '$form->{model}'",
1127 drawing => $locale->text('Drawing') . ": '$form->{drawing}'",
1128 microfiche => $locale->text('Microfiche') . ": '$form->{microfiche}'",
1129 l_soldtotal => $locale->text('soldtotal'),
1130 ean => $locale->text('EAN') . ": '$form->{ean}'",
1133 my @itemstatus_keys = qw(active obsolete orphaned onhand short);
1134 my @callback_keys = qw(onorder ordered rfq quoted bought sold partnumber partsgroup serialnumber description make model
1135 drawing microfiche l_soldtotal l_deliverydate transdatefrom transdateto ean);
1137 # calculate dependencies
1138 for (@itemstatus_keys, @callback_keys) {
1139 next if ($form->{itemstatus} ne $_ && !$form->{$_});
1140 map { $form->{$_} = 'Y' } @{ $dependencies{$_} } if $dependencies{$_};
1143 # generate callback and optionstrings
1145 for my $key (@itemstatus_keys, @callback_keys) {
1146 next if ($form->{itemstatus} ne $key && !$form->{$key});
1147 push @options, $optiontexts{$key};
1150 # special case for lastcost
1151 if ($form->{ledgerchecks}){
1152 # ledgerchecks don't know about sellprice or lastcost. they just return a
1153 # price. so rename sellprice to price, and drop lastcost.
1154 $column_defs{sellprice}{text} = $locale->text('Price');
1155 $form->{l_lastcost} = ""
1158 if ($form->{description}) {
1159 $description = $form->{description};
1160 $description =~ s/\n/<br>/g;
1163 if ($form->{l_linetotal}) {
1164 $form->{l_onhand} = "Y";
1165 $form->{l_linetotalsellprice} = "Y" if $form->{l_sellprice};
1166 $form->{l_linetotallastcost} = $form->{searchitems} eq 'assembly' && !$form->{bom} ? "" : 'Y' if $form->{l_lastcost};
1167 $form->{l_linetotallistprice} = "Y" if $form->{l_listprice};
1170 if ($form->{searchitems} eq 'service') {
1172 # remove bin, weight and rop from list
1173 map { $form->{"l_$_"} = "" } qw(bin weight rop);
1175 $form->{l_onhand} = "";
1177 # qty is irrelevant unless bought or sold
1178 if ( $form->{bought}
1183 || $form->{quoted}) {
1184 $form->{l_onhand} = "Y";
1186 $form->{l_linetotalsellprice} = "";
1187 $form->{l_linetotallastcost} = "";
1191 IC->all_parts(\%myconfig, \%$form);
1194 partnumber description partsgroup bin onhand rop unit listprice
1195 linetotallistprice sellprice linetotalsellprice lastcost linetotallastcost
1196 priceupdate weight image drawing microfiche invnumber ordnumber quonumber
1197 transdate name serialnumber soldtotal deliverydate ean
1200 my @includeable_custom_variables = grep { $_->{includeable} } @{ $cvar_configs };
1201 my @searchable_custom_variables = grep { $_->{searchable} } @{ $cvar_configs };
1202 my %column_defs_cvars = map { +"cvar_$_->{name}" => { 'text' => $_->{description} } } @includeable_custom_variables;
1204 push @columns, map { "cvar_$_->{name}" } @includeable_custom_variables;
1206 %column_defs = (%column_defs,%column_defs_cvars); # nochmal die cvars als überschrift hinzufügen
1207 map { $column_defs{$_}->{visible} = $form->{"l_$_"} ? 1 : 0 } @columns;
1208 map { $column_defs{$_}->{align} = 'right' } qw(onhand sellprice listprice lastcost linetotalsellprice linetotallastcost linetotallistprice rop weight soldtotal);
1210 my @hidden_variables = (qw(l_subtotal l_linetotal searchitems itemstatus bom), @itemstatus_keys, @callback_keys,
1211 map({ "cvar_$_->{name}" } @searchable_custom_variables), map { "l_$_" } @columns);
1212 my $callback = build_std_url('action=generate_report', grep { $form->{$_} } @hidden_variables);
1214 my @sort_full = qw(partnumber description onhand soldtotal deliverydate);
1215 my @sort_no_revers = qw(partsgroup bin priceupdate invnumber ordnumber quonumber name image drawing serialnumber);
1217 foreach my $col (@sort_full) {
1218 $column_defs{$col}->{link} = join '&', $callback, "sort=$col", map { "$_=" . E($form->{$_}) } qw(revers lastsort);
1220 map { $column_defs{$_}->{link} = "${callback}&sort=$_" } @sort_no_revers;
1222 # add order to callback
1223 $form->{callback} = join '&', ($callback, map { "${_}=" . E($form->{$_}) } qw(sort revers));
1225 my $report = SL::ReportGenerator->new(\%myconfig, $form);
1227 my %attachment_basenames = (
1228 'part' => $locale->text('part_list'),
1229 'service' => $locale->text('service_list'),
1230 'assembly' => $locale->text('assembly_list'),
1233 $report->set_options('top_info_text' => $locale->text('Options') . ': ' . join(', ', grep $_, @options),
1234 'raw_bottom_info_text' => $form->parse_html_template('ic/generate_report_bottom'),
1235 'output_format' => 'HTML',
1236 'title' => $form->{title},
1237 'attachment_basename' => $attachment_basenames{$form->{searchitems}} . strftime('_%Y%m%d', localtime time),
1239 $report->set_options_from_form();
1240 $locale->set_numberformat_wo_thousands_separator(\%myconfig) if lc($report->{options}->{output_format}) eq 'csv';
1242 $report->set_columns(%column_defs);
1243 $report->set_column_order(@columns);
1245 $report->set_export_options('generate_report', @hidden_variables, qw(sort revers));
1247 $report->set_sort_indicator($form->{sort}, $form->{revers} ? 0 : 1);
1249 CVar->add_custom_variables_to_report('module' => 'IC',
1250 'trans_id_field' => 'id',
1251 'configs' => $cvar_configs,
1252 'column_defs' => \%column_defs,
1253 'data' => $form->{parts});
1255 CVar->add_custom_variables_to_report('module' => 'IC',
1256 'sub_module' => sub { $_[0]->{ioi} },
1257 'trans_id_field' => 'ioi_id',
1258 'configs' => $cvar_configs,
1259 'column_defs' => \%column_defs,
1260 'data' => $form->{parts});
1262 my @subtotal_columns = qw(sellprice listprice lastcost);
1263 my %subtotals = map { $_ => 0 } ('onhand', @subtotal_columns);
1264 my %totals = map { $_ => 0 } @subtotal_columns;
1266 my $same_item = $form->{parts}[0]{ $form->{sort} } if (scalar @{ $form->{parts} });
1268 my $defaults = AM->get_defaults();
1271 foreach my $ref (@{ $form->{parts} }) {
1273 # fresh row, for inserting later
1274 my $row = { map { $_ => { 'data' => $ref->{$_} } } @columns };
1276 $ref->{exchangerate} ||= 1;
1277 $ref->{price_factor} ||= 1;
1278 $ref->{sellprice} *= $ref->{exchangerate} / $ref->{price_factor};
1279 $ref->{listprice} *= $ref->{exchangerate} / $ref->{price_factor};
1280 $ref->{lastcost} *= $ref->{exchangerate} / $ref->{price_factor};
1282 # use this for assemblies
1283 my $onhand = $ref->{onhand};
1285 if ($ref->{assemblyitem}) {
1286 $row->{partnumber}{align} = 'right';
1287 $row->{onhand}{data} = 0;
1288 $onhand = 0 if ($form->{sold});
1291 my $edit_link = build_std_url('action=edit', 'id=' . E($ref->{id}), 'callback');
1292 $row->{partnumber}->{link} = $edit_link;
1293 $row->{description}->{link} = $edit_link;
1295 foreach (qw(sellprice listprice lastcost)) {
1296 $row->{$_}{data} = $form->format_amount(\%myconfig, $ref->{$_}, -2);
1297 $row->{"linetotal$_"}{data} = $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{$_}, 2);
1300 map { $row->{$_}{data} = $form->format_amount(\%myconfig, $ref->{$_}); } qw(onhand rop weight soldtotal);
1302 $row->{weight}->{data} .= ' ' . $defaults->{weightunit};
1304 if (!$ref->{assemblyitem}) {
1305 foreach my $col (@subtotal_columns) {
1306 $totals{$col} += $onhand * $ref->{$col};
1307 $subtotals{$col} += $onhand * $ref->{$col};
1310 $subtotals{onhand} += $onhand;
1314 if ($ref->{module} eq 'oe') {
1315 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');
1316 $row->{ordnumber}{link} = $edit_oe_link;
1317 $row->{quonumber}{link} = $edit_oe_link if (!$ref->{ordnumber});
1320 $row->{invnumber}{link} = build_std_url("script=$ref->{module}.pl", 'action=edit', 'type=invoice', 'id=' . E($ref->{trans_id}), 'callback');
1323 # set properties of images
1324 if ($ref->{image} && (lc $report->{options}->{output_format} eq 'html')) {
1325 $row->{image}{data} = '';
1326 $row->{image}{raw_data} = '<a href="' . H($ref->{image}) . '"><img src="' . H($ref->{image}) . '" height="32" border="0"></a>';
1328 map { $row->{$_}{link} = $ref->{$_} } qw(drawing microfiche);
1330 $report->add_data($row);
1332 my $next_ref = $form->{parts}[$idx + 1];
1334 # insert subtotal rows
1335 if (($form->{l_subtotal} eq 'Y') &&
1337 (!$next_ref->{assemblyitem} && ($same_item ne $next_ref->{ $form->{sort} })))) {
1338 my $row = { map { $_ => { 'class' => 'listsubtotal', } } @columns };
1340 if (($form->{searchitems} ne 'assembly') || !$form->{bom}) {
1341 $row->{onhand}->{data} = $form->format_amount(\%myconfig, $subtotals{onhand});
1344 map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $subtotals{$_}, 2) } @subtotal_columns;
1345 map { $subtotals{$_} = 0 } ('onhand', @subtotal_columns);
1347 $report->add_data($row);
1349 $same_item = $next_ref->{ $form->{sort} };
1355 if ($form->{"l_linetotal"}) {
1356 my $row = { map { $_ => { 'class' => 'listtotal', } } @columns };
1358 map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $totals{$_}, 2) } @subtotal_columns;
1360 $report->add_separator();
1361 $report->add_data($row);
1364 $report->generate_with_headers();
1366 $lxdebug->leave_sub();
1367 } #end generate_report
1369 sub parts_subtotal {
1370 $lxdebug->enter_sub();
1372 $auth->assert('part_service_assembly_edit');
1375 my ($column_index, $subtotalonhand, $subtotalsellprice, $subtotallastcost, $subtotallistprice) = @_;
1377 map { $column_data{$_} = "<td> </td>" } @{ $column_index };
1378 $$subtotalonhand = 0 if ($form->{searchitems} eq 'assembly' && $form->{bom});
1380 $column_data{onhand} =
1381 "<th class=listsubtotal align=right>"
1382 . $form->format_amount(\%myconfig, $$subtotalonhand)
1385 $column_data{linetotalsellprice} =
1386 "<th class=listsubtotal align=right>"
1387 . $form->format_amount(\%myconfig, $$subtotalsellprice, 2)
1389 $column_data{linetotallistprice} =
1390 "<th class=listsubtotal align=right>"
1391 . $form->format_amount(\%myconfig, $$subtotallistprice, 2)
1393 $column_data{linetotallastcost} =
1394 "<th class=listsubtotal align=right>"
1395 . $form->format_amount(\%myconfig, $$subtotallastcost, 2)
1398 $$subtotalonhand = 0;
1399 $$subtotalsellprice = 0;
1400 $$subtotallistprice = 0;
1401 $$subtotallastcost = 0;
1403 print "<tr class=listsubtotal>";
1405 map { print "\n$column_data{$_}" } @{ $column_index };
1411 $lxdebug->leave_sub();
1415 $lxdebug->enter_sub();
1417 $auth->assert('part_service_assembly_edit');
1419 # show history button
1420 $form->{javascript} = qq|<script type="text/javascript" src="js/show_history.js"></script>|;
1421 #/show hhistory button
1422 IC->get_part(\%myconfig, \%$form);
1424 $form->{"original_partnumber"} = $form->{"partnumber"};
1426 my $title = 'Edit ' . ucfirst $form->{item};
1427 $form->{title} = $locale->text($title);
1432 $lxdebug->leave_sub();
1436 $lxdebug->enter_sub();
1438 $auth->assert('part_service_assembly_edit');
1440 IC->create_links("IC", \%myconfig, \%$form);
1443 map({ $form->{selectcurrency} .= "<option>$_\n" }
1444 split(/:/, $form->{currencies}));
1446 # parts and assemblies have the same links
1447 my $item = $form->{item};
1448 if ($form->{item} eq 'assembly') {
1452 # build the popup menus
1453 $form->{taxaccounts} = "";
1454 foreach my $key (keys %{ $form->{IC_links} }) {
1455 foreach my $ref (@{ $form->{IC_links}{$key} }) {
1457 # if this is a tax field
1458 if ($key =~ /IC_tax/) {
1459 if ($key =~ /\Q$item\E/) {
1460 $form->{taxaccounts} .= "$ref->{accno} ";
1461 $form->{"IC_tax_$ref->{accno}_description"} =
1462 "$ref->{accno}--$ref->{description}";
1465 if ($form->{amount}{ $ref->{accno} }) {
1466 $form->{"IC_tax_$ref->{accno}"} = "checked";
1469 $form->{"IC_tax_$ref->{accno}"} = "checked";
1474 $form->{"select$key"} .=
1475 "<option $ref->{selected}>$ref->{accno}--$ref->{description}\n";
1476 if ($form->{amount}{$key} eq $ref->{accno}) {
1477 $form->{$key} = "$ref->{accno}--$ref->{description}";
1483 chop $form->{taxaccounts};
1485 if (($form->{item} eq "part") || ($form->{item} eq "assembly")) {
1486 $form->{selectIC_income} = $form->{selectIC_sale};
1487 $form->{selectIC_expense} = $form->{selectIC_cogs};
1488 $form->{IC_income} = $form->{IC_sale};
1489 $form->{IC_expense} = $form->{IC_cogs};
1492 delete $form->{IC_links};
1493 delete $form->{amount};
1495 $form->get_partsgroup(\%myconfig, { all => 1 });
1497 $form->{partsgroup} = "$form->{partsgroup}--$form->{partsgroup_id}";
1499 if (@{ $form->{all_partsgroup} }) {
1500 $form->{selectpartsgroup} = qq|<option>\n|;
1501 map { $form->{selectpartsgroup} .= qq|<option value="$_->{partsgroup}--$_->{id}">$_->{partsgroup}\n| } @{ $form->{all_partsgroup} };
1504 if ($form->{item} eq 'assembly') {
1506 foreach my $i (1 .. $form->{assembly_rows}) {
1507 if ($form->{"partsgroup_id_$i"}) {
1508 $form->{"partsgroup_$i"} =
1509 qq|$form->{"partsgroup_$i"}--$form->{"partsgroup_id_$i"}|;
1512 $form->get_partsgroup(\%myconfig);
1514 if (@{ $form->{all_partsgroup} }) {
1515 $form->{selectassemblypartsgroup} = qq|<option>\n|;
1518 $form->{selectassemblypartsgroup} .=
1519 qq|<option value="$_->{partsgroup}--$_->{id}">$_->{partsgroup}\n|
1520 } @{ $form->{all_partsgroup} };
1523 $lxdebug->leave_sub();
1527 $lxdebug->enter_sub();
1529 $auth->assert('part_service_assembly_edit');
1531 # what does eur set here? why is it in namespace?
1532 # call of get_accounting_method preserves format of $form->{eur}, which expects 1 or 0
1533 $form->{eur} = $::instance_conf->get_accounting_method eq 'cash' ? 1 : 0; # config dumps into namespace - yuck
1534 $form->{pg_keys} = sub { "$_[0]->{partsgroup}--$_[0]->{id}" };
1535 $form->{description_area} = ($form->{rows} = $form->numtextrows($form->{description}, 40)) > 1;
1536 $form->{notes_rows} = max 4, $form->numtextrows($form->{notes}, 40), $form->numtextrows($form->{formel}, 40);
1538 map { $form->{"is_$_"} = ($form->{item} eq $_) } qw(part service assembly);
1539 map { $form->{$_} =~ s/"/"/g; } qw(unit);
1541 $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS',
1542 'partsgroup' => 'all_partsgroup',
1543 'vendors' => 'ALL_VENDORS',);
1546 IC->retrieve_buchungsgruppen(\%myconfig, $form);
1547 @{ $form->{BUCHUNGSGRUPPEN} } = grep { $_->{id} eq $form->{buchungsgruppen_id} || ($form->{id} && $form->{orphaned}) || !$form->{id} } @{ $form->{BUCHUNGSGRUPPEN} };
1549 # use JavaScript Calendar or not (yes!)
1550 $form->{jsscript} = 1;
1552 my $units = AM->retrieve_units(\%myconfig, $form);
1553 $form->{ALL_UNITS} = [ map +{ name => $_ }, sort { $units->{$a}{sortkey} <=> $units->{$b}{sortkey} } keys %$units ];
1555 $form->{defaults} = AM->get_defaults();
1557 $form->{fokus} = "ic.partnumber";
1559 $form->{CUSTOM_VARIABLES} = CVar->get_custom_variables('module' => 'IC', 'trans_id' => $form->{id});
1561 CVar->render_inputs('variables' => $form->{CUSTOM_VARIABLES}, show_disabled_message => 1)
1562 if (scalar @{ $form->{CUSTOM_VARIABLES} });
1565 #print $form->parse_html_template('ic/form_header', { ALL_PRICE_FACTORS => $form->{ALL_PRICE_FACTORS},
1566 # ALL_UNITS => $form->{ALL_UNITS},
1567 # BUCHUNGSGRUPPEN => $form->{BUCHUNGSGRUPPEN},
1568 # payment_terms => $form->{payment_terms},
1569 # all_partsgroup => $form->{all_partsgroup}});
1570 print $form->parse_html_template('ic/form_header');
1571 $lxdebug->leave_sub();
1575 $lxdebug->enter_sub();
1577 $auth->assert('part_service_assembly_edit');
1579 print $form->parse_html_template('ic/form_footer');
1581 $lxdebug->leave_sub();
1585 $lxdebug->enter_sub();
1588 my @mm_data = grep { any { $_ ne '' } @$_{qw(make model)} } map +{ make => $form->{"make_$_"}, model => $form->{"model_$_"}, lastcost => $form->{"lastcost_$_"}, lastupdate => $form->{"lastupdate_$_"}, sortorder => $form->{"sortorder_$_"} }, 1 .. $numrows;
1589 delete @{$form}{grep { m/^make_\d+/ || m/^model_\d+/ } keys %{ $form }};
1590 print $form->parse_html_template('ic/makemodel', { MM_DATA => [ @mm_data, {} ], mm_rows => scalar @mm_data + 1 });
1592 $lxdebug->leave_sub();
1596 $lxdebug->enter_sub();
1599 my ($nochange, $callback, $previousform, $linetotal, $line_purchase_price, $href);
1601 @column_index = qw(runningnumber qty unit bom partnumber description partsgroup lastcost total);
1603 if ($form->{previousform}) {
1605 @column_index = qw(qty unit bom partnumber description partsgroup total);
1609 $form->{old_callback} = $form->{callback};
1610 $callback = $form->{callback};
1611 $form->{callback} = "$form->{script}?action=display_form";
1614 map { delete $form->{$_} } qw(action header);
1616 # save form variables in a previousform variable
1617 my %form_to_save = map { ($_ => m/^ (?: listprice | sellprice | lastcost ) $/x ? $form->format_amount(\%myconfig, $form->{$_}) : $form->{$_}) }
1619 $previousform = $::auth->save_form_in_session(form => \%form_to_save);
1621 $form->{callback} = $callback;
1622 $form->{assemblytotal} = 0;
1623 $form->{assembly_purchase_price_total} = 0;
1624 $form->{weight} = 0;
1628 runningnumber => { text => $locale->text('No.'), nowrap => 1, width => '5%' },
1629 qty => { text => $locale->text('Qty'), nowrap => 1, width => '10%' },
1630 unit => { text => $locale->text('Unit'), nowrap => 1, width => '5%' },
1631 partnumber => { text => $locale->text('Part Number'), nowrap => 1, width => '20%' },
1632 description => { text => $locale->text('Part Description'), nowrap => 1, width => '50%' },
1633 lastcost => { text => $locale->text('Purchase Prices'), nowrap => 1, width => '50%' },
1634 total => { text => $locale->text('Sale Prices'), nowrap => 1, },
1635 bom => { text => $locale->text('BOM'), },
1636 partsgroup => { text => $locale->text('Group'), },
1641 for my $i (1 .. $numrows) {
1642 my (%row, @row_hiddens);
1644 $form->{"partnumber_$i"} =~ s/\"/"/g;
1646 $linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"} / ($form->{"price_factor_$i"} || 1), 4);
1647 $line_purchase_price = $form->round_amount($form->{"lastcost_$i"} * $form->{"qty_$i"} / ($form->{"price_factor_$i"} || 1), 4);
1648 $form->{assemblytotal} += $linetotal;
1649 $form->{assembly_purchase_price_total} += $line_purchase_price;
1650 $form->{"qty_$i"} = $form->format_amount(\%myconfig, $form->{"qty_$i"});
1651 $linetotal = $form->format_amount(\%myconfig, $linetotal, 2);
1652 $line_purchase_price = $form->format_amount(\%myconfig, $line_purchase_price, 2);
1653 $href = qq|$form->{script}?action=edit&id=$form->{"id_$i"}&rowcount=$i&previousform=$previousform|;
1654 map { $row{$_}{data} = "" } qw(qty unit partnumber description bom partsgroup runningnumber);
1657 if (($i >= 1) && ($i == $numrows)) {
1658 if (!$form->{previousform}) {
1659 $row{partnumber}{data} = qq|<input name="partnumber_$i" size=15 value="$form->{"partnumber_$i"}">|;
1660 $row{qty}{data} = qq|<input name="qty_$i" size=5 value="$form->{"qty_$i"}">|;
1661 $row{description}{data} = qq|<input name="description_$i" size=40 value="$form->{"description_$i"}">|;
1662 $row{partsgroup}{data} = qq|<input name="partsgroup_$i" size=10 value="$form->{"partsgroup_$i"}">|;
1666 if ($form->{previousform}) {
1667 push @row_hiddens, qw(qty bom);
1668 $row{partnumber}{data} = $form->{"partnumber_$i"};
1669 $row{qty}{data} = $form->{"qty_$i"};
1670 $row{bom}{data} = $form->{"bom_$i"} ? "x" : " ";
1671 $row{qty}{align} = 'right';
1673 $row{partnumber}{data} = qq|<a href=$href>$form->{"partnumber_$i"}</a>|;
1674 $row{qty}{data} = qq|<input name="qty_$i" size=5 value="$form->{"qty_$i"}">|;
1675 $row{runningnumber}{data} = qq|<input name="runningnumber_$i" size=3 value="$i">|;
1676 $row{bom}{data} = sprintf qq|<input name="bom_$i" type=checkbox class=checkbox value=1 %s>|,
1677 $form->{"bom_$i"} ? 'checked' : '';
1679 push @row_hiddens, qw(unit description partnumber partsgroup);
1680 $row{unit}{data} = $form->{"unit_$i"};
1681 $row{description}{data} = $form->{"description_$i"};
1682 $row{partsgroup}{data} = $form->{"partsgroup_$i"};
1683 $row{bom}{align} = 'center';
1686 $row{lastcost}{data} = $line_purchase_price;
1687 $row{total}{data} = $linetotal;
1688 $row{lastcost}{align} = 'right';
1689 $row{total}{align} = 'right';
1690 $row{deliverydate}{align} = 'right';
1692 push @row_hiddens, qw(id sellprice lastcost weight price_factor_id price_factor);
1693 $row{hiddens} = [ map +{ name => "${_}_$i", value => $form->{"${_}_$i"} }, @row_hiddens ];
1698 print $form->parse_html_template('ic/assembly_row', { COLUMNS => \@column_index, ROWS => \@ROWS, HEADER => \%header });
1700 $lxdebug->leave_sub();
1704 $lxdebug->enter_sub();
1706 # parse pricegroups. and no, don't rely on check_form for this...
1707 map { $form->{"price_$_"} = $form->parse_amount(\%myconfig, $form->{"price_$_"}) } 1 .. $form->{price_rows};
1709 # same for lastcosts
1710 map { $form->{"lastcost_$_"} = $form->parse_amount(\%myconfig, $form->{"lastcost_$_"}) } 1 .. $form->{"makemodel_rows"};
1712 if ($form->{item} eq "assembly") {
1713 my $i = $form->{assembly_rows};
1715 # if last row is empty check the form otherwise retrieve item
1716 if ( ($form->{"partnumber_$i"} eq "")
1717 && ($form->{"description_$i"} eq "")
1718 && ($form->{"partsgroup_$i"} eq "")) {
1724 IC->assembly_item(\%myconfig, \%$form);
1726 my $rows = scalar @{ $form->{item_list} };
1729 $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
1732 $form->{makemodel_rows}--;
1733 select_item(mode => 'IC');
1736 map { $form->{item_list}[$i]{$_} =~ s/\"/"/g }
1737 qw(partnumber description unit partsgroup);
1738 map { $form->{"${_}_$i"} = $form->{item_list}[0]{$_} }
1739 keys %{ $form->{item_list}[0] };
1740 $form->{"runningnumber_$i"} = $form->{assembly_rows};
1741 $form->{assembly_rows}++;
1749 $form->{rowcount} = $i;
1750 $form->{assembly_rows}++;
1757 } elsif (($form->{item} eq 'part') || ($form->{item} eq 'service')) {
1761 $lxdebug->leave_sub();
1765 $lxdebug->enter_sub();
1767 $auth->assert('part_service_assembly_edit');
1769 my ($parts_id, %newform, $amount, $callback);
1771 # check if there is a part number - commented out, cause there is an automatic allocation of numbers
1772 # $form->isblank("partnumber", $locale->text(ucfirst $form->{item}." Part Number missing!"));
1774 # check if there is a description
1775 $form->isblank("description", $locale->text("Part Description missing!"));
1777 $form->error($locale->text("Inventory quantity must be zero before you can set this $form->{item} obsolete!"))
1778 if $form->{obsolete} && $form->{onhand} * 1 && $form->{item} ne 'service';
1780 if (!$form->{buchungsgruppen_id}) {
1781 $form->error($locale->text("Parts must have an entry type.") . " " .
1782 $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.")
1786 $form->error($locale->text('Description must not be empty!')) unless $form->{description};
1787 $form->error($locale->text('Partnumber must not be set to empty!')) if $form->{id} && !$form->{partnumber};
1790 $lxdebug->message($LXDebug::DEBUG1, "ic.pl: sellprice in save = $form->{sellprice}\n");
1791 if (IC->save(\%myconfig, \%$form) == 3) {
1792 $form->error($locale->text('Partnumber not unique!'));
1794 # saving the history
1795 if(!exists $form->{addition}) {
1796 $form->{snumbers} = qq|partnumber_| . $form->{partnumber};
1797 $form->{addition} = "SAVED";
1798 $form->save_history;
1800 # /saving the history
1801 $parts_id = $form->{id};
1804 # load previous variables
1805 if ($form->{previousform}) {
1807 # save the new form variables before splitting previousform
1808 map { $newform{$_} = $form->{$_} } keys %$form;
1810 # don't trample on previous variables
1811 map { delete $form->{$_} } keys %newform;
1813 my $ic_cvar_configs = CVar->get_configs(module => 'IC');
1814 my @ic_cvar_fields = map { "cvar_$_->{name}" } @{ $ic_cvar_configs };
1816 # restore original values
1817 $::auth->restore_form_from_session($newform{previousform}, form => $form);
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 lastcost 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;
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;
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 my $languages = IC->retrieve_languages(\%myconfig, $form);
1983 if ($form->{language_values} ne "") {
1984 foreach my $item (split(/---\+\+\+---/, $form->{language_values})) {
1985 my ($language_id, $translation, $longdescription) = split(/--\+\+--/, $item);
1987 foreach my $language (@{ $languages }) {
1988 next unless ($language->{id} == $language_id);
1990 $language->{translation} = $translation;
1991 $language->{longdescription} = $longdescription;
1997 my @header_sort = qw(name longdescription);
1998 my %header_title = ( "name" => $locale->text("Name"),
1999 "longdescription" => $locale->text("Long Description"),
2003 map(+{ "column_title" => $header_title{$_},
2008 $form->{"title"} = $locale->text("Language Values");
2010 print $form->parse_html_template("ic/parts_language_selection", { "HEADER" => \@header,
2011 "LANGUAGES" => $languages, });
2013 $lxdebug->leave_sub();
2016 sub ajax_autocomplete {
2017 $main::lxdebug->enter_sub();
2019 my $form = $main::form;
2020 my %myconfig = %main::myconfig;
2022 $form->{column} = 'description' unless $form->{column} =~ /^partnumber|description$/;
2023 $form->{$form->{column}} = $form->{q} || '';
2024 $form->{limit} = ($form->{limit} * 1) || 10;
2025 $form->{searchitems} ||= '';
2027 my @results = IC->all_parts(\%myconfig, $form);
2029 print $form->ajax_response_header(),
2030 $form->parse_html_template('ic/ajax_autocomplete');
2032 $main::lxdebug->leave_sub();
2035 sub continue { call_sub($form->{"nextsub"}); }