package OE;
use List::Util qw(max first);
+use YAML;
+
use SL::AM;
use SL::Common;
use SL::CVar;
+use SL::DB::Order;
+use SL::DB::PeriodicInvoicesConfig;
+use SL::DB::Status;
use SL::DBUtils;
use SL::IC;
use strict;
-=head1 NAME
-
-OE.pm - Order entry module
-
-=head1 DESCRIPTION
-
-OE.pm is part of the OE module. OE is responsible for sales and purchase orders, as well as sales quotations and purchase requests. This file abstracts the database tables C<oe> and C<orderitems>.
-
-=head1 FUNCTIONS
-
-=over 4
-
-=cut
-
sub transactions {
$main::lxdebug->enter_sub();
my ($self, $myconfig, $form) = @_;
# connect to database
- my $dbh = $form->dbconnect($myconfig);
+ my $dbh = $form->get_standard_dbh;
my $query;
my $ordnumber = 'ordnumber';
my @values;
my $where;
+ my ($periodic_invoices_columns, $periodic_invoices_joins);
+
my $rate = ($form->{vc} eq 'customer') ? 'buy' : 'sell';
if ($form->{type} =~ /_quotation$/) {
$quotation = '1';
$ordnumber = 'quonumber';
+
+ } elsif ($form->{type} eq 'sales_order') {
+ $periodic_invoices_columns = qq| , COALESCE(pcfg.active, 'f') AS periodic_invoices |;
+ $periodic_invoices_joins = qq| LEFT JOIN periodic_invoices_configs pcfg ON (o.id = pcfg.oe_id) |;
}
my $vc = $form->{vc} eq "customer" ? "customer" : "vendor";
$query =
qq|SELECT o.id, o.ordnumber, o.transdate, o.reqdate, | .
- qq| o.amount, ct.name, o.netamount, o.${vc}_id, o.globalproject_id, | .
+ qq| o.amount, ct.${vc}number, ct.name, o.netamount, o.${vc}_id, o.globalproject_id, | .
qq| o.closed, o.delivered, o.quonumber, o.shippingpoint, o.shipvia, | .
qq| o.transaction_description, | .
qq| o.marge_total, o.marge_percent, | .
qq| ex.$rate AS exchangerate, | .
qq| pr.projectnumber AS globalprojectnumber, | .
qq| e.name AS employee, s.name AS salesman, | .
- qq| ct.customernumber, ct.country, ct.ustid | .
+ qq| ct.${vc}number AS vcnumber, ct.country, ct.ustid | .
+ $periodic_invoices_columns .
qq|FROM oe o | .
qq|JOIN $vc ct ON (o.${vc}_id = ct.id) | .
qq|LEFT JOIN employee e ON (o.employee_id = e.id) | .
qq|LEFT JOIN employee s ON (o.salesman_id = s.id) | .
- qq|LEFT JOIN exchangerate ex ON (ex.curr = o.curr | .
+ qq|LEFT JOIN exchangerate ex ON (ex.currency_id = o.currency_id | .
qq| AND ex.transdate = o.transdate) | .
qq|LEFT JOIN project pr ON (o.globalproject_id = pr.id) | .
+ qq|$periodic_invoices_joins | .
qq|WHERE (o.quotation = ?) |;
push(@values, $quotation);
if ($form->{"projectnumber"}) {
$query .= <<SQL;
- AND (pr.projectnumber ILIKE ?) OR EXISTS (
+ AND ((pr.projectnumber ILIKE ?) OR EXISTS (
SELECT * FROM orderitems oi
LEFT JOIN project proi ON proi.id = oi.project_id
WHERE proi.projectnumber ILIKE ? AND oi.trans_id = o.id
- )
+ ))
SQL
push @values, "%" . $form->{"projectnumber"} . "%", "%" . $form->{"projectnumber"} . "%" ;
}
push(@values, '%' . $form->{$vc} . '%');
}
+ if (!$main::auth->assert('sales_all_edit', 1)) {
+ $query .= " AND o.employee_id = (select id from employee where login= ?)";
+ push @values, $form->{login};
+ }
if ($form->{employee_id}) {
$query .= " AND o.employee_id = ?";
push @values, conv_i($form->{employee_id});
push(@values, '%' . $form->{transaction_description} . '%');
}
+ if ($form->{periodic_invoices_active} ne $form->{periodic_invoices_inactive}) {
+ my $not = $form->{periodic_invoices_inactive} ? 'NOT' : '';
+ $query .= qq| AND ${not} COALESCE(pcfg.active, 'f')|;
+ }
+
my $sortdir = !defined $form->{sortdir} ? 'ASC' : $form->{sortdir} ? 'ASC' : 'DESC';
my $sortorder = join(', ', map { "${_} ${sortdir} " } ("o.id", $form->sort_columns("transdate", $ordnumber, "name")));
my %allowed_sort_columns = (
"quonumber" => "o.quonumber",
"name" => "ct.name",
"employee" => "e.name",
- "salesman" => "e.name",
+ "salesman" => "s.name",
"shipvia" => "o.shipvia",
"transaction_description" => "o.transaction_description"
);
}
$sth->finish;
- $dbh->disconnect;
$main::lxdebug->leave_sub();
}
my ($self, $myconfig, $form) = @_;
# connect to database, turn off autocommit
- my $dbh = $form->dbconnect_noauto($myconfig);
+ my $dbh = $form->get_standard_dbh;
my ($query, @values, $sth, $null);
my $exchangerate = 0;
$query = qq|SELECT nextval('id')|;
($form->{id}) = selectrow_query($form, $dbh, $query);
- $query = qq|INSERT INTO oe (id, ordnumber, employee_id) VALUES (?, '', ?)|;
+ $query = qq|INSERT INTO oe (id, ordnumber, employee_id, currency_id) VALUES (?, '', ?, (SELECT currency_id FROM defaults))|;
do_query($form, $dbh, $query, $form->{id}, $form->{employee_id});
}
my $baseqty = $form->{"qty_$i"} * $basefactor;
$form->{"marge_percent_$i"} = $form->parse_amount($myconfig, $form->{"marge_percent_$i"}) * 1;
- $form->{"marge_total_$i"} = $form->parse_amount($myconfig, $form->{"marge_total_$i"}) * 1;
- $form->{"lastcost_$i"} = $form->{"lastcost_$i"} * 1;
+ $form->{"marge_absolut_$i"} = $form->parse_amount($myconfig, $form->{"marge_absolut_$i"}) * 1;
+
+ $form->{"lastcost_$i"} = $form->parse_amount($myconfig, $form->{"lastcost_$i"});
# set values to 0 if nothing entered
$form->{"discount_$i"} = $form->parse_amount($myconfig, $form->{"discount_$i"}) / 100;
$reqdate = ($form->{"reqdate_$i"}) ? $form->{"reqdate_$i"} : undef;
- # get pricegroup_id and save ist
+ # Get pricegroup_id and save it. Unfortunately the interface
+ # also uses ID "0" for signalling that none is selected, but "0"
+ # must not be stored in the database. Therefore we cannot simply
+ # use conv_i().
($null, my $pricegroup_id) = split(/--/, $form->{"sellprice_pg_$i"});
$pricegroup_id *= 1;
+ $pricegroup_id = undef if !$pricegroup_id;
# save detail record in orderitems table
my $orderitems_id = $form->{"orderitems_id_$i"};
$form->{"qty_$i"}, $baseqty,
$fxsellprice, $form->{"discount_$i"},
$form->{"unit_$i"}, conv_date($reqdate), conv_i($form->{"project_id_$i"}),
- $form->{"serialnumber_$i"}, $form->{"ship_$i"}, conv_i($pricegroup_id),
+ $form->{"serialnumber_$i"}, $form->{"ship_$i"}, $pricegroup_id,
$form->{"ordnumber_$i"}, conv_date($form->{"transdate_$i"}),
$form->{"cusordnumber_$i"}, $form->{"subtotal_$i"} ? 't' : 'f',
- $form->{"marge_percent_$i"}, $form->{"marge_total_$i"},
+ $form->{"marge_percent_$i"}, $form->{"marge_absolut_$i"},
$form->{"lastcost_$i"},
conv_i($form->{"price_factor_id_$i"}), conv_i($form->{"price_factor_id_$i"}),
conv_i($form->{"marge_price_factor_$i"}));
qq|UPDATE oe SET
ordnumber = ?, quonumber = ?, cusordnumber = ?, transdate = ?, vendor_id = ?,
customer_id = ?, amount = ?, netamount = ?, reqdate = ?, taxincluded = ?,
- shippingpoint = ?, shipvia = ?, notes = ?, intnotes = ?, curr = ?, closed = ?,
+ shippingpoint = ?, shipvia = ?, notes = ?, intnotes = ?, currency_id = (SELECT id FROM currencies WHERE name=?), closed = ?,
delivered = ?, proforma = ?, quotation = ?, department_id = ?, language_id = ?,
taxzone_id = ?, shipto_id = ?, payment_id = ?, delivery_vendor_id = ?, delivery_customer_id = ?,
globalproject_id = ?, employee_id = ?, salesman_id = ?, cp_id = ?, transaction_description = ?, marge_total = ?, marge_percent = ?
$amount, $netamount, conv_date($reqdate),
$form->{taxincluded} ? 't' : 'f', $form->{shippingpoint},
$form->{shipvia}, $form->{notes}, $form->{intnotes},
- substr($form->{currency}, 0, 3), $form->{closed} ? 't' : 'f',
+ $form->{currency}, $form->{closed} ? 't' : 'f',
$form->{delivered} ? "t" : "f", $form->{proforma} ? 't' : 'f',
$quotation, conv_i($form->{department_id}),
conv_i($form->{language_id}), conv_i($form->{taxzone_id}),
$form->{saved_xyznumber} = $form->{$form->{type} =~ /_quotation$/ ?
"quonumber" : "ordnumber"};
- Common::webdav_folder($form) if ($main::webdav);
+ Common::webdav_folder($form);
my $rc = $dbh->commit;
- $dbh->disconnect;
+
+ $self->save_periodic_invoices_config(dbh => $dbh,
+ oe_id => $form->{id},
+ config_yaml => $form->{periodic_invoices_config})
+ if ($form->{type} eq 'sales_order');
$main::lxdebug->leave_sub();
return $rc;
}
+sub save_periodic_invoices_config {
+ my ($self, %params) = @_;
+
+ return if !$params{oe_id};
+
+ my $config = $params{config_yaml} ? YAML::Load($params{config_yaml}) : undef;
+ return if 'HASH' ne ref $config;
+
+ my $obj = SL::DB::Manager::PeriodicInvoicesConfig->find_by(oe_id => $params{oe_id})
+ || SL::DB::PeriodicInvoicesConfig->new(oe_id => $params{oe_id});
+ $obj->update_attributes(%{ $config });
+}
+
+sub load_periodic_invoice_config {
+ my $self = shift;
+ my $form = shift;
+
+ delete $form->{periodic_invoices_config};
+
+ if ($form->{id}) {
+ my $config_obj = SL::DB::Manager::PeriodicInvoicesConfig->find_by(oe_id => $form->{id});
+
+ if ($config_obj) {
+ my $config = { map { $_ => $config_obj->$_ } qw(active terminated periodicity start_date_as_date end_date_as_date extend_automatically_by ar_chart_id
+ print printer_id copies) };
+ $form->{periodic_invoices_config} = YAML::Dump($config);
+ }
+ }
+}
+
sub _close_quotations_rfqs {
$main::lxdebug->enter_sub();
sub delete {
$main::lxdebug->enter_sub();
- my ($self, $myconfig, $form, $spool) = @_;
-
- # connect to database
- my $dbh = $form->dbconnect_noauto($myconfig);
-
- # delete spool files
- my $query = qq|SELECT s.spoolfile FROM status s | .
- qq|WHERE s.trans_id = ?|;
- my @values = (conv_i($form->{id}));
- my $sth = $dbh->prepare($query);
- $sth->execute(@values) || $self->dberror($query);
-
- my $spoolfile;
- my @spoolfiles = ();
-
- while (($spoolfile) = $sth->fetchrow_array) {
- push @spoolfiles, $spoolfile;
- }
- $sth->finish;
-
- # delete-values
- @values = (conv_i($form->{id}));
-
- # delete status entries
- $query = qq|DELETE FROM status | .
- qq|WHERE trans_id = ?|;
- do_query($form, $dbh, $query, @values);
+ my ($self, $myconfig, $form) = @_;
- # delete OE record
- $query = qq|DELETE FROM oe | .
- qq|WHERE id = ?|;
- do_query($form, $dbh, $query, @values);
+ my $rc = SL::DB::Order->new->db->with_transaction(sub {
+ my @spoolfiles = grep { $_ } map { $_->spoolfile } @{ SL::DB::Manager::Status->get_all(where => [ trans_id => $form->{id} ]) };
- # delete individual entries
- $query = qq|DELETE FROM orderitems | .
- qq|WHERE trans_id = ?|;
- do_query($form, $dbh, $query, @values);
+ SL::DB::Order->new(id => $form->{id})->delete;
- $query = qq|DELETE FROM shipto | .
- qq|WHERE trans_id = ? AND module = 'OE'|;
- do_query($form, $dbh, $query, @values);
+ my $spool = $::lx_office_conf{paths}->{spool};
+ unlink map { "$spool/$_" } @spoolfiles if $spool;
- my $rc = $dbh->commit;
- $dbh->disconnect;
-
- if ($rc) {
- foreach $spoolfile (@spoolfiles) {
- unlink "$spool/$spoolfile" if $spoolfile;
- }
- }
+ 1;
+ });
$main::lxdebug->leave_sub();
my ($self, $myconfig, $form) = @_;
# connect to database
- my $dbh = $form->dbconnect_noauto($myconfig);
+ my $dbh = $form->get_standard_dbh;
my ($query, $query_add, @values, @ids, $sth);
- my $ic_cvar_configs = CVar->get_configs(module => 'IC',
- dbh => $dbh);
-
# translate the ids (given by id_# and trans_id_#) into one array of ids, so we can join them later
map {
push @ids, $form->{"trans_id_$_"}
(SELECT c.accno FROM chart c WHERE d.income_accno_id = c.id) AS income_accno,
(SELECT c.accno FROM chart c WHERE d.expense_accno_id = c.id) AS expense_accno,
(SELECT c.accno FROM chart c WHERE d.fxgain_accno_id = c.id) AS fxgain_accno,
- (SELECT c.accno FROM chart c WHERE d.fxloss_accno_id = c.id) AS fxloss_accno,
- d.curr AS currencies
+ (SELECT c.accno FROM chart c WHERE d.fxloss_accno_id = c.id) AS fxloss_accno
$query_add
FROM defaults d|;
my $ref = selectfirst_hashref_query($form, $dbh, $query);
map { $form->{$_} = $ref->{$_} } keys %$ref;
- ($form->{currency}) = split(/:/, $form->{currencies}) unless ($form->{currency});
+ $form->{currency} = $form->get_default_currency($myconfig);
# set reqdate if this is an invoice->order conversion. If someone knows a better check to ensure
# we come from invoices, feel free.
$query =
qq|SELECT o.cp_id, o.ordnumber, o.transdate, o.reqdate,
o.taxincluded, o.shippingpoint, o.shipvia, o.notes, o.intnotes,
- o.curr AS currency, e.name AS employee, o.employee_id, o.salesman_id,
+ (SELECT cu.name FROM currencies cu WHERE cu.id=o.currency_id) AS currency, e.name AS employee, o.employee_id, o.salesman_id,
o.${vc}_id, cv.name AS ${vc}, o.amount AS invtotal,
o.closed, o.reqdate, o.quonumber, o.department_id, o.cusordnumber,
d.description AS department, o.payment_id, o.language_id, o.taxzone_id,
$sth = prepare_execute_query($form, $dbh, $query, @values);
$ref = $sth->fetchrow_hashref("NAME_lc");
- map { $form->{$_} = $ref->{$_} } keys %$ref;
- $form->{saved_xyznumber} = $form->{$form->{type} =~ /_quotation$/ ?
- "quonumber" : "ordnumber"};
+ if ($ref) {
+ map { $form->{$_} = $ref->{$_} } keys %$ref;
- # set all entries for multiple ids blank that yield different information
- while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
- map { $form->{$_} = '' if ($ref->{$_} ne $form->{$_}) } keys %$ref;
+ $form->{saved_xyznumber} = $form->{$form->{type} =~ /_quotation$/ ? "quonumber" : "ordnumber"};
+
+ # set all entries for multiple ids blank that yield different information
+ while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
+ map { $form->{$_} = '' if ($ref->{$_} ne $form->{$_}) } keys %$ref;
+ }
}
# if not given, fill transdate with current_date
map { $form->{$_} =~ s/ +$//g } qw(printed emailed queued);
} # if !@ids
- my %oid = ('Pg' => 'oid',
- 'Oracle' => 'rowid');
-
my $transdate = $form->{transdate} ? $dbh->quote($form->{transdate}) : "current_date";
$form->{taxzone_id} = 0 unless ($form->{taxzone_id});
c2.accno AS income_accno, c2.new_chart_id AS income_new_chart, date($transdate) - c2.valid_from as income_valid,
c3.accno AS expense_accno, c3.new_chart_id AS expense_new_chart, date($transdate) - c3.valid_from as expense_valid,
oe.ordnumber AS ordnumber_oe, oe.transdate AS transdate_oe, oe.cusordnumber AS cusordnumber_oe,
- p.partnumber, p.assembly, o.description, o.qty,
- o.sellprice, o.parts_id AS id, o.unit, o.discount, p.bin, p.notes AS partnotes, p.inventory_accno_id AS part_inventory_accno_id,
+ p.partnumber, p.assembly, p.listprice, o.description, o.qty,
+ o.sellprice, o.parts_id AS id, o.unit, o.discount, p.notes AS partnotes, p.inventory_accno_id AS part_inventory_accno_id,
o.reqdate, o.project_id, o.serialnumber, o.ship, o.lastcost,
o.ordnumber, o.transdate, o.cusordnumber, o.subtotal, o.longdescription,
o.price_factor_id, o.price_factor, o.marge_price_factor,
($form->{id}
? qq|WHERE o.trans_id = ?|
: qq|WHERE o.trans_id IN (| . join(", ", map("?", @ids)) . qq|)|) .
- qq|ORDER BY o.$oid{$myconfig->{dbdriver}}|;
+ qq|ORDER BY o.oid|;
@ids = $form->{id} ? ($form->{id}) : @ids;
$sth = prepare_execute_query($form, $dbh, $query, @values);
$form->{exchangerate} = $form->get_exchangerate($dbh, $form->{currency}, $form->{transdate}, ($form->{vc} eq 'customer') ? "buy" : "sell");
- Common::webdav_folder($form) if ($main::webdav);
+ Common::webdav_folder($form);
+
+ $self->load_periodic_invoice_config($form);
my $rc = $dbh->commit;
- $dbh->disconnect;
$main::lxdebug->leave_sub();
return $rc;
}
-=item retrieve_simple PARAMS
-
-simple OE retrieval by id. does not look up customer, vendor, units or any other stuff. only oe and orderitems.
-
- my $order = retrieve_simple(id => 2);
-
- $order => {
- %_OE_CONTENT,
- orderitems => [
- %_ORDERITEM_ROW_1,
- %_ORDERITEM_ROW_2,
- ...
- ]
- }
-
-=cut
sub retrieve_simple {
$main::lxdebug->enter_sub();
my ($self, $myconfig, $form) = @_;
# connect to database
- my $dbh = $form->dbconnect($myconfig);
+ my $dbh = $form->get_standard_dbh;
my $query;
my @values = ();
my $sth;
my $tax_rate;
my $taxamount;
-
- my %oid = ('Pg' => 'oid',
- 'Oracle' => 'rowid');
-
- my (@project_ids, %projectnumbers);
+ my (@project_ids, %projectnumbers, %projectdescriptions);
push(@project_ids, $form->{"globalproject_id"}) if ($form->{"globalproject_id"});
}
if (@project_ids) {
- $query = "SELECT id, projectnumber FROM project WHERE id IN (" .
+ $query = "SELECT id, projectnumber, description FROM project WHERE id IN (" .
join(", ", map("?", @project_ids)) . ")";
$sth = prepare_execute_query($form, $dbh, $query, @project_ids);
while (my $ref = $sth->fetchrow_hashref()) {
$projectnumbers{$ref->{id}} = $ref->{projectnumber};
+ $projectdescriptions{$ref->{id}} = $ref->{description};
}
$sth->finish();
}
$form->{"globalprojectnumber"} = $projectnumbers{$form->{"globalproject_id"}};
+ $form->{"globalprojectdescription"} = $projectdescriptions{$form->{"globalproject_id"}};
$form->{discount} = [];
$form->{TEMPLATE_ARRAYS} = { };
- IC->prepare_parts_for_printing();
+ IC->prepare_parts_for_printing(myconfig => $myconfig, form => $form);
my $ic_cvar_configs = CVar->get_configs(module => 'IC');
qw(runningnumber number description longdescription qty ship unit bin
partnotes serialnumber reqdate sellprice listprice netprice
discount p_discount discount_sub nodiscount_sub
- linetotal nodiscount_linetotal tax_rate projectnumber
- price_factor price_factor_name partsgroup);
+ linetotal nodiscount_linetotal tax_rate projectnumber projectdescription
+ price_factor price_factor_name partsgroup weight lineweight);
push @arrays, map { "ic_cvar_$_->{name}" } @{ $ic_cvar_configs };
map { $form->{TEMPLATE_ARRAYS}->{$_} = [] } (@arrays, @tax_arrays);
+ my $totalweight = 0;
my $sameitem = "";
foreach $item (sort { $a->[1] cmp $b->[1] } @partsgroup) {
$i = $item->[0];
push @{ $form->{TEMPLATE_ARRAYS}->{description} }, $form->{"description_$i"};
push @{ $form->{TEMPLATE_ARRAYS}->{longdescription} }, $form->{"longdescription_$i"};
push @{ $form->{TEMPLATE_ARRAYS}->{qty} }, $form->format_amount($myconfig, $form->{"qty_$i"});
+ push @{ $form->{TEMPLATE_ARRAYS}->{qty_nofmt} }, $form->{"qty_$i"};
push @{ $form->{TEMPLATE_ARRAYS}->{ship} }, $form->format_amount($myconfig, $form->{"ship_$i"});
+ push @{ $form->{TEMPLATE_ARRAYS}->{ship_nofmt} }, $form->{"ship_$i"};
push @{ $form->{TEMPLATE_ARRAYS}->{unit} }, $form->{"unit_$i"};
push @{ $form->{TEMPLATE_ARRAYS}->{bin} }, $form->{"bin_$i"};
push @{ $form->{TEMPLATE_ARRAYS}->{partnotes} }, $form->{"partnotes_$i"};
push @{ $form->{TEMPLATE_ARRAYS}->{serialnumber} }, $form->{"serialnumber_$i"};
push @{ $form->{TEMPLATE_ARRAYS}->{reqdate} }, $form->{"reqdate_$i"};
push @{ $form->{TEMPLATE_ARRAYS}->{sellprice} }, $form->{"sellprice_$i"};
+ push @{ $form->{TEMPLATE_ARRAYS}->{sellprice_nofmt} }, $form->parse_amount($myconfig, $form->{"sellprice_$i"});
push @{ $form->{TEMPLATE_ARRAYS}->{listprice} }, $form->{"listprice_$i"};
push @{ $form->{TEMPLATE_ARRAYS}->{price_factor} }, $price_factor->{formatted_factor};
push @{ $form->{TEMPLATE_ARRAYS}->{price_factor_name} }, $price_factor->{description};
my ($dec) = ($sellprice =~ /\.(\d+)/);
my $decimalplaces = max 2, length($dec);
- my $parsed_discount = $form->parse_amount($myconfig, $form->{"discount_$i"});
- my $linetotal_exact = $form->{"qty_$i"} * $sellprice * (100 - $parsed_discount) / 100 / $price_factor->{factor};
- my $linetotal = $form->round_amount($linetotal_exact, 2);
- my $discount = $form->round_amount($form->{"qty_$i"} * $sellprice * $parsed_discount / 100 / $price_factor->{factor} - ($linetotal - $linetotal_exact),
- $decimalplaces);
- my $nodiscount_linetotal = $form->round_amount($form->{"qty_$i"} * $sellprice / $price_factor->{factor}, 2);
+ my $parsed_discount = $form->parse_amount($myconfig, $form->{"discount_$i"});
+
+ my $linetotal_exact = $form->{"qty_$i"} * $sellprice * (100 - $parsed_discount) / 100 / $price_factor->{factor};
+ my $linetotal = $form->round_amount($linetotal_exact, 2);
+
+ my $nodiscount_exact_linetotal = $form->{"qty_$i"} * $sellprice / $price_factor->{factor};
+ my $nodiscount_linetotal = $form->round_amount($nodiscount_exact_linetotal,2);
+
+ my $discount = $nodiscount_linetotal - $linetotal; # is always rounded because $nodiscount_linetotal and $linetotal are rounded
+
+ my $discount_round_error = $discount + ($linetotal_exact - $nodiscount_exact_linetotal); # not used
+
$form->{"netprice_$i"} = $form->round_amount($form->{"qty_$i"} ? ($linetotal / $form->{"qty_$i"}) : 0, 2);
- push @{ $form->{TEMPLATE_ARRAYS}->{netprice} }, ($form->{"netprice_$i"} != 0) ? $form->format_amount($myconfig, $form->{"netprice_$i"}, $decimalplaces) : '';
+ push @{ $form->{TEMPLATE_ARRAYS}->{netprice} }, ($form->{"netprice_$i"} != 0) ? $form->format_amount($myconfig, $form->{"netprice_$i"}, $decimalplaces) : '';
+ push @{ $form->{TEMPLATE_ARRAYS}->{netprice_nofmt} }, ($form->{"netprice_$i"} != 0) ? $form->{"netprice_$i"} : '';
$linetotal = ($linetotal != 0) ? $linetotal : '';
- push @{ $form->{TEMPLATE_ARRAYS}->{discount} }, ($discount != 0) ? $form->format_amount($myconfig, $discount * -1, 2) : '';
- push @{ $form->{TEMPLATE_ARRAYS}->{p_discount} }, $form->{"discount_$i"};
+ push @{ $form->{TEMPLATE_ARRAYS}->{discount} }, ($discount != 0) ? $form->format_amount($myconfig, $discount * -1, 2) : '';
+ push @{ $form->{TEMPLATE_ARRAYS}->{discount_nofmt} }, ($discount != 0) ? $discount * -1 : '';
+ push @{ $form->{TEMPLATE_ARRAYS}->{p_discount} }, $form->{"discount_$i"};
$form->{ordtotal} += $linetotal;
$form->{nodiscount_total} += $nodiscount_linetotal;
}
if ($form->{"subtotal_$i"} && $subtotal_header && ($subtotal_header != $i)) {
- push @{ $form->{TEMPLATE_ARRAYS}->{discount_sub} }, $form->format_amount($myconfig, $discount_subtotal, 2);
- push @{ $form->{TEMPLATE_ARRAYS}->{nodiscount_sub} }, $form->format_amount($myconfig, $nodiscount_subtotal, 2);
+ push @{ $form->{TEMPLATE_ARRAYS}->{discount_sub} }, $form->format_amount($myconfig, $discount_subtotal, 2);
+ push @{ $form->{TEMPLATE_ARRAYS}->{discount_sub_nofmt} }, $discount_subtotal;
+ push @{ $form->{TEMPLATE_ARRAYS}->{nodiscount_sub} }, $form->format_amount($myconfig, $nodiscount_subtotal, 2);
+ push @{ $form->{TEMPLATE_ARRAYS}->{nodiscount_sub_nofmt} }, $nodiscount_subtotal;
$discount_subtotal = 0;
$nodiscount_subtotal = 0;
$subtotal_header = 0;
} else {
- push @{ $form->{TEMPLATE_ARRAYS}->{discount_sub} }, "";
- push @{ $form->{TEMPLATE_ARRAYS}->{nodiscount_sub} }, "";
+ push @{ $form->{TEMPLATE_ARRAYS}->{$_} }, "" for qw(discount_sub nodiscount_sub discount_sub_nofmt nodiscount_sub_nofmt);
}
if (!$form->{"discount_$i"}) {
$nodiscount += $linetotal;
}
- push @{ $form->{TEMPLATE_ARRAYS}->{linetotal} }, $form->format_amount($myconfig, $linetotal, 2);
- push @{ $form->{TEMPLATE_ARRAYS}->{nodiscount_linetotal} }, $form->format_amount($myconfig, $nodiscount_linetotal, 2);
+ push @{ $form->{TEMPLATE_ARRAYS}->{linetotal} }, $form->format_amount($myconfig, $linetotal, 2);
+ push @{ $form->{TEMPLATE_ARRAYS}->{linetotal_nofmt} }, $linetotal_exact;
+ push @{ $form->{TEMPLATE_ARRAYS}->{nodiscount_linetotal} }, $form->format_amount($myconfig, $nodiscount_linetotal, 2);
+ push @{ $form->{TEMPLATE_ARRAYS}->{nodiscount_linetotal_nofmt} }, $nodiscount_linetotal;
+ push(@{ $form->{TEMPLATE_ARRAYS}->{projectnumber} }, $projectnumbers{$form->{"project_id_$i"}});
+ push(@{ $form->{TEMPLATE_ARRAYS}->{projectdescription} }, $projectdescriptions{$form->{"project_id_$i"}});
- push(@{ $form->{TEMPLATE_ARRAYS}->{projectnumber} }, $projectnumbers{$form->{"project_id_$i"}});
+ my $lineweight = $form->{"qty_$i"} * $form->{"weight_$i"};
+ $totalweight += $lineweight;
+ push @{ $form->{TEMPLATE_ARRAYS}->{weight} }, $form->format_amount($myconfig, $form->{"weight_$i"}, 3);
+ push @{ $form->{TEMPLATE_ARRAYS}->{weight_nofmt} }, $form->{"weight_$i"};
+ push @{ $form->{TEMPLATE_ARRAYS}->{lineweight} }, $form->format_amount($myconfig, $lineweight, 3);
+ push @{ $form->{TEMPLATE_ARRAYS}->{lineweight_nofmt} }, $lineweight;
my ($taxamount, $taxbase);
my $taxrate = 0;
# get parts and push them onto the stack
my $sortorder = "";
if ($form->{groupitems}) {
- $sortorder = qq|ORDER BY pg.partsgroup, a.$oid{$myconfig->{dbdriver}}|;
+ $sortorder = qq|ORDER BY pg.partsgroup, a.oid|;
} else {
- $sortorder = qq|ORDER BY a.$oid{$myconfig->{dbdriver}}|;
+ $sortorder = qq|ORDER BY a.oid|;
}
$query = qq|SELECT p.partnumber, p.description, p.unit, a.qty, | .
- qq|pg.partsgroup | .
- qq|FROM assembly a | .
- qq| JOIN parts p ON (a.parts_id = p.id) | .
- qq| LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) | .
- qq| WHERE a.bom = '1' | .
- qq| AND a.id = ? | . $sortorder;
- @values = ($form->{"id_$i"});
+ qq|pg.partsgroup | .
+ qq|FROM assembly a | .
+ qq| JOIN parts p ON (a.parts_id = p.id) | .
+ qq| LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) | .
+ qq| WHERE a.bom = '1' | .
+ qq| AND a.id = ? | . $sortorder;
+ @values = ($form->{"id_$i"});
$sth = $dbh->prepare($query);
$sth->execute(@values) || $form->dberror($query);
$sth->finish;
}
- map { push @{ $form->{TEMPLATE_ARRAYS}->{"ic_cvar_$_->{name}"} }, $form->{"ic_cvar_$_->{name}_$i"} } @{ $ic_cvar_configs };
+ push @{ $form->{TEMPLATE_ARRAYS}->{"ic_cvar_$_->{name}"} },
+ CVar->format_to_template(CVar->parse($form->{"ic_cvar_$_->{name}_$i"}, $_), $_)
+ for @{ $ic_cvar_configs };
}
}
+ $form->{totalweight} = $form->format_amount($myconfig, $totalweight, 3);
+ $form->{totalweight_nofmt} = $totalweight;
+ my $defaults = AM->get_defaults();
+ $form->{weightunit} = $defaults->{weightunit};
+
my $tax = 0;
foreach $item (sort keys %taxaccounts) {
$tax += $taxamount = $form->round_amount($taxaccounts{$item}, 2);
push(@{ $form->{TEMPLATE_ARRAYS}->{taxbase} }, $form->format_amount($myconfig, $taxbase{$item}, 2));
+ push(@{ $form->{TEMPLATE_ARRAYS}->{taxbase_nofmt} }, $taxbase{$item});
push(@{ $form->{TEMPLATE_ARRAYS}->{tax} }, $form->format_amount($myconfig, $taxamount, 2));
+ push(@{ $form->{TEMPLATE_ARRAYS}->{tax_nofmt} }, $taxamount);
push(@{ $form->{TEMPLATE_ARRAYS}->{taxrate} }, $form->format_amount($myconfig, $form->{"${item}_rate"} * 100));
+ push(@{ $form->{TEMPLATE_ARRAYS}->{taxrate_nofmt} }, $form->{"${item}_rate"} * 100);
push(@{ $form->{TEMPLATE_ARRAYS}->{taxdescription} }, $form->{"${item}_description"} . q{ } . 100 * $form->{"${item}_rate"} . q{%});
push(@{ $form->{TEMPLATE_ARRAYS}->{taxnumber} }, $form->{"${item}_taxnumber"});
}
$form->{yesdiscount} = $form->format_amount($myconfig, $form->{nodiscount_total} - $nodiscount, 2);
if($form->{taxincluded}) {
- $form->{subtotal} = $form->format_amount($myconfig, $form->{ordtotal} - $tax, 2);
+ $form->{subtotal} = $form->format_amount($myconfig, $form->{ordtotal} - $tax, 2);
+ $form->{subtotal_nofmt} = $form->{ordtotal} - $tax;
} else {
- $form->{subtotal} = $form->format_amount($myconfig, $form->{ordtotal}, 2);
+ $form->{subtotal} = $form->format_amount($myconfig, $form->{ordtotal}, 2);
+ $form->{subtotal_nofmt} = $form->{ordtotal};
}
$form->{ordtotal} = ($form->{taxincluded}) ? $form->{ordtotal} : $form->{ordtotal} + $tax;
}
1;
+
+__END__
+
+=head1 NAME
+
+OE.pm - Order entry module
+
+=head1 DESCRIPTION
+
+OE.pm is part of the OE module. OE is responsible for sales and purchase orders, as well as sales quotations and purchase requests. This file abstracts the database tables C<oe> and C<orderitems>.
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item retrieve_simple PARAMS
+
+simple OE retrieval by id. does not look up customer, vendor, units or any other stuff. only oe and orderitems.
+
+ my $order = retrieve_simple(id => 2);
+
+ $order => {
+ %_OE_CONTENT,
+ orderitems => [
+ %_ORDERITEM_ROW_1,
+ %_ORDERITEM_ROW_2,
+ ...
+ ]
+ }
+
+=back
+
+=cut