Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 5c49b870

Von Bernd Bleßmann vor 9 Monaten hinzugefügt

  • ID 5c49b870647f3fc2ca898ae664dfc3878f5695f4
  • Vorgänger cc38bb72
  • Nachfolger 933ade61

Erzeugnis fertigen: Chargenauswahl

Unterschiede anzeigen:

bin/mozilla/wh.pl
33 33
#######################################################################
34 34

  
35 35
use Carp;
36
use List::Util qw(first);
36
use List::Util qw(any first none);
37 37
use POSIX qw(strftime);
38 38
use Scalar::Util qw(blessed);
39 39

  
......
43 43
use SL::AM;
44 44
use SL::CVar;
45 45
use SL::CT;
46
use SL::Helper::Flash qw(flash_later);
46
use SL::Helper::Flash qw(flash flash_later);
47 47
use SL::IC;
48 48
use SL::WH;
49 49
use SL::OE;
50
use SL::Helper::Inventory qw(produce_assembly);
50
use SL::Helper::Inventory qw(get_stock produce_assembly allocate_for_assembly check_allocations_for_assembly);
51
use SL::Helper::Inventory::Allocation;
51 52
use SL::Locale::String qw(t8);
52 53
use SL::ReportGenerator;
53 54
use SL::Presenter::Tag qw(checkbox_tag);
......
398 399
    $form->{bestbefore} = '';
399 400
  }
400 401

  
402
  # Check if there are more than one chargenumber for one part of an assembly.
403
  # In this case let the user select the wanted chargenumbers.
404
  my $stocked_wh_id = $::instance_conf->get_produce_assembly_same_warehouse ? $form->{warehouse_id} : undef;
405
  my @stocked_by    = qw(part warehouse bin chargenumber); # Or 'for_allocate'? That would include 'bestbefore'.
406
  my $stocked_parts = get_stock(part         => [ map { $_->part } @{$assembly->assemblies} ],
407
                                warehouse    => $stocked_wh_id,
408
                                by           => \@stocked_by,
409
                                with_objects => [qw(part warehouse bin)]);
410

  
411
  # Remove entries with no stock.
412
  $stocked_parts = [ grep { $_->{qty} != 0 } @$stocked_parts];
413

  
414
  my %stocked_by_parts_id = map { my $p_id = $_->{parts_id }; $p_id => [grep { $_->{parts_id} == $p_id } @$stocked_parts] } @$stocked_parts;
415

  
416
  my $is_stock_ambiguous = any { scalar(@{$_ || []}) > 1 } values %stocked_by_parts_id;
417
  my $allocation_check_failed;
418
  my $stock_check_failed;
419

  
420
  my @allocations;
421
  if ($is_stock_ambiguous) {
422
    if (!scalar @{$form->{allocations} || []}) {
423
      # User has not selected something / first_time.
424
      # Pre-fill allocations for selection form.
425
      eval {
426
        @allocations = allocate_for_assembly(part             => $assembly,
427
                                             qty              => $form->{qty},
428
                                             warehouse        => ($form->{warehouse_id} ? SL::DB::Warehouse->new(id => $form->{warehouse_id})->load : undef),
429
                                             chargenumber     => $form->{chargenumber},);
430
        1;
431
      } or do  {
432
        my $ex = $@;
433
        die $ex unless blessed($ex) && $ex->isa('SL::X::Inventory::Allocation::Multi');
434

  
435
        $form->{title} = $locale->text('Allocate for Assembly');
436
        $form->header;
437
        print $form->parse_html_template(
438
          'wh/produce_assembly_error',
439
          {
440
            missing_qty_exceptions => [ grep {  $_->isa('SL::X::Inventory::Allocation::MissingQty') } @{ $ex->errors } ],
441
            other_exceptions       => [ grep { !$_->isa('SL::X::Inventory::Allocation::MissingQty') } @{ $ex->errors } ],
442
          });
443

  
444
        return $::lxdebug->leave_sub();
445
      };
446

  
447
    } else {
448
      # User has selected something / selection form was sent.
449
      # Check allocations.
450

  
451
      # Create allocation helper objects from form.
452
      @allocations = map {
453
        SL::Helper::Inventory::Allocation->new(
454
          parts_id      => $_->{parts_id},
455
          qty           => $form->parse_amount(\%myconfig, $_->{qty}),
456
          bin_id        => $_->{bin_id},
457
          warehouse_id  => $_->{warehouse_id},
458
          chargenumber  => $_->{chargenumber},
459
          bestbefore    => $_->{bestbefore},
460
          comment       => $_->{comment},
461
          for_object_id => undef,
462
        )
463
      } grep { $form->parse_amount(\%myconfig, $_->{qty}) != 0 } @{$form->{allocations}};
464

  
465
      $allocation_check_failed = !check_allocations_for_assembly(part                 => $assembly,
466
                                                                 qty                  => $form->{qty},
467
                                                                 allocations          => \@allocations,
468
                                                                 check_overfulfilment => 1);
469

  
470
      if (!$allocation_check_failed) {
471
        # Check, if all allocations are stocked.
472
        foreach my $allocation (@allocations) {
473
          $stock_check_failed = none {
474
            $_->{parts_id}     == $allocation->parts_id     &&
475
            $_->{warehouse_id} == $allocation->warehouse_id &&
476
            $_->{bin_id}       == $allocation->bin_id       &&
477
            $_->{chargenumber} eq $allocation->chargenumber &&
478
            $_->{qty}          >= $allocation->qty
479
          } @$stocked_parts;
480

  
481
          last if $stock_check_failed;
482
        }
483
      }
484
    }
485

  
486
    # Show selection form if requested or check was not ok. Continue to production otherwise.
487
    if ($form->{show_allocations} || $allocation_check_failed || $stock_check_failed) {
488
      flash('warning', t8("Allocations are not sufficient or overfulfilled")) if ($allocation_check_failed);
489
      flash('warning', t8("Not enough on stock for one or more allocations")) if ($stock_check_failed);
490

  
491
      my %allocations_by_parts_id = map { my $p_id = $_->{parts_id}; $p_id => [grep { $_->{parts_id} == $p_id } @allocations] } @allocations;
492

  
493
      my %needed_by_parts_id = map { $_->{parts_id} => $_->qty * $form->{qty} } @{$assembly->assemblies};
494
      return create_assembly_chargenumbers($form, \%stocked_by_parts_id, \%needed_by_parts_id, \%allocations_by_parts_id);
495
    }
496

  
497
  }
498

  
401 499
  eval {
402 500
    produce_assembly(
403 501
              part           => $assembly,               # target assembly
404 502
              qty            => $form->{qty},            # qty
405
              auto_allocate  => 1,
503
              allocations    => ($is_stock_ambiguous ? \@allocations : undef),
504
              auto_allocate  => !$is_stock_ambiguous,
406 505
              bin            => $bin,                    # needed unless a global standard target is configured
407 506
              chargenumber   => $form->{chargenumber},   # optional
408 507
              bestbefore     => $form->{bestbefore},
......
436 535
  $main::lxdebug->leave_sub();
437 536
}
438 537

  
538
sub create_assembly_chargenumbers {
539
  my ($form, $stocked_by_parts_id, $needed_by_parts_id, $allocated_by_parts_id) = @_;
540

  
541
  setup_wh_create_assembly_chargenumbers_action_bar();
542

  
543
  my $hidden_vars = { map { $_ => $form->{$_} } qw(parts_id warehouse_id bin_id chargenumber qty unit comment) };
544

  
545
  $form->{title} = $::locale->text('Select Chargenumbers');
546
  $form->header;
547

  
548
  print $form->parse_html_template(
549
    'wh/create_assembly_chargenumbers',
550
    {
551
      hidden_vars           => $hidden_vars,
552
      stocked_by_parts_id   => $stocked_by_parts_id,
553
      needed_by_parts_id    => $needed_by_parts_id,
554
      allocated_by_parts_id => $allocated_by_parts_id,
555
    }
556
  );
557
}
558

  
439 559
# --------------------------------------------------------------------
440 560
# Transfer: removal
441 561
# --------------------------------------------------------------------
......
1200 1320
        submit    => [ '#form', { action => 'transfer_assembly_update_part' } ],
1201 1321
        accesskey => 'enter',
1202 1322
      ],
1323
      action => [
1324
        t8('Produce'),
1325
        submit   => [ '#form', { action => 'create_assembly', show_allocations => 1 } ],
1326
        disabled => $::form->{parts_id} ? undef : $::locale->text('No assembly has been selected yet.'),
1327
      ],
1328
    );
1329
  }
1330
}
1331

  
1332
sub setup_wh_create_assembly_chargenumbers_action_bar {
1333
  my ($action) = @_;
1334

  
1335
  for my $bar ($::request->layout->get('actionbar')) {
1336
    $bar->add(
1337
      action => [
1338
        t8('Update'),
1339
        submit    => [ '#form', { action => 'create_assembly', show_allocations => 1 } ],
1340
        accesskey => 'enter',
1341
      ],
1203 1342
      action => [
1204 1343
        t8('Produce'),
1205 1344
        submit   => [ '#form', { action => 'create_assembly' } ],
templates/webpages/wh/create_assembly_chargenumbers.html
1
[%- USE P -%]
2
[%- USE T8 %]
3
[%- USE HTML %]
4
[%- USE LxERP %]
5

  
6
<h1>[% HTML.escape(title) %]</h1>
7

  
8
[%- INCLUDE 'common/flash.html' %]
9

  
10
<p>
11
  [% 'Some of the following assembly items are ambigious. Please check the selection.' | $T8 %]
12
</p>
13

  
14
<form name="Form" method="post" action="wh.pl" id="form">
15
  [%
16
    FOREACH key = hidden_vars.keys;
17
      P.hidden_tag(key, HTML.escape(hidden_vars.$key));
18
    END
19
  %]
20

  
21
  <table>
22
    <thead>
23
      <tr class="listheading">
24
        <th>[% 'Partnumber'   | $T8%]</th>
25
        <th>[% 'Description'  | $T8%]</th>
26
        <th>[% 'Chargenumber' | $T8%]</th>
27
        <th>[% 'Warehouse'    | $T8%]</th>
28
        <th>[% 'Bin'          | $T8%]</th>
29
        <th>[% 'Onhand'       | $T8%]</th>
30
        <th>[% 'Qty'          | $T8%]</th>
31
        <th>[% 'Unit'         | $T8%]</th>
32
      </tr>
33
    </thead>
34
    <tbody>
35
      [% FOREACH part_id = stocked_by_parts_id.keys.sort -%]
36
        <tr class="listheading">
37
          <td colspan="6">[% 'needed qty' | $T8 %]</td>
38
          <td class="numeric">[% LxERP.format_amount(needed_by_parts_id.$part_id, -2) %]</td>
39
          <td>[% stocked_by_parts_id.$part_id.0.part.unit | html %]</td>
40
        </tr>
41
        [% FOREACH part = stocked_by_parts_id.$part_id -%]
42
          <tr class="listrow">
43
            [% SET alloc_qty = '';
44
               FOREACH alloc = allocated_by_parts_id.$part_id;
45
                 IF (alloc.warehouse_id == part.warehouse.id && alloc.bin_id == part.bin_id && HTML.escape(alloc.chargenumber) == HTML.escape(part.chargenumber));
46
                   SET alloc_qty = alloc.qty;
47
                 END;
48
               END
49
            -%]
50
            <td>
51
              [% P.hidden_tag('allocations[+].parts_id', part_id )%]
52
              [% P.hidden_tag('allocations[].chargenumber', part.chargenumber )%]
53
              [% P.hidden_tag('allocations[].warehouse_id', part.warehouse_id )%]
54
              [% P.hidden_tag('allocations[].bin_id', part.bin_id )%]
55
              [% part.part.partnumber | html %]
56
            </td>
57
            <td>[% part.part.description      | html                 %]</td>
58
            <td>[% part.chargenumber          | html                 %]</td>
59
            <td>[% part.warehouse.description | html                 %]</td>
60
            <td>[% part.bin.description       | html                 %]</td>
61
            <td class="numeric">[% LxERP.format_amount(part.qty, -2) %]</td>
62
            <td>[% P.input_number_tag('allocations[].qty', alloc_qty, precision => -2, size => 8) %]</td>
63
            <td>[% part.part.unit             | html                 %]</td>
64
          </tr>
65
        [% END %]
66
        <tr></tr>
67
        <tr></tr>
68
      [% END %]
69
    </tbody>
70
  </table>
71

  
72
</form>

Auch abrufbar als: Unified diff