Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 127f5b5c

Von Tamino Steinert vor etwa 1 Jahr hinzugefügt

  • ID 127f5b5cb43589b31144a8a0d97af4b7b42dbc27
  • Vorgänger 0ed6ca32
  • Nachfolger a0a735e0

DeliveryOrder: Ein-/Auslagern über Standard-Lagerplatz

Unterschiede anzeigen:

SL/Controller/DeliveryOrder.pm
14 14
use SL::File;
15 15
use SL::MIME;
16 16
use SL::YAML;
17
use SL::DBUtils qw(selectall_hashref_query);
17 18
use SL::DB::History;
18 19
use SL::DB::Order;
19 20
use SL::DB::Default;
......
1053 1054
}
1054 1055

  
1055 1056
sub action_transfer_stock {
1056
  my ($self) = @_;
1057
  my ($self, $default_transfer) = @_;
1057 1058

  
1058 1059
  if ($self->order->delivered) {
1059 1060
    return $self->js->flash("error",
......
1084 1085
      $transfer->oe_id($order->id);
1085 1086
      $transfer->qty($transfer->qty * -1) if $inout eq 'out';
1086 1087
      $transfer->qty($transfer->qty * 1) if $inout eq 'in';
1088
      $transfer->comment(t8("Default transfer delivery order")) if $default_transfer;
1087 1089

  
1088 1090
      push @transfer_requests, $transfer if defined $transfer->qty && $transfer->qty != 0;
1089 1091
    };
......
1097 1099
    $_->save for @transfer_requests;
1098 1100
    $self->order->update_attributes(delivered => 1, closed => 1);
1099 1101
  });
1100
  # update stock info (set new delivery_order_items_stock_id)
1102
  # update qty and stock info
1101 1103
  foreach my $item (@{$self->order->items}) {
1102 1104
    $self->order->prepare_stock_info($item);
1105
    my $stock_info_yaml = $item->{stock_info};
1103 1106
    my $item_position = $item->position;
1107
    my $stock_qty = $self->calculate_stock_in_out($item);
1108
    my $unit = $item->unit;
1109
    $self->js->text("[data-position=$item_position] .data-stock-qty", "$stock_qty $unit");
1104 1110
    my $selector = "[data-position=$item_position] .data-stock-info";
1105
    $self->js->val($selector, $item->{stock_info});
1111
    $self->js->val($selector, $stock_info_yaml);
1106 1112
  }
1107 1113

  
1108 1114
  $self->js
......
1111 1117
          t8('This record has already been delivered.'))
1112 1118
    ->run('kivi.ActionBar.setDisabled', '#transfer_out_action',
1113 1119
          t8('The parts for this order have already been transferred'))
1120
    ->run('kivi.ActionBar.setDisabled', '#transfer_out_default_action',
1121
          t8('The parts for this order have already been transferred'))
1114 1122
    ->run('kivi.ActionBar.setDisabled', '#transfer_in_action',
1115 1123
          t8('The parts for this order have already been transferred'))
1124
    ->run('kivi.ActionBar.setDisabled', '#transfer_in_default_action',
1125
          t8('The parts for this order have already been transferred'))
1116 1126
    ->run('kivi.ActionBar.setDisabled', '#delete_action',
1117 1127
          t8('The parts for this order have already been transferred'))
1118 1128
    ->run('kivi.ActionBar.setEnabled', '#undo_transfer_action',
......
1121 1131
    ->render;
1122 1132
}
1123 1133

  
1134
sub action_transfer_stock_default {
1135
  my ($self) = @_;
1136
  my $delivery_order = $self->order;
1137
  my @items = @{$delivery_order->items_sorted};
1138

  
1139
  # get default bin if set in config
1140
  my ($default_warehouse_id, $default_bin_id);
1141
  if ($::instance_conf->get_transfer_default_use_master_default_bin) {
1142
    $default_warehouse_id = $::instance_conf->get_warehouse_id;
1143
    $default_bin_id       = $::instance_conf->get_bin_id;
1144
  }
1145

  
1146
  my @transfer_requests = ();
1147
  my %parts_qty = ();
1148
  my %units_by_name = map { $_->name => $_ } @{ SL::DB::Manager::Unit->get_all };
1149
  foreach my $item (@items) {
1150
    my $part = $item->part;
1151
    my $base_unit_factor = $units_by_name{$part->unit}->factor || 1;
1152
    my $item_unit_factor = $units_by_name{$item->unit}->factor || 1;
1153
    my $qty = $item->qty * $item_unit_factor / $base_unit_factor;
1154
    return $self->js->flash('error', t8('Cannot transfer negative entries.'))->render() if $qty < 0;
1155
    $qty = 0 if (!$::instance_conf->get_transfer_default_services && $part->is_service);
1156

  
1157
    $parts_qty{$part->id} += $qty if $qty;
1158
    push @transfer_requests, {
1159
      'delivery_order_item_id' => $item->id,
1160
      'warehouse_id'           => $part->warehouse_id || $default_warehouse_id,
1161
      'bin_id'                 => $part->bin_id       || $default_bin_id,
1162
      'unit'                   => $part->unit,
1163
      'qty'                    => $qty,
1164
      # added in check transfer_request out direction if possible
1165
      'chargenumber'           => undef, # $item->serialnumber, # Is not used in delivery order
1166
      'bestbefore'             => undef, # $item->bestbefore,   # Is not used in delivery order
1167
    }
1168
  }
1169

  
1170
  # check transfer_requests are correctly
1171
  my %parts_errors = (); # missing_bin, missing_qty, multiple_options
1172
  my $grouped_qty_query = qq|
1173
    SELECT SUM(qty) as qty, chargenumber, bestbefore
1174
    FROM inventory
1175
    WHERE parts_id = ? AND bin_id = ?
1176
    GROUP BY chargenumber, bestbefore
1177
  |;
1178
  my $dbh = $self->order->dbh;
1179
  my $in_out_direction = $delivery_order->type_data->properties('transfer');
1180
  for my $idx (0 .. scalar @transfer_requests - 1) {
1181
    my $transfer_request = $transfer_requests[$idx];
1182
    next unless $transfer_request->{qty}; # empty request
1183
    my $item = $items[$idx];
1184
    my $part_id = $item->parts_id;
1185
    my $bin_id  = $transfer_request->{bin_id};
1186
    $parts_errors{$part_id}{missing_bin} = 1 unless $bin_id;
1187
    next                                     unless $bin_id;
1188
    if ($in_out_direction eq 'out') {
1189
      my @grouped_qty = selectall_hashref_query(
1190
        $::form, $dbh, $grouped_qty_query, $part_id, $bin_id);
1191

  
1192
      if (1 < scalar grep {$_->{qty} != 0} @grouped_qty) {
1193
        $parts_errors{$part_id}{multiple_options} = 1;
1194
      }
1195
      my $max_qty = sum0(map {$_->{qty}} @grouped_qty);
1196
      if ($max_qty < $parts_qty{$part_id}) {
1197
        $parts_errors{$part_id}{missing_qty} = $parts_qty{$part_id} - $max_qty;
1198
      }
1199

  
1200
      next if $parts_errors{$part_id};
1201
      # find correct chargenumber and bestbefore
1202
      my $stock_info = first {$_->{qty} >= $transfer_request->{qty}} @grouped_qty;
1203
      $transfer_request->{chargenumber} = $stock_info->{chargenumber};
1204
      $transfer_request->{bestbefore}   = $stock_info->{bestbefore};
1205
    }
1206
  }
1207

  
1208
  # auslagern soll immer gehen, auch wenn nicht genügend auf lager ist.
1209
  # der lagerplatz ist hier extra konfigurierbar, bspw. Lager-Korrektur mit
1210
  # Lagerplatz Lagerplatz-Korrektur
1211
  my $default_warehouse_id_ignore_onhand = $::instance_conf->get_warehouse_id_ignore_onhand;
1212
  my $default_bin_id_ignore_onhand       = $::instance_conf->get_bin_id_ignore_onhand;
1213
  if ($::instance_conf->get_transfer_default_ignore_onhand && $default_bin_id_ignore_onhand) {
1214
    foreach my $part_id (keys %parts_errors) {
1215
      # entsprechende defaults holen
1216
      # falls chargenumber, bestbefore oder anzahl nicht stimmt, auf automatischen
1217
      # lagerplatz wegbuchen!
1218
      foreach (@transfer_requests) {
1219
        if ($_->{delivery_order_item}->parts_id eq $part_id){
1220
          $_->{bin_id}        = $default_bin_id_ignore_onhand;
1221
          $_->{warehouse_id}  = $default_warehouse_id_ignore_onhand;
1222
        }
1223
      }
1224
      delete %parts_errors{$part_id};
1225
    }
1226
  }
1227

  
1228
  # render errors
1229
  if (scalar keys %parts_errors) {
1230
    my @multiple_options = ();
1231
    foreach my $part_id (keys %parts_errors) {
1232
      my $part = SL::DB::Part->new(id => $part_id)->load();
1233
      if ($parts_errors{$part_id}{missing_bin}){
1234
        $self->js->error(t8('No standard bin set for #1.', $part->displayable_name));
1235
      }
1236
      if ($parts_errors{$part_id}{missing_qty}) {
1237
        $self->js->error(
1238
          t8('There are #1 of "#2" missing from the standard bin #3 for transfer.',
1239
            $parts_errors{$part_id}{missing_qty}, $part->displayable_name, $part->bin->full_description));
1240
      }
1241
      if ($parts_errors{$part_id}{multiple_options}){
1242
        push @multiple_options, $part;
1243
      }
1244
    }
1245
    if (scalar @multiple_options) {
1246
        $self->js->error(t8(
1247
            "There are parts with multiple chargenumbers or bestbefore dates set. This can't be decided automatically. Pleas transfer this delivery order manually. Can't decided for #1.",
1248
            join ", ", map {$_->displayable_name} @multiple_options)
1249
        );
1250
    }
1251
    return $self->js->render();
1252
  }
1253

  
1254
  # assign each delivery_order_item it's stock
1255
  for my $idx (0 .. scalar @transfer_requests - 1) {
1256
    my %transfer_request = %{$transfer_requests[$idx]};
1257
    next unless $transfer_request{qty}; # empty request
1258

  
1259
    my $item = $items[$idx];
1260
    my @stocks = (SL::DB::DeliveryOrderItemsStock->new(%transfer_request));
1261
    $item->delivery_order_stock_entries(@stocks);
1262
  }
1263

  
1264
  my $default_transfer = 1;
1265
  $self->action_transfer_stock($default_transfer);
1266
}
1267

  
1124 1268
sub action_undo_transfers {
1125 1269
  my ( $self ) = @_;
1126 1270

  
......
1892 2036
          only_if  => $self->type_data->properties('transfer') eq 'out',
1893 2037
          confirm  => t8('Do you really want to transfer the stock and set this order to delivered?'),
1894 2038
        ],
2039
        action => [
2040
          t8('Transfer out via default'),
2041
          id       => 'transfer_out_default_action',
2042
          call     => [ 'kivi.DeliveryOrder.save', {
2043
              action => 'transfer_stock_default',
2044
            }],
2045
          disabled => !$may_edit_create       ? t8('You do not have the permissions to access this function.')
2046
                    : !$self->order->id       ? t8('This object has not been saved yet.')
2047
                    : $self->order->delivered ? t8('The parts for this order have already been transferred')
2048
                    :                           undef,
2049
          only_if  => $self->type_data->properties('transfer') eq 'out',
2050
          confirm  => t8('Do you really want to transfer the stock and set this order to delivered?'),
2051
        ],
1895 2052
        action => [
1896 2053
          t8('Transfer in'),
1897 2054
          id       => 'transfer_in_action',
......
1905 2062
          only_if  => $self->type_data->properties('transfer') eq 'in',
1906 2063
          confirm  => t8('Do you really want to transfer the stock and set this order to delivered?'),
1907 2064
        ],
2065
        action => [
2066
          t8('Transfer in via default'),
2067
          id       => 'transfer_in_default_action',
2068
          call     => [ 'kivi.DeliveryOrder.save', {
2069
              action => 'transfer_stock_default',
2070
            }],
2071
          disabled => !$may_edit_create       ? t8('You do not have the permissions to access this function.')
2072
                    : !$self->order->id       ? t8('This object has not been saved yet.')
2073
                    : $self->order->delivered ? t8('The parts for this order have already been transferred')
2074
                    :                           undef,
2075
          only_if  => $self->type_data->properties('transfer') eq 'in',
2076
          confirm  => t8('Do you really want to transfer the stock and set this order to delivered?'),
2077
        ],
1908 2078
        action => [
1909 2079
          t8('Undo Transfer'),
1910 2080
          id       => 'undo_transfer_action',
locale/de/all
1143 1143
  'Default printer'             => 'Standarddrucker',
1144 1144
  'Default taxzone'             => 'Standardsteuerzone',
1145 1145
  'Default template format'     => 'Standardvorlagenformat',
1146
  'Default transfer delivery order' => 'Standard-Auslagern über Lieferschein',
1146
  'Default transfer delivery order' => 'Standard-Ein-/Auslagern über Lieferschein',
1147 1147
  'Default transfer invoice'    => 'Standard-Auslagern über Rechnung',
1148 1148
  'Default transfer invoice with charge number' => 'Standard-Auslagern über Rechnung mit Chargennummer',
1149 1149
  'Default transport article number' => 'Standard Versand / Transport-Erinnerungs-Artikel',
......
2519 2519
  'No sections have been created yet.' => 'Es wurden noch keine Abschnitte angelegt.',
2520 2520
  'No shipto city'              => 'Die Stadt für die Lieferadresse fehlt',
2521 2521
  'No shipto selected to delete' => 'Keine Lieferadresse zum Löschen ausgewählt',
2522
  'No standard bin set for #1.' => 'Kein Standard-Lagerplatz ausgewählt für #1.',
2522 2523
  'No start date given, setting to #1' => 'Kein Startdatum gegeben, setze Startdatum auf #1',
2523 2524
  'No stock to transfer'        => 'Keine Lagerbewegungen vorhanden',
2524 2525
  'No such job #1 in the database.' => 'Hintergrund-Job #1 existiert nicht mehr.',
......
4243 4244
  'Then go to the database administration and chose "create database".' => 'Dann gehen Sie in den Datenbankverwaltung, und wählen Sie dort "Datenbank anlegen" aus.',
4244 4245
  'There are #1 more open invoices for this customer with other currencies.' => 'Es gibt #1 weitere offene Rechnungen für diesen Kunden, die in anderen Währungen ausgestellt wurden.',
4245 4246
  'There are #1 more open invoices from this vendor with other currencies.' => 'Es gibt #1 weitere offene Rechnungen von diesem Lieferanten, die in anderen Währungen ausgestellt wurden.',
4247
  'There are #1 of "#2" missing from the standard bin #3 for transfer.' => 'Es fehlen #1 von "#2" auf dem Standard-Lagerplatz #3 zum Auslagern',
4246 4248
  'There are #1 unfinished follow-ups of which #2 are due.' => 'Es gibt #1 Wiedervorlage(n), von denen #2 fällig ist/sind.',
4247 4249
  'There are Bins defined in your Inventory.' => 'Unter Stammdaten/Waren sind Lagerplätze definiert.',
4248 4250
  'There are Bins defined in your master data.' => 'Unter Stammdaten/Waren sind Lagerplätze defininert',
......
4265 4267
  'There are no items selected' => 'Es wurden keine Positionen ausgewählt',
4266 4268
  'There are no orders for the selected time period.' => 'Es gibt für den ausgewählten Zeitraum keine Aufträge.',
4267 4269
  'There are no record templates yet.' => 'Es gibt noch keine Belegvorlagen.',
4270
  'There are parts with multiple chargenumbers or bestbefore dates set. This can\'t be decided automatically. Pleas transfer this delivery order manually. Can\'t decided for #1.' => 'Es gibt Waren mit mehreren Chargennummern oder Mindesthaltbarkeiten. Es kann nicht automatisch entscheiden werden. Bitte diesen Lieferschein mauell auslagern. Kann nicht entschieden werden für: #1',
4268 4271
  'There are parts with no reclamation reason at position:' => 'Es gibt Artikel mit keinem Reklamationsgrund an Position:',
4269 4272
  'There are several options you can handle this problem, please select one:' => 'Bitte wählen Sie eine der folgenden Optionen, um mit dem Problem umzugehen:',
4270 4273
  'There are some errors in the file and it was requested to not save any datasets on errors.' => 'Es sind Fehler aufgetreten und es sollen bei Fehlern überhaupt keine Datensätze gespeichert werden.',
locale/en/all
2518 2518
  'No sections have been created yet.' => '',
2519 2519
  'No shipto city'              => '',
2520 2520
  'No shipto selected to delete' => '',
2521
  'No standard bin set for #1.' => '',
2521 2522
  'No start date given, setting to #1' => '',
2522 2523
  'No stock to transfer'        => '',
2523 2524
  'No such job #1 in the database.' => '',
......
4241 4242
  'Then go to the database administration and chose "create database".' => '',
4242 4243
  'There are #1 more open invoices for this customer with other currencies.' => '',
4243 4244
  'There are #1 more open invoices from this vendor with other currencies.' => '',
4245
  'There are #1 of "#2" missing from the standard bin #3 for transfer.' => '',
4244 4246
  'There are #1 unfinished follow-ups of which #2 are due.' => '',
4245 4247
  'There are Bins defined in your Inventory.' => '',
4246 4248
  'There are Bins defined in your master data.' => '',
......
4263 4265
  'There are no items selected' => '',
4264 4266
  'There are no orders for the selected time period.' => '',
4265 4267
  'There are no record templates yet.' => '',
4268
  'There are parts with multiple chargenumbers or bestbefore dates set. This can\'t be decided automatically. Pleas transfer this delivery order manually. Can\'t decided for #1.' => '',
4266 4269
  'There are parts with no reclamation reason at position:' => '',
4267 4270
  'There are several options you can handle this problem, please select one:' => '',
4268 4271
  'There are some errors in the file and it was requested to not save any datasets on errors.' => '',

Auch abrufbar als: Unified diff