From: Stephan Köhler Date: Mon, 12 Dec 2005 15:53:06 +0000 (+0000) Subject: Merge von 681 aus unstable: Sammelauftraege + Bugfix X-Git-Tag: release-2.2.0~75 X-Git-Url: http://wagnertech.de/git?a=commitdiff_plain;h=626e02403cbcee241b2be41f3c2d827663864523;p=kivitendo-erp.git Merge von 681 aus unstable: Sammelauftraege + Bugfix Feature Sammelauftraege - Kann jetzt mehrere Auftraege in der Suchmaske anwaehlen und zusammenfassen zu einem Sammelauftrag. - Kann diesen Sammelauftrag als neu speichern und eine Rechnung dafuer ausstellen. - Kann die folgende Rechnung wiederum speichern und buchen. - Wird Sammelauftraege mit nur einem Auftrag abfangen und wie gehabt als einzelnen behandeln. - Wird soviele Daten wie moeglich im Header des Sammelauftrags beibehalten, wobei customer, ordnumber und transdate eindeutig sein m uessen. - transdate und ordnumber werden bei Bedarf ueberschrieben, nicht eindeutiger customer wird mit Fehlermeldung quittiert Zusaetzlich: - Bugfix in Form::get_exchangerate, genauso gefixt wie in Form::check_exchangerate - neue Routine OE:close_orders, die genau das tut. - Der Versuch oe::edit ohne eine id aufzurufen wird nun auf oe::add umgeleitet --- diff --git a/SL/Form.pm b/SL/Form.pm index 867f946c6..5fb58aff2 100644 --- a/SL/Form.pm +++ b/SL/Form.pm @@ -1,4 +1,4 @@ -#===================================================================== +#==================================================================== # LX-Office ERP # Copyright (C) 2004 # Based on SQL-Ledger Version 2.1.9 @@ -1277,6 +1277,11 @@ sub get_exchangerate { $main::lxdebug->enter_sub(); my ($self, $dbh, $curr, $transdate, $fld) = @_; + + unless ($transdate) { + $main::lxdebug->leave_sub(); + return ""; + } my $query = qq|SELECT e.$fld FROM exchangerate e WHERE e.curr = '$curr' diff --git a/SL/OE.pm b/SL/OE.pm index cf20a1b07..4c65c0545 100644 --- a/SL/OE.pm +++ b/SL/OE.pm @@ -1,4 +1,4 @@ -#===================================================================== +#==================================================================== # LX-Office ERP # Copyright (C) 2004 # Based on SQL-Ledger Version 2.1.9 @@ -459,6 +459,27 @@ Message: $form->{message}\r| if $form->{message}; return $rc; } +# this function closes multiple orders given in $form->{ordnumber_#}. +# use this for multiple orders that don't have to be saved back +# single orders should use OE::save instead. +sub close_orders { + $main::lxdebug->enter_sub(); + + my ($self, $myconfig ,$form) = @_; + + # get ids from $form + map { push @ids, $form->{"ordnumber_$_"} if $form->{"ordnumber_$_"} } (1 .. $form->{rowcount}); + + my $dbh = $form->dbconnect($myconfig); + $query = qq|UPDATE oe SET + closed = TRUE + WHERE ordnumber IN (|.join(', ', map{ $dbh->quote($_) }@ids).qq|)|; + $dbh->do($query) || $form->dberror($query); + $dbh->disconnect; + + $main::lxdebug->leave_sub(); +} + sub delete { $main::lxdebug->enter_sub(); @@ -539,6 +560,15 @@ sub retrieve { my $query; + # translate the ids (given by id_# and trans_id_#) into one array of ids, so we can join them later + map { push @ids, $form->{"trans_id_$_"} if ($form->{"id_$_"}) } (1 .. $form->{"rowcount"}); + + # if called in multi id mode, and still only got one id, switch back to single id + if ($form->{"rowcount"} and $#ids == 0) { + $form->{"id"} = $ids[0]; + undef @ids; + } + if ($form->{id}) { # get default accounts and last order number @@ -578,10 +608,13 @@ sub retrieve { ($form->{currency}) = split /:/, $form->{currencies}; - if ($form->{id}) { + if ($form->{id} or @ids) { - # retrieve order - $query = qq|SELECT o.cp_id,o.ordnumber, o.transdate, o.reqdate, + # retrieve order for single id + # NOTE: this query is intended to fetch all information only ONCE. + # so if any of these infos is important (or even different) for any item, + # it will be killed out and then has to be fetched from the item scope query further down + $query = qq|SELECT o.cp_id, o.ordnumber, o.transdate, o.reqdate, o.taxincluded, o.shippingpoint, o.shipvia, o.notes, o.intnotes, o.curr AS currency, e.name AS employee, o.employee_id, o.$form->{vc}_id, cv.name AS $form->{vc}, o.amount AS invtotal, @@ -591,47 +624,67 @@ sub retrieve { JOIN $form->{vc} cv ON (o.$form->{vc}_id = cv.id) LEFT JOIN employee e ON (o.employee_id = e.id) LEFT JOIN department d ON (o.department_id = d.id) - WHERE o.id = $form->{id}|; - $sth = $dbh->prepare($query); - $sth->execute || $form->dberror($query); + |. ($form->{id} + ? qq|WHERE o.id = $form->{id}| + : qq|WHERE o.id IN (|.join(', ', @ids).qq|)| + ); - $ref = $sth->fetchrow_hashref(NAME_lc); - map { $form->{$_} = $ref->{$_} } keys %$ref; - $sth->finish; +#$main::lxdebug->message(0, $query); - $query = qq|SELECT s.* FROM shipto s - WHERE s.trans_id = $form->{id}|; $sth = $dbh->prepare($query); $sth->execute || $form->dberror($query); $ref = $sth->fetchrow_hashref(NAME_lc); map { $form->{$_} = $ref->{$_} } keys %$ref; - $sth->finish; - - # get printed, emailed and queued - $query = qq|SELECT s.printed, s.emailed, s.spoolfile, s.formname - FROM status s - WHERE s.trans_id = $form->{id}|; - $sth = $dbh->prepare($query); - $sth->execute || $form->dberror($query); + # destroy all entries for multiple ids that yield different information while ($ref = $sth->fetchrow_hashref(NAME_lc)) { - $form->{printed} .= "$ref->{formname} " if $ref->{printed}; - $form->{emailed} .= "$ref->{formname} " if $ref->{emailed}; - $form->{queued} .= "$ref->{formname} $ref->{spoolfile} " - if $ref->{spoolfile}; + map { undef $form->{$_} if ($ref->{$_} ne $form->{$_}) } keys %$ref; } + + # if not given, fill transdate with current_date + $form->{transdate} = $form->current_date($myconfig) unless $form->{transdate}; + $sth->finish; - map { $form->{$_} =~ s/ +$//g } qw(printed emailed queued); + + # shipto and pinted/mailed/queued status makes only sense for single id retrieve + if (!@ids) { + $query = qq|SELECT s.* FROM shipto s + WHERE s.trans_id = $form->{id}|; + $sth = $dbh->prepare($query); + $sth->execute || $form->dberror($query); + + $ref = $sth->fetchrow_hashref(NAME_lc); + map { $form->{$_} = $ref->{$_} } keys %$ref; + $sth->finish; + + # get printed, emailed and queued + $query = qq|SELECT s.printed, s.emailed, s.spoolfile, s.formname + FROM status s + WHERE s.trans_id = $form->{id}|; + $sth = $dbh->prepare($query); + $sth->execute || $form->dberror($query); + + while ($ref = $sth->fetchrow_hashref(NAME_lc)) { + $form->{printed} .= "$ref->{formname} " if $ref->{printed}; + $form->{emailed} .= "$ref->{formname} " if $ref->{emailed}; + $form->{queued} .= "$ref->{formname} $ref->{spoolfile} " if $ref->{spoolfile}; + } + $sth->finish; + map { $form->{$_} =~ s/ +$//g } qw(printed emailed queued); + } # if !@ids my %oid = ('Pg' => 'oid', 'Oracle' => 'rowid'); # retrieve individual items + # this query looks up all information about the items + # stuff different from the whole will not be overwritten, but saved with a suffix. $query = qq|SELECT o.id AS orderitems_id, c1.accno AS inventory_accno, c2.accno AS income_accno, c3.accno AS expense_accno, + oe.ordnumber, oe.transdate, oe.cusordnumber, p.partnumber, p.assembly, o.description, o.qty, o.sellprice, o.parts_id AS id, o.unit, o.discount, p.bin, p.notes AS partnotes, o.reqdate, o.project_id, o.serialnumber, o.ship, @@ -639,13 +692,18 @@ sub retrieve { 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 (p.inventory_accno_id = c1.id) LEFT JOIN chart c2 ON (p.income_accno_id = c2.id) LEFT JOIN chart c3 ON (p.expense_accno_id = c3.id) LEFT JOIN project pr ON (o.project_id = pr.id) LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) - WHERE o.trans_id = $form->{id} + |. ($form->{id} + ? qq|WHERE o.trans_id = $form->{id}| + : qq|WHERE o.trans_id IN (|.join(", ", @ids).qq|)| + ).qq| ORDER BY o.$oid{$myconfig->{dbdriver}}|; + $sth = $dbh->prepare($query); $sth->execute || $form->dberror($query); diff --git a/bin/mozilla/io.pl b/bin/mozilla/io.pl index ae8f500bb..d4eabdf79 100644 --- a/bin/mozilla/io.pl +++ b/bin/mozilla/io.pl @@ -357,6 +357,9 @@ sub display_row { + + + |; diff --git a/bin/mozilla/oe.pl b/bin/mozilla/oe.pl index cf6bd40b2..dbb74a9f9 100644 --- a/bin/mozilla/oe.pl +++ b/bin/mozilla/oe.pl @@ -1,4 +1,4 @@ -#===================================================================== +# #===================================================================== # LX-Office ERP # Copyright (C) 2004 # Based on SQL-Ledger Version 2.1.9 @@ -77,6 +77,22 @@ sub add { sub edit { $lxdebug->enter_sub(); + # editing without stuff to edit? try adding it first + if ($form->{rowcount}) { + map {$id++ if $form->{"id_$_"}} (1 .. $form->{rowcount}); + if (!$id) { + # reset rowcount + undef $form->{rowcount}; + &add; + return; + } + } else { + if (!$form->{id}) { + &add; + return; + } + } + if ($form->{type} eq 'purchase_order') { $form->{title} = $locale->text('Edit Purchase Order'); $form->{heading} = $locale->text('Purchase Order'); @@ -121,6 +137,14 @@ sub order_links { OE->retrieve(\%myconfig, \%$form); + # if multiple rowcounts (== collective order) then check if the + # there were more than one customer (in that case OE::retrieve removes + # the content from the field) + if ($form->{rowcount} && $form->{type} eq 'sales_order' && $form->{customer} eq '') { +# $main::lxdebug->message(0, "Detected Edit order with concurrent customers"); + $form->error($locale->text('Collective Orders only work for orders from one customer!')); + } + $taxincluded = $form->{taxincluded}; $form->{shipto} = 1 if $form->{id}; @@ -197,40 +221,20 @@ sub prepare_order { $form->{media} = "screen"; $form->{formname} = $form->{type}; - if ($form->{id}) { - map { $form->{$_} =~ s/\"/"/g } qw(ordnumber quonumber shippingpoint shipvia notes intnotes shiptoname shiptostreet shiptozipcode shiptocity shiptocountry shiptocontact); foreach $ref (@{ $form->{form_details} }) { - $i++; - map { $form->{"${_}_$i"} = $ref->{$_} } keys %{$ref}; - $form->{"discount_$i"} = - $form->format_amount(\%myconfig, $form->{"discount_$i"} * 100); + $form->{rowcount} = ++$i; - ($dec) = ($form->{"sellprice_$i"} =~ /\.(\d+)/); - $dec = length $dec; - $decimalplaces = ($dec > 2) ? $dec : 2; - - $form->{"sellprice_$i"} = - $form->format_amount(\%myconfig, $form->{"sellprice_$i"}, - $decimalplaces); - - (my $dec_qty) = ($form->{"qty_$i"} =~ /\.(\d+)/); - $dec_qty = length $dec_qty; - - $form->{"qty_$i"} = $form->format_amount(\%myconfig, $form->{"qty_$i"}, $dec_qty); - - map { $form->{"${_}_$i"} =~ s/\"/"/g } - qw(partnumber description unit); - $form->{rowcount} = $i; + map { $form->{"${_}_$i"} = $ref->{$_} } keys %{$ref}; } - } elsif ($form->{rowcount}) { + for my $i (1 .. $form->{rowcount}) { $form->{"discount_$i"} = $form->format_amount(\%myconfig, $form->{"discount_$i"} * 100); - ($dec) = ($form->{"sellprice_$i"} =~ /\.(\d+)/); + ($dec) = ($form->{"sellprice_$i"} =~ /\.(\d+)/); $dec = length $dec; $decimalplaces = ($dec > 2) ? $dec : 2; @@ -245,7 +249,6 @@ sub prepare_order { map { $form->{"${_}_$i"} =~ s/\"/"/g } qw(partnumber description unit); } - } $lxdebug->leave_sub(); } @@ -860,7 +863,16 @@ Bearbeiten des $form->{heading}
. $locale->text('Order') . qq|"> |; } + } elsif ($form->{type} =~ /sales_order$/ && $form->{rowcount}) { + print qq| +
Workflow $form->{heading}
+ + +|; } + if ($form->{menubar}) { require "$form->{path}/menu.pl"; @@ -1312,6 +1324,11 @@ sub orders { } } + # only show checkboxes if gotten here via sales_order form. + if ($form->{type} =~ /sales_order/) { + unshift @column_index, "ids"; + } + if ($form->{l_subtotal} eq 'Y') { $callback .= "&l_subtotal=Y"; $href .= "&l_subtotal=Y"; @@ -1384,6 +1401,8 @@ sub orders { $column_header{employee} = qq|$employee|; + $column_header{ids} = qq||; + if ($form->{ $form->{vc} }) { $option = $locale->text(ucfirst $form->{vc}); $option .= " : $form->{$form->{vc}}"; @@ -1423,6 +1442,7 @@ sub orders { print qq| +
@@ -1443,7 +1463,7 @@ sub orders { |; # add sort and escape callback - $callback = $form->escape($callback . "&sort=$form->{sort}"); + $callback_escaped = $form->escape($callback . "&sort=$form->{sort}"); if (@{ $form->{OE} }) { $sameitem = $form->{OE}->[0]->{ $form->{sort} }; @@ -1455,6 +1475,7 @@ sub orders { $warehouse = $form->escape($form->{warehouse}); foreach $oe (@{ $form->{OE} }) { + $form->{rowcount} = ++$j; if ($form->{l_subtotal} eq 'Y') { if ($sameitem ne $oe->{ $form->{sort} }) { @@ -1483,12 +1504,13 @@ sub orders { $subtotalnetamount += $oe->{netamount}; $subtotalamount += $oe->{amount}; + $column_data{ids} = qq||; $column_data{id} = ""; $column_data{transdate} = ""; $column_data{reqdate} = ""; $column_data{$ordnumber} = - ""; + ""; $column_data{name} = ""; $column_data{employee} = ""; @@ -1546,7 +1568,27 @@ sub orders { -
$form->{title}$oe->{id}$oe->{transdate} $oe->{reqdate} {path}&action=$action&type=$form->{type}&id=$oe->{id}&warehouse=$warehouse&vc=$form->{vc}&login=$form->{login}&password=$form->{password}&callback=$callback>$oe->{$ordnumber}{path}&action=$action&type=$form->{type}&id=$oe->{id}&warehouse=$warehouse&vc=$form->{vc}&login=$form->{login}&password=$form->{password}&callback=$callback_escaped>$oe->{$ordnumber}$oe->{name}$oe->{employee} 

+|; + +# multiple invoice edit button only if gotten there via sales_order form. + +if ($form->{type} =~ /sales_order/) { +print qq| + + + + + + + + + + |; +} + +print qq| +

{script}> @@ -1751,8 +1793,10 @@ sub invoice { $lxdebug->enter_sub(); if ($form->{type} =~ /_order$/) { - $form->isblank("ordnumber", $locale->text('Order Number missing!')); - $form->isblank("transdate", $locale->text('Order Date missing!')); + # these checks only apply if the items don't bring their own ordnumbers/transdates. + # The if clause ensures that by searching for empty ordnumber_#/transdate_# fields. + $form->isblank("ordnumber", $locale->text('Order Number missing!')) if ( +{ map { $form->{"ordnumber_$_"}, 1 } ( 1 .. $form->{rowcount}-1 ) }->{''} ); + $form->isblank("transdate", $locale->text('Order Date missing!')) if ( +{ map { $form->{"transdate_$_"}, 1 } ( 1 .. $form->{rowcount}-1 ) }->{''} ); } else { $form->isblank("quonumber", $locale->text('Quotation Number missing!')); @@ -1788,7 +1832,15 @@ sub invoice { # close orders/quotations $form->{closed} = 1; - OE->save(\%myconfig, \%$form); + + # save order iff one ordnumber has been given + # if not it's most likely a collective order, which can't be saved back + # so they just have to be closed + if ($form->{ordnumber} ne '') { + OE->save(\%myconfig, \%$form); + } else { + OE->close_orders(\%myconfig, \%$form); + } $form->{transdate} = $form->{invdate} = $form->current_date(\%myconfig); $form->{duedate} = diff --git a/locale/de/admin b/locale/de/admin index 759d6c865..d352367ad 100644 --- a/locale/de/admin +++ b/locale/de/admin @@ -39,6 +39,7 @@ $self{texts} = { 'Hostname missing!' => 'Computername fehlt!', 'Incorrect Password!' => 'Ungültiges Passwort!', 'Language' => 'Sprache', + 'Leave host and port field empty unless you want to make a remote connection.' => 'Leave host and port field empty unless you want to make a remote connection.', 'Lock System' => 'System sperren', 'Lockfile created!' => 'System gesperrt!', 'Lockfile removed!' => 'System entsperrt!', @@ -70,8 +71,8 @@ $self{texts} = { 'Templates' => 'Vorlagen', 'The following Datasets are not in use and can be deleted' => 'Die folgenden Datenbanken sind nicht in Verwendung und können gelöscht werden', 'The following Datasets need to be updated' => 'Folgende Datenbanken müssen aktualisiert werden', - 'This is a preliminary check for existing sources. Nothing will be created or deleted at this stage!' => 'In diesem Schritt werden bestehende Datenbanken gesucht. Es werden noch keine Änderungen vorgenommen!', - 'To add a user to a group edit a name, change the login name and save. A new user with the same variables will then be saved under the new login name.' => 'Um einer Gruppe einen neuen Benutzer hinzuzufügen, ändern und speichern Sie am einfachsten einen bestehenden Zugriffsnamen. Unter dem neuen Namen wird dann ein Benutzer mit denselben Einstellungen angelegt.', + 'This is a preliminary check for existing sources. Nothing will be created or deleted at this stage!' => 'This is a preliminary check for existing sources. Nothing will be created or deleted at this stage!', + 'To add a user to a group edit a name, change the login name and save. A new user with the same variables will then be saved under the new login name.' => 'To add a user to a group edit a name, change the login name and save. A new user with the same variables will then be saved under the new login name.', 'Unlock System' => 'System entsperren', 'Update Dataset' => 'Datenbank aktualisieren', 'Use Templates' => 'benutze Vorlagen', @@ -81,6 +82,7 @@ $self{texts} = { 'Ust-IDNr' => 'USt-IdNr.', 'Version' => 'Version', 'WEBDAV-Zugriff' => 'WEBDAV-Zugriff', + 'You must enter a host and port for local and remote connections!' => 'You must enter a host and port for local and remote connections!', 'does not exist' => 'existiert nicht', 'is already a member!' => 'ist bereits ein Mitglied!', 'localhost' => 'lokaler Rechner', diff --git a/locale/de/all b/locale/de/all index 2f869d192..691288b8f 100644 --- a/locale/de/all +++ b/locale/de/all @@ -174,6 +174,7 @@ $self{texts} = { 'Closed' => 'Geschlossen', 'Code' => 'kode', 'Code missing!' => 'kode fehlt!', + 'Collective Orders only work for orders from one customer!' => 'Sammelaufträge funktionieren nur für Aufträge von einem Kunden!', 'Comment' => 'Kommentar', 'Company' => 'Firma', 'Company Name' => 'Firmenname', @@ -429,6 +430,7 @@ $self{texts} = { 'Last Sales Quotation Number' => 'Letzte Angebotsnummer', 'Last Service Number' => 'Letzte Dienstleistungsnr.', 'Last Vendor Number' => 'Letzte Lieferantennummer', + 'Leave host and port field empty unless you want to make a remote connection.' => '', 'Liability' => 'Passiva', 'License' => 'Lizenz', 'License key' => 'Lizenzschlüssel', @@ -707,8 +709,10 @@ $self{texts} = { 'The following Datasets are not in use and can be deleted' => 'Die folgenden Datenbanken sind nicht in Verwendung und können gelöscht werden', 'The following Datasets need to be updated' => 'Folgende Datenbanken müssen aktualisiert werden', 'The licensing module has been deactivated in lx-erp.conf.' => 'Das Lizenzverwaltungsmodul wurde in lx-erp.conf deaktiviert.', + 'This is a preliminary check for existing sources. Nothing will be created or deleted at this stage!' => '', 'Title' => 'Titel', 'To' => 'An', + 'To add a user to a group edit a name, change the login name and save. A new user with the same variables will then be saved under the new login name.' => '', 'Top 100' => 'Top 100', 'Top 100 hinzufuegen' => 'Top 100 hinzufügen', 'Top Level' => 'Hauptartikelbezeichnung', @@ -776,6 +780,7 @@ $self{texts} = { 'Yes' => 'Ja', 'You are logged out!' => 'Auf Wiedersehen!', 'You did not enter a name!' => 'Sie haben keinen Namen eingegeben!', + 'You must enter a host and port for local and remote connections!' => '', 'Zeitraum' => 'Zeitraum', 'Zipcode' => 'PLZ', 'accrual' => 'Bilanzierung (Soll-Versteuerung)', diff --git a/locale/en_GB/all b/locale/en_GB/all index e45542a0c..bed4415c8 100644 --- a/locale/en_GB/all +++ b/locale/en_GB/all @@ -114,6 +114,7 @@ $self{texts} = { 'Click on login name to edit!' => '', 'Close Books up to' => '', 'Closed' => '', + 'Collective Orders only work for orders from one customer!' => '', 'Company' => '', 'Compare to' => '', 'Confirm!' => '',