In der Mandantenkonfiguration kann ein Mengenschwellwert eingegeben werden.
Wenn die bei der Inventur gezählte/eingegebene Zielmenge mehr als dieser
Schwellwert von der Menge in der Datenbank abweicht, dann wird eine Warnung
angezeigt.
Hintergrund: Mitarbeiter lesen den Artikel mit einem Barcode-Scanner ein und
vergessen manchmal, die vorher eingegebene Menge zu speichern. Dann wird die
Artikelnummer oder EAN in das Mengenfeld geschrieben und ein "Enter" ausgelöst.
Dann ist die Zielmenge sehr groß und falsch. Das kann damit verhindert bzw.
abgeschwächt werden.
__PACKAGE__->run_before('_check_auth');
__PACKAGE__->run_before('_check_warehouses');
-__PACKAGE__->run_before('load_part_from_form', only => [ qw(stock_in part_changed mini_stock stock stocktaking_part_changed save_stocktaking) ]);
-__PACKAGE__->run_before('load_unit_from_form', only => [ qw(stock_in part_changed mini_stock stock stocktaking_part_changed save_stocktaking) ]);
-__PACKAGE__->run_before('load_wh_from_form', only => [ qw(stock_in warehouse_changed stock stocktaking save_stocktaking) ]);
-__PACKAGE__->run_before('load_bin_from_form', only => [ qw(stock_in stock stocktaking save_stocktaking) ]);
+__PACKAGE__->run_before('load_part_from_form', only => [ qw(stock_in part_changed mini_stock stock stocktaking_part_changed stocktaking_get_warn_qty_threshold save_stocktaking) ]);
+__PACKAGE__->run_before('load_unit_from_form', only => [ qw(stock_in part_changed mini_stock stock stocktaking_part_changed stocktaking_get_warn_qty_threshold save_stocktaking) ]);
+__PACKAGE__->run_before('load_wh_from_form', only => [ qw(stock_in warehouse_changed stock stocktaking stocktaking_get_warn_qty_threshold save_stocktaking) ]);
+__PACKAGE__->run_before('load_bin_from_form', only => [ qw(stock_in stock stocktaking stocktaking_get_warn_qty_threshold save_stocktaking) ]);
__PACKAGE__->run_before('set_target_from_part', only => [ qw(part_changed) ]);
__PACKAGE__->run_before('mini_stock', only => [ qw(stock_in mini_stock) ]);
-__PACKAGE__->run_before('sanitize_target', only => [ qw(stock_usage stock_in warehouse_changed part_changed stocktaking stocktaking_part_changed save_stocktaking) ]);
+__PACKAGE__->run_before('sanitize_target', only => [ qw(stock_usage stock_in warehouse_changed part_changed stocktaking stocktaking_part_changed stocktaking_get_warn_qty_threshold save_stocktaking) ]);
__PACKAGE__->run_before('set_layout');
sub action_stock_in {
$self->prepare_stocktaking_report(full => 1);
$self->report_generator_list_objects(report => $self->{report}, objects => $self->stocktaking_models->get);
}
+
+sub action_stocktaking_get_warn_qty_threshold {
+ my ($self) = @_;
+
+ return $_[0]->render(\ !!0, { type => 'text' }) if $::form->{target_qty} eq '';
+ return $_[0]->render(\ !!0, { type => 'text' }) if 0 == $::instance_conf->get_stocktaking_qty_threshold;
+
+ my $target_qty = $::form->parse_amount(\%::myconfig, $::form->{target_qty});
+ my $stocked_qty = _get_stocked_qty($self->part,
+ warehouse_id => $self->warehouse->id,
+ bin_id => $self->bin->id,
+ chargenumber => $::form->{chargenumber},
+ bestbefore => $::form->{bestbefore},);
+ my $stocked_qty_in_form_units = $self->part->unit_obj->convert_to($stocked_qty, $self->unit);
+ my $qty = $target_qty - $stocked_qty_in_form_units;
+ $qty = abs($qty);
+
+ my $warn;
+ if ($qty > $::instance_conf->get_stocktaking_qty_threshold) {
+ $warn = t8('The target quantity of #1 differs more than the threshold quantity of #2.',
+ $::form->{target_qty} . " " . $self->unit->name,
+ $::form->format_amount(\%::myconfig, $::instance_conf->get_stocktaking_qty_threshold, 2));
+ $warn .= "\n";
+ $warn .= t8('Choose "continue" if you want to use this value. Choose "cancel" otherwise.');
+ }
+ return $_[0]->render(\ $warn, { type => 'text' });
+}
+
#================================================================
sub _check_auth {
$bar->add(
action => [
t8('Save'),
+ checks => [ 'kivi.Inventory.check_stocktaking_qty_threshold' ],
call => [ 'kivi.Inventory.save_stocktaking' ],
accesskey => 'enter',
],
This action is called after the user selected or changed the part.
+=item C<action_stocktaking_get_warn_qty_threshold>
+
+This action checks if a warning should be shown and returns the warning text via
+ajax. The warning will be shown if the given target value is greater than the
+threshold given in the client configuration.
+
=item C<is_stocktaking>
This is a method to check if actions are called from stocktaking form.
+This actions should contain "stocktaking" in their name.
=back
sqnumber => { type => 'text' },
stocktaking_bin_id => { type => 'integer' },
stocktaking_cutoff_date => { type => 'date' },
+ stocktaking_qty_threshold => { type => 'numeric', default => '0', precision => 25, scale => 5 },
stocktaking_warehouse_id => { type => 'integer' },
taxnumber => { type => 'text' },
templates => { type => 'text' },
$('#already_counted_dialog').dialog("close");
};
+ ns.check_stocktaking_qty_threshold = function() {
+ var data = $('#stocktaking_form').serializeArray();
+ data.push({ name: 'action', value: 'Inventory/stocktaking_get_warn_qty_threshold' });
+
+ var warn = false;
+ $.ajax({
+ url: 'controller.pl',
+ data: data,
+ method: "GET",
+ async: false,
+ dataType: 'text',
+ success: function(val) {
+ warn = val;
+ }
+ });
+
+ if (warn) {
+ return confirm(warn);
+ } else {
+ return true;
+ }
+ };
});
$(function(){
'Check on purchase invoice' => 'Prüfen bei Einkaufsrechnung',
'Check on sales invoice' => 'Prüfen bei Verkaufsrechnung',
'Checks' => 'Schecks',
+ 'Choose "continue" if you want to use this value. Choose "cancel" otherwise.' => 'Wählen Sie "Ok" um diesen Wert zu übernehmen. Andernfalls wählen Sie "Abbrechen".',
'Choose Customer' => 'Endkunde wählen:',
'Choose Outputformat' => 'Ausgabeformat auswählen...',
'Choose Vendor' => 'Händler wählen',
'If searching a part from a document and no part is found then offer to create a new part.' => 'Wenn bei der Artikelsuche aus einem Dokument heraus kein Artikel gefunden wird, dann wird ermöglicht, von dort aus einen neuen Artikel anzulegen.',
'If the article type is set to \'mixed\' then a column called \'part_type\' or called \'pclass\' must be present.' => 'Falls der Artikeltyp auf \'mixed\' gesetzt ist muss entweder eine Spalte \'part_type\' oder \'pclass\' im Import vorhanden sein',
'If the automatic creation of invoices for fees and interest is switched on for a dunning level then the following accounts will be used for the invoice.' => 'Wenn das automatische Erstellen einer Rechnung über Mahngebühren und Zinsen für ein Mahnlevel aktiviert ist, so werden die folgenden Konten für die Rechnung benutzt.',
+ 'If the counted quantity differs more than this threshold from the quantity in the database, a warning will be shown. Set to 0 to switch of this feature.' => 'Wenn die gezählte Menge mehr als dieser Schwellwert von der Menge in der Datenbank abweicht, wird eine Warnmeldung angezeigt. Setzen Sie den Schwellwert auf 0, um dieses Feature abzuschalten.',
'If the database user listed above does not have the right to create a database then enter the name and password of the superuser below:' => 'Falls der oben genannte Datenbankbenutzer nicht die Berechtigung zum Anlegen neuer Datenbanken hat, so können Sie hier den Namen und das Passwort des Datenbankadministratoraccounts angeben:',
'If the default transfer out always succeed use this bin for negative stock quantity.' => 'Standardlagerplatz für Auslagern ohne Prüfung auf Bestand',
'If yes, delivery order positions are considered "delivered" only if they have been stocked out of the inventory. Otherwise saving the delivery order is considered delivered.' => 'Wenn diese Option aktiviert ist, gelten Lieferscheinpositionen nur dann als geliefert wenn sie im Lieferschein ausgelagert wurden, und die Ware aus dem Lager ausgebucht wurde. Andernfalls gilt das Speichern des Lieferscheins als Lieferung.',
'The subject is missing.' => 'Der Betreff fehlt.',
'The tables for user management and authentication do not exist. They will be created in the next step in the following database:' => 'Die Tabellen zum Speichern der Benutzerdaten und zur Benutzerauthentifizierung wurden nicht gefunden. Sie werden in der folgenden Datenbank angelegt:',
'The tabulator character' => 'Das Tabulator-Symbol',
+ 'The target quantity of #1 differs more than the threshold quantity of #2.' => 'Die Abweichung der Zielmenge #1 ist größer als der Mengenschwellwert #2.',
'The task server does not appear to be running.' => 'Der Task-Server scheint nicht zu laufen.',
'The task server is already running.' => 'Der Task-Server läuft bereits.',
'The task server is not running at the moment but needed for this module' => 'Der Taskserver wird für dieses Modul benötigt, läuft aber im Moment nicht.',
'This will remove the invoice from showing as unpaid even if the unpaid amount does not match the amount. Proceed?' => 'Dies wird die Rechnung nicht mehr als offen anzeigen, auch wenn der unbezahlte Betrag nicht dem Rechnungsbetrag entspricht. Fortfahren?',
'This will set an exact price.' => 'Diese Option setzt einen festen Preis.',
'Three Options:' => 'Drei Optionen:',
+ 'Threshold for warning on quantity difference' => 'Schwellwert für Warnung bei Mengenabweichung',
'Time' => 'Zeit',
'Time Format' => 'Uhrzeitformat',
'Time and price estimate' => 'Zeit- und Preisschätzung',
'Check on purchase invoice' => '',
'Check on sales invoice' => '',
'Checks' => '',
+ 'Choose "continue" if you want to use this value. Choose "cancel" otherwise.' => '',
'Choose Customer' => '',
'Choose Outputformat' => '',
'Choose Vendor' => '',
'If searching a part from a document and no part is found then offer to create a new part.' => '',
'If the article type is set to \'mixed\' then a column called \'part_type\' or called \'pclass\' must be present.' => '',
'If the automatic creation of invoices for fees and interest is switched on for a dunning level then the following accounts will be used for the invoice.' => '',
+ 'If the counted quantity differs more than this threshold from the quantity in the database, a warning will be shown. Set to 0 to switch of this feature.' => '',
'If the database user listed above does not have the right to create a database then enter the name and password of the superuser below:' => '',
'If the default transfer out always succeed use this bin for negative stock quantity.' => '',
'If yes, delivery order positions are considered "delivered" only if they have been stocked out of the inventory. Otherwise saving the delivery order is considered delivered.' => '',
'The subject is missing.' => '',
'The tables for user management and authentication do not exist. They will be created in the next step in the following database:' => '',
'The tabulator character' => '',
+ 'The target quantity of #1 differs more than the threshold quantity of #2.' => '',
'The task server does not appear to be running.' => '',
'The task server is already running.' => '',
'The task server is not running at the moment but needed for this module' => '',
'This will remove the invoice from showing as unpaid even if the unpaid amount does not match the amount. Proceed?' => '',
'This will set an exact price.' => '',
'Three Options:' => '',
+ 'Threshold for warning on quantity difference' => '',
'Time' => '',
'Time Format' => '',
'Time and price estimate' => '',
--- /dev/null
+-- @tag: add_stocktaking_qty_threshold_client_config_default
+-- @description: Konfigurations-Option für Mengen-Schwellwert zur Inventur
+-- @depends: add_stocktaking_preselects_client_config_default
+
+ALTER TABLE defaults ADD COLUMN stocktaking_qty_threshold NUMERIC(25,5) DEFAULT 0;
</tr>
<tr>
+ <tr>
+ <td align="right" nowrap="true">[% LxERP.t8('Threshold for warning on quantity difference') %]</td>
+ <td>[% L.input_tag('defaults.stocktaking_qty_threshold_as_number', SELF.defaults.stocktaking_qty_threshold_as_number, size=15, class="numeric") %]</td>
+ <td>
+ [% LxERP.t8('If the counted quantity differs more than this threshold from the quantity in the database, a warning will be shown. Set to 0 to switch of this feature.') %]<br>
+ </td>
+ </tr>
+ <tr>
+
</table>
</div>