Projekt

Allgemein

Profil

Herunterladen (72,8 KB) Statistiken
| Zweig: | Markierung: | Revision:
626e0240 Stephan Köhler
#====================================================================
d319704a Moritz Bunkus
# LX-Office ERP
# Copyright (C) 2004
# Based on SQL-Ledger Version 2.1.9
# Web http://www.lx-office.org
#
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 1999-2003
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# 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
f7b15d43 Christian Wittmer
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1335, USA.
d319704a Moritz Bunkus
#======================================================================
#
# Order entry module
# Quotation
#======================================================================

package OE;

0a6affab Sven Schöling
use List::Util qw(max first);
92331b8e Moritz Bunkus
54e4131e Moritz Bunkus
use SL::AM;
8e206587 Moritz Bunkus
use SL::Common;
ef220490 Moritz Bunkus
use SL::CVar;
3b9c2119 Moritz Bunkus
use SL::DB::Order;
92331b8e Moritz Bunkus
use SL::DB::PeriodicInvoicesConfig;
c2eb03d4 Geoffrey Richardson
use SL::DB::Project;
use SL::DB::ProjectType;
f0ddfbfe Moritz Bunkus
use SL::DB::RequirementSpecOrder;
3b9c2119 Moritz Bunkus
use SL::DB::Status;
e90048c8 Bernd Bleßmann
use SL::DB::Tax;
8a996479 Moritz Bunkus
use SL::DBUtils;
5f6d6d4e Moritz Bunkus
use SL::HTML::Restrict;
47c3bf62 Moritz Bunkus
use SL::IC;
aff32344 Moritz Bunkus
use SL::TransNumber;
88dea78e Moritz Bunkus
use SL::Util qw(trim);
8e0f6e70 Sven Schöling
use SL::DB;
65b2387a Moritz Bunkus
use SL::YAML;
aa4fda0e Sven Schöling
use Text::ParseWords;
54e4131e Moritz Bunkus
c510d88b Sven Schöling
use strict;

d319704a Moritz Bunkus
sub transactions {
$main::lxdebug->enter_sub();

my ($self, $myconfig, $form) = @_;

# connect to database
76a25c8c Sven Schöling
my $dbh = $form->get_standard_dbh;
d319704a Moritz Bunkus
my $query;
my $ordnumber = 'ordnumber';
my $quotation = '0';

72eaa1a7 Moritz Bunkus
my @values;
9d0ebf28 Moritz Bunkus
my $where;

92331b8e Moritz Bunkus
my ($periodic_invoices_columns, $periodic_invoices_joins);

9d0ebf28 Moritz Bunkus
my $rate = ($form->{vc} eq 'customer') ? 'buy' : 'sell';

if ($form->{type} =~ /_quotation$/) {
$quotation = '1';
$ordnumber = 'quonumber';
92331b8e Moritz Bunkus
} 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) |;
9d0ebf28 Moritz Bunkus
}

my $vc = $form->{vc} eq "customer" ? "customer" : "vendor";

50133d13 Sven Schöling
my %billed_amount;
my %billed_netamount;
if ($form->{l_remaining_amount} || $form->{l_remaining_netamount}) {
$query = <<'';
SELECT from_id, ar.amount, ar.netamount FROM (
SELECT from_id, to_id
FROM record_links
WHERE from_table = 'oe' AND to_table = 'ar'
UNION
SELECT rl1.from_id, rl2.to_id
FROM record_links rl1
LEFT JOIN record_links rl2 ON (rl1.to_table = rl2.from_table AND rl1.to_id = rl2.from_id)
WHERE rl1.from_table = 'oe' AND rl2.to_table = 'ar'
4c8c615a Jan Büren
UNION
SELECT rl1.from_id, rl3.to_id
FROM record_links rl1
JOIN record_links rl2 ON (rl1.to_table = rl2.from_table AND rl1.to_id = rl2.from_id)
JOIN record_links rl3 ON (rl2.to_table = rl3.from_table AND rl2.to_id = rl3.from_id)
99382a64 Jan Büren
WHERE rl1.from_table = 'oe' AND rl2.to_table = 'ar' AND rl3.to_table = 'ar'
50133d13 Sven Schöling
) rl
LEFT JOIN ar ON ar.id = rl.to_id

for my $ref (@{ selectall_hashref_query($form, $dbh, $query) }) {
$billed_amount{ $ref->{from_id}} += $ref->{amount};
$billed_netamount{$ref->{from_id}} += $ref->{netamount};
}
}

2d51ec2e Bernd Bleßmann
my ($phone_notes_columns, $phone_notes_join);
$form->{phone_notes} = trim($form->{phone_notes});
if ($form->{phone_notes}) {
$phone_notes_columns = qq| , phone_notes.subject AS phone_notes_subject, phone_notes.body AS phone_notes_body |;
$phone_notes_join = qq| JOIN notes phone_notes ON (o.id = phone_notes.trans_id AND phone_notes.trans_module LIKE 'oe') |;
}

9d0ebf28 Moritz Bunkus
$query =
qq|SELECT o.id, o.ordnumber, o.transdate, o.reqdate, | .
7d026c7c Niclas Zimmermann
qq| o.amount, ct.${vc}number, ct.name, o.netamount, o.${vc}_id, o.globalproject_id, | .
b96c67e5 Moritz Bunkus
qq| o.closed, o.delivered, o.quonumber, o.cusordnumber, o.shippingpoint, o.shipvia, | .
ce3ce404 Moritz Bunkus
qq| o.transaction_description, | .
4d8a6515 Philip Reetz
qq| o.marge_total, o.marge_percent, | .
2a267805 Bernd Bleßmann
qq| o.exchangerate, | .
a809ab0a Bernd Bleßmann
qq| o.itime::DATE AS insertdate, | .
fa51a82e Bernd Bleßmann
qq| o.intnotes,| .
bead93d9 Bernd Bleßmann
qq| department.description as department, | .
2a267805 Bernd Bleßmann
qq| ex.$rate AS daily_exchangerate, | .
ba8e82fe Bernd Bleßmann
qq| pt.description AS payment_terms, | .
9d0ebf28 Moritz Bunkus
qq| pr.projectnumber AS globalprojectnumber, | .
15bcb411 Sven Schöling
qq| e.name AS employee, s.name AS salesman, | .
3fcf64fc Bernd Bleßmann
qq| ct.${vc}number AS vcnumber, ct.country, ct.ustid, ct.business_id, | .
fa51a82e Bernd Bleßmann
qq| tz.description AS taxzone, | .
qq| order_statuses.name AS order_status | .
92331b8e Moritz Bunkus
$periodic_invoices_columns .
2d51ec2e Bernd Bleßmann
$phone_notes_columns .
3da73190 Moritz Bunkus
qq| , o.order_probability, o.expected_billing_date, (o.netamount * o.order_probability / 100) AS expected_netamount | .
9d0ebf28 Moritz Bunkus
qq|FROM oe o | .
qq|JOIN $vc ct ON (o.${vc}_id = ct.id) | .
b98b8e3f Sven Schöling
qq|LEFT JOIN contacts cp ON (o.cp_id = cp.cp_id) | .
9d0ebf28 Moritz Bunkus
qq|LEFT JOIN employee e ON (o.employee_id = e.id) | .
4a19c3d4 Udo Spallek
qq|LEFT JOIN employee s ON (o.salesman_id = s.id) | .
a4d74009 Niclas Zimmermann
qq|LEFT JOIN exchangerate ex ON (ex.currency_id = o.currency_id | .
9d0ebf28 Moritz Bunkus
qq| AND ex.transdate = o.transdate) | .
qq|LEFT JOIN project pr ON (o.globalproject_id = pr.id) | .
ba8e82fe Bernd Bleßmann
qq|LEFT JOIN payment_terms pt ON (pt.id = o.payment_id)| .
3fcf64fc Bernd Bleßmann
qq|LEFT JOIN tax_zones tz ON (o.taxzone_id = tz.id) | .
bead93d9 Bernd Bleßmann
qq|LEFT JOIN department ON (o.department_id = department.id) | .
fa51a82e Bernd Bleßmann
qq|LEFT JOIN order_statuses ON (o.order_status_id = order_statuses.id) | .
92331b8e Moritz Bunkus
qq|$periodic_invoices_joins | .
2d51ec2e Bernd Bleßmann
$phone_notes_join .
9d0ebf28 Moritz Bunkus
qq|WHERE (o.quotation = ?) |;
push(@values, $quotation);

dd2ee66b Geoffrey Richardson
if ($form->{department_id}) {
9d0ebf28 Moritz Bunkus
$query .= qq| AND o.department_id = ?|;
dd2ee66b Geoffrey Richardson
push(@values, $form->{department_id});
9d0ebf28 Moritz Bunkus
}
72eaa1a7 Moritz Bunkus
if ($form->{"project_id"}) {
9d0ebf28 Moritz Bunkus
$query .=
72eaa1a7 Moritz Bunkus
qq|AND ((globalproject_id = ?) OR EXISTS | .
qq| (SELECT * FROM orderitems oi | .
qq| WHERE oi.project_id = ? AND oi.trans_id = o.id))|;
777d9b30 Sven Schöling
push(@values, conv_i($form->{"project_id"}), conv_i($form->{"project_id"}));
}

if ($form->{"projectnumber"}) {
$query .= <<SQL;
7e47ffd0 Bernd Bleßmann
AND ((pr.projectnumber ILIKE ?) OR EXISTS (
777d9b30 Sven Schöling
SELECT * FROM orderitems oi
LEFT JOIN project proi ON proi.id = oi.project_id
WHERE proi.projectnumber ILIKE ? AND oi.trans_id = o.id
7e47ffd0 Bernd Bleßmann
))
777d9b30 Sven Schöling
SQL
bc40bcab Moritz Bunkus
push @values, like($form->{"projectnumber"}), like($form->{"projectnumber"});
72eaa1a7 Moritz Bunkus
}
d319704a Moritz Bunkus
fac049a0 Bernd Bleßmann
if ($form->{"business_id"}) {
$query .= " AND ct.business_id = ?";
push(@values, $form->{"business_id"});
}

9d0ebf28 Moritz Bunkus
if ($form->{"${vc}_id"}) {
$query .= " AND o.${vc}_id = ?";
push(@values, $form->{"${vc}_id"});
d319704a Moritz Bunkus
9d0ebf28 Moritz Bunkus
} elsif ($form->{$vc}) {
$query .= " AND ct.name ILIKE ?";
bc40bcab Moritz Bunkus
push(@values, like($form->{$vc}));
d319704a Moritz Bunkus
}

b98b8e3f Sven Schöling
if ($form->{"cp_name"}) {
$query .= " AND (cp.cp_name ILIKE ? OR cp.cp_givenname ILIKE ?)";
bc40bcab Moritz Bunkus
push(@values, (like($form->{"cp_name"}))x2);
b98b8e3f Sven Schöling
}

ab010352 Bernd Bleßmann
if ( !( ($vc eq 'customer' && ($main::auth->assert('sales_all_edit', 1) || $main::auth->assert('sales_order_view', 1)))
|| ($vc eq 'vendor' && ($main::auth->assert('purchase_all_edit', 1) || $main::auth->assert('purchase_order_view', 1))) ) ) {
c9e93ded Jan Büren
$query .= " AND o.employee_id = (select id from employee where login= ?)";
4bd1e2f8 Sven Schöling
push @values, $::myconfig{login};
c9e93ded Jan Büren
}
9ba2705f Moritz Bunkus
if ($form->{employee_id}) {
$query .= " AND o.employee_id = ?";
push @values, conv_i($form->{employee_id});
}
06d98024 Sven Schöling
4a19c3d4 Udo Spallek
if ($form->{salesman_id}) {
$query .= " AND o.salesman_id = ?";
push @values, conv_i($form->{salesman_id});
}
9ba2705f Moritz Bunkus
d319704a Moritz Bunkus
if (!$form->{open} && !$form->{closed}) {
$query .= " AND o.id = 0";
} elsif (!($form->{open} && $form->{closed})) {
$query .= ($form->{open}) ? " AND o.closed = '0'" : " AND o.closed = '1'";
}

222c7e21 Moritz Bunkus
if (($form->{"notdelivered"} || $form->{"delivered"}) &&
($form->{"notdelivered"} ne $form->{"delivered"})) {
$query .= $form->{"delivered"} ?
" AND o.delivered " : " AND NOT o.delivered";
}

9d0ebf28 Moritz Bunkus
if ($form->{$ordnumber}) {
e70d4cf2 Moritz Bunkus
$query .= qq| AND o.$ordnumber ILIKE ?|;
bc40bcab Moritz Bunkus
push(@values, like($form->{$ordnumber}));
9d0ebf28 Moritz Bunkus
}

b96c67e5 Moritz Bunkus
if ($form->{cusordnumber}) {
$query .= qq| AND o.cusordnumber ILIKE ?|;
bc40bcab Moritz Bunkus
push(@values, like($form->{cusordnumber}));
b96c67e5 Moritz Bunkus
}

9d0ebf28 Moritz Bunkus
if($form->{transdatefrom}) {
$query .= qq| AND o.transdate >= ?|;
push(@values, conv_date($form->{transdatefrom}));
}
d319704a Moritz Bunkus
9d0ebf28 Moritz Bunkus
if($form->{transdateto}) {
$query .= qq| AND o.transdate <= ?|;
push(@values, conv_date($form->{transdateto}));
}

813b99ca Geoffrey Richardson
if($form->{reqdatefrom}) {
$query .= qq| AND o.reqdate >= ?|;
push(@values, conv_date($form->{reqdatefrom}));
}

if($form->{reqdateto}) {
$query .= qq| AND o.reqdate <= ?|;
push(@values, conv_date($form->{reqdateto}));
}

a809ab0a Bernd Bleßmann
if($form->{insertdatefrom}) {
$query .= qq| AND o.itime::DATE >= ?|;
push(@values, conv_date($form->{insertdatefrom}));
}

if($form->{insertdateto}) {
$query .= qq| AND o.itime::DATE <= ?|;
push(@values, conv_date($form->{insertdateto}));
}

3fcf64fc Bernd Bleßmann
if ($form->{shippingpoint}) {
$query .= qq| AND o.shippingpoint ILIKE ?|;
bc40bcab Moritz Bunkus
push(@values, like($form->{shippingpoint}));
3fcf64fc Bernd Bleßmann
}

if ($form->{taxzone_id} ne '') { # taxzone_id could be 0
$query .= qq| AND tz.id = ?|;
push(@values, $form->{taxzone_id});
}

ce3ce404 Moritz Bunkus
if ($form->{transaction_description}) {
$query .= qq| AND o.transaction_description ILIKE ?|;
bc40bcab Moritz Bunkus
push(@values, like($form->{transaction_description}));
ce3ce404 Moritz Bunkus
}

92331b8e Moritz Bunkus
if ($form->{periodic_invoices_active} ne $form->{periodic_invoices_inactive}) {
74fca575 Sven Schöling
my $not = $form->{periodic_invoices_inactive} ? 'NOT' : '';
92331b8e Moritz Bunkus
$query .= qq| AND ${not} COALESCE(pcfg.active, 'f')|;
}

2ea1a379 Moritz Bunkus
if ($form->{reqdate_unset_or_old}) {
$query .= qq| AND ((o.reqdate IS NULL) OR (o.reqdate < date_trunc('month', current_date)))|;
}

3da73190 Moritz Bunkus
if (($form->{order_probability_value} || '') ne '') {
my $op = $form->{order_probability_value} eq 'le' ? '<=' : '>=';
$query .= qq| AND (o.order_probability ${op} ?)|;
88dea78e Moritz Bunkus
push @values, trim($form->{order_probability_value});
3da73190 Moritz Bunkus
}

if ($form->{expected_billing_date_from}) {
$query .= qq| AND (o.expected_billing_date >= ?)|;
push @values, conv_date($form->{expected_billing_date_from});
}

if ($form->{expected_billing_date_to}) {
$query .= qq| AND (o.expected_billing_date <= ?)|;
push @values, conv_date($form->{expected_billing_date_to});
}

3906bb6a Bernd Bleßmann
if ($form->{intnotes}) {
$query .= qq| AND o.intnotes ILIKE ?|;
push(@values, like($form->{intnotes}));
}

fa51a82e Bernd Bleßmann
if ($form->{order_status_id}) {
$query .= qq| AND o.order_status_id = ?|;
push(@values, $form->{order_status_id});
}

2d51ec2e Bernd Bleßmann
if ($form->{phone_notes}) {
a5531bb6 Bernd Bleßmann
$query .= qq| AND (phone_notes.subject ILIKE ? OR regexp_replace(phone_notes.body, '<[^>]*>', '', 'g') ILIKE ?)|;
2d51ec2e Bernd Bleßmann
push(@values, like($form->{phone_notes}), like($form->{phone_notes}));
}

991369b1 Bernd Bleßmann
$form->{fulltext} = trim($form->{fulltext});
if ($form->{fulltext}) {
my @fulltext_fields = qw(o.notes
o.intnotes
o.shippingpoint
o.shipvia
o.transaction_description
o.quonumber
o.ordnumber
o.cusordnumber);
$query .= ' AND (';
$query .= join ' ILIKE ? OR ', @fulltext_fields;
$query .= ' ILIKE ?';
d1cd59d4 Bernd Bleßmann
$query .= <<SQL;
OR EXISTS (
SELECT files.id FROM files LEFT JOIN file_full_texts ON (file_full_texts.file_id = files.id)
WHERE files.object_id = o.id AND files.object_type = 'sales_order'
AND file_full_texts.full_text ILIKE ?)
SQL

$query .= <<SQL;
OR EXISTS (
SELECT notes.id FROM notes
WHERE notes.trans_id = o.id AND notes.trans_module LIKE 'oe'
a5531bb6 Bernd Bleßmann
AND (notes.subject ILIKE ? OR regexp_replace(notes.body, '<[^>]*>', '', 'g') ILIKE ?))
d1cd59d4 Bernd Bleßmann
SQL

$query .= <<SQL;
OR EXISTS (
SELECT follow_up_links.id FROM follow_up_links
WHERE follow_up_links.trans_id = o.id AND trans_type = 'sales_order'
AND EXISTS (
SELECT notes.id FROM notes
WHERE trans_module LIKE 'fu' AND trans_id = follow_up_links.follow_up_id
AND (notes.subject ILIKE ? OR notes.body ILIKE ?)))
SQL

991369b1 Bernd Bleßmann
$query .= ')';
d1cd59d4 Bernd Bleßmann
45ee0662 Bernd Bleßmann
push(@values, like($form->{fulltext})) for 1 .. (scalar @fulltext_fields) + 5;
991369b1 Bernd Bleßmann
}

fdf5b8ae Moritz Bunkus
if ($form->{parts_partnumber}) {
$query .= <<SQL;
AND EXISTS (
SELECT orderitems.trans_id
FROM orderitems
LEFT JOIN parts ON (orderitems.parts_id = parts.id)
WHERE (orderitems.trans_id = o.id)
AND (parts.partnumber ILIKE ?)
LIMIT 1
)
SQL
push @values, like($form->{parts_partnumber});
}

if ($form->{parts_description}) {
$query .= <<SQL;
AND EXISTS (
SELECT orderitems.trans_id
FROM orderitems
WHERE (orderitems.trans_id = o.id)
AND (orderitems.description ILIKE ?)
LIMIT 1
)
SQL
push @values, like($form->{parts_description});
}

aa4fda0e Sven Schöling
if ($form->{all}) {
my @tokens = parse_line('\s+', 0, $form->{all});
# ordnumber quonumber customer.name vendor.name transaction_description
$query .= qq| AND (
o.ordnumber ILIKE ? OR
o.quonumber ILIKE ? OR
ct.name ILIKE ? OR
o.transaction_description ILIKE ?
)| for @tokens;
bc40bcab Moritz Bunkus
push @values, (like($_))x4 for @tokens;
aa4fda0e Sven Schöling
}

7e19c216 Bernd Bleßmann
my ($cvar_where, @cvar_values) = CVar->build_filter_query('module' => 'CT',
'trans_id_field' => 'ct.id',
'filter' => $form,
);
if ($cvar_where) {
$query .= qq| AND ($cvar_where)|;
push @values, @cvar_values;
}

c654c46b Moritz Bunkus
my $sortdir = !defined $form->{sortdir} ? 'ASC' : $form->{sortdir} ? 'ASC' : 'DESC';
f3dba42c Bernd Bleßmann
my $sortorder = join(', ', map { "${_} ${sortdir} " } ("o.id", $form->sort_columns("transdate", $ordnumber, "name"), "o.itime"));
d38dee8d Moritz Bunkus
my %allowed_sort_columns = (
"transdate" => "o.transdate",
"reqdate" => "o.reqdate",
"id" => "o.id",
"ordnumber" => "o.ordnumber",
b96c67e5 Moritz Bunkus
"cusordnumber" => "o.cusordnumber",
d38dee8d Moritz Bunkus
"quonumber" => "o.quonumber",
"name" => "ct.name",
"employee" => "e.name",
56ce7563 Bernd Bleßmann
"salesman" => "s.name",
d38dee8d Moritz Bunkus
"shipvia" => "o.shipvia",
3fcf64fc Bernd Bleßmann
"transaction_description" => "o.transaction_description",
"shippingpoint" => "o.shippingpoint",
a809ab0a Bernd Bleßmann
"insertdate" => "o.itime",
3fcf64fc Bernd Bleßmann
"taxzone" => "tz.description",
ba8e82fe Bernd Bleßmann
"payment_terms" => "pt.description",
bead93d9 Bernd Bleßmann
"department" => "department.description",
3906bb6a Bernd Bleßmann
"intnotes" => "o.intnotes",
fa51a82e Bernd Bleßmann
"order_status" => "order_statuses.name",
d38dee8d Moritz Bunkus
);
9d0ebf28 Moritz Bunkus
if ($form->{sort} && grep($form->{sort}, keys(%allowed_sort_columns))) {
f3dba42c Bernd Bleßmann
$sortorder = $allowed_sort_columns{$form->{sort}} . " ${sortdir}" . ", o.itime ${sortdir}";
9d0ebf28 Moritz Bunkus
}
$query .= qq| ORDER by | . $sortorder;
d319704a Moritz Bunkus
my $sth = $dbh->prepare($query);
72eaa1a7 Moritz Bunkus
$sth->execute(@values) ||
$form->dberror($query . " (" . join(", ", @values) . ")");

d319704a Moritz Bunkus
my %id = ();
9d0ebf28 Moritz Bunkus
$form->{OE} = [];
90daea72 Sven Schöling
while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
50133d13 Sven Schöling
$ref->{billed_amount} = $billed_amount{$ref->{id}};
$ref->{billed_netamount} = $billed_netamount{$ref->{id}};
ad4a0fc9 Jan Büren
if ($ref->{billed_amount} < 0) { # case: credit note(s) higher than invoices
$ref->{remaining_amount} = $ref->{amount} + $ref->{billed_amount};
$ref->{remaining_netamount} = $ref->{netamount} + $ref->{billed_netamount};
} else {
$ref->{remaining_amount} = $ref->{amount} - $ref->{billed_amount};
$ref->{remaining_netamount} = $ref->{netamount} - $ref->{billed_netamount};
}
2a267805 Bernd Bleßmann
$ref->{exchangerate} ||= $ref->{daily_exchangerate};
$ref->{exchangerate} ||= 1;
d319704a Moritz Bunkus
push @{ $form->{OE} }, $ref if $ref->{id} != $id{ $ref->{id} };
$id{ $ref->{id} } = $ref->{id};
}

$sth->finish;

3a77cbe1 Bernd Bleßmann
if ($form->{l_items} && scalar @{ $form->{OE} }) {
my ($items_query, $items_sth);
if ($form->{l_items}) {
$items_query =
qq|SELECT id
FROM orderitems
WHERE trans_id = ?
ORDER BY position|;

$items_sth = prepare_query($form, $dbh, $items_query);
}

foreach my $oe (@{ $form->{OE} }) {
do_statement($form, $items_sth, $items_query, $oe->{id});
$oe->{item_ids} = $dbh->selectcol_arrayref($items_sth);
$oe->{item_ids} = undef if !@{$oe->{item_ids}};
}
$items_sth->finish();
}

d319704a Moritz Bunkus
$main::lxdebug->leave_sub();
}

7a7f33b5 Moritz Bunkus
sub transactions_for_todo_list {
$main::lxdebug->enter_sub();

34ff9415 Bernd Bleßmann
my $self = shift;
my %params = @_;
7a7f33b5 Moritz Bunkus
34ff9415 Bernd Bleßmann
my $myconfig = \%main::myconfig;
my $form = $main::form;
7a7f33b5 Moritz Bunkus
34ff9415 Bernd Bleßmann
my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig);
7a7f33b5 Moritz Bunkus
34ff9415 Bernd Bleßmann
my $query = qq|SELECT id FROM employee WHERE login = ?|;
my ($e_id) = selectrow_query($form, $dbh, $query, $::myconfig{login});
7a7f33b5 Moritz Bunkus
a46b8625 Bernd Bleßmann
my $sales_purchase_filter = 'AND (1 = 0';
$sales_purchase_filter .= $params{sales} ? qq| OR customer_id IS NOT NULL| : '';
$sales_purchase_filter .= $params{purchase} ? qq| OR vendor_id IS NOT NULL| : '';
$sales_purchase_filter .= ')';

34ff9415 Bernd Bleßmann
$query =
7a7f33b5 Moritz Bunkus
qq|SELECT oe.id, oe.transdate, oe.reqdate, oe.quonumber, oe.transaction_description, oe.amount,
58ff4d6a Moritz Bunkus
CASE WHEN (COALESCE(oe.customer_id, 0) = 0) THEN 'vendor' ELSE 'customer' END AS vc,
7a7f33b5 Moritz Bunkus
c.name AS customer,
c9860c6f Moritz Bunkus
v.name AS vendor,
7a7f33b5 Moritz Bunkus
e.name AS employee
FROM oe
LEFT JOIN customer c ON (oe.customer_id = c.id)
c9860c6f Moritz Bunkus
LEFT JOIN vendor v ON (oe.vendor_id = v.id)
7a7f33b5 Moritz Bunkus
LEFT JOIN employee e ON (oe.employee_id = e.id)
WHERE (COALESCE(quotation, FALSE) = TRUE)
AND (COALESCE(closed, FALSE) = FALSE)
AND ((oe.employee_id = ?) OR (oe.salesman_id = ?))
AND NOT (oe.reqdate ISNULL)
AND (oe.reqdate < current_date)
a46b8625 Bernd Bleßmann
$sales_purchase_filter
7a7f33b5 Moritz Bunkus
ORDER BY transdate|;

my $quotations = selectall_hashref_query($form, $dbh, $query, $e_id, $e_id);

$main::lxdebug->leave_sub();

return $quotations;
}

d319704a Moritz Bunkus
sub save {
8e0f6e70 Sven Schöling
my ($self, $myconfig, $form) = @_;
$main::lxdebug->enter_sub();

my $rc = SL::DB->client->with_transaction(\&_save, $self, $myconfig, $form);

$::lxdebug->leave_sub;

return $rc;
}

sub _save {
d319704a Moritz Bunkus
$main::lxdebug->enter_sub();

my ($self, $myconfig, $form) = @_;

8e0f6e70 Sven Schöling
my $dbh = SL::DB->client->dbh;
5f6d6d4e Moritz Bunkus
my $restricter = SL::HTML::Restrict->create;
d319704a Moritz Bunkus
9d0ebf28 Moritz Bunkus
my ($query, @values, $sth, $null);
d319704a Moritz Bunkus
my $exchangerate = 0;

9d0ebf28 Moritz Bunkus
my $all_units = AM->retrieve_units($myconfig, $form);
$form->{all_units} = $all_units;
54e4131e Moritz Bunkus
ef220490 Moritz Bunkus
my $ic_cvar_configs = CVar->get_configs(module => 'IC',
dbh => $dbh);

e6ef45f2 Moritz Bunkus
$form->{employee_id} = (split /--/, $form->{employee})[1] if !$form->{employee_id};
d319704a Moritz Bunkus
unless ($form->{employee_id}) {
$form->get_employee($dbh);
}

my $ml = ($form->{type} eq 'sales_order') ? 1 : -1;

aff32344 Moritz Bunkus
my $number_field = $form->{type} =~ m{order} ? 'ordnumber' : 'quonumber';
my $trans_number = SL::TransNumber->new(type => $form->{type}, dbh => $dbh, number => $form->{$number_field}, id => $form->{id});
c2eb03d4 Geoffrey Richardson
$form->{$number_field} ||= $trans_number->create_unique; # set $form->{ordnumber} or $form->{quonumber}
f0ddfbfe Moritz Bunkus
my $is_new = !$form->{id};
aff32344 Moritz Bunkus
d319704a Moritz Bunkus
if ($form->{id}) {
4493d1eb Moritz Bunkus
$query = qq|DELETE FROM custom_variables
WHERE (config_id IN (SELECT id FROM custom_variable_configs WHERE (module = 'ShipTo')))
AND (trans_id IN (SELECT shipto_id FROM shipto WHERE (module = 'OE') AND (trans_id = ?)))|;
do_query($form, $dbh, $query, $form->{id});

9d0ebf28 Moritz Bunkus
$query = qq|DELETE FROM shipto | .
qq|WHERE trans_id = ? AND module = 'OE'|;
do_query($form, $dbh, $query, $form->{id});
d319704a Moritz Bunkus
} else {

9d0ebf28 Moritz Bunkus
$query = qq|SELECT nextval('id')|;
($form->{id}) = selectrow_query($form, $dbh, $query);
d319704a Moritz Bunkus
ea14cfa5 Moritz Bunkus
$query = qq|INSERT INTO oe (id, ordnumber, employee_id, currency_id, taxzone_id) VALUES (?, '', ?, (SELECT currency_id FROM defaults), ?)|;
do_query($form, $dbh, $query, $form->{id}, $form->{employee_id}, $form->{taxzone_id});
d319704a Moritz Bunkus
}

6cdecee0 Moritz Bunkus
my $amount = 0;
my $linetotal = 0;
my $discount = 0;
d319704a Moritz Bunkus
my $project_id;
my $reqdate;
my $taxrate;
90daea72 Sven Schöling
my $taxbase;
my $taxdiff;
6cdecee0 Moritz Bunkus
my $taxamount = 0;
d319704a Moritz Bunkus
my $fxsellprice;
my %taxbase;
my @taxaccounts;
my %taxaccounts;
my $netamount = 0;
280261a5 Sven Schöling
my @processed_orderitems;
d319704a Moritz Bunkus
1e251313 Moritz Bunkus
$form->get_lists('price_factors' => 'ALL_PRICE_FACTORS');
my %price_factors = map { $_->{id} => $_->{factor} } @{ $form->{ALL_PRICE_FACTORS} };
my $price_factor;

d319704a Moritz Bunkus
for my $i (1 .. $form->{rowcount}) {

b6dc5623 Sven Schöling
map({ $form->{"${_}_$i"} = $form->parse_amount($myconfig, $form->{"${_}_$i"}) } qw(qty ship));
d319704a Moritz Bunkus
8c89bb02 Moritz Bunkus
if ($form->{"id_$i"}) {
d319704a Moritz Bunkus
54e4131e Moritz Bunkus
# get item baseunit
9d0ebf28 Moritz Bunkus
$query = qq|SELECT unit FROM parts WHERE id = ?|;
my ($item_unit) = selectrow_query($form, $dbh, $query, $form->{"id_$i"});

my $basefactor = 1;
if (defined($all_units->{$item_unit}->{factor}) &&
(($all_units->{$item_unit}->{factor} * 1) != 0)) {
b6dc5623 Sven Schöling
$basefactor = $all_units->{$form->{"unit_$i"}}->{factor} / $all_units->{$item_unit}->{factor};
54e4131e Moritz Bunkus
}
9d0ebf28 Moritz Bunkus
my $baseqty = $form->{"qty_$i"} * $basefactor;
d319704a Moritz Bunkus
4d8a6515 Philip Reetz
$form->{"marge_percent_$i"} = $form->parse_amount($myconfig, $form->{"marge_percent_$i"}) * 1;
da804bf2 Geoffrey Richardson
$form->{"marge_absolut_$i"} = $form->parse_amount($myconfig, $form->{"marge_absolut_$i"}) * 1;
1ffb4200 Moritz Bunkus
da804bf2 Geoffrey Richardson
$form->{"lastcost_$i"} = $form->parse_amount($myconfig, $form->{"lastcost_$i"});
4d8a6515 Philip Reetz
2e5f7860 Bernd Bleßmann
# keep entered selling price
my $fxsellprice =
$form->parse_amount($myconfig, $form->{"sellprice_$i"});
d319704a Moritz Bunkus
2e5f7860 Bernd Bleßmann
my ($dec) = ($fxsellprice =~ /\.(\d+)/);
$dec = length $dec;
d319704a Moritz Bunkus
my $decimalplaces = ($dec > 2) ? $dec : 2;

2e5f7860 Bernd Bleßmann
# undo discount formatting
$form->{"discount_$i"} = $form->parse_amount($myconfig, $form->{"discount_$i"}) / 100;
d319704a Moritz Bunkus
2e5f7860 Bernd Bleßmann
# deduct discount
$form->{"sellprice_$i"} = $fxsellprice * (1 - $form->{"discount_$i"});
d319704a Moritz Bunkus
2e5f7860 Bernd Bleßmann
# round linetotal at least to 2 decimal places
1e251313 Moritz Bunkus
$price_factor = $price_factors{ $form->{"price_factor_id_$i"} } || 1;
$linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"} / $price_factor, 2);
d319704a Moritz Bunkus
2e5f7860 Bernd Bleßmann
$form->{"inventory_accno_$i"} *= 1;
$form->{"expense_accno_$i"} *= 1;

9d0ebf28 Moritz Bunkus
@taxaccounts = split(/ /, $form->{"taxaccounts_$i"});
d319704a Moritz Bunkus
$taxrate = 0;
$taxdiff = 0;

map { $taxrate += $form->{"${_}_rate"} } @taxaccounts;

if ($form->{taxincluded}) {
$taxamount = $linetotal * $taxrate / (1 + $taxrate);
$taxbase = $linetotal - $taxamount;

# we are not keeping a natural price, do not round
$form->{"sellprice_$i"} =
$form->{"sellprice_$i"} * (1 / (1 + $taxrate));
} else {
$taxamount = $linetotal * $taxrate;
$taxbase = $linetotal;
}

if ($form->round_amount($taxrate, 7) == 0) {
if ($form->{taxincluded}) {
90daea72 Sven Schöling
foreach my $item (@taxaccounts) {
b6dc5623 Sven Schöling
$taxamount = $form->round_amount($linetotal * $form->{"${item}_rate"} / (1 + abs($form->{"${item}_rate"})), 2);
d319704a Moritz Bunkus
$taxaccounts{$item} += $taxamount;
$taxdiff += $taxamount;
b6dc5623 Sven Schöling
$taxbase{$item} += $taxbase;
d319704a Moritz Bunkus
}
$taxaccounts{ $taxaccounts[0] } += $taxdiff;
} else {
90daea72 Sven Schöling
foreach my $item (@taxaccounts) {
d319704a Moritz Bunkus
$taxaccounts{$item} += $linetotal * $form->{"${item}_rate"};
$taxbase{$item} += $taxbase;
}
}
} else {
90daea72 Sven Schöling
foreach my $item (@taxaccounts) {
b6dc5623 Sven Schöling
$taxaccounts{$item} += $taxamount * $form->{"${item}_rate"} / $taxrate;
d319704a Moritz Bunkus
$taxbase{$item} += $taxbase;
}
}

1e251313 Moritz Bunkus
$netamount += $form->{"sellprice_$i"} * $form->{"qty_$i"} / $price_factor;
d319704a Moritz Bunkus
b6dc5623 Sven Schöling
$reqdate = ($form->{"reqdate_$i"}) ? $form->{"reqdate_$i"} : undef;
d319704a Moritz Bunkus
b632cee8 Moritz Bunkus
# 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().
9d0ebf28 Moritz Bunkus
($null, my $pricegroup_id) = split(/--/, $form->{"sellprice_pg_$i"});
07d71c33 Stephan Köhler
$pricegroup_id *= 1;
b632cee8 Moritz Bunkus
$pricegroup_id = undef if !$pricegroup_id;
07d71c33 Stephan Köhler
19e40226 Jan Büren
# force new project, if not set yet
if ($::instance_conf->get_order_always_project && !$form->{"globalproject_id"} && ($form->{type} eq 'sales_order')) {
32b92345 Geoffrey Richardson
require SL::DB::Customer;
6010f8bf Jan Büren
my $customer = SL::DB::Manager::Customer->find_by(id => $form->{customer_id});
32b92345 Geoffrey Richardson
die "Can't find customer" unless $customer;
1de47931 Geoffrey Richardson
die $main::locale->text("Error while creating project with project number of new order number, project number #1 already exists!", $form->{ordnumber})
if SL::DB::Manager::Project->find_by(projectnumber => $form->{ordnumber});

c2eb03d4 Geoffrey Richardson
my $new_project = SL::DB::Project->new(
19e40226 Jan Büren
projectnumber => $form->{ordnumber},
32b92345 Geoffrey Richardson
description => $customer->name,
customer_id => $customer->id,
19e40226 Jan Büren
active => 1,
project_type_id => $::instance_conf->get_project_type_id,
c2eb03d4 Geoffrey Richardson
project_status_id => $::instance_conf->get_project_status_id,
);
$new_project->save;
$form->{"globalproject_id"} = $new_project->id;
918c39c0 Jan Büren
}
c2eb03d4 Geoffrey Richardson
be42a450 Bernd Bleßmann
CVar->get_non_editable_ic_cvars(form => $form,
dbh => $dbh,
f4051b8f Bernd Bleßmann
row => $i,
be42a450 Bernd Bleßmann
sub_module => 'orderitems',
may_converted_from => ['orderitems', 'invoice']);

8b60748b Bernd Bleßmann
my $position = $i;

d319704a Moritz Bunkus
# save detail record in orderitems table
280261a5 Sven Schöling
if (! $form->{"orderitems_id_$i"}) {
$query = qq|SELECT nextval('orderitemsid')|;
($form->{"orderitems_id_$i"}) = selectrow_query($form, $dbh, $query);

8b60748b Bernd Bleßmann
$query = qq|INSERT INTO orderitems (id, position) VALUES (?, ?)|;
do_query($form, $dbh, $query, $form->{"orderitems_id_$i"}, conv_i($position));
280261a5 Sven Schöling
}
6b4a71ff Bernd Bleßmann
ef220490 Moritz Bunkus
my $orderitems_id = $form->{"orderitems_id_$i"};
280261a5 Sven Schöling
push @processed_orderitems, $orderitems_id;

$query = <<SQL;
UPDATE orderitems SET
8b60748b Bernd Bleßmann
trans_id = ?, position = ?, parts_id = ?, description = ?, longdescription = ?, qty = ?, base_qty = ?,
280261a5 Sven Schöling
sellprice = ?, discount = ?, unit = ?, reqdate = ?, project_id = ?, serialnumber = ?, ship = ?,
c1ec3f4f Geoffrey Richardson
pricegroup_id = ?, subtotal = ?,
280261a5 Sven Schöling
marge_percent = ?, marge_total = ?, lastcost = ?, price_factor_id = ?,
89b26688 Sven Schöling
active_price_source = ?, active_discount_source = ?,
280261a5 Sven Schöling
price_factor = (SELECT factor FROM price_factors WHERE id = ?), marge_price_factor = ?
WHERE id = ?
SQL
@values = (
8b60748b Bernd Bleßmann
conv_i($form->{id}), conv_i($position), conv_i($form->{"id_$i"}),
5f6d6d4e Moritz Bunkus
$form->{"description_$i"}, $restricter->process($form->{"longdescription_$i"}),
9d0ebf28 Moritz Bunkus
$form->{"qty_$i"}, $baseqty,
$fxsellprice, $form->{"discount_$i"},
$form->{"unit_$i"}, conv_date($reqdate), conv_i($form->{"project_id_$i"}),
c1ec3f4f Geoffrey Richardson
$form->{"serialnumber_$i"}, $form->{"ship_$i"},
$pricegroup_id, $form->{"subtotal_$i"} ? 't' : 'f',
da804bf2 Geoffrey Richardson
$form->{"marge_percent_$i"}, $form->{"marge_absolut_$i"},
7e64504f Jan Büren
$form->{"lastcost_$i"}, conv_i($form->{"price_factor_id_$i"}),
89b26688 Sven Schöling
$form->{"active_price_source_$i"}, $form->{"active_discount_source_$i"},
7e64504f Jan Büren
conv_i($form->{"price_factor_id_$i"}), conv_i($form->{"marge_price_factor_$i"}),
280261a5 Sven Schöling
conv_i($orderitems_id),
);

9d0ebf28 Moritz Bunkus
do_query($form, $dbh, $query, @values);
d319704a Moritz Bunkus
$form->{"sellprice_$i"} = $fxsellprice;
$form->{"discount_$i"} *= 100;
ef220490 Moritz Bunkus
CVar->save_custom_variables(module => 'IC',
sub_module => 'orderitems',
trans_id => $orderitems_id,
configs => $ic_cvar_configs,
variables => $form,
name_prefix => 'ic_',
name_postfix => "_$i",
dbh => $dbh);
b8125c17 Bernd Bleßmann
991d16bb Jan Büren
# link previous items with orderitems
583f1f0f Jan Büren
# assume we have a new workflow if we link from invoice or order to quotation
# unluckily orderitems are used for quotation and orders - therefore one more
# check to be sure NOT to link from order to quotation
foreach (qw(orderitems)) {
if (!$form->{saveasnew} && !$form->{useasnew} && $form->{"converted_from_${_}_id_$i"}
&& $form->{type} !~ 'quotation') {
991d16bb Jan Büren
RecordLinks->create_links('dbh' => $dbh,
'mode' => 'ids',
2f9a5220 Jan Büren
'from_table' => $_,
991d16bb Jan Büren
'from_ids' => $form->{"converted_from_${_}_id_$i"},
'to_table' => 'orderitems',
'to_id' => $orderitems_id,
);
}
b8125c17 Bernd Bleßmann
delete $form->{"converted_from_${_}_id_$i"};
6b6a2ddf Jan Büren
}
d319704a Moritz Bunkus
}
}
b8125c17 Bernd Bleßmann
280261a5 Sven Schöling
# search for orphaned ids
$query = sprintf 'SELECT id FROM orderitems WHERE trans_id = ? AND NOT id IN (%s)', join ', ', ("?") x scalar @processed_orderitems;
@values = (conv_i($form->{id}), map { conv_i($_) } @processed_orderitems);
my @orphaned_ids = map { $_->{id} } selectall_hashref_query($form, $dbh, $query, @values);

if (scalar @orphaned_ids) {
# clean up orderitems
$query = sprintf 'DELETE FROM orderitems WHERE id IN (%s)', join ', ', ("?") x scalar @orphaned_ids;
do_query($form, $dbh, $query, @orphaned_ids);
}
d319704a Moritz Bunkus
9d0ebf28 Moritz Bunkus
$reqdate = ($form->{reqdate}) ? $form->{reqdate} : undef;
d319704a Moritz Bunkus
# add up the tax
my $tax = 0;
map { $tax += $form->round_amount($taxaccounts{$_}, 2) } keys %taxaccounts;

030c2086 Rolf Fluehmann
$amount = $form->round_amount($netamount + $tax, 2, 1);
d319704a Moritz Bunkus
$netamount = $form->round_amount($netamount, 2);

if ($form->{currency} eq $form->{defaultcurrency}) {
$form->{exchangerate} = 1;
} else {
b6dc5623 Sven Schöling
$exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{transdate}, ($form->{vc} eq 'customer') ? 'buy' : 'sell');
d319704a Moritz Bunkus
}

4fae9f45 Bernd Bleßmann
# from inputfield (exchangerate) or hidden (forex)
my $exchangerate_from_form = $form->{forex} || $form->parse_amount($myconfig, $form->{exchangerate});

$form->{exchangerate} = $exchangerate || $exchangerate_from_form;
d319704a Moritz Bunkus
6d1df9ca Moritz Bunkus
my $quotation = $form->{type} =~ /_order$/ ? 'f' : 't';
d319704a Moritz Bunkus
# save OE record
9d0ebf28 Moritz Bunkus
$query =
6cdecee0 Moritz Bunkus
qq|UPDATE oe SET
ordnumber = ?, quonumber = ?, cusordnumber = ?, transdate = ?, vendor_id = ?,
0b36b225 Moritz Bunkus
customer_id = ?, amount = ?, netamount = ?, reqdate = ?, tax_point = ?, taxincluded = ?,
a4d74009 Niclas Zimmermann
shippingpoint = ?, shipvia = ?, notes = ?, intnotes = ?, currency_id = (SELECT id FROM currencies WHERE name=?), closed = ?,
6cdecee0 Moritz Bunkus
delivered = ?, proforma = ?, quotation = ?, department_id = ?, language_id = ?,
844a541e Moritz Bunkus
taxzone_id = ?, shipto_id = ?, billing_address_id = ?, payment_id = ?, delivery_vendor_id = ?, delivery_customer_id = ?,delivery_term_id = ?,
6cdecee0 Moritz Bunkus
globalproject_id = ?, employee_id = ?, salesman_id = ?, cp_id = ?, transaction_description = ?, marge_total = ?, marge_percent = ?
3da73190 Moritz Bunkus
, order_probability = ?, expected_billing_date = ?
6cdecee0 Moritz Bunkus
WHERE id = ?|;
9d0ebf28 Moritz Bunkus
abd2032c Moritz Bunkus
@values = ($form->{ordnumber} || '', $form->{quonumber},
9d0ebf28 Moritz Bunkus
$form->{cusordnumber}, conv_date($form->{transdate}),
conv_i($form->{vendor_id}), conv_i($form->{customer_id}),
0b36b225 Moritz Bunkus
$amount, $netamount, conv_date($reqdate), conv_date($form->{tax_point}),
9d0ebf28 Moritz Bunkus
$form->{taxincluded} ? 't' : 'f', $form->{shippingpoint},
a34c05f3 Moritz Bunkus
$form->{shipvia}, $restricter->process($form->{notes}), $form->{intnotes},
d331a3d7 Niclas Zimmermann
$form->{currency}, $form->{closed} ? 't' : 'f',
9d0ebf28 Moritz Bunkus
$form->{delivered} ? "t" : "f", $form->{proforma} ? 't' : 'f',
$quotation, conv_i($form->{department_id}),
conv_i($form->{language_id}), conv_i($form->{taxzone_id}),
844a541e Moritz Bunkus
conv_i($form->{shipto_id}), conv_i($form->{billing_address_id}), conv_i($form->{payment_id}),
9d0ebf28 Moritz Bunkus
conv_i($form->{delivery_vendor_id}),
conv_i($form->{delivery_customer_id}),
03d3d025 Bernd Bleßmann
conv_i($form->{delivery_term_id}),
9d0ebf28 Moritz Bunkus
conv_i($form->{globalproject_id}), conv_i($form->{employee_id}),
conv_i($form->{salesman_id}), conv_i($form->{cp_id}),
ce3ce404 Moritz Bunkus
$form->{transaction_description},
6cdecee0 Moritz Bunkus
$form->{marge_total} * 1, $form->{marge_percent} * 1,
3da73190 Moritz Bunkus
$form->{order_probability} * 1, conv_date($form->{expected_billing_date}),
9d0ebf28 Moritz Bunkus
conv_i($form->{id}));
do_query($form, $dbh, $query, @values);
d319704a Moritz Bunkus
8c1d5d75 Martin Helmling
$form->new_lastmtime('oe');

d319704a Moritz Bunkus
$form->{ordtotal} = $amount;

$form->{name} = $form->{ $form->{vc} };
5cf977e5 Moritz Bunkus
$form->{name} =~ s/--\Q$form->{"$form->{vc}_id"}\E//;
54e4131e Moritz Bunkus
b6213d35 Moritz Bunkus
# add shipto
54e4131e Moritz Bunkus
if (!$form->{shipto_id}) {
$form->add_shipto($dbh, $form->{id}, "OE");
}
d319704a Moritz Bunkus
# save printed, emailed, queued
$form->save_status($dbh);

94e11003 Moritz Bunkus
# Link this record to the records it was created from.
b7b5192a Moritz Bunkus
$form->{convert_from_oe_ids} =~ s/^\s+//;
$form->{convert_from_oe_ids} =~ s/\s+$//;
my @convert_from_oe_ids = split m/\s+/, $form->{convert_from_oe_ids};
94e11003 Moritz Bunkus
delete $form->{convert_from_oe_ids};
583f1f0f Jan Büren
if (!$form->{useasnew} && scalar @convert_from_oe_ids) {
f3a02fb6 Jan Büren
RecordLinks->create_links('dbh' => $dbh,
'mode' => 'ids',
'from_table' => 'oe',
'from_ids' => \@convert_from_oe_ids,
'to_table' => 'oe',
'to_id' => $form->{id},
);
b7b5192a Moritz Bunkus
$self->_close_quotations_rfqs('dbh' => $dbh,
'from_id' => \@convert_from_oe_ids,
f3a02fb6 Jan Büren
'to_id' => $form->{id});
b7b5192a Moritz Bunkus
}

d319704a Moritz Bunkus
if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
if ($form->{vc} eq 'customer') {
b6dc5623 Sven Schöling
$form->update_exchangerate($dbh, $form->{currency}, $form->{transdate}, $form->{exchangerate}, 0);
d319704a Moritz Bunkus
}
if ($form->{vc} eq 'vendor') {
b6dc5623 Sven Schöling
$form->update_exchangerate($dbh, $form->{currency}, $form->{transdate}, 0, $form->{exchangerate});
d319704a Moritz Bunkus
}
}

06bbc8e7 Moritz Bunkus
$form->{saved_xyznumber} = $form->{$form->{type} =~ /_quotation$/ ?
"quonumber" : "ordnumber"};

be6f6cfd Moritz Bunkus
Common::webdav_folder($form);
8e206587 Moritz Bunkus
0fc62572 Moritz Bunkus
$self->save_periodic_invoices_config(dbh => $dbh,
oe_id => $form->{id},
config_yaml => $form->{periodic_invoices_config})
if ($form->{type} eq 'sales_order');

f0ddfbfe Moritz Bunkus
$self->_link_created_sales_order_to_requirement_specs_for_sales_quotations(
type => $form->{type},
converted_from_ids => \@convert_from_oe_ids,
sales_order_id => $form->{id},
is_new => $is_new,
);

bebdc2ce Moritz Bunkus
$self->_set_project_in_linked_requirement_spec(
type => $form->{type},
project_id => $form->{globalproject_id},
sales_order_id => $form->{id},
);

d319704a Moritz Bunkus
$main::lxdebug->leave_sub();

8e0f6e70 Sven Schöling
return 1;
d319704a Moritz Bunkus
}

f0ddfbfe Moritz Bunkus
sub _link_created_sales_order_to_requirement_specs_for_sales_quotations {
my ($self, %params) = @_;

# If this is a sales order created from a sales quotation and if
# that sales quotation was created from a requirement spec document
# then link the newly created sales order to the requirement spec
# document, too.

return if !$params{is_new};
return if $params{type} ne 'sales_order';
return if !@{ $params{converted_from_ids} };

my $oe_objects = SL::DB::Manager::Order->get_all(where => [ id => $params{converted_from_ids} ]);
my @sales_quotations = grep { $_->is_type('sales_quotation') } @{ $oe_objects };

return if !@sales_quotations;

my $rs_orders = SL::DB::Manager::RequirementSpecOrder->get_all(where => [ order_id => [ map { $_->id } @sales_quotations ] ]);

return if !@{ $rs_orders };

$rs_orders->[0]->db->with_transaction(sub {
foreach my $rs_order (@{ $rs_orders }) {
SL::DB::RequirementSpecOrder->new(
order_id => $params{sales_order_id},
requirement_spec_id => $rs_order->requirement_spec_id,
version_id => $rs_order->version_id,
)->save;
}

1;
});
}

bebdc2ce Moritz Bunkus
sub _set_project_in_linked_requirement_spec {
my ($self, %params) = @_;

return if $params{type} ne 'sales_order';
return if !$params{project_id} || !$params{sales_order_id};

my $query = <<SQL;
UPDATE requirement_specs
SET project_id = ?
WHERE id IN (
SELECT so.requirement_spec_id
FROM requirement_spec_orders so
WHERE so.order_id = ?
)
SQL

do_query($::form, $::form->get_standard_dbh, $query, $params{project_id}, $params{sales_order_id});
}

92331b8e Moritz Bunkus
sub save_periodic_invoices_config {
my ($self, %params) = @_;

return if !$params{oe_id};

65b2387a Moritz Bunkus
my $config = $params{config_yaml} ? SL::YAML::Load($params{config_yaml}) : undef;
92331b8e Moritz Bunkus
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 });
}

f49ad7f1 Moritz Bunkus
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) {
82ff5451 Moritz Bunkus
my $config = { map { $_ => $config_obj->$_ } qw(active terminated periodicity order_value_periodicity start_date_as_date end_date_as_date first_billing_date_as_date extend_automatically_by ar_chart_id
9c5f94c0 Moritz Bunkus
print printer_id copies direct_debit send_email email_recipient_contact_id email_recipient_address email_sender email_subject email_body) };
65b2387a Moritz Bunkus
$form->{periodic_invoices_config} = SL::YAML::Dump($config);
f49ad7f1 Moritz Bunkus
}
}
}

b7b5192a Moritz Bunkus
sub _close_quotations_rfqs {
626e0240 Stephan Köhler
$main::lxdebug->enter_sub();

b7b5192a Moritz Bunkus
my $self = shift;
my %params = @_;
626e0240 Stephan Köhler
b7b5192a Moritz Bunkus
Common::check_params(\%params, qw(from_id to_id));
081a4f97 Moritz Bunkus
b7b5192a Moritz Bunkus
my $myconfig = \%main::myconfig;
my $form = $main::form;
626e0240 Stephan Köhler
8e0f6e70 Sven Schöling
my $dbh = $params{dbh} || SL::DB->client->dbh;
626e0240 Stephan Köhler
8e0f6e70 Sven Schöling
SL::DB->client->with_transaction(sub {
8a996479 Moritz Bunkus
8e0f6e70 Sven Schöling
my $query = qq|SELECT quotation FROM oe WHERE id = ?|;
my $sth = prepare_query($form, $dbh, $query);
8a996479 Moritz Bunkus
8e0f6e70 Sven Schöling
do_statement($form, $sth, $query, conv_i($params{to_id}));
8a996479 Moritz Bunkus
8e0f6e70 Sven Schöling
my ($quotation) = $sth->fetchrow_array();
b7b5192a Moritz Bunkus
8e0f6e70 Sven Schöling
if ($quotation) {
ea4101ec Martin Helmling
return 1;
8e0f6e70 Sven Schöling
}
b7b5192a Moritz Bunkus
8e0f6e70 Sven Schöling
my @close_ids;
b7b5192a Moritz Bunkus
8e0f6e70 Sven Schöling
foreach my $from_id (@{ $params{from_id} }) {
$from_id = conv_i($from_id);
do_statement($form, $sth, $query, $from_id);
($quotation) = $sth->fetchrow_array();
push @close_ids, $from_id if ($quotation);
}
b7b5192a Moritz Bunkus
8e0f6e70 Sven Schöling
$sth->finish();
b7b5192a Moritz Bunkus
8e0f6e70 Sven Schöling
if (scalar @close_ids) {
$query = qq|UPDATE oe SET closed = TRUE WHERE id IN (| . join(', ', ('?') x scalar @close_ids) . qq|)|;
do_query($form, $dbh, $query, @close_ids);
}
6b23fb21 Sven Schöling
1;
}) or do { die SL::DB->client->error };
8a996479 Moritz Bunkus
$main::lxdebug->leave_sub();
}

d319704a Moritz Bunkus
sub delete {
$main::lxdebug->enter_sub();

8cd05ad6 Moritz Bunkus
my ($self, $myconfig, $form) = @_;
d319704a Moritz Bunkus
3b9c2119 Moritz Bunkus
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} ]) };
d319704a Moritz Bunkus
3b9c2119 Moritz Bunkus
SL::DB::Order->new(id => $form->{id})->delete;
ddf1c00a Moritz Bunkus
8cd05ad6 Moritz Bunkus
my $spool = $::lx_office_conf{paths}->{spool};
3b9c2119 Moritz Bunkus
unlink map { "$spool/$_" } @spoolfiles if $spool;

1;
6b23fb21 Sven Schöling
}) or do { die SL::DB->client->error };
d319704a Moritz Bunkus
$main::lxdebug->leave_sub();

return $rc;
}

sub retrieve {
8e0f6e70 Sven Schöling
my ($self, $myconfig, $form) = @_;
d319704a Moritz Bunkus
$main::lxdebug->enter_sub();

8e0f6e70 Sven Schöling
my $rc = SL::DB->client->with_transaction(\&_retrieve, $self, $myconfig, $form);

$::lxdebug->leave_sub;
return $rc;
}

sub _retrieve {
d319704a Moritz Bunkus
my ($self, $myconfig, $form) = @_;

# connect to database
8e0f6e70 Sven Schöling
my $dbh = SL::DB->client->dbh;
d319704a Moritz Bunkus
f5c548f0 Moritz Bunkus
my ($query, $query_add, @values, @ids, $sth);
d319704a Moritz Bunkus
626e0240 Stephan Köhler
# translate the ids (given by id_# and trans_id_#) into one array of ids, so we can join them later
081a4f97 Moritz Bunkus
map {
push @ids, $form->{"trans_id_$_"}
9d0ebf28 Moritz Bunkus
if ($form->{"multi_id_$_"} and $form->{"trans_id_$_"})
081a4f97 Moritz Bunkus
} (1 .. $form->{"rowcount"});
626e0240 Stephan Köhler
94e11003 Moritz Bunkus
if ($form->{rowcount} && scalar @ids) {
$form->{convert_from_oe_ids} = join ' ', @ids;
}

081a4f97 Moritz Bunkus
# if called in multi id mode, and still only got one id, switch back to single id
626e0240 Stephan Köhler
if ($form->{"rowcount"} and $#ids == 0) {
583f1f0f Jan Büren
$form->{"id"} = $ids[0];
626e0240 Stephan Köhler
undef @ids;
d40a8e20 Bernd Bleßmann
delete $form->{convert_from_oe_ids};
626e0240 Stephan Köhler
}

90daea72 Sven Schöling
# and remember for the rest of the function
my $is_collective_order = scalar @ids;
cc369842 Geoffrey Richardson
# If collective order was created from exactly 1 order, we assume the same
# behaviour as a "save as new" from within an order is actually desired, i.e.
# the original order isn't part of a workflow where we want to remember
# record_links, but simply a quick way of generating a new order from an old
# one without having to enter everything again.
# Setting useasnew will prevent the creation of record_links for the items
# when saving the new order.
# This form variable is probably not necessary, could just set saveasnew instead
$form->{useasnew} = 1 if $is_collective_order == 1;
90daea72 Sven Schöling
34ca68b5 Moritz Bunkus
if (!$form->{id}) {
2d44a547 Jan Büren
my $extra_days = $form->{type} eq 'sales_quotation' ? $::instance_conf->get_reqdate_interval :
$form->{type} eq 'sales_order' ? $::instance_conf->get_delivery_date_interval : 1;
bee7d33f Jan Büren
if ( ($form->{type} eq 'sales_order' && !$::instance_conf->get_deliverydate_on)
|| ($form->{type} eq 'sales_quotation' && !$::instance_conf->get_reqdate_on)) {
$form->{reqdate} = '';
} else {
$form->{reqdate} = DateTime->today_local->next_workday(extra_days => $extra_days)->to_kivitendo;
}
ff494355 Moritz Bunkus
$form->{transdate} = DateTime->today_local->to_kivitendo;
34ca68b5 Moritz Bunkus
}
f5c548f0 Moritz Bunkus
# get default accounts
$query = qq|SELECT (SELECT c.accno FROM chart c WHERE d.inventory_accno_id = c.id) AS inventory_accno,
(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,
030c2086 Rolf Fluehmann
(SELECT c.accno FROM chart c WHERE d.fxloss_accno_id = c.id) AS fxloss_accno,
(SELECT c.accno FROM chart c WHERE d.rndgain_accno_id = c.id) AS rndgain_accno,
(SELECT c.accno FROM chart c WHERE d.rndloss_accno_id = c.id) AS rndloss_accno
f5c548f0 Moritz Bunkus
$query_add
FROM defaults d|;
my $ref = selectfirst_hashref_query($form, $dbh, $query);
d319704a Moritz Bunkus
map { $form->{$_} = $ref->{$_} } keys %$ref;

d331a3d7 Niclas Zimmermann
$form->{currency} = $form->get_default_currency($myconfig);
d319704a Moritz Bunkus
081a4f97 Moritz Bunkus
# set reqdate if this is an invoice->order conversion. If someone knows a better check to ensure
487d4f1f Stephan Köhler
# we come from invoices, feel free.
081a4f97 Moritz Bunkus
$form->{reqdate} = $form->{deliverydate}
if ( $form->{deliverydate}
and $form->{callback} =~ /action=ar_transactions/);
487d4f1f Stephan Köhler
9d0ebf28 Moritz Bunkus
my $vc = $form->{vc} eq "customer" ? "customer" : "vendor";

626e0240 Stephan Köhler
if ($form->{id} or @ids) {
d319704a Moritz Bunkus
626e0240 Stephan Köhler
# retrieve order for single id
# NOTE: this query is intended to fetch all information only ONCE.
081a4f97 Moritz Bunkus
# so if any of these infos is important (or even different) for any item,
626e0240 Stephan Köhler
# it will be killed out and then has to be fetched from the item scope query further down
9d0ebf28 Moritz Bunkus
$query =
60eb41d8 Sven Schöling
qq|SELECT o.cp_id, o.ordnumber, o.transdate, o.reqdate,
o.taxincluded, o.shippingpoint, o.shipvia, o.notes, o.intnotes,
a4d74009 Niclas Zimmermann
(SELECT cu.name FROM currencies cu WHERE cu.id=o.currency_id) AS currency, e.name AS employee, o.employee_id, o.salesman_id,
60eb41d8 Sven Schöling
o.${vc}_id, cv.name AS ${vc}, o.amount AS invtotal,
0b36b225 Moritz Bunkus
o.closed, o.reqdate, o.tax_point, o.quonumber, o.department_id, o.cusordnumber,
d735aab3 Martin Helmling
o.mtime, o.itime,
60eb41d8 Sven Schöling
d.description AS department, o.payment_id, o.language_id, o.taxzone_id,
844a541e Moritz Bunkus
o.delivery_customer_id, o.delivery_vendor_id, o.proforma, o.shipto_id, o.billing_address_id,
a809ab0a Bernd Bleßmann
o.globalproject_id, o.delivered, o.transaction_description, o.delivery_term_id,
o.itime::DATE AS insertdate, o.order_probability, o.expected_billing_date
60eb41d8 Sven Schöling
FROM oe o
JOIN ${vc} cv ON (o.${vc}_id = cv.id)
LEFT JOIN employee e ON (o.employee_id = e.id)
LEFT JOIN department d ON (o.department_id = d.id) | .
06d98024 Sven Schöling
($form->{id}
? "WHERE o.id = ?"
60eb41d8 Sven Schöling
: "WHERE o.id IN (" . join(', ', map("? ", @ids)) . ")"
);
9d0ebf28 Moritz Bunkus
@values = $form->{id} ? ($form->{id}) : @ids;
$sth = prepare_execute_query($form, $dbh, $query, @values);
d319704a Moritz Bunkus
90daea72 Sven Schöling
$ref = $sth->fetchrow_hashref("NAME_lc");
d319704a Moritz Bunkus
2a795624 Moritz Bunkus
if ($ref) {
map { $form->{$_} = $ref->{$_} } keys %$ref;
54e4131e Moritz Bunkus
2a795624 Moritz Bunkus
$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;
}
d319704a Moritz Bunkus
}
d2af074a Jan Büren
$form->{mtime} ||= $form->{itime};
d735aab3 Martin Helmling
$form->{lastmtime} = $form->{mtime};
626e0240 Stephan Köhler
# if not given, fill transdate with current_date
081a4f97 Moritz Bunkus
$form->{transdate} = $form->current_date($myconfig)
unless $form->{transdate};
626e0240 Stephan Köhler
d319704a Moritz Bunkus
$sth->finish;
626e0240 Stephan Köhler
54e4131e Moritz Bunkus
if ($form->{delivery_customer_id}) {
9d0ebf28 Moritz Bunkus
$query = qq|SELECT name FROM customer WHERE id = ?|;
60eb41d8 Sven Schöling
($form->{delivery_customer_string}) = selectrow_query($form, $dbh, $query, $form->{delivery_customer_id});
54e4131e Moritz Bunkus
}

if ($form->{delivery_vendor_id}) {
9d0ebf28 Moritz Bunkus
$query = qq|SELECT name FROM customer WHERE id = ?|;
60eb41d8 Sven Schöling
($form->{delivery_vendor_string}) = selectrow_query($form, $dbh, $query, $form->{delivery_vendor_id});
54e4131e Moritz Bunkus
}

081a4f97 Moritz Bunkus
# shipto and pinted/mailed/queued status makes only sense for single id retrieve
626e0240 Stephan Köhler
if (!@ids) {
60eb41d8 Sven Schöling
$query = qq|SELECT s.* FROM shipto s WHERE s.trans_id = ? AND s.module = 'OE'|;
9d0ebf28 Moritz Bunkus
$sth = prepare_execute_query($form, $dbh, $query, $form->{id});
626e0240 Stephan Köhler
90daea72 Sven Schöling
$ref = $sth->fetchrow_hashref("NAME_lc");
a8cba95a Moritz Bunkus
$form->{$_} = $ref->{$_} for grep { m{^shipto(?!_id$)} } keys %$ref;
626e0240 Stephan Köhler
$sth->finish;

a8cba95a Moritz Bunkus
if ($ref->{shipto_id}) {
4493d1eb Moritz Bunkus
my $cvars = CVar->get_custom_variables(
dbh => $dbh,
module => 'ShipTo',
a8cba95a Moritz Bunkus
trans_id => $ref->{shipto_id},
4493d1eb Moritz Bunkus
);
$form->{"shiptocvar_$_->{name}"} = $_->{value} for @{ $cvars };
}

626e0240 Stephan Köhler
# get printed, emailed and queued
60eb41d8 Sven Schöling
$query = qq|SELECT s.printed, s.emailed, s.spoolfile, s.formname FROM status s WHERE s.trans_id = ?|;
9d0ebf28 Moritz Bunkus
$sth = prepare_execute_query($form, $dbh, $query, $form->{id});
626e0240 Stephan Köhler
90daea72 Sven Schöling
while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
626e0240 Stephan Köhler
$form->{printed} .= "$ref->{formname} " if $ref->{printed};
$form->{emailed} .= "$ref->{formname} " if $ref->{emailed};
60eb41d8 Sven Schöling
$form->{queued} .= "$ref->{formname} $ref->{spoolfile} " if $ref->{spoolfile};
626e0240 Stephan Köhler
}
$sth->finish;
map { $form->{$_} =~ s/ +$//g } qw(printed emailed queued);
081a4f97 Moritz Bunkus
} # if !@ids
d319704a Moritz Bunkus
0b36b225 Moritz Bunkus
my $transdate = $form->{tax_point} ? $dbh->quote($form->{tax_point}) : $form->{transdate} ? $dbh->quote($form->{transdate}) : "current_date";
2e5a8be3 Moritz Bunkus
9d0ebf28 Moritz Bunkus
$form->{taxzone_id} = 0 unless ($form->{taxzone_id});
1f225563 Moritz Bunkus
unshift @values, ($form->{taxzone_id}) x 2;
9d0ebf28 Moritz Bunkus
d319704a Moritz Bunkus
# retrieve individual items
626e0240 Stephan Köhler
# this query looks up all information about the items
# stuff different from the whole will not be overwritten, but saved with a suffix.
9d0ebf28 Moritz Bunkus
$query =
60eb41d8 Sven Schöling
qq|SELECT o.id AS orderitems_id,
06d98024 Sven Schöling
c1.accno AS inventory_accno, c1.new_chart_id AS inventory_new_chart, date($transdate) - c1.valid_from as inventory_valid,
60eb41d8 Sven Schöling
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,
98b64fe1 Geoffrey Richardson
p.partnumber, p.part_type, p.listprice, o.description, o.qty,
65d2537d Martin Helmling
p.classification_id,
723a1158 Geoffrey Richardson
o.sellprice, o.parts_id AS id, o.unit, o.discount, p.notes AS partnotes, p.part_type,
60eb41d8 Sven Schöling
o.reqdate, o.project_id, o.serialnumber, o.ship, o.lastcost,
o.ordnumber, o.transdate, o.cusordnumber, o.subtotal, o.longdescription,
89b26688 Sven Schöling
o.price_factor_id, o.price_factor, o.marge_price_factor, o.active_price_source, o.active_discount_source,
60eb41d8 Sven Schöling
pr.projectnumber, p.formel,
pg.partsgroup, o.pricegroup_id, (SELECT pricegroup FROM pricegroup WHERE id=o.pricegroup_id) as pricegroup
FROM orderitems o
JOIN parts p ON (o.parts_id = p.id)
JOIN oe ON (o.trans_id = oe.id)
LEFT JOIN chart c1 ON ((SELECT inventory_accno_id FROM buchungsgruppen WHERE id=p.buchungsgruppen_id) = c1.id)
1f225563 Moritz Bunkus
LEFT JOIN chart c2 ON ((SELECT tc.income_accno_id FROM taxzone_charts tc WHERE tc.taxzone_id = ? and tc.buchungsgruppen_id = p.buchungsgruppen_id) = c2.id)
LEFT JOIN chart c3 ON ((SELECT tc.expense_accno_id FROM taxzone_charts tc WHERE tc.taxzone_id = ? and tc.buchungsgruppen_id = p.buchungsgruppen_id) = c3.id)
60eb41d8 Sven Schöling
LEFT JOIN project pr ON (o.project_id = pr.id)
LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) | .
($form->{id}
? qq|WHERE o.trans_id = ?|
: qq|WHERE o.trans_id IN (| . join(", ", map("?", @ids)) . qq|)|) .
8b60748b Bernd Bleßmann
qq|ORDER BY o.trans_id, o.position|;
9d0ebf28 Moritz Bunkus
@ids = $form->{id} ? ($form->{id}) : @ids;
$sth = prepare_execute_query($form, $dbh, $query, @values);
d319704a Moritz Bunkus
90daea72 Sven Schöling
while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
ef220490 Moritz Bunkus
# Retrieve custom variables.
my $cvars = CVar->get_custom_variables(dbh => $dbh,
module => 'IC',
sub_module => 'orderitems',
trans_id => $ref->{orderitems_id},
);
map { $ref->{"ic_cvar_$_->{name}"} = $_->{value} } @{ $cvars };

# Handle accounts.
723a1158 Geoffrey Richardson
if (!$ref->{"part_type"} eq 'part') {
54e4131e Moritz Bunkus
map({ delete($ref->{$_}); } qw(inventory_accno inventory_new_chart inventory_valid));
}
723a1158 Geoffrey Richardson
# delete($ref->{"part_inventory_accno_id"});
081a4f97 Moritz Bunkus
041a8bb7 Stephan Köhler
# in collective order, copy global ordnumber, transdate, cusordnumber into item scope
081a4f97 Moritz Bunkus
# unless already present there
041a8bb7 Stephan Köhler
# remove _oe entries afterwards
map { $ref->{$_} = $ref->{"${_}_oe"} if ($ref->{$_} eq '') }
081a4f97 Moritz Bunkus
qw|ordnumber transdate cusordnumber|
if (@ids);
map { delete $ref->{$_} } qw|ordnumber_oe transdate_oe cusordnumber_oe|;
d319704a Moritz Bunkus
54e4131e Moritz Bunkus

9d0ebf28 Moritz Bunkus
while ($ref->{inventory_new_chart} && ($ref->{inventory_valid} >= 0)) {
my $query =
qq|SELECT accno AS inventory_accno, | .
qq| new_chart_id AS inventory_new_chart, | .
qq| date($transdate) - valid_from AS inventory_valid | .
qq|FROM chart WHERE id = $ref->{inventory_new_chart}|;
($ref->{inventory_accno}, $ref->{inventory_new_chart},
$ref->{inventory_valid}) = selectrow_query($form, $dbh, $query);
}
54e4131e Moritz Bunkus
9d0ebf28 Moritz Bunkus
while ($ref->{income_new_chart} && ($ref->{income_valid} >= 0)) {
my $query =
qq|SELECT accno AS income_accno, | .
qq| new_chart_id AS income_new_chart, | .
qq| date($transdate) - valid_from AS income_valid | .
qq|FROM chart WHERE id = $ref->{income_new_chart}|;
($ref->{income_accno}, $ref->{income_new_chart},
$ref->{income_valid}) = selectrow_query($form, $dbh, $query);
}
54e4131e Moritz Bunkus
9d0ebf28 Moritz Bunkus
while ($ref->{expense_new_chart} && ($ref->{expense_valid} >= 0)) {
my $query =
qq|SELECT accno AS expense_accno, | .
qq| new_chart_id AS expense_new_chart, | .
qq| date($transdate) - valid_from AS expense_valid | .
qq|FROM chart WHERE id = $ref->{expense_new_chart}|;
($ref->{expense_accno}, $ref->{expense_new_chart},
$ref->{expense_valid}) = selectrow_query($form, $dbh, $query);
}
37df0ebf Sven Schöling
b518ce7a Moritz Bunkus
# delete orderitems_id in collective orders, so that they get cloned no matter what
cc369842 Geoffrey Richardson
# is this correct? or is the following meant?
# remember orderitems_ids in converted_from_orderitems_ids, so that they may be linked
cd812c6b Bernd Bleßmann
$ref->{converted_from_orderitems_id} = delete $ref->{orderitems_id} if $is_collective_order;
b518ce7a Moritz Bunkus
d319704a Moritz Bunkus
# get tax rates and description
90daea72 Sven Schöling
my $accno_id = ($form->{vc} eq "customer") ? $ref->{income_accno} : $ref->{expense_accno};
9d0ebf28 Moritz Bunkus
$query =
4e8e33e9 Geoffrey Richardson
qq|SELECT c.accno, t.taxdescription, t.rate, t.id as tax_id, c.accno as taxnumber | .
543d7822 Geoffrey Richardson
qq|FROM tax t | .
qq|LEFT JOIN chart c on (c.id = t.chart_id) | .
9d0ebf28 Moritz Bunkus
qq|WHERE t.id IN (SELECT tk.tax_id FROM taxkeys tk | .
qq| WHERE tk.chart_id = (SELECT id FROM chart WHERE accno = ?) | .
qq| AND startdate <= $transdate ORDER BY startdate DESC LIMIT 1) | .
qq|ORDER BY c.accno|;
90daea72 Sven Schöling
my $stw = prepare_execute_query($form, $dbh, $query, $accno_id);
d319704a Moritz Bunkus
$ref->{taxaccounts} = "";
54e4131e Moritz Bunkus
my $i = 0;
90daea72 Sven Schöling
while (my $ptr = $stw->fetchrow_hashref("NAME_lc")) {
54e4131e Moritz Bunkus
if (($ptr->{accno} eq "") && ($ptr->{rate} == 0)) {
$i++;
$ptr->{accno} = $i;
}
d319704a Moritz Bunkus
$ref->{taxaccounts} .= "$ptr->{accno} ";
5cf977e5 Moritz Bunkus
if (!($form->{taxaccounts} =~ /\Q$ptr->{accno}\E/)) {
d319704a Moritz Bunkus
$form->{"$ptr->{accno}_rate"} = $ptr->{rate};
54e4131e Moritz Bunkus
$form->{"$ptr->{accno}_description"} = $ptr->{taxdescription};
d319704a Moritz Bunkus
$form->{"$ptr->{accno}_taxnumber"} = $ptr->{taxnumber};
4e8e33e9 Geoffrey Richardson
$form->{"$ptr->{accno}_tax_id"} = $ptr->{tax_id};
d319704a Moritz Bunkus
$form->{taxaccounts} .= "$ptr->{accno} ";
}

}

chop $ref->{taxaccounts};
ef220490 Moritz Bunkus
d319704a Moritz Bunkus
push @{ $form->{form_details} }, $ref;
$stw->finish;
}
$sth->finish;

} else {

# get last name used
$form->lastname_used($dbh, $myconfig, $form->{vc})
unless $form->{"$form->{vc}_id"};

}

60eb41d8 Sven Schöling
$form->{exchangerate} = $form->get_exchangerate($dbh, $form->{currency}, $form->{transdate}, ($form->{vc} eq 'customer') ? "buy" : "sell");
d319704a Moritz Bunkus
be6f6cfd Moritz Bunkus
Common::webdav_folder($form);
d319704a Moritz Bunkus
f49ad7f1 Moritz Bunkus
$self->load_periodic_invoice_config($form);

8e0f6e70 Sven Schöling
return 1;
d319704a Moritz Bunkus
}

9bc40390 Sven Schöling
sub retrieve_simple {
$main::lxdebug->enter_sub();

my $self = shift;
my %params = @_;

Common::check_params(\%params, qw(id));

my $myconfig = \%main::myconfig;
my $form = $main::form;

my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig);

my $oe_query = qq|SELECT * FROM oe WHERE id = ?|;
8b60748b Bernd Bleßmann
my $oi_query = qq|SELECT * FROM orderitems WHERE trans_id = ? ORDER BY position|;
9bc40390 Sven Schöling
879070c7 Sven Schöling
my $order = selectfirst_hashref_query($form, $dbh, $oe_query, conv_i($params{id}));
$order->{orderitems} = selectall_hashref_query( $form, $dbh, $oi_query, conv_i($params{id}));
9bc40390 Sven Schöling
$main::lxdebug->leave_sub();

return $order;
}

d319704a Moritz Bunkus
sub order_details {
$main::lxdebug->enter_sub();

my ($self, $myconfig, $form) = @_;

# connect to database
f2cbb7d7 Sven Schöling
my $dbh = SL::DB->client->dbh;
d319704a Moritz Bunkus
my $query;
9d0ebf28 Moritz Bunkus
my @values = ();
d319704a Moritz Bunkus
my $sth;
54e4131e Moritz Bunkus
my $nodiscount;
my $yesdiscount;
my $nodiscount_subtotal = 0;
my $discount_subtotal = 0;
d319704a Moritz Bunkus
my $item;
my $i;
my @partsgroup = ();
my $partsgroup;
54e4131e Moritz Bunkus
my $position = 0;
my $subtotal_header = 0;
my $subposition = 0;
90daea72 Sven Schöling
my %taxaccounts;
my %taxbase;
my $tax_rate;
my $taxamount;

fde1df0b Sven Schöling
my (@project_ids);
96d10ecc Moritz Bunkus
push(@project_ids, $form->{"globalproject_id"}) if ($form->{"globalproject_id"});

dd2ee66b Geoffrey Richardson
$form->get_lists('price_factors' => 'ALL_PRICE_FACTORS');
1e251313 Moritz Bunkus
my %price_factors;

foreach my $pfac (@{ $form->{ALL_PRICE_FACTORS} }) {
$price_factors{$pfac->{id}} = $pfac;
$pfac->{factor} *= 1;
$pfac->{formatted_factor} = $form->format_amount($myconfig, $pfac->{factor});
}

d319704a Moritz Bunkus
# sort items by partsgroup
for $i (1 .. $form->{rowcount}) {
$partsgroup = "";
if ($form->{"partsgroup_$i"} && $form->{groupitems}) {
$partsgroup = $form->{"partsgroup_$i"};
}
push @partsgroup, [$i, $partsgroup];
96d10ecc Moritz Bunkus
push(@project_ids, $form->{"project_id_$i"}) if ($form->{"project_id_$i"});
}

fde1df0b Sven Schöling
my $projects = [];
my %projects_by_id;
96d10ecc Moritz Bunkus
if (@project_ids) {
fde1df0b Sven Schöling
$projects = SL::DB::Manager::Project->get_all(query => [ id => \@project_ids ]);
%projects_by_id = map { $_->id => $_ } @$projects;
d319704a Moritz Bunkus
}

fde1df0b Sven Schöling
if ($projects_by_id{$form->{"globalproject_id"}}) {
896ef9aa Sven Schöling
$form->{globalprojectnumber} = $projects_by_id{$form->{"globalproject_id"}}->projectnumber;
$form->{globalprojectdescription} = $projects_by_id{$form->{"globalproject_id"}}->description;

fde1df0b Sven Schöling
for (@{ $projects_by_id{$form->{"globalproject_id"}}->cvars_by_config }) {
$form->{"project_cvar_" . $_->config->name} = $_->value_as_text;
}
}
96d10ecc Moritz Bunkus
af59820c Moritz Bunkus
$form->{discount} = [];

0e470b13 Bernd Bleßmann
# get some values of parts from db on store them in extra array,
# so that they can be sorted in later
my %prepared_template_arrays = IC->prepare_parts_for_printing(myconfig => $myconfig, form => $form);
my @prepared_arrays = keys %prepared_template_arrays;
219d88ab Martin Helmling
my @separate_totals = qw(non_separate_subtotal);
0e470b13 Bernd Bleßmann
b0059459 Moritz Bunkus
$form->{TEMPLATE_ARRAYS} = { };
47c3bf62 Moritz Bunkus
ef220490 Moritz Bunkus
my $ic_cvar_configs = CVar->get_configs(module => 'IC');
fde1df0b Sven Schöling
my $project_cvar_configs = CVar->get_configs(module => 'Projects');
ef220490 Moritz Bunkus
96d10ecc Moritz Bunkus
my @arrays =
0e470b13 Bernd Bleßmann
qw(runningnumber number description longdescription qty qty_nofmt ship ship_nofmt unit bin
partnotes serialnumber reqdate sellprice sellprice_nofmt listprice listprice_nofmt netprice netprice_nofmt
discount discount_nofmt p_discount discount_sub discount_sub_nofmt nodiscount_sub nodiscount_sub_nofmt
linetotal linetotal_nofmt nodiscount_linetotal nodiscount_linetotal_nofmt tax_rate projectnumber projectdescription
5a618706 Jan Büren
price_factor price_factor_name partsgroup weight weight_nofmt lineweight lineweight_nofmt optional);
96d10ecc Moritz Bunkus
ef220490 Moritz Bunkus
push @arrays, map { "ic_cvar_$_->{name}" } @{ $ic_cvar_configs };
fde1df0b Sven Schöling
push @arrays, map { "project_cvar_$_->{name}" } @{ $project_cvar_configs };
ef220490 Moritz Bunkus
9c63c160 Moritz Bunkus
my @tax_arrays = qw(taxbase tax taxdescription taxrate taxnumber);

0e470b13 Bernd Bleßmann
map { $form->{TEMPLATE_ARRAYS}->{$_} = [] } (@arrays, @tax_arrays, @prepared_arrays);
9c63c160 Moritz Bunkus
79c048aa Niclas Zimmermann
my $totalweight = 0;
d319704a Moritz Bunkus
my $sameitem = "";
foreach $item (sort { $a->[1] cmp $b->[1] } @partsgroup) {
$i = $item->[0];

if ($item->[1] ne $sameitem) {
0e470b13 Bernd Bleßmann
push(@{ $form->{TEMPLATE_ARRAYS}->{entry_type} }, 'partsgroup');
9c63c160 Moritz Bunkus
push(@{ $form->{TEMPLATE_ARRAYS}->{description} }, qq|$item->[1]|);
d319704a Moritz Bunkus
$sameitem = $item->[1];

0e470b13 Bernd Bleßmann
map({ push(@{ $form->{TEMPLATE_ARRAYS}->{$_} }, "") } grep({ $_ ne "description" } (@arrays, @prepared_arrays)));
d319704a Moritz Bunkus
}

$form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});

8c89bb02 Moritz Bunkus
if ($form->{"id_$i"} != 0) {
d319704a Moritz Bunkus
# add number, description and qty to $form->{number}, ....
54e4131e Moritz Bunkus
if ($form->{"subtotal_$i"} && !$subtotal_header) {
$subtotal_header = $i;
$position = int($position);
$subposition = 0;
$position++;
} elsif ($subtotal_header) {
$subposition += 1;
$position = int($position);
$position = $position.".".$subposition;
} else {
$position = int($position);
$position++;
}

1e251313 Moritz Bunkus
my $price_factor = $price_factors{$form->{"price_factor_id_$i"}} || { 'factor' => 1 };

0e470b13 Bernd Bleßmann
push(@{ $form->{TEMPLATE_ARRAYS}->{$_} }, $prepared_template_arrays{$_}[$i - 1]) for @prepared_arrays;

push @{ $form->{TEMPLATE_ARRAYS}->{entry_type} }, 'normal';
9c63c160 Moritz Bunkus
push @{ $form->{TEMPLATE_ARRAYS}->{runningnumber} }, $position;
push @{ $form->{TEMPLATE_ARRAYS}->{number} }, $form->{"partnumber_$i"};
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"});
8461199d Moritz Bunkus
push @{ $form->{TEMPLATE_ARRAYS}->{qty_nofmt} }, $form->{"qty_$i"};
9c63c160 Moritz Bunkus
push @{ $form->{TEMPLATE_ARRAYS}->{ship} }, $form->format_amount($myconfig, $form->{"ship_$i"});
8461199d Moritz Bunkus
push @{ $form->{TEMPLATE_ARRAYS}->{ship_nofmt} }, $form->{"ship_$i"};
9c63c160 Moritz Bunkus
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"};
8461199d Moritz Bunkus
push @{ $form->{TEMPLATE_ARRAYS}->{sellprice_nofmt} }, $form->parse_amount($myconfig, $form->{"sellprice_$i"});
2f6636f6 Bernd Bleßmann
push @{ $form->{TEMPLATE_ARRAYS}->{listprice} }, $form->format_amount($myconfig, $form->{"listprice_$i"}, 2);
push @{ $form->{TEMPLATE_ARRAYS}->{listprice_nofmt} }, $form->{"listprice_$i"};
9c63c160 Moritz Bunkus
push @{ $form->{TEMPLATE_ARRAYS}->{price_factor} }, $price_factor->{formatted_factor};
push @{ $form->{TEMPLATE_ARRAYS}->{price_factor_name} }, $price_factor->{description};
push @{ $form->{TEMPLATE_ARRAYS}->{partsgroup} }, $form->{"partsgroup_$i"};
5a618706 Jan Büren
push @{ $form->{TEMPLATE_ARRAYS}->{optional} }, $form->{"optional_$i"};
d9c9bc22 Moritz Bunkus
my $sellprice = $form->parse_amount($myconfig, $form->{"sellprice_$i"});
my ($dec) = ($sellprice =~ /\.(\d+)/);
my $decimalplaces = max 2, length($dec);

c126984e Geoffrey Richardson
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

99d8aaf4 Geoffrey Richardson
$form->{"netprice_$i"} = $form->round_amount($form->{"qty_$i"} ? ($linetotal / $form->{"qty_$i"}) : 0, $decimalplaces);
d9c9bc22 Moritz Bunkus
8461199d Moritz Bunkus
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"} : '';
d9c9bc22 Moritz Bunkus
$linetotal = ($linetotal != 0) ? $linetotal : '';

8461199d Moritz Bunkus
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"};
d9c9bc22 Moritz Bunkus
219d88ab Martin Helmling
if ( $prepared_template_arrays{separate}[$i - 1] ) {
my $pabbr = $prepared_template_arrays{separate}[$i - 1];
if ( ! $form->{"separate_${pabbr}_subtotal"} ) {
push @separate_totals , "separate_${pabbr}_subtotal";
$form->{"separate_${pabbr}_subtotal"} = 0;
}
$form->{"separate_${pabbr}_subtotal"} += $linetotal;
} else {
$form->{non_separate_subtotal} += $linetotal;
}

5a618706 Jan Büren
$form->{ordtotal} += $linetotal unless $form->{"optional_$i"};
54e4131e Moritz Bunkus
$form->{nodiscount_total} += $nodiscount_linetotal;
d9c9bc22 Moritz Bunkus
$form->{discount_total} += $discount;

if ($subtotal_header) {
$discount_subtotal += $linetotal;
$nodiscount_subtotal += $nodiscount_linetotal;
}
54e4131e Moritz Bunkus
if ($form->{"subtotal_$i"} && $subtotal_header && ($subtotal_header != $i)) {
8461199d Moritz Bunkus
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;
d9c9bc22 Moritz Bunkus
$discount_subtotal = 0;
54e4131e Moritz Bunkus
$nodiscount_subtotal = 0;
d9c9bc22 Moritz Bunkus
$subtotal_header = 0;

54e4131e Moritz Bunkus
} else {
e1a38ef7 Moritz Bunkus
push @{ $form->{TEMPLATE_ARRAYS}->{$_} }, "" for qw(discount_sub nodiscount_sub discount_sub_nofmt nodiscount_sub_nofmt);
54e4131e Moritz Bunkus
}
d319704a Moritz Bunkus
d9c9bc22 Moritz Bunkus
if (!$form->{"discount_$i"}) {
54e4131e Moritz Bunkus
$nodiscount += $linetotal;
}
d9c9bc22 Moritz Bunkus
fde1df0b Sven Schöling
my $project = $projects_by_id{$form->{"project_id_$i"}} || SL::DB::Project->new;

8461199d Moritz Bunkus
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;
fde1df0b Sven Schöling
push @{ $form->{TEMPLATE_ARRAYS}->{projectnumber} }, $project->projectnumber;
push @{ $form->{TEMPLATE_ARRAYS}->{projectdescription} }, $project->description;
96d10ecc Moritz Bunkus
79c048aa Niclas Zimmermann
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;

d319704a Moritz Bunkus
my ($taxamount, $taxbase);
my $taxrate = 0;

9d0ebf28 Moritz Bunkus
map { $taxrate += $form->{"${_}_rate"} } split(/ /, $form->{"taxaccounts_$i"});
d319704a Moritz Bunkus
5a618706 Jan Büren
unless ($form->{"optional_$i"}) {
if ($form->{taxincluded}) {
d319704a Moritz Bunkus
5a618706 Jan Büren
# calculate tax
$taxamount = $linetotal * $taxrate / (1 + $taxrate);
$taxbase = $linetotal / (1 + $taxrate);
} else {
$taxamount = $linetotal * $taxrate;
$taxbase = $linetotal;
}
d319704a Moritz Bunkus
}

if ($taxamount != 0) {
eeb560af Moritz Bunkus
foreach my $accno (split / /, $form->{"taxaccounts_$i"}) {
$taxaccounts{$accno} += $taxamount * $form->{"${accno}_rate"} / $taxrate;
$taxbase{$accno} += $taxbase;
d319704a Moritz Bunkus
}
}

081a4f97 Moritz Bunkus
$tax_rate = $taxrate * 100;
9c63c160 Moritz Bunkus
push(@{ $form->{TEMPLATE_ARRAYS}->{tax_rate} }, qq|$tax_rate|);
eb8a578d Stephan Köhler
5bc5af9f Geoffrey Richardson
if ($form->{"part_type_$i"} eq 'assembly') {
d319704a Moritz Bunkus
$sameitem = "";

# get parts and push them onto the stack
my $sortorder = "";
if ($form->{groupitems}) {
53db54a8 Moritz Bunkus
$sortorder = qq|ORDER BY pg.partsgroup, a.position|;
d319704a Moritz Bunkus
} else {
53db54a8 Moritz Bunkus
$sortorder = qq|ORDER BY a.position|;
d319704a Moritz Bunkus
}

9d0ebf28 Moritz Bunkus
$query = qq|SELECT p.partnumber, p.description, p.unit, a.qty, | .
c09536f4 Sven Schöling
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"});
d319704a Moritz Bunkus
$sth = $dbh->prepare($query);
9d0ebf28 Moritz Bunkus
$sth->execute(@values) || $form->dberror($query);
d319704a Moritz Bunkus
90daea72 Sven Schöling
while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
d319704a Moritz Bunkus
if ($form->{groupitems} && $ref->{partsgroup} ne $sameitem) {
0e470b13 Bernd Bleßmann
map({ push(@{ $form->{TEMPLATE_ARRAYS}->{$_} }, "") } grep({ $_ ne "description" } (@arrays, @prepared_arrays)));
d319704a Moritz Bunkus
$sameitem = ($ref->{partsgroup}) ? $ref->{partsgroup} : "--";
0e470b13 Bernd Bleßmann
push(@{ $form->{TEMPLATE_ARRAYS}->{entry_type} }, 'assembly-item-partsgroup');
9c63c160 Moritz Bunkus
push(@{ $form->{TEMPLATE_ARRAYS}->{description} }, $sameitem);
d319704a Moritz Bunkus
}

0e470b13 Bernd Bleßmann
push(@{ $form->{TEMPLATE_ARRAYS}->{entry_type} }, 'assembly-item');
9c63c160 Moritz Bunkus
push(@{ $form->{TEMPLATE_ARRAYS}->{description} }, $form->format_amount($myconfig, $ref->{qty} * $form->{"qty_$i"}) . qq|, $ref->{partnumber}, $ref->{description}|);
0e470b13 Bernd Bleßmann
map({ push(@{ $form->{TEMPLATE_ARRAYS}->{$_} }, "") } grep({ $_ ne "description" } (@arrays, @prepared_arrays)));
d319704a Moritz Bunkus
}
$sth->finish;
}

be42a450 Bernd Bleßmann
CVar->get_non_editable_ic_cvars(form => $form,
dbh => $dbh,
f4051b8f Bernd Bleßmann
row => $i,
be42a450 Bernd Bleßmann
sub_module => 'orderitems',
may_converted_from => ['orderitems', 'invoice']);
6b4a71ff Bernd Bleßmann
d729e328 Sven Schöling
push @{ $form->{TEMPLATE_ARRAYS}->{"ic_cvar_$_->{name}"} },
CVar->format_to_template(CVar->parse($form->{"ic_cvar_$_->{name}_$i"}, $_), $_)
for @{ $ic_cvar_configs };
fde1df0b Sven Schöling
push @{ $form->{TEMPLATE_ARRAYS}->{"project_cvar_" . $_->config->name} }, $_->value_as_text for @{ $project->cvars_by_config };
d319704a Moritz Bunkus
}
}

79c048aa Niclas Zimmermann
$form->{totalweight} = $form->format_amount($myconfig, $totalweight, 3);
$form->{totalweight_nofmt} = $totalweight;
fe6275f8 Niclas Zimmermann
my $defaults = AM->get_defaults();
$form->{weightunit} = $defaults->{weightunit};
79c048aa Niclas Zimmermann
d319704a Moritz Bunkus
my $tax = 0;
foreach $item (sort keys %taxaccounts) {
96d10ecc Moritz Bunkus
$tax += $taxamount = $form->round_amount($taxaccounts{$item}, 2);
d319704a Moritz Bunkus
9c63c160 Moritz Bunkus
push(@{ $form->{TEMPLATE_ARRAYS}->{taxbase} }, $form->format_amount($myconfig, $taxbase{$item}, 2));
8461199d Moritz Bunkus
push(@{ $form->{TEMPLATE_ARRAYS}->{taxbase_nofmt} }, $taxbase{$item});
9c63c160 Moritz Bunkus
push(@{ $form->{TEMPLATE_ARRAYS}->{tax} }, $form->format_amount($myconfig, $taxamount, 2));
8461199d Moritz Bunkus
push(@{ $form->{TEMPLATE_ARRAYS}->{tax_nofmt} }, $taxamount);
9c63c160 Moritz Bunkus
push(@{ $form->{TEMPLATE_ARRAYS}->{taxrate} }, $form->format_amount($myconfig, $form->{"${item}_rate"} * 100));
8461199d Moritz Bunkus
push(@{ $form->{TEMPLATE_ARRAYS}->{taxrate_nofmt} }, $form->{"${item}_rate"} * 100);
9c63c160 Moritz Bunkus
push(@{ $form->{TEMPLATE_ARRAYS}->{taxnumber} }, $form->{"${item}_taxnumber"});
4e8e33e9 Geoffrey Richardson
push(@{ $form->{TEMPLATE_ARRAYS}->{tax_id} }, $form->{"${item}_tax_id"});
e90048c8 Bernd Bleßmann
4e8e33e9 Geoffrey Richardson
if ( $form->{"${item}_tax_id"} ) {
my $tax_obj = SL::DB::Manager::Tax->find_by(id => $form->{"${item}_tax_id"}) or die "Can't find tax with id " . $form->{"${item}_tax_id"};
my $description = $tax_obj ? $tax_obj->translated_attribute('taxdescription', $form->{language_id}, 0) : '';
push(@{ $form->{TEMPLATE_ARRAYS}->{taxdescription} }, $description . q{ } . 100 * $form->{"${item}_rate"} . q{%});
543d7822 Geoffrey Richardson
}
d319704a Moritz Bunkus
}
d9c9bc22 Moritz Bunkus
54e4131e Moritz Bunkus
$form->{nodiscount_subtotal} = $form->format_amount($myconfig, $form->{nodiscount_total}, 2);
d9c9bc22 Moritz Bunkus
$form->{discount_total} = $form->format_amount($myconfig, $form->{discount_total}, 2);
$form->{nodiscount} = $form->format_amount($myconfig, $nodiscount, 2);
$form->{yesdiscount} = $form->format_amount($myconfig, $form->{nodiscount_total} - $nodiscount, 2);
d319704a Moritz Bunkus
92b2f11d Thomas Kasulke
if($form->{taxincluded}) {
8461199d Moritz Bunkus
$form->{subtotal} = $form->format_amount($myconfig, $form->{ordtotal} - $tax, 2);
1e26c0d4 Wulf Coulmann
$form->{subtotal_nofmt} = $form->{ordtotal} - $tax;
d9c9bc22 Moritz Bunkus
} else {
8461199d Moritz Bunkus
$form->{subtotal} = $form->format_amount($myconfig, $form->{ordtotal}, 2);
1e26c0d4 Wulf Coulmann
$form->{subtotal_nofmt} = $form->{ordtotal};
92b2f11d Thomas Kasulke
}
d9c9bc22 Moritz Bunkus
c0cc8bb2 Rolf Fluehmann
my $grossamount = ($form->{taxincluded}) ? $form->{ordtotal} : $form->{ordtotal} + $tax;
$form->{ordtotal} = $form->round_amount( $grossamount, 2, 1);
$form->{rounding} = $form->round_amount(
$form->{ordtotal} - $form->round_amount($grossamount, 2),
2
);
d319704a Moritz Bunkus
# format amounts
c0cc8bb2 Rolf Fluehmann
$form->{rounding} = $form->format_amount($myconfig, $form->{rounding}, 2);
d9c9bc22 Moritz Bunkus
$form->{quototal} = $form->{ordtotal} = $form->format_amount($myconfig, $form->{ordtotal}, 2);
d319704a Moritz Bunkus
de009a3f Moritz Bunkus
$form->set_payment_options($myconfig, $form->{$form->{type} =~ /_quotation/ ? 'quodate' : 'orddate'}, $form->{type});
54e4131e Moritz Bunkus
d319704a Moritz Bunkus
$form->{username} = $myconfig->{name};

01591fa7 Bernd Bleßmann
$form->{department} = SL::DB::Manager::Department->find_by(id => $form->{department_id})->description if $form->{department_id};
03d3d025 Bernd Bleßmann
$form->{delivery_term} = SL::DB::Manager::DeliveryTerm->find_by(id => $form->{delivery_term_id} || undef);
2134f89a Moritz Bunkus
$form->{delivery_term}->description_long($form->{delivery_term}->translated_attribute('description_long', $form->{language_id})) if $form->{delivery_term} && $form->{language_id};
03d3d025 Bernd Bleßmann
aa76c8a2 Bernd Bleßmann
$form->{order} = SL::DB::Manager::Order->find_by(id => $form->{id}) if $form->{id};
219d88ab Martin Helmling
$form->{$_} = $form->format_amount($myconfig, $form->{$_}, 2) for @separate_totals;
dcb37275 Sven Schöling
d319704a Moritz Bunkus
$main::lxdebug->leave_sub();
}

1;
66022cbd Sven Schöling
__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