X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=bin%2Fmozilla%2Fio.pl;h=41145fcbfa8f618a29a2acbc3de91940d276bd3f;hb=fee85764baaeeecac00c862a979cd52b4655fece;hp=f7084c4dfc622832d30d6aca77ce8e872e0511ee;hpb=f2af9def6777d0192a83c8a86f1332569c742051;p=kivitendo-erp.git
diff --git a/bin/mozilla/io.pl b/bin/mozilla/io.pl
index f7084c4df..41145fcbf 100644
--- a/bin/mozilla/io.pl
+++ b/bin/mozilla/io.pl
@@ -28,7 +28,8 @@
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1335, USA.
#
#######################################################################
#
@@ -36,15 +37,33 @@
#
#######################################################################
+use Carp;
use CGI;
-use CGI::Ajax;
+use List::MoreUtils qw(any uniq apply);
use List::Util qw(min max first);
+use List::UtilsBy qw(sort_by uniq_by);
+use SL::ClientJS;
use SL::CVar;
use SL::Common;
+use SL::Controller::Base;
use SL::CT;
+use SL::Locale::String qw(t8);
use SL::IC;
use SL::IO;
+use SL::File;
+use SL::PriceSource;
+
+use SL::DB::Contact;
+use SL::DB::Customer;
+use SL::DB::Default;
+use SL::DB::Language;
+use SL::DB::Printer;
+use SL::DB::Vendor;
+use SL::Helper::CreatePDF;
+use SL::Helper::Flash;
+use SL::Helper::PrintOptions;
+use SL::Helper::ShippedQty;
require "bin/mozilla/common.pl";
@@ -54,8 +73,8 @@ use strict;
if (-f "bin/mozilla/custom_io.pl") {
eval { require "bin/mozilla/custom_io.pl"; };
}
-if (-f "bin/mozilla/$::form->{login}_io.pl") {
- eval { require "bin/mozilla/$::form->{login}_io.pl"; };
+if (-f "bin/mozilla/$::myconfig{login}_io.pl") {
+ eval { require "bin/mozilla/$::myconfig{login}_io.pl"; };
}
1;
@@ -90,14 +109,13 @@ if (-f "bin/mozilla/$::form->{login}_io.pl") {
# $locale->text('Nov')
# $locale->text('Dec')
use SL::IS;
-use SL::PE;
use SL::AM;
use Data::Dumper;
sub _check_io_auth {
$main::auth->assert('part_service_assembly_edit | vendor_invoice_edit | sales_order_edit | invoice_edit |' .
'request_quotation_edit | sales_quotation_edit | purchase_order_edit | ' .
- 'purchase_delivery_order_edit | sales_delivery_order_edit');
+ 'purchase_delivery_order_edit | sales_delivery_order_edit | part_service_assembly_details');
}
########################################
@@ -112,20 +130,27 @@ sub display_row {
my $form = $main::form;
my %myconfig = %main::myconfig;
my $locale = $main::locale;
- my $cgi = $main::cgi;
+ my $cgi = $::request->{cgi};
my $numrows = shift;
- my ($readonly, $stock_in_out, $stock_in_out_title);
+ my ($stock_in_out, $stock_in_out_title);
+
+ my $defaults = AM->get_defaults();
+ $form->{show_weight} = $defaults->{show_weight};
+ $form->{weightunit} = $defaults->{weightunit};
my $is_purchase = (first { $_ eq $form->{type} } qw(request_quotation purchase_order purchase_delivery_order)) || ($form->{script} eq 'ir.pl');
my $show_min_order_qty = first { $_ eq $form->{type} } qw(request_quotation purchase_order);
my $is_delivery_order = $form->{type} =~ /_delivery_order$/;
+ my $is_quotation = $form->{type} =~ /_quotation$/;
+ my $is_invoice = $form->{type} =~ /invoice/;
+ my $is_credit_note = $form->{type} =~ /credit_note/;
my $is_s_p_order = (first { $_ eq $form->{type} } qw(sales_order purchase_order));
+ my $show_ship_missing = $is_s_p_order && $::instance_conf->get_sales_purchase_order_ship_missing_column;
+ my $show_marge = (!$is_purchase || $is_invoice || $is_credit_note) && !$is_delivery_order;
if ($is_delivery_order) {
- $readonly = ' readonly' if ($form->{closed});
-
if ($form->{type} eq 'sales_delivery_order') {
$stock_in_out_title = $locale->text('Release From Stock');
$stock_in_out = 'out';
@@ -138,34 +163,48 @@ sub display_row {
}
# column_index
- my @header_sort = qw(runningnumber partnumber description ship qty unit sellprice_pg sellprice discount linetotal);
- my @HEADER = (
- { id => 'runningnumber', width => 5, value => $locale->text('No.'), display => 1, },
- { id => 'partnumber', width => 8, value => $locale->text('Number'), display => 1, },
- { id => 'description', width => 30, value => $locale->text('Part Description'), display => 1, },
- { id => 'ship', width => 5, value => $locale->text('Delivered'), display => $is_s_p_order, },
- { id => 'qty', width => 5, value => $locale->text('Qty'), display => 1, },
- { id => 'price_factor', width => 5, value => $locale->text('Price Factor'), display => !$is_delivery_order, },
- { id => 'unit', width => 5, value => $locale->text('Unit'), display => 1, },
- { id => 'license', width => 10, value => $locale->text('License'), display => 0, },
- { id => 'serialnr', width => 10, value => $locale->text('Serial No.'), display => 0, },
- { id => 'projectnr', width => 10, value => $locale->text('Project'), display => 0, },
- { id => 'sellprice', width => 15, value => $locale->text('Price'), display => !$is_delivery_order, },
- { id => 'sellprice_pg', width => 8, value => $locale->text('Pricegroup'), display => !$is_delivery_order && !$is_purchase, },
- { id => 'discount', width => 5, value => $locale->text('Discount'), display => !$is_delivery_order, },
- { id => 'linetotal', width => 10, value => $locale->text('Extended'), display => !$is_delivery_order, },
- { id => 'bin', width => 10, value => $locale->text('Bin'), display => 0, },
- { id => 'stock_in_out', width => 10, value => $stock_in_out_title, display => $is_delivery_order, },
+ my @header_sort = qw(
+ runningnumber partnumber type_and_classific description ship ship_missing qty price_factor
+ unit weight price_source sellprice discount linetotal
+ bin stock_in_out
);
- my @column_index = map { $_->{id} } grep { $_->{display} } @HEADER;
-
+ my @row2_sort = qw(
+ serialnr projectnr reqdate subtotal marge listprice lastcost onhand
+ );
+ my %column_def = (
+ runningnumber => { width => 5, value => $locale->text('No.'), display => 1, },
+ partnumber => { width => 8, value => $locale->text('Number'), display => 1, },
+ type_and_classific
+ => { width => 2, value => $locale->text('Type'), display => 1, },
+ description => { width => 30, value => $locale->text('Part Description'), display => 1, },
+ ship => { width => 5, value => $locale->text('Delivered'), display => $is_s_p_order, },
+ ship_missing => { width => 5, value => $locale->text('Not delivered'), display => $show_ship_missing, },
+ qty => { width => 5, value => $locale->text('Qty'), display => 1, },
+ price_factor => { width => 5, value => $locale->text('Price Factor'), display => !$is_delivery_order, },
+ unit => { width => 5, value => $locale->text('Unit'), display => 1, },
+ weight => { width => 5, value => $locale->text('Weight'), display => $defaults->{show_weight}, },
+ serialnr => { width => 10, value => $locale->text('Serial No.'), display => !$is_quotation },
+ projectnr => { width => 10, value => $locale->text('Project'), display => 1, },
+ price_source => { width => 5, value => $locale->text('Price Source'), display => !$is_delivery_order, },
+ sellprice => { width => 15, value => $locale->text('Price'), display => !$is_delivery_order, },
+ discount => { width => 5, value => $locale->text('Discount'), display => !$is_delivery_order, },
+ linetotal => { width => 10, value => $locale->text('Extended'), display => !$is_delivery_order, },
+ bin => { width => 10, value => $locale->text('Bin'), display => 0, },
+ stock_in_out => { width => 10, value => $stock_in_out_title, display => $is_delivery_order, },
+ reqdate => { value => $locale->text('Reqdate'), display => $is_s_p_order || $is_delivery_order || $is_invoice, },
+ subtotal => { value => $locale->text('Subtotal'), display => 1, },
+ marge => { value => $locale->text('Ertrag'), display => $show_marge, },
+ listprice => { value => $locale->text('LP'), display => $show_marge, },
+ lastcost => { value => $locale->text('EK'), display => $show_marge, },
+ onhand => { value => $locale->text('On Hand'), display => 1, },
+ );
+ my @HEADER = map { $column_def{$_} } @header_sort;
# cache units
my $all_units = AM->retrieve_units(\%myconfig, $form);
my %price_factors = map { $_->{id} => $_->{factor} } @{ $form->{ALL_PRICE_FACTORS} };
- my $colspan = scalar @column_index;
$form->{invsubtotal} = 0;
map { $form->{"${_}_base"} = 0 } (split(/ /, $form->{taxaccounts}));
@@ -176,21 +215,16 @@ sub display_row {
# /about details
# translations, unused commented out
-# $runningnumber = $locale->text('No.');
-# my $deliverydate = $locale->text('Delivery Date');
- my $serialnumber = $locale->text('Serial No.');
- my $projectnumber = $locale->text('Project');
-# $partsgroup = $locale->text('Group');
- my $reqdate = $locale->text('Reqdate');
my $deliverydate = $locale->text('Required by');
# special alignings
- my %align = map { $_ => 'right' } qw(qty ship right sellprice_pg discount linetotal stock_in_out);
- my %nowrap = map { $_ => 1 } qw(description unit);
+ my %align = map { $_ => 'right' } qw(qty ship right discount linetotal stock_in_out weight ship_missing);
+ my %nowrap = map { $_ => 1 } qw(description unit price_source);
$form->{marge_total} = 0;
$form->{sellprice_total} = 0;
$form->{lastcost_total} = 0;
+ $form->{totalweight} = 0;
my %projectnumber_labels = ();
my @projectnumber_values = ("");
@@ -203,17 +237,26 @@ sub display_row {
_update_ship() if ($is_s_p_order);
_update_custom_variables();
+ my $totalweight = 0;
+
+ my $record = _make_record();
# rows
my @ROWS;
for my $i (1 .. $numrows) {
my %column_data = ();
+ my $record_item = $record->id && $record->items ? $record->items->[$i-1] : _make_record_item($i);
+
# undo formatting
map { $form->{"${_}_$i"} = $form->parse_amount(\%myconfig, $form->{"${_}_$i"}) }
qw(qty discount sellprice lastcost price_new price_old)
unless ($form->{simple_save});
+ if ($form->{"prices_$i"} && ($form->{"new_pricegroup_$i"} != $form->{"old_pricegroup_$i"})) {
+ $form->{"sellprice_$i"} = $form->{"price_new_$i"};
+ }
+
# unit begin
$form->{"unit_old_$i"} ||= $form->{"unit_$i"};
$form->{"selected_unit_$i"} ||= $form->{"unit_$i"};
@@ -222,11 +265,11 @@ sub display_row {
|| !AM->convert_unit($form->{"selected_unit_$i"}, $form->{"unit_old_$i"}, $all_units)) { # (z.B. Dimensionseinheit war ausgewaehlt, es handelt sich aber
$form->{"unit_old_$i"} = $form->{"selected_unit_$i"} = $form->{"unit_$i"}; # um eine Dienstleistung). Dann keinerlei Umrechnung vornehmen.
}
- # adjust prices by unit, ignore if pricegroup changed
- if ((!$form->{"prices_$i"}) || ($form->{"new_pricegroup_$i"} == $form->{"old_pricegroup_$i"})) {
- $form->{"sellprice_$i"} *= AM->convert_unit($form->{"selected_unit_$i"}, $form->{"unit_old_$i"}, $all_units) || 1;
- $form->{"unit_old_$i"} = $form->{"selected_unit_$i"};
- }
+
+ $form->{"sellprice_$i"} *= AM->convert_unit($form->{"selected_unit_$i"}, $form->{"unit_old_$i"}, $all_units) || 1;
+ $form->{"lastcost_$i"} *= AM->convert_unit($form->{"selected_unit_$i"}, $form->{"unit_old_$i"}, $all_units) || 1;
+ $form->{"unit_old_$i"} = $form->{"selected_unit_$i"};
+
my $this_unit = $form->{"unit_$i"};
$this_unit = $form->{"selected_unit_$i"} if AM->convert_unit($this_unit, $form->{"selected_unit_$i"}, $all_units);
@@ -243,27 +286,38 @@ sub display_row {
} else {
$column_data{price_factor} = ' ';
}
+ $form->{"weight_$i"} *= AM->convert_unit($form->{"selected_unit_$i"}, $form->{"partunit_$i"}, $all_units) || 1;
$column_data{"unit"} = AM->unit_select_html($all_units, "unit_$i", $this_unit, $form->{"id_$i"} ? $form->{"unit_$i"} : undef);
# / unit ending
+#count the max of decimalplaces of sellprice and lastcost, so the same number of decimalplaces
+#is shown for lastcost and sellprice.
my $decimalplaces = ($form->{"sellprice_$i"} =~ /\.(\d+)/) ? max 2, length $1 : 2;
+ $decimalplaces = ($form->{"lastcost_$i"} =~ /\.(\d+)/) ? max $decimalplaces, length $1 : $decimalplaces;
my $price_factor = $price_factors{$form->{"price_factor_id_$i"}} || 1;
my $discount = $form->round_amount($form->{"qty_$i"} * $form->{"sellprice_$i"} * $form->{"discount_$i"} / 100 / $price_factor, 2);
my $linetotal = $form->round_amount($form->{"qty_$i"} * $form->{"sellprice_$i"} * (100 - $form->{"discount_$i"}) / 100 / $price_factor, 2);
my $rows = $form->numtextrows($form->{"description_$i"}, 30, 6);
- $column_data{runningnumber} = $cgi->textfield(-name => "runningnumber_$i", -size => 5, -value => $i); # HuT
- $column_data{partnumber} = $cgi->textfield(-name => "partnumber_$i", -size => 12, -value => $form->{"partnumber_$i"});
+ # quick delete single row
+ $column_data{runningnumber} = q|| .
+ q| |;
+ $column_data{runningnumber} .= $cgi->textfield(-name => "runningnumber_$i", -id => "runningnumber_$i", -size => 5, -value => $i); # HuT
+
+
+ $column_data{partnumber} = $cgi->textfield(-name => "partnumber_$i", -id => "partnumber_$i", -size => 12, -value => $form->{"partnumber_$i"});
+ $column_data{type_and_classific} = $::request->presenter->type_abbreviation($form->{"part_type_$i"}).
+ $::request->presenter->classification_abbreviation($form->{"classification_id_$i"}) if $form->{"id_$i"};
$column_data{description} = (($rows > 1) # if description is too large, use a textbox instead
- ? $cgi->textarea( -name => "description_$i", -default => $form->{"description_$i"}, -rows => $rows, -columns => 30)
- : $cgi->textfield(-name => "description_$i", -size => 30, -value => $form->{"description_$i"}))
- . $cgi->button(-value => $locale->text('L'), -onClick => "set_longdescription_window('longdescription_$i')");
+ ? $cgi->textarea( -name => "description_$i", -id => "description_$i", -default => $form->{"description_$i"}, -rows => $rows, -columns => 30)
+ : $cgi->textfield(-name => "description_$i", -id => "description_$i", -value => $form->{"description_$i"}, -size => 30))
+ . $cgi->button(-value => $locale->text('L'), -onClick => "kivi.SalesPurchase.edit_longdescription($i)");
my $qty_dec = ($form->{"qty_$i"} =~ /\.(\d+)/) ? length $1 : 2;
- $column_data{qty} = $cgi->textfield(-name => "qty_$i", -size => 5, -value => $form->format_amount(\%myconfig, $form->{"qty_$i"}, $qty_dec));
+ $column_data{qty} = $cgi->textfield(-name => "qty_$i", -size => 5, -"data-validate" => "number", -class => "numeric", -value => $form->format_amount(\%myconfig, $form->{"qty_$i"}, $qty_dec));
$column_data{qty} .= $cgi->button(-onclick => "calculate_qty_selection_window('qty_$i','alu_$i', 'formel_$i', $i)", -value => $locale->text('*/'))
. $cgi->hidden(-name => "formel_$i", -value => $form->{"formel_$i"}) . $cgi->hidden("-name" => "alu_$i", "-value" => $form->{"alu_$i"})
if $form->{"formel_$i"};
@@ -274,60 +328,93 @@ sub display_row {
$ship_qty *= $all_units->{$form->{"partunit_$i"}}->{factor};
$ship_qty /= ( $all_units->{$form->{"unit_$i"}}->{factor} || 1 );
- $column_data{ship} = $form->format_amount(\%myconfig, $form->round_amount($ship_qty, 2) * 1) . ' ' . $form->{"unit_$i"};
- }
+ $column_data{ship} = $form->format_amount(\%myconfig, $form->round_amount($ship_qty, 2) * 1) . ' ' . $form->{"unit_$i"}
+ . $cgi->hidden(-name => "ship_$i", -value => $form->format_amount(\%myconfig, $form->{"ship_$i"}, $qty_dec));
- # build in drop down list for pricesgroups
- if ($form->{"prices_$i"}) {
- $column_data{sellprice_pg} = qq||;
- $column_data{sellprice} = $cgi->textfield(-name => "sellprice_$i", -size => 10, -onBlur => 'check_right_number_format(this)', -value =>
- (($form->{"new_pricegroup_$i"} != $form->{"old_pricegroup_$i"})
- ? $form->format_amount(\%myconfig, $form->{"price_new_$i"}, $decimalplaces)
- : $form->format_amount(\%myconfig, $form->{"sellprice_$i"}, $decimalplaces)));
- } else {
- # for last row and report
- # set pricegroup drop down list from report menu
- if ($form->{"sellprice_$i"} != 0) {
- # remember the pricegroup_id in pricegroup_old
- # but don't overwrite it
- $form->{"pricegroup_old_$i"} = $form->{"pricegroup_id_$i"};
- my $default_option = $form->{"sellprice_$i"}.'--'.$form->{"pricegroup_id_$i"};
- $column_data{sellprice_pg} = NTI($cgi->popup_menu("sellprice_pg_$i", [ $default_option ], $default_option, { $default_option => $form->{"pricegroup_$i"} || '' }));
- } else {
- $column_data{sellprice_pg} = qq| |;
- }
- $column_data{sellprice} = $cgi->textfield(-name => "sellprice_$i", -size => 10, -onBlur => "check_right_number_format(this)", -value =>
- $form->format_amount(\%myconfig, $form->{"sellprice_$i"}, $decimalplaces));
+ my $ship_missing_qty = $form->{"qty_$i"} - $ship_qty;
+ my $ship_missing_amount = $form->round_amount($ship_missing_qty * $form->{"sellprice_$i"} * (100 - $form->{"discount_$i"}) / 100 / $price_factor, 2);
+ $column_data{ship_missing} = $form->format_amount(\%myconfig, $ship_missing_qty) . ' ' . $form->{"unit_$i"} . '; ' . $form->format_amount(\%myconfig, $ship_missing_amount, $decimalplaces);
}
- $column_data{discount} = $cgi->textfield(-name => "discount_$i", -size => 3, -value => $form->format_amount(\%myconfig, $form->{"discount_$i"}));
+
$column_data{linetotal} = $form->format_amount(\%myconfig, $linetotal, 2);
$column_data{bin} = $form->{"bin_$i"};
+ $column_data{weight} = $form->format_amount(\%myconfig, $form->{"qty_$i"} * $form->{"weight_$i"}, 3) . ' ' . $defaults->{weightunit} if $defaults->{show_weight};
+
+ my $sellprice_value = $form->format_amount(\%myconfig, $form->{"sellprice_$i"}, $decimalplaces);
+ my $discount_value = $form->format_amount(\%myconfig, $form->{"discount_$i"});
+
+ my $price;
+ if ($form->{"id_${i}"} && !$is_delivery_order) {
+ my $price_source = SL::PriceSource->new(record_item => $record_item, record => $record);
+ $price = $price_source->price_from_source($::form->{"active_price_source_$i"});
+ my $discount = $price_source->discount_from_source($::form->{"active_discount_source_$i"});
+ my $best_price = $price_source->best_price;
+ my $best_discount = $price_source->best_discount;
+ $column_data{price_source} .= $cgi->button(-value => $price->source_description, -onClick => "kivi.io.price_chooser($i)");
+ if ($price->source) {
+ $column_data{price_source} .= ' ' . $cgi->img({src => 'image/flag-red.png', alt => $price->invalid, title => $price->invalid }) if $price->invalid;
+ $column_data{price_source} .= ' ' . $cgi->img({src => 'image/flag-red.png', alt => $price->missing, title => $price->missing }) if $price->missing;
+ if (!$price->missing && !$price->invalid) {
+ $column_data{price_source} .= ' ' . $cgi->img({src => 'image/up.png', alt => t8('This price has since gone up'), title => t8('This price has since gone up' ) }) if $price->price - $record_item->sellprice > 0.01;
+ $column_data{price_source} .= ' ' . $cgi->img({src => 'image/down.png', alt => t8('This price has since gone down'), title => t8('This price has since gone down') }) if $price->price - $record_item->sellprice < -0.01;
+ $column_data{price_source} .= ' ' . $cgi->img({src => 'image/ok.png', alt => t8('There is a better price available'), title => t8('There is a better price available') }) if $best_price && $price->source ne $price_source->best_price->source;
+ }
+ }
+ if ($discount->source) {
+ $column_data{discount_source} .= ' ' . $cgi->img({src => 'image/flag-red.png', alt => $discount->invalid, title => $discount->invalid }) if $discount->invalid;
+ $column_data{discount_source} .= ' ' . $cgi->img({src => 'image/flag-red.png', alt => $discount->missing, title => $discount->missing }) if $discount->missing;
+ if (!$discount->missing && !$discount->invalid) {
+ $column_data{price_source} .= ' ' . $cgi->img({src => 'image/up.png', alt => t8('This discount has since gone up'), title => t8('This discount has since gone up') }) if $discount->discount * 100 - $record_item->discount > 0.01;
+ $column_data{price_source} .= ' ' . $cgi->img({src => 'image/down.png', alt => t8('This discount has since gone down'), title => t8('This discount has since gone down') }) if $discount->discount * 100 - $record_item->discount < -0.01;
+ $column_data{price_source} .= ' ' . $cgi->img({src => 'image/ok.png', alt => t8('There is a better discount available'), title => t8('There is a better discount available') }) if $best_discount && $discount->source ne $price_source->best_discount->source;
+ }
+ }
+ }
+
+ my $edit_prices = $main::auth->assert('edit_prices', 1) && (!$::form->{"active_price_source_$i"} || !$price || $price->editable);
+ my $edit_discounts = $main::auth->assert('edit_prices', 1) && !$::form->{"active_discount_source_$i"};
+ $column_data{sellprice} = (!$edit_prices)
+ ? $cgi->hidden( -name => "sellprice_$i", -id => "sellprice_$i", -value => $sellprice_value) . $sellprice_value
+ : $cgi->textfield(-name => "sellprice_$i", -id => "sellprice_$i", -size => 10, -"data-validate" => "number", -class => "numeric", -value => $sellprice_value);
+ $column_data{discount} = (!$edit_discounts)
+ ? $cgi->hidden( -name => "discount_$i", -id => "discount_$i", -value => $discount_value) . $discount_value . ' %'
+ : $cgi->textfield(-name => "discount_$i", -id => "discount_$i", -size => 3, -"data-validate" => "number", -class => "numeric", -value => $discount_value);
+
if ($is_delivery_order) {
$column_data{stock_in_out} = calculate_stock_in_out($i);
}
- my @ROW1 = map { value => $column_data{$_}, align => $align{$_}, nowrap => $nowrap{$_} }, @column_index;
-
- # second row
- my @ROW2 = ();
- push @ROW2, { value => qq|$serialnumber | }
- if $form->{type} !~ /_quotation/;
- push @ROW2, { value => qq|$projectnumber | . NTI($cgi->popup_menu('-name' => "project_id_$i", '-values' => \@projectnumber_values,
- '-labels' => \%projectnumber_labels, '-default' => $form->{"project_id_$i"})) };
- push @ROW2, { value => qq|$reqdate | }
- if ($form->{type} =~ /order/ || $form->{type} =~ /invoice/);
- push @ROW2, { value => sprintf qq|%s |,
- $locale->text('Subtotal'), $form->{"subtotal_$i"} ? 'checked' : '' };
+ $column_data{serialnr} = qq||;
+ $column_data{projectnr} = NTI($cgi->popup_menu(
+ '-name' => "project_id_$i",
+ '-values' => \@projectnumber_values,
+ '-labels' => \%projectnumber_labels,
+ '-default' => $form->{"project_id_$i"}
+ ));
+ $column_data{reqdate} = qq||;
+ $column_data{subtotal} = sprintf qq||, $form->{"subtotal_$i"} ? 'checked' : '';
# begin marge calculations
$form->{"lastcost_$i"} *= 1;
$form->{"marge_percent_$i"} = 0;
my $marge_color;
- my $real_sellprice = $linetotal;
- my $real_lastcost = $form->{"lastcost_$i"} * $form->{"qty_$i"} / ( $form->{"marge_price_factor_$i"} || 1 );
+ my $real_sellprice;
+ if ( $form->{taxincluded} and $form->{"qty_$i"} * 1 and $form->{$form->{"taxaccounts_$i"} . "_rate"} * 1) {
+ # if we use taxincluded we need to calculate the marge from the net_value
+ # all the marge calculations are based on linetotal which we need to
+ # convert to net first
+
+ # there is no direct form value for the tax_rate of the item, but
+ # form->{taxaccounts_$i} gives the tax account (e.g. 3806) and 3806_rate
+ # gives the tax percentage (e.g. 0.19)
+ $real_sellprice = $linetotal / (1 + $form->{$form->{"taxaccounts_$i"} . "_rate"});
+ } else {
+ $real_sellprice = $linetotal;
+ };
+ my $real_lastcost = $form->round_amount($form->{"lastcost_$i"} * $form->{"qty_$i"} / $price_factor, 2);
my $marge_percent_warn = $myconfig{marge_percent_warn} * 1 || 15;
my $marge_adjust_credit_note = $form->{type} eq 'credit_note' ? -1 : 1;
@@ -343,44 +430,57 @@ sub display_row {
map { $form->{"${_}_$i"} = $form->format_amount(\%myconfig, $form->{"${_}_$i"}, 2) } qw(marge_absolut marge_percent);
- push @ROW2, { value => sprintf qq|
- %s %s %s%%
- %s %s
- %s |,
- $marge_color, $locale->text('Ertrag'),$form->{"marge_absolut_$i"}, $form->{"marge_percent_$i"},
- $locale->text('LP'), $form->format_amount(\%myconfig, $form->{"listprice_$i"}, 2),
- $locale->text('EK'), $form->format_amount(\%myconfig, $form->{"lastcost_$i"}, 2) }
- if $form->{"id_$i"} && ($form->{type} =~ /^sales_/ || $form->{type} =~ /invoice/) && !$is_delivery_order;
+ $column_data{marge} = sprintf qq|%s %s%%|,
+ $marge_color, $form->{"marge_absolut_$i"}, $form->{"marge_percent_$i"};
+ $column_data{listprice} = $form->format_amount(\%myconfig, $form->{"listprice_$i"}, 2);
+ $column_data{lastcost} = sprintf qq||, $form->format_amount(\%myconfig, $form->{"lastcost_$i"}, $decimalplaces);
# / marge calculations ending
+# Calculate total weight
+ $totalweight += ($form->{"qty_$i"} * $form->{"weight_$i"});
+
# calculate onhand
if ($form->{"id_$i"}) {
my $part = IC->get_basic_part_info(id => $form->{"id_$i"});
- my $onhand_color = 'color="#ff0000"' if $part->{onhand} < $part->{rop};
- push @ROW2, { value => sprintf "%s %s %s",
- $locale->text('On Hand'),
+ my $onhand_color = $part->{onhand} < $part->{rop} ? 'color="#ff0000"' : '';
+ $column_data{onhand} = sprintf "%s %s",
$onhand_color,
$form->format_amount(\%myconfig, $part->{onhand}, 2),
- $part->{unit}
- };
+ $part->{unit};
}
# / calculate onhand
- my @hidden_vars;
+ my @ROW1 = map { { value => $column_data{$_}, align => $align{$_}, nowrap => $nowrap{$_} } } grep { $column_def{$_}{display} } @header_sort;
+ my @ROW2 = map { { value => sprintf "%s %s", $column_def{$_}{value}, $column_data{$_} } } grep { $column_def{$_}{display} } @row2_sort;
- if ($is_delivery_order) {
+ my @hidden_vars;
+ # add hidden ids for persistent (item|invoice)_ids and previous (converted_from*) ids
+ if ($is_quotation) {
+ push @hidden_vars, qw(orderitems_id converted_from_orderitems_id);
+ }
+ if ($is_s_p_order) {
+ push @hidden_vars, qw(orderitems_id converted_from_orderitems_id converted_from_invoice_id);
+ }
+ if ($is_invoice) {
+ push @hidden_vars, qw(invoice_id converted_from_orderitems_id converted_from_delivery_order_items_id converted_from_invoice_id);
+ }
+ if ($::form->{type} =~ /credit_note/) {
+ push @hidden_vars, qw(invoice_id converted_from_invoice_id);
+ }
+ if ($is_delivery_order) {
map { $form->{"${_}_${i}"} = $form->format_amount(\%myconfig, $form->{"${_}_${i}"}) } qw(sellprice discount lastcost);
- push @hidden_vars, qw(sellprice discount price_factor_id lastcost);
+ push @hidden_vars, grep { defined $form->{"${_}_${i}"} } qw(sellprice discount not_discountable price_factor_id lastcost);
push @hidden_vars, "stock_${stock_in_out}_sum_qty", "stock_${stock_in_out}";
+ push @hidden_vars, qw(delivery_order_items_id converted_from_orderitems_id converted_from_delivery_order_items_id);
}
my @HIDDENS = map { value => $_}, (
$cgi->hidden("-name" => "unit_old_$i", "-value" => $form->{"selected_unit_$i"}),
$cgi->hidden("-name" => "price_new_$i", "-value" => $form->format_amount(\%myconfig, $form->{"price_new_$i"})),
- map { ($cgi->hidden("-name" => $_, "-value" => $form->{$_})); } map { $_."_$i" }
- (qw(orderitems_id bo pricegroup_old price_old id inventory_accno bin partsgroup partnotes
- income_accno expense_accno listprice assembly taxaccounts ordnumber transdate cusordnumber
- longdescription basefactor marge_absolut marge_percent marge_price_factor), @hidden_vars)
+ map { ($cgi->hidden("-name" => $_, "-id" => $_, "-value" => $form->{$_})); } map { $_."_$i" }
+ (qw(bo price_old id inventory_accno bin partsgroup partnotes active_price_source active_discount_source
+ income_accno expense_accno listprice assembly taxaccounts ordnumber donumber transdate cusordnumber
+ longdescription basefactor marge_absolut marge_percent marge_price_factor weight), @hidden_vars)
);
map { $form->{"${_}_base"} += $linetotal } (split(/ /, $form->{"taxaccounts_$i"}));
@@ -390,334 +490,247 @@ sub display_row {
# Benutzerdefinierte Variablen für Waren/Dienstleistungen/Erzeugnisse
_render_custom_variables_inputs(ROW2 => \@ROW2, row => $i, part_id => $form->{"id_$i"});
- push @ROWS, { ROW1 => \@ROW1, ROW2 => \@ROW2, HIDDENS => \@HIDDENS, colspan => $colspan, error => $form->{"row_error_$i"}, };
+ my $colspan = scalar @ROW1;
+ push @ROWS, { ROW1 => \@ROW1, ROW2 => \@ROW2, HIDDENS => \@HIDDENS, colspan => $colspan, error => $form->{"row_error_$i"}, obj => $record_item };
}
+ $form->{totalweight} = $totalweight;
+
print $form->parse_html_template('oe/sales_order', { ROWS => \@ROWS,
HEADER => \@HEADER,
});
- if (0 != ($form->{sellprice_total} * 1)) {
+ if (abs($form->{sellprice_total} * 1) >= 0.01) {
$form->{marge_percent} = ($form->{sellprice_total} - $form->{lastcost_total}) / $form->{sellprice_total} * 100;
}
$main::lxdebug->leave_sub();
}
-##################################################
-# build html-code for pricegroups in variable $form->{prices_$j}
-
-sub set_pricegroup {
+sub select_item {
$main::lxdebug->enter_sub();
- my $form = $main::form;
- my $locale = $main::locale;
- my $cgi = $main::cgi;
-
+ my %params = @_;
+ my $mode = $params{mode} || croak "Missing parameter 'mode'";
+ my $pre_entered_qty = $params{pre_entered_qty} || 1;
_check_io_auth();
- my $rowcount = shift;
- for my $j (1 .. $rowcount) {
- next unless $form->{PRICES}{$j};
- # build drop down list for pricegroups
- my $option_tmpl = qq||;
- $form->{"prices_$j"} = join '', map { sprintf $option_tmpl, @$_{qw(price pricegroup_id selected pricegroup)} }
- (+{ pricegroup => $locale->text("none (pricegroup)") }, @{ $form->{PRICES}{$j} });
-
- foreach my $item (@{ $form->{PRICES}{$j} }) {
- # set new selectedpricegroup_id and prices for "Preis"
- $form->{"pricegroup_old_$j"} = $item->{pricegroup_id} if $item->{selected} && $item->{pricegroup_id};
- $form->{"sellprice_$j"} = $item->{price} if $item->{selected} && $item->{pricegroup_id};
- $form->{"price_new_$j"} = $form->{"sellprice_$j"} if $item->{selected} || !$item->{pricegroup_id};
- }
- }
+ my $previous_form = $::auth->save_form_in_session(form => $::form);
+ $::form->{title} = $::myconfig{item_multiselect} ?
+ $::locale->text('Set count for one or more of the items to select them'):
+ $::locale->text('Select from one of the items below');
+ $::form->header;
+
+ my @item_list = map {
+ # maybe there is a better backend function or way to calc
+ $_->{display_sellprice} = ($_->{price_factor}) ? $_->{sellprice} / $_->{price_factor} : $_->{sellprice};
+ $_;
+ } @{ $::form->{item_list} };
+
+ # delete action variable
+ delete @{$::form}{qw(action item_list)};
+
+ print $::form->parse_html_template('io/select_item', { PREVIOUS_FORM => $previous_form,
+ MODE => $mode,
+ ITEM_LIST => \@item_list,
+ IS_ASSEMBLY => $mode eq 'IC',
+ IS_PURCHASE => $mode eq 'IS',
+ PRE_ENTERED_QTY => $pre_entered_qty, });
+
$main::lxdebug->leave_sub();
}
-sub select_item {
+sub item_selected {
+
+ # this function is used for adding parts to records (mode = IR/IS)
+ # and to assemblies (mode = IC)
+
$main::lxdebug->enter_sub();
my $form = $main::form;
my %myconfig = %main::myconfig;
- my $locale = $main::locale;
- my $cgi = $main::cgi;
-# diese variable kommt schon in der methode display_row vor, kann man die besser wiederverwenden? @mb fragen. ich check das jetzt erstmal so ein
- my $is_purchase = (first { $_ eq $form->{type} } qw(request_quotation purchase_order purchase_delivery_order)) || ($form->{script} eq 'ir.pl');
_check_io_auth();
- my @column_index = qw(ndx partnumber description rop onhand unit sellprice);
- my %column_data;
- $column_data{ndx} = qq|