From: Jan Büren Date: Thu, 19 Mar 2009 09:09:07 +0000 (+0000) Subject: Erzeugnisse fertigen, erste Version fertiggestellt. Bugzilla noch oeffnen fuer rueckv... X-Git-Tag: release-2.6.0beta2~131 X-Git-Url: http://wagnertech.de/git?a=commitdiff_plain;h=4f63ea874f629459e1a73643595ab5e23e38e7f0;p=kivitendo-erp.git Erzeugnisse fertigen, erste Version fertiggestellt. Bugzilla noch oeffnen fuer rueckverfolgbarkeit - Ferner offen, Lagerplaetze und verschiedene Lager --- diff --git a/SL/WH.pm b/SL/WH.pm index 6f4319919..97b5a41fe 100644 --- a/SL/WH.pm +++ b/SL/WH.pm @@ -37,7 +37,8 @@ package WH; use SL::AM; use SL::DBUtils; use SL::Form; - +use warnings; +#use strict; sub transfer { $main::lxdebug->enter_sub(); @@ -122,6 +123,103 @@ sub transfer { $main::lxdebug->leave_sub(); } +# +# Testfall: +# + +sub transfer_assembly { + $main::lxdebug->enter_sub(); + + my $self = shift; + my %params = @_; + Common::check_params(\%params, qw(assembly_id dst_warehouse_id login qty unit dst_bin_id chargenumber comment)); + +# my $maxcreate=WH->check_assembly_max_create(assembly_id =>$params{'assembly_id'}, dbh => $my_dbh); + + my $myconfig = \%main::myconfig; + my $form = $main::form; + my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig); + + +# Ablauferklärung +# +# ... Standard-Check oben Ende. Hier die eigentliche SQL-Abfrage +# select parts_id,qty from assembly where id=1064; +# + + my $query = qq|select parts_id,qty from assembly where id = ?|; + my $sth_part_qty_assembly = prepare_execute_query($form, $dbh, $query, $params{assembly_id}); + +# Hier wird das prepared Statement für die Schleife über alle Lagerplätze vorbereitet + my $transferPartSQL = qq|INSERT INTO inventory (parts_id, warehouse_id, bin_id, chargenumber, comment, employee_id, qty, trans_id, trans_type_id) + VALUES (?, ?, ?, ?, ?,(SELECT id FROM employee WHERE login = ?), ?, nextval('id'), + (SELECT id FROM transfer_type WHERE direction = 'out' AND description = 'used'))|; + my $sthTransferPartSQL = prepare_query($form, $dbh, $transferPartSQL); + + my $kannNichtFertigen =""; # der return-string für die fehlermeldung inkl. welche waren zum fertigen noch fehlen + + while (my $hash_ref = $sth_part_qty_assembly->fetchrow_hashref()) { # Schleife für $query=select parts_id,qty from assembly + + my $partsQTY = $hash_ref->{qty} * $params{qty}; # benötigte teile * anzahl erzeugnisse + my $currentPart_ID = $hash_ref->{parts_id}; + + # Überprüfen, ob diese Anzahl gefertigt werden kann + my $max_parts = get_max_qty_parts($self, parts_id => $currentPart_ID, warehouse_id => $params{dst_warehouse_id}); #$self angeben, damit die Standardkonvention (Name, Parameter) eingehalten wird + + if ($partsQTY > $max_parts){ + + # Gibt es hier ein Problem mit nicht "escapten" Zeichen? + $kannNichtFertigen .= "Zum Fertigen fehlen:" . abs($partsQTY) . " Stueck der Ware:" . get_part_description($self, parts_id => $currentPart_ID) . ", um das Erzeugnis herzustellen.
"; # Konnte die Menge nicht mit der aktuellen Anzahl der Waren fertigen + } + +# Eine kurze Vorabfrage, um den Lagerplatz und die Chargennummber zu bestimmen +# Offen: Die Summe über alle Lagerplätze wird noch nicht gebildet +# Gelöst: Wir haben vorher schon die Abfrage durchgeführt, ob wir fertigen können. +# Noch besser gelöst: Wir laufen durch alle benötigten Waren zum Fertigen und geben eine Rückmeldung an den Benutzer was noch fehlt +# und lösen den Rest dann so wie bei xplace im Barcode-Programm +# S.a. Kommentar im bin/mozilla-Code mb übernimmt und macht das in ordentlich + + my $tempquery = qq|SELECT SUM(qty), bin_id, chargenumber FROM inventory WHERE warehouse_id = ? AND parts_id = ? GROUP BY bin_id, chargenumber having SUM(qty)>0|; + my $tempsth = prepare_execute_query($form, $dbh, $tempquery, $params{dst_warehouse_id}, $currentPart_ID); + + # Alle Werte zu dem einzelnen Artikel, die wir später auslagern + my $tmpPartsQTY = $partsQTY; + + while (my $temphash_ref = $tempsth->fetchrow_hashref()) { + my $temppart_bin_id = $temphash_ref->{bin_id}; # kann man hier den quelllagerplatz beim verbauen angeben? + my $temppart_chargenumber = $temphash_ref->{chargenumber}; + my $temppart_qty = $temphash_ref->{sum}; + if ($tmpPartsQTY > $temppart_qty) { # wir haben noch mehr waren zum wegbuchen. Wir buchen den kompletten Lagerplatzbestand und zählen die Hilfsvariable runter + $tmpPartsQTY = $tmpPartsQTY - $temppart_qty; + $temppart_qty = $temppart_qty * -1; # beim analyiseren des sql-trace, war dieser wert positiv, wenn * -1 als berechnung in der parameter-übergabe angegeben wird. Dieser Wert IST und BLEIBT positiv!! Hilfe. Liegt das daran, dass dieser Wert aus einem SQL-Statement stammt? + do_statement($form, $sthTransferPartSQL, $transferPartSQL, $currentPart_ID, $params{dst_warehouse_id}, $temppart_bin_id, $temppart_chargenumber, 'Verbraucht für ' . get_part_description($self, parts_id => $params{assembly_id}), $params{login}, $temppart_qty); + + # hier ist noch ein fehler am besten mit definierten erzeugnissen debuggen 02/2009 jb + # idee: ausbuch algorithmus mit rekursion lösen und an- und abschaltbar machen + # das problem könnte sein, dass strict nicht an war und sth global eine andere zuweisung bekam + # auf jeden fall war der internal-server-error nach aktivierung von strict und warnings plus ein paar my-definitionen weg + } else { # okay, wir haben weniger oder gleich Waren die wir wegbuchen müssen, wir können also aufhören + $tmpPartsQTY *=-1; + do_statement($form, $sthTransferPartSQL, $transferPartSQL, $currentPart_ID, $params{dst_warehouse_id}, $temppart_bin_id, $temppart_chargenumber, 'Verbraucht für ' . get_part_description($self, parts_id => $params{assembly_id}), $params{login}, $tmpPartsQTY); + last; # beendet die schleife (springt zum letzten element) + } + } # ende while SELECT SUM(qty), bin_id, chargenumber FROM inventory WHERE warehouse_id + } #ende while select parts_id,qty from assembly where id = ? + if ($kannNichtFertigen) { + return $kannNichtFertigen; + } + + # soweit alles gut. Jetzt noch die wirkliche Lagerbewegung für das Erzeugnis ausführen ... + my $transferAssemblySQL = qq|INSERT INTO inventory (parts_id, warehouse_id, bin_id, chargenumber, comment, employee_id, qty, trans_id, trans_type_id) + VALUES (?, ?, ?, ?, ?, (SELECT id FROM employee WHERE login = ?), ?, nextval('id'), + (SELECT id FROM transfer_type WHERE direction = 'in' AND description = 'stock'))|; + my $sthTransferAssemblySQL = prepare_query($form, $dbh, $transferAssemblySQL); + do_statement($form, $sthTransferAssemblySQL, $transferAssemblySQL, $params{assembly_id}, $params{dst_warehouse_id}, $params{dst_bin_id}, $params{chargenumber}, $params{comment}, $params{login}, $params{qty}); + $dbh->commit(); + + $main::lxdebug->leave_sub(); + return 1; # Alles erfolgreich +} sub get_warehouse_journal { $main::lxdebug->enter_sub(); @@ -515,7 +613,7 @@ sub get_warehouse_report { $sth = prepare_execute_query($form, $dbh, $query, @filter_vars); - while ($ref = $sth->fetchrow_hashref()) { + while (my $ref = $sth->fetchrow_hashref()) { map { $ref->{$_} ||= "" } @all_fields; push @contents, $ref; } @@ -607,6 +705,65 @@ sub get_basic_bin_info { return map { $_->{bin_id} => $_ } @{ $result }; } +# +# Eingabe: Teilenummer, Lagernummer (warehouse) +# Ausgabe: Die maximale Anzahl der Teile in diesem Lager +# +sub get_max_qty_parts { +$main::lxdebug->enter_sub(); + + my $self = shift; + my %params = @_; + + Common::check_params(\%params, qw(parts_id warehouse_id)); #die brauchen wir + + my $myconfig = \%main::myconfig; + my $form = $main::form; + + my $dbh = $params{dbh} || $form->get_standard_dbh(); + + my $query = qq| SELECT SUM(qty), bin_id, chargenumber FROM inventory where parts_id = ? AND warehouse_id = ? GROUP BY bin_id, chargenumber|; + + my $sth_QTY = prepare_execute_query($form, $dbh, $query, ,$params{parts_id}, $params{warehouse_id}); #info: aufruf an DBUtils.pm + + my $max_qty_parts = 0; #Initialisierung mit 0 + while (my $ref = $sth_QTY->fetchrow_hashref()) { # wir laufen über alle chargen und Lagerorte (s.a. SQL-Query oben) + $max_qty_parts += $ref->{sum}; + } + + $main::lxdebug->leave_sub(); + + return $max_qty_parts; +} + +# +# Eingabe: Teilenummer, Lagernummer (warehouse) +# Ausgabe: Die Beschreibung der Ware bzw. Erzeugnis +# +sub get_part_description { +$main::lxdebug->enter_sub(); + + my $self = shift; + my %params = @_; + + Common::check_params(\%params, qw(parts_id )); #die brauchen wir + + my $myconfig = \%main::myconfig; + my $form = $main::form; + + my $dbh = $params{dbh} || $form->get_standard_dbh(); + + my $query = qq| SELECT partnumber, description FROM parts where id = ? |; + + my $sth = prepare_execute_query($form, $dbh, $query, ,$params{parts_id}); #info: aufruf zu DBUtils.pm + + my $ref = $sth->fetchrow_hashref(); + my $part_description = $ref->{partnumber} . " " . $ref->{description}; + + $main::lxdebug->leave_sub(); + + return $part_description; +} 1; diff --git a/bin/mozilla/io.pl b/bin/mozilla/io.pl index 771b29b6e..eb26778e8 100644 --- a/bin/mozilla/io.pl +++ b/bin/mozilla/io.pl @@ -290,7 +290,7 @@ sub display_row { $column_data{bin} = $form->{"bin_$i"}; if ($is_delivery_order) { - $column_data{stock_in_out} = (!$form->{"assembly_$i"} && $form->{"inventory_accno_$i"}) ? calculate_stock_in_out($i) : ' '; + $column_data{stock_in_out} = $form->{"inventory_accno_$i"} ? calculate_stock_in_out($i) : ' '; } my @ROW1 = map { value => $column_data{$_}, align => $align{$_}, nowrap => $nowrap{$_} }, @column_index; diff --git a/bin/mozilla/wh.pl b/bin/mozilla/wh.pl index 415ed39be..4c969a20e 100644 --- a/bin/mozilla/wh.pl +++ b/bin/mozilla/wh.pl @@ -104,6 +104,9 @@ sub transfer_warehouse_selection { $form->{title} = $locale->text('Transfer'); $content = $form->parse_html_template('wh/warehouse_selection'); + } elsif ($form->{trans_type} eq 'assembly') { + $form->{title} = $locale->text('Assembly'); + $content = $form->parse_html_template('wh/warehouse_selection_assembly'); } $form->header(); @@ -305,6 +308,45 @@ sub transfer_stock_update_part { $lxdebug->leave_sub(); } +# -------------------------------------------------------------------- +# Transfer: assemblies +# Dies ist die Auswahlmaske für ein assembly. +# Die ist einfach von transfer_assembly_update_part kopiert und nur um den trans_type (assembly) korrigiert worden +# Es wäre schön, hier nochmal check_assembly_max_create auf, um die max. Fertigungszahl herauszufinden. +# Ich lass das mal als auskommentierte Idee bestehen jb 18.3.09 +# -------------------------------------------------------------------- + +sub transfer_assembly_update_part { + $lxdebug->enter_sub(); + + $form->{trans_type} = 'assembly'; + $form->{qty} = $form->parse_amount(\%myconfig, $form->{qty}); + + if (!$form->{partnumber} && !$form->{description}) { + delete @{$form}{qw(parts_id partunit)}; + transfer_warehouse_selection(); + + } elsif (($form->{partnumber} && ($form->{partnumber} ne $form->{old_partnumber})) || $form->{description}) { + $form->{assemblies} = 1; + $form->{no_assemblies} = 0; + my $parts = Common->retrieve_parts(\%myconfig, $form, 'description', 1); + if (scalar @{ $parts } == 1) { + @{$form}{qw(parts_id partnumber description)} = @{$parts->[0]}{qw(id partnumber description)}; + transfer_stock_get_partunit(); + transfer_warehouse_selection(); + } else { + select_part('transfer_stock_part_selected', @{ $parts }); + } + + } else { + transfer_stock_get_partunit(); + transfer_warehouse_selection(); + } + +# hier die oben benannte idee +# my $maxcreate = Common->check_assembly_max_create(assembly_id => $form->{parts_id}, dbh => $my_dbh); + $lxdebug->leave_sub(); +} sub transfer_stock_part_selected { $lxdebug->enter_sub(); @@ -329,6 +371,60 @@ sub transfer_stock_get_partunit { $lxdebug->leave_sub(); } +# vorüberlegung jb 22.2.2009 +# wir benötigen für diese funktion, die anzahl die vom erzeugnis hergestellt werden soll. vielleicht direkt per js fehleingaben verhindern? +# ferner dann nochmal mit check_asssembly_max_create gegenprüfen und dann transaktionssicher wegbuchen. +# wir brauchen eine hilfsfunktion, die nee. brauchen wir nicht. der algorithmus läuft genau wie bei check max_create, nur dass hier auch eine lagerbewegung (verbraucht) stattfindet +# Manko ist derzeit noch, dass unterschiedliche Lagerplätze, bzw. das Quelllager an sich nicht ausgewählt werden können. +# Laut Absprache in KW11 09 übernimmt mb hier den rest im April ... jb 18.3.09 +sub create_assembly { +# my $maxcreate=shift; # oben begonnene auskommentierte idee, hier als motiv weiterverfolgen (umkehrungen und sequenzierungen als stilmittel nicht vergessen) + $lxdebug->enter_sub(); + + $form->{qty} = $form->parse_amount(\%myconfig, $form->{qty}); +# my $maxcreate = WH->check_assembly_max_create(assembly_id => $form->{parts_id}); + if ($form->{qty} <= 0) { + $form->show_generic_error($locale->text('Invalid quantity.'), 'back_button' => 1); + } #else { if ($form->{qty} > $maxcreate) { #s.o. +# $form->show_generic_error($locale->text('Can not create that quantity with current stock'), 'back_button' => 1); +# $form->show_generic_error('Maximale Stückzahl' . $maxcreate , 'back_button' => 1); +# } +# } + + if (!$form->{warehouse_id} || !$form->{bin_id}) { + $form->error($locale->text('The warehouse or the bin is missing.')); + } +# WIESO war das nicht vorher schon ein %HASH?? ein hash ist ein hash! das hat mich mehr als eine Stunde gekostet herauszufinden. grr. jb 3.3.2009 +# Anm. jb 18.3. vielleicht auch nur meine unwissenheit in perl-datenstrukturen + my %TRANSFER = ( + 'transfer_type' => 'assembly', + 'login' => $form->{login}, + 'dst_warehouse_id' => $form->{warehouse_id}, + 'dst_bin_id' => $form->{bin_id}, + 'chargenumber' => $form->{chargenumber}, + 'assembly_id' => $form->{parts_id}, + 'qty' => $form->{qty}, + 'unit' => $form->{unit}, + 'comment' => $form->{comment}, + ); + + my $ret = WH->transfer_assembly (%TRANSFER); +# Frage: Ich pack in den return-wert auch gleich die Fehlermeldung. Irgendwelche Nummern als Fehlerkonstanten definieren find ich auch nicht besonders schick... +# Ideen? jb 18.3.09 + if ($ret ne "1"){ + $form->show_generic_error($locale->text($ret), 'back_button' => 1); + } + + delete @{$form}{qw(parts_id partnumber description qty unit chargenumber comment)}; + + $form->{saved_message} = $locale->text('The assembly has been created.'); + $form->{trans_type} = 'assembly'; + + transfer_warehouse_selection(); + + $lxdebug->leave_sub(); +} + sub transfer_stock { $lxdebug->enter_sub(); diff --git a/locale/de/all b/locale/de/all index 8d2b74cb7..106c881a7 100644 --- a/locale/de/all +++ b/locale/de/all @@ -186,6 +186,9 @@ $self->{texts} = { 'Article Code missing!' => 'Artikelkürzel fehlt', 'As a result, the saved onhand values of the present goods can be stored into a warehouse designated by you, or will be reset for a proper warehouse tracking' => 'Als Konsequenz können die gespeicherten Mengen entweder in ein Lager überführt werden, oder für eine frische Lagerverwaltung resettet werden.', 'Assemblies' => 'Erzeugnisse', + 'Assembly' => 'Erzeugnis', + 'Assembly Description' => 'Erzeugnis-Beschreibung', + 'Assembly Number' => 'Erzeugnis-Nummer', 'Assembly Number missing!' => 'Erzeugnisnummer fehlt!', 'Asset' => 'Aktiva/Mittelverwendung', 'Assets' => 'Aktiva', @@ -278,6 +281,7 @@ $self->{texts} = { 'CRM user' => 'Admin Benutzer', 'CSV export -- options' => 'CSV-Export -- Optionen', 'Calculate' => 'Berechnen', + 'Can not create that quantity with current stock' => 'Ich kann diese Anzahl mit dem gegenwärtigen Lagerbestand nicht herstellen.', 'Cancel' => 'Abbrechen', 'Cancel Accounts Payables Transaction' => 'Kreditorenbuchung stornieren', 'Cancel Accounts Receivables Transaction' => 'Debitorenbuchung stornieren', @@ -362,6 +366,7 @@ $self->{texts} = { 'Could not spawn the printer command.' => 'Die Druckanwendung konnte nicht gestartet werden.', 'Could not update prices!' => 'Preise konnten nicht aktualisiert werden!', 'Country' => 'Land', + 'Create Assembly' => 'Erzeugnis fertigen', 'Create Buchungsgruppen' => 'Buchungsgruppe erfassen', 'Create Chart of Accounts' => 'Kontenplan anlegen', 'Create Dataset' => 'Datenbank anlegen', @@ -1383,6 +1388,7 @@ $self->{texts} = { 'The \'tag\' field must only consist of alphanumeric characters or the carachters - _ ( )' => 'Das Feld \'tag\' darf nur aus alphanumerischen Zeichen und den Zeichen - _ ( ) bestehen.', 'The LDAP server "#1:#2" is unreachable. Please check config/authentication.pl.' => 'Der LDAP-Server "#1:#2" ist nicht erreichbar. Bitte überprüfen Sie die Angaben in config/authentication.pl.', 'The access rights have been saved.' => 'Die Zugriffsrechte wurden gespeichert.', + 'The assembly has been created.' => 'Das Erzeugnis wurde hergestellt.', 'The authentication configuration file "config/authentication.pl" does not exist. This Lx-Office installation has probably not been updated correctly yet. Please contact your administrator.' => 'Die Konfigurationsdatei für die Authentifizierung "config/authentication.pl" wurde nicht gefunden. Diese Lx-Office-Installation wurde vermutlich noch nicht vollständig aktualisiert oder eingerichtet. Bitte wenden Sie sich an Ihren Administrator.', 'The authentication database is not reachable at the moment. Either it hasn\'t been set up yet or the database server might be down. Please contact your administrator.' => 'Die Authentifizierungsdatenbank kann momentan nicht erreicht werden. Entweder wurde sie noch nicht eingerichtet, oder der Datenbankserver antwortet nicht. Bitte wenden Sie sich an Ihren Administrator.', 'The available options depend on the varibale type:' => 'Die verfügbaren Optionen hängen vom Variablentypen ab:', diff --git a/templates/webpages/wh/warehouse_selection_assembly_de.html b/templates/webpages/wh/warehouse_selection_assembly_de.html new file mode 100644 index 000000000..49bea84b7 --- /dev/null +++ b/templates/webpages/wh/warehouse_selection_assembly_de.html @@ -0,0 +1,135 @@ +[% USE HTML %][% USE JavaScript %][% USE LxERP %] + + + + + +
+ + + + + [% IF saved_message %] +

[% saved_message %]

+ [% END %] + +
[% title %]
+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Ziellager + +
Ziellagerplatz:
Erzeugnis-Nummer + + + +
Erzeugnis-Beschreibung + + +
Chargennummer
Menge + + +
Optionaler Kommentar
+

+ +

+ + [%- IF parts_id %] + + [%- END %] +

+
+ + + diff --git a/templates/webpages/wh/warehouse_selection_assembly_master.html b/templates/webpages/wh/warehouse_selection_assembly_master.html new file mode 100644 index 000000000..dd9c86594 --- /dev/null +++ b/templates/webpages/wh/warehouse_selection_assembly_master.html @@ -0,0 +1,135 @@ +[% USE HTML %][% USE JavaScript %][% USE LxERP %] + + + + + +
+ + + + + [% IF saved_message %] +

[% saved_message %]

+ [% END %] + +
[% title %]
+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Destination warehouse + +
Destination bin:
Assembly Number + + + +
Assembly Description + + +
Charge number
Quantity + + +
Optional comment
+

+ +

+ + [%- IF parts_id %] + + [%- END %] +

+
+ + +