X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FOE.pm;h=974a1a1bdcedc935e7cdc6ad82116f348a610a2f;hb=b9cd11d78faef7815e435c11aa6a12793e9cb9c9;hp=c82a3322e731c7c6c36a3a7148aefd987577d303;hpb=ea4101ecf18d6fd6e8804db16c4f871a56dda441;p=kivitendo-erp.git diff --git a/SL/OE.pm b/SL/OE.pm index c82a3322e..974a1a1bd 100644 --- a/SL/OE.pm +++ b/SL/OE.pm @@ -25,7 +25,8 @@ # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1335, USA. #====================================================================== # # Order entry module @@ -35,7 +36,6 @@ package OE; use List::Util qw(max first); -use YAML; use SL::AM; use SL::Common; @@ -52,6 +52,7 @@ use SL::IC; use SL::TransNumber; use SL::Util qw(trim); use SL::DB; +use SL::YAML; use Text::ParseWords; use strict; @@ -99,6 +100,12 @@ sub transactions { 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' + 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) + WHERE rl1.from_table = 'oe' AND rl2.to_table = 'ar' AND rl3.to_table = 'ar' ) rl LEFT JOIN ar ON ar.id = rl.to_id @@ -114,8 +121,10 @@ sub transactions { qq| o.closed, o.delivered, o.quonumber, o.cusordnumber, o.shippingpoint, o.shipvia, | . qq| o.transaction_description, | . qq| o.marge_total, o.marge_percent, | . + qq| o.exchangerate, | . qq| o.itime::DATE AS insertdate, | . - qq| ex.$rate AS exchangerate, | . + qq| department.description as department, | . + qq| ex.$rate AS daily_exchangerate, | . qq| pt.description AS payment_terms, | . qq| pr.projectnumber AS globalprojectnumber, | . qq| e.name AS employee, s.name AS salesman, | . @@ -133,15 +142,14 @@ sub transactions { qq|LEFT JOIN project pr ON (o.globalproject_id = pr.id) | . qq|LEFT JOIN payment_terms pt ON (pt.id = o.payment_id)| . qq|LEFT JOIN tax_zones tz ON (o.taxzone_id = tz.id) | . + qq|LEFT JOIN department ON (o.department_id = department.id) | . qq|$periodic_invoices_joins | . qq|WHERE (o.quotation = ?) |; push(@values, $quotation); - my ($null, $split_department_id) = split /--/, $form->{department}; - my $department_id = $form->{department_id} || $split_department_id; - if ($department_id) { + if ($form->{department_id}) { $query .= qq| AND o.department_id = ?|; - push(@values, $department_id); + push(@values, $form->{department_id}); } if ($form->{"project_id"}) { @@ -182,7 +190,7 @@ SQL push(@values, (like($form->{"cp_name"}))x2); } - if (!$main::auth->assert('sales_all_edit', 1)) { + if ( !(($vc eq 'customer' && $main::auth->assert('sales_all_edit', 1)) || ($vc eq 'vendor' && $main::auth->assert('purchase_all_edit', 1))) ) { $query .= " AND o.employee_id = (select id from employee where login= ?)"; push @values, $::myconfig{login}; } @@ -354,6 +362,7 @@ SQL "insertdate" => "o.itime", "taxzone" => "tz.description", "payment_terms" => "pt.description", + "department" => "department.description", ); if ($form->{sort} && grep($form->{sort}, keys(%allowed_sort_columns))) { $sortorder = $allowed_sort_columns{$form->{sort}} . " ${sortdir}" . ", o.itime ${sortdir}"; @@ -369,9 +378,15 @@ SQL while (my $ref = $sth->fetchrow_hashref("NAME_lc")) { $ref->{billed_amount} = $billed_amount{$ref->{id}}; $ref->{billed_netamount} = $billed_netamount{$ref->{id}}; - $ref->{remaining_amount} = $ref->{amount} - $ref->{billed_amount}; - $ref->{remaining_netamount} = $ref->{netamount} - $ref->{billed_netamount}; - $ref->{exchangerate} = 1 unless $ref->{exchangerate}; + 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}; + } + $ref->{exchangerate} ||= $ref->{daily_exchangerate}; + $ref->{exchangerate} ||= 1; push @{ $form->{OE} }, $ref if $ref->{id} != $id{ $ref->{id} }; $id{ $ref->{id} } = $ref->{id}; } @@ -597,6 +612,9 @@ sub _save { require SL::DB::Customer; my $customer = SL::DB::Manager::Customer->find_by(id => $form->{customer_id}); die "Can't find customer" unless $customer; + 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}); + my $new_project = SL::DB::Project->new( projectnumber => $form->{ordnumber}, description => $customer->name, @@ -607,7 +625,7 @@ sub _save { ); $new_project->save; $form->{"globalproject_id"} = $new_project->id; - }; + } CVar->get_non_editable_ic_cvars(form => $form, dbh => $dbh, @@ -721,8 +739,6 @@ SQL my $quotation = $form->{type} =~ /_order$/ ? 'f' : 't'; - ($null, $form->{department_id}) = split(/--/, $form->{department}) if $form->{department}; - # save OE record $query = qq|UPDATE oe SET @@ -819,7 +835,7 @@ sub save_periodic_invoices_config { return if !$params{oe_id}; - my $config = $params{config_yaml} ? YAML::Load($params{config_yaml}) : undef; + my $config = $params{config_yaml} ? SL::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}) @@ -839,7 +855,7 @@ sub load_periodic_invoice_config { if ($config_obj) { 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 print printer_id copies direct_debit send_email email_recipient_contact_id email_recipient_address email_sender email_subject email_body) }; - $form->{periodic_invoices_config} = YAML::Dump($config); + $form->{periodic_invoices_config} = SL::YAML::Dump($config); } } } @@ -961,7 +977,8 @@ sub _retrieve { $form->{useasnew} = 1 if $is_collective_order == 1; if (!$form->{id}) { - my $extra_days = $form->{type} eq 'sales_quotation' ? $::instance_conf->get_reqdate_interval : 1; + 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; $form->{reqdate} = DateTime->today_local->next_workday(extra_days => $extra_days)->to_kivitendo; $form->{transdate} = DateTime->today_local->to_kivitendo; } @@ -1054,15 +1071,14 @@ sub _retrieve { $sth = prepare_execute_query($form, $dbh, $query, $form->{id}); $ref = $sth->fetchrow_hashref("NAME_lc"); - delete($ref->{id}); - map { $form->{$_} = $ref->{$_} } keys %$ref; + $form->{$_} = $ref->{$_} for grep { m{^shipto(?!_id$)} } keys %$ref; $sth->finish; - if ($form->{shipto_id}) { + if ($ref->{shipto_id}) { my $cvars = CVar->get_custom_variables( dbh => $dbh, module => 'ShipTo', - trans_id => $form->{shipto_id}, + trans_id => $ref->{shipto_id}, ); $form->{"shiptocvar_$_->{name}"} = $_->{value} for @{ $cvars }; } @@ -1083,6 +1099,7 @@ sub _retrieve { my $transdate = $form->{transdate} ? $dbh->quote($form->{transdate}) : "current_date"; $form->{taxzone_id} = 0 unless ($form->{taxzone_id}); + unshift @values, ($form->{taxzone_id}) x 2; # retrieve individual items # this query looks up all information about the items @@ -1093,8 +1110,9 @@ sub _retrieve { 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, 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, + p.partnumber, p.part_type, p.listprice, o.description, o.qty, + p.classification_id, + o.sellprice, o.parts_id AS id, o.unit, o.discount, p.notes AS partnotes, p.part_type, 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, o.active_price_source, o.active_discount_source, @@ -1104,8 +1122,8 @@ sub _retrieve { 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) - LEFT JOIN chart c2 ON ((SELECT tc.income_accno_id FROM taxzone_charts tc WHERE tc.taxzone_id = '$form->{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 = '$form->{taxzone_id}' and tc.buchungsgruppen_id = p.buchungsgruppen_id) = c3.id) + 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) LEFT JOIN project pr ON (o.project_id = pr.id) LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) | . ($form->{id} @@ -1126,10 +1144,10 @@ sub _retrieve { map { $ref->{"ic_cvar_$_->{name}"} = $_->{value} } @{ $cvars }; # Handle accounts. - if (!$ref->{"part_inventory_accno_id"}) { + if (!$ref->{"part_type"} eq 'part') { map({ delete($ref->{$_}); } qw(inventory_accno inventory_new_chart inventory_valid)); } - delete($ref->{"part_inventory_accno_id"}); + # delete($ref->{"part_inventory_accno_id"}); # in collective order, copy global ordnumber, transdate, cusordnumber into item scope # unless already present there @@ -1179,8 +1197,9 @@ sub _retrieve { # get tax rates and description my $accno_id = ($form->{vc} eq "customer") ? $ref->{income_accno} : $ref->{expense_accno}; $query = - qq|SELECT c.accno, t.taxdescription, t.rate, t.taxnumber | . - qq|FROM tax t LEFT JOIN chart c on (c.id = t.chart_id) | . + qq|SELECT c.accno, t.taxdescription, t.rate, t.id as tax_id, c.accno as taxnumber | . + qq|FROM tax t | . + qq|LEFT JOIN chart c on (c.id = t.chart_id) | . 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) | . @@ -1198,6 +1217,7 @@ sub _retrieve { $form->{"$ptr->{accno}_rate"} = $ptr->{rate}; $form->{"$ptr->{accno}_description"} = $ptr->{taxdescription}; $form->{"$ptr->{accno}_taxnumber"} = $ptr->{taxnumber}; + $form->{"$ptr->{accno}_tax_id"} = $ptr->{tax_id}; $form->{taxaccounts} .= "$ptr->{accno} "; } @@ -1281,8 +1301,7 @@ sub order_details { push(@project_ids, $form->{"globalproject_id"}) if ($form->{"globalproject_id"}); - $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS', - 'departments' => 'ALL_DEPARTMENTS'); + $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS'); my %price_factors; foreach my $pfac (@{ $form->{ALL_PRICE_FACTORS} }) { @@ -1291,13 +1310,6 @@ sub order_details { $pfac->{formatted_factor} = $form->format_amount($myconfig, $pfac->{factor}); } - # lookup department - foreach my $dept (@{ $form->{ALL_DEPARTMENTS} }) { - next unless $dept->{id} eq $form->{department_id}; - $form->{department} = $dept->{description}; - last; - } - # sort items by partsgroup for $i (1 .. $form->{rowcount}) { $partsgroup = ""; @@ -1330,6 +1342,7 @@ sub order_details { # 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; + my @separate_totals = qw(non_separate_subtotal); $form->{TEMPLATE_ARRAYS} = { }; @@ -1436,6 +1449,17 @@ sub order_details { push @{ $form->{TEMPLATE_ARRAYS}->{discount_nofmt} }, ($discount != 0) ? $discount * -1 : ''; push @{ $form->{TEMPLATE_ARRAYS}->{p_discount} }, $form->{"discount_$i"}; + 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; + } + $form->{ordtotal} += $linetotal; $form->{nodiscount_total} += $nodiscount_linetotal; $form->{discount_total} += $discount; @@ -1504,15 +1528,15 @@ sub order_details { $tax_rate = $taxrate * 100; push(@{ $form->{TEMPLATE_ARRAYS}->{tax_rate} }, qq|$tax_rate|); - if ($form->{"assembly_$i"}) { + if ($form->{"part_type_$i"} eq 'assembly') { $sameitem = ""; # get parts and push them onto the stack my $sortorder = ""; if ($form->{groupitems}) { - $sortorder = qq|ORDER BY pg.partsgroup, a.oid|; + $sortorder = qq|ORDER BY pg.partsgroup, a.position|; } else { - $sortorder = qq|ORDER BY a.oid|; + $sortorder = qq|ORDER BY a.position|; } $query = qq|SELECT p.partnumber, p.description, p.unit, a.qty, | . @@ -1571,10 +1595,13 @@ sub order_details { 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}->{taxnumber} }, $form->{"${item}_taxnumber"}); + push(@{ $form->{TEMPLATE_ARRAYS}->{tax_id} }, $form->{"${item}_tax_id"}); - my $tax_obj = SL::DB::Manager::Tax->find_by(taxnumber => $form->{"${item}_taxnumber"}); - 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{%}); + 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{%}); + } } $form->{nodiscount_subtotal} = $form->format_amount($myconfig, $form->{nodiscount_total}, 2); @@ -1605,27 +1632,16 @@ sub order_details { $form->{username} = $myconfig->{name}; + $form->{department} = SL::DB::Manager::Department->find_by(id => $form->{department_id})->description if $form->{department_id}; $form->{delivery_term} = SL::DB::Manager::DeliveryTerm->find_by(id => $form->{delivery_term_id} || undef); $form->{delivery_term}->description_long($form->{delivery_term}->translated_attribute('description_long', $form->{language_id})) if $form->{delivery_term} && $form->{language_id}; $form->{order} = SL::DB::Manager::Order->find_by(id => $form->{id}) if $form->{id}; + $form->{$_} = $form->format_amount($myconfig, $form->{$_}, 2) for @separate_totals; $main::lxdebug->leave_sub(); } -sub project_description { - $main::lxdebug->enter_sub(); - - my ($self, $dbh, $id) = @_; - - my $query = qq|SELECT description FROM project WHERE id = ?|; - my ($value) = selectrow_query($main::form, $dbh, $query, $id); - - $main::lxdebug->leave_sub(); - - return $value; -} - 1; __END__