Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 007fe204

Von Tamino Steinert vor etwa 1 Jahr hinzugefügt

  • ID 007fe20449e99307bd7425f50bd1ad5173b92698
  • Vorgänger 37d373f8
  • Nachfolger ca8f8f08

DispositionManager: Popup Artikeldetails überarbeitet

Unterschiede anzeigen:

SL/Controller/Part.pm
768 768
sub action_showdetails {
769 769
  my ($self, %params) = @_;
770 770

  
771
  eval {
772
      my @bindata;
773
      my $bins = SL::DB::Manager::Bin->get_all(with_objects => ['warehouse' ]);
774
      my %bins_by_id = map { $_->id => $_ } @$bins;
775
      my $inventories = SL::DB::Manager::Inventory->get_all(where => [ parts_id => $self->part->id],
776
                             with_objects => ['parts', 'trans_type' ], sort_by => 'bin_id ASC');
777
      foreach my $bin (@{ $bins }) {
778
          $bin->{qty} = 0;
779
      }
780

  
781
      foreach my $inv (@{ $inventories }) {
782
          my $bin = $bins_by_id{ $inv->bin_id };
783
          $bin->{qty}      += $inv->qty;
784
          $bin->{unit}     =  $inv->parts->unit;
785
          $bin->{reserved} =  defined $inv->reserve_for_id ? 1 : 0;
786
      }
787
      my $sum = 0;
788
      my $reserve_sum = 0;
789
      for my $bin (@{ $bins }) {
790
        push @bindata , {
791
          'warehouse'    => $bin->warehouse->forreserve ? $bin->warehouse->description.' (R)' : $bin->warehouse->description,
792
          'description'  => $bin->description,
793
          'qty'          => $bin->{qty},
794
          'unit'         => $bin->{unit},
795
        } if $bin->{qty} != 0;
796

  
797
        $sum += $bin->{qty};
798
        if($bin->warehouse->forreserve || defined $bin->warehouse->{reserve_for_id}){
799
          $reserve_sum += $bin->{qty};
800
        }
801
      }
802
      # Einfacher ? $sum = $self->part->onhand
803
      my $todate   = DateTime->now_local;
804
      my $fromdate = DateTime->now_local->add_duration(DateTime::Duration->new(years => -1));
805
      my $average  = 0;
806
      foreach my $inv (@{ $inventories }) {
807
        $average += abs($inv->qty) if $inv->shippingdate && $inv->trans_type->direction eq 'out' &&
808
          DateTime->compare($inv->shippingdate,$fromdate) != -1 &&
809
          DateTime->compare($inv->shippingdate,$todate)   == -1;
810
      }
811
      my $openitems = SL::DB::Manager::OrderItem->get_all(where => [ parts_id => $self->part->id, 'order.closed' => 0 ],
812
                                                           with_objects => ['order'],);
813
      my ($not_delivered, $ordered) = 0;
814
      for my $openitem (@{ $openitems }) {
815
        if($openitem -> order -> type eq 'sales_order') {
816
          $not_delivered += $openitem->qty - $openitem->shipped_qty;
817
        } elsif ( $openitem->order->type eq 'purchase_order' ) {
818
          $ordered += $openitem->qty - $openitem->delivered_qty;
819
        }
820
      }
821
      my $print_form = Form->new('');
822
      my $part = $self->part;
823

  
824
      my $stock_amounts = $self->part->get_simple_stock_sql;
825
      $print_form->{type}      = 'part';
826
      $print_form->{printers}  = SL::DB::Manager::Printer->get_all_sorted;
827
      my $output = SL::Presenter->get->render('part/showdetails',
828
          part          => $self->part,
829
          BINS          => \@bindata,
830
          stock_amounts => $stock_amounts,
831
          average       => $average/12,
832
          fromdate      => $fromdate,
833
          todate        => $todate,
834
          sum           => $sum,
835
          reserve_sum   => $reserve_sum,
836
          not_delivered => $not_delivered,
837
          ordered       => $ordered,
838
          type_beleg    => $::form->{type},
839
          type_id       => $::form->{type_id},
840
          maker_id      => $::form->{maker_id},
841
          drawing       => $::form->{drawing},
771
  my @bindata;
772
  my $bins = SL::DB::Manager::Bin->get_all(with_objects => ['warehouse' ]);
773
  my %bins_by_id = map { $_->id => $_ } @$bins;
774
  my $inventories = SL::DB::Manager::Inventory->get_all(where => [ parts_id => $self->part->id],
775
    with_objects => ['parts', 'trans_type' ], sort_by => 'bin_id ASC');
776
  foreach my $bin (@{ $bins }) {
777
    $bin->{qty} = 0;
778
  }
779

  
780
  foreach my $inv (@{ $inventories }) {
781
    my $bin = $bins_by_id{ $inv->bin_id };
782
    $bin->{qty}      += $inv->qty;
783
    $bin->{unit}     =  $inv->parts->unit;
784
  }
785
  my $sum = 0;
786
  for my $bin (@{ $bins }) {
787
    push @bindata , {
788
      'warehouse'    => $bin->warehouse->description,
789
      'description'  => $bin->description,
790
      'qty'          => $bin->{qty},
791
      'unit'         => $bin->{unit},
792
    } if $bin->{qty} != 0;
793

  
794
    $sum += $bin->{qty};
795
  }
796

  
797
  my $todate   = DateTime->now_local;
798
  my $fromdate = DateTime->now_local->add_duration(DateTime::Duration->new(years => -1));
799
  my $average  = 0;
800
  foreach my $inv (@{ $inventories }) {
801
    $average += abs($inv->qty) if $inv->shippingdate && $inv->trans_type->direction eq 'out' &&
802
    DateTime->compare($inv->shippingdate,$fromdate) != -1 &&
803
    DateTime->compare($inv->shippingdate,$todate)   == -1;
804
  }
805
  my $openitems = SL::DB::Manager::OrderItem->get_all(where => [ parts_id => $self->part->id, 'order.closed' => 0 ],
806
    with_objects => ['order'],);
807
  my ($not_delivered, $ordered) = 0;
808
  for my $openitem (@{ $openitems }) {
809
    if($openitem -> order -> type eq 'sales_order') {
810
      $not_delivered += $openitem->qty - $openitem->shipped_qty;
811
    } elsif ( $openitem->order->type eq 'purchase_order' ) {
812
      $ordered += $openitem->qty - $openitem->delivered_qty;
813
    }
814
  }
815

  
816
  my $stock_amounts = $self->part->get_simple_stock_sql;
817

  
818
  my $output = SL::Presenter->get->render('part/showdetails',
819
    part          => $self->part,
820
    stock_amounts => $stock_amounts,
821
    average       => $average/12,
822
    fromdate      => $fromdate,
823
    todate        => $todate,
824
    sum           => $sum,
825
    not_delivered => $not_delivered,
826
    ordered       => $ordered,
842 827
    print_options   => SL::Helper::PrintOptions->get_print_options(
843
      form => $print_form,
844
      options => {dialog_name_prefix => 'print_options.',
845
                  show_headers       => 1,
846
                  no_queue           => 1,
847
                  no_postscript      => 1,
848
                  no_opendocument    => 1,
849
                  hide_language_id_print => 1,
850
                  no_html            => 1},
828
      form => Form->new(
829
        type     => 'part',
830
        printers => SL::DB::Manager::Printer->get_all_sorted,
831
      ),
832
      options => {
833
        dialog_name_prefix     => 'print_options.',
834
        show_headers           => 1,
835
        no_queue               => 1,
836
        no_postscript          => 1,
837
        no_opendocument        => 1,
838
        hide_language_id_print => 1,
839
        no_html                => 1,
840
      },
851 841
    ),
852
      );
853
      $self->render(\$output, { layout => 0, process => 0 });
854
    1;
855
  } or do {
856
  };
842
  );
843
  $self->render(\$output, { layout => 0, process => 0 });
857 844
}
858 845

  
859 846
sub action_print_label {
js/kivi.DispositionManager.js
35 35

  
36 36
  ns.show_detail_dialog = function(part_id,partnumber) {
37 37
    if ( part_id && partnumber ) {
38
        var title  = kivi.t8('Details of article number "#1"',[partnumber]);
39
        kivi.popup_dialog({
40
                         url:     'controller.pl',
41
                         data: {
42
                                 action: 'Part/showdetails',
43
                                 id    : part_id,
44
                               },
45
                         id:     'detail_menu',
46
                         dialog: { title: title
47
                                  , width:  1000
48
                                  , height: 450
49
                                  , modal:  false }
50
                        });
38
      var title  = kivi.t8('Details of article number "#1"',[partnumber]);
39
      kivi.popup_dialog({
40
        url:     'controller.pl',
41
        data: {
42
          action: 'Part/showdetails',
43
          id    : part_id,
44
        },
45
        id:     'detail_menu',
46
        dialog: {
47
          title: title,
48
          width:  900,
49
          height: 600,
50
          modal:  false
51
        }
52
      });
51 53
    }
52 54
    return true;
53 55
  };
templates/design40_webpages/part/showdetails.html
1
[%- USE LxERP -%][% USE L %][% USE HTML %][%- USE JavaScript -%][% USE T8 %][%- USE Dumper %]
2

  
3
<div class="wrapper">
4
<div class="col"> <!-- part info -->
5
<div class="wrapper">
6
  <table class="tbl-horizontal">
7
    <tbody>
8
      <tr>
9
        <td><b>[%  LxERP.t8('Description') %]</b></td>
10
        <td>[% part.description %]</td>
11
      </tr>
12
      <tr>
13
        <td><b>[%  LxERP.t8('Default Warehouse') %]</b></td>
14
        <td>[% part.warehouse.description %]</td>
15
      </tr>
16
      <tr>
17
        <td><b>[%  LxERP.t8('Default Bin') %]</b></td>
18
        <td>[% part.bin.description %]</td>
19
      </tr>
20
      <tr>
21
        <td><b>[%  LxERP.t8('ROP') %]</b></td><td>[% part.rop_as_number %]</td>
22
      </tr>
23
    </tbody>
24
  </table>
25
</div>
26

  
27
<div class="wrapper">
28
  <table class="tbl-list" style="margin-right: 1em;">
29
    [%- IF stock_amounts.size %]
30
    <thead>
31
      <tr class='listheading'>
32
        <th>[% 'Warehouse'    | $T8 %]</th>
33
        <th>[% 'Bin'          | $T8 %]</th>
34
        <th>[% 'Chargenumber' | $T8 %]</th>
35
        <th>[% 'Qty'          | $T8 %]</th>
36
        <th>[% 'Unit'         | $T8 %]</th>
37
      </tr>
38
    </thead>
39
    <tbody>
40
      [% FOREACH stock = stock_amounts %]
41
      <tr>
42
        <td>[% HTML.escape(stock.warehouse_description) %]</td>
43
        <td>[% HTML.escape(stock.bin_description) %]</td>
44
        <td>[% HTML.escape(stock.chargenumber) %]</td>
45
        <td class='numeric'>[% LxERP.format_amount(stock.qty, dec) %]</td>
46
        <td>[% HTML.escape(stock.unit) %]</td>
47
      </tr>
48
        [% IF stock.wh_lead != stock.warehouse_description %]
49
        <tr>
50
          <th><b>[% HTML.escape(stock.warehouse_description) %]</b></th>
51
          <td></td>
52
          <td></td>
53
          <td class='numeric bold'>[% LxERP.format_amount(stock.wh_run_qty, dec)         %]</td>
54
          <td></td>
55
        </tr>
56
        [% END %]
57
        [% IF loop.last %]
58
        <tr>
59
          <th><b>[% 'Total' | $T8 %]</b></th>
60
          <td></td>
61
          <td></td>
62
          <td class='numeric bold'>[% LxERP.format_amount(stock.run_qty, dec)         %]</td>
63
          <td></td>
64
        </tr>
65
        [% END %]
66
      [% END %]
67
    </tbody>
68
    [% ELSE %]
69
    <thead>
70
      <th>
71
        <p>[% 'No transactions yet.' | $T8 %]</p>
72
      </th>
73
    </thead>
74
    [% END %]
75
  </table>
76
</div>
77

  
78
<div class="wrapper">
79
  <table class="tbl-horizontal">
80
    <tbody>
81
      <tr>
82
        <td><b>[%  LxERP.t8('Sum Amount') %]</b></td>
83
        <td>[% LxERP.format_amount(sum, 2) %] [% part.unit %]</td>
84
      </tr>
85
      <tr>
86
        <td><b>[%  LxERP.t8('Not delivered amount') %]</b></td>
87
        <td>[% LxERP.format_amount(not_delivered, 2) %] [% part.unit %]
88
        </td>
89
      </tr>
90
      <tr>
91
        <td><b>[%  LxERP.t8('Ordered, but not delivered (purchase)') %]</b></td>
92
        <td>[% LxERP.format_amount(ordered, 2) %] [% part.unit %]</td>
93
      </tr>
94
      <tr>
95
        <td><b>[%  LxERP.t8('Available amount') %]</b></td>
96
        <td>[% LxERP.format_amount(part.onhandqty, 2) %] [% part.unit %]</td>
97
      </tr>
98
      <tr>
99
        <td><b>[%  LxERP.t8('Consume average') %]</b></td>
100
        <td>[% LxERP.format_amount(average, 2) %] [% part.unit %] [% LxERP.t8('per month') %]</td>
101
      </tr>
102
      <tr>
103
        <td colspan="2" nowrap>([%  LxERP.t8('in the time between') %] [% fromdate.to_kivitendo %] - [% todate.to_kivitendo %])</td>
104
      </tr>
105
    </tbody></table>
106
</div>
107

  
108
<td>[%- L.button_tag("return \$('#detail_menu').dialog('close');", LxERP.t8('Close Details'), class => "submit") %]</td>
109
</div> <!-- col 1 -->
110

  
111
<div class="col"> <!-- col 2 -->
112
<div id="print_options" class="wrapper">
113
  <form id="print_options_form">
114
    [% print_options %]
115
    <br>
116
    [% L.button_tag('kivi.Part.print_from_showdetail(' _ part.id _ ')', LxERP.t8('Print')) %]
117
  </form>
118
</div>
119

  
120
[% IF part.image && INSTANCE_CONF.get_parts_show_image %]
121
<div class="wrapper">
122
  <a href="[% part.image | html %]" target="_blank"><img style="[% INSTANCE_CONF.get_parts_image_css %]" src="[% part.image | html %]"/></a>
123
</div>
124
[% END %]
125
</div> <!-- col 2 -->
templates/webpages/part/showdetails.html
5 5
      <tr>
6 6
        <td><b>[%  LxERP.t8('Description') %]</b></td><td colspan="3">[% part.description %]</td>
7 7
      </tr>
8
      <tr>
9
        <td style="background:wheat;"><b>[%  LxERP.t8('Internal Notes') %]</b></td><td colspan="3" style="background:wheat;">[% part.intnotes %]</td>
10
      </tr>
11
      <tr>
8
     <tr>
12 9
        <td><b>[%  LxERP.t8('Default Warehouse') %]</b></td><td>[% part.warehouse.description %]</td>
13 10
        <td><b>[%  LxERP.t8('Default Bin') %]</b></td><td>[% part.bin.description %]</td>
14 11
      </tr>
......
64 61
      <tr>
65 62
        <td><b>[%  LxERP.t8('Sum Amount') %]</b></td><td>[% LxERP.format_amount(sum, 2) %] [% part.unit %]</td>
66 63
        <td rowspan="5">
67
          [% file = part.default_partimage %]
68
          [%- IF file && INSTANCE_CONF.get_parts_show_image %]
69
          <img src="controller.pl?action=File/download&id=[% file.id %][%- IF file.version %]&version=[%- file.version %][%- END %]" alt="[% file.title %]" style="[% INSTANCE_CONF.get_parts_image_css %]">
64
          [%- IF part.image && INSTANCE_CONF.get_parts_show_image %]
65
          <a href="[% part.image | html %]" target="_blank"><img style="[% INSTANCE_CONF.get_parts_image_css %]" src="[% part.image | html %]"/></a>
70 66
          [% END %]
71 67
        </td>
72 68
        <td rowspan="5">
73
  [%- FOREACH file = part.get_files %]
74
      <a href="controller.pl?action=File/download&id=[% file.id %][%- IF file.version %]&version=[%- file.version %][%- END %]">
75
        <span id="[% "filename_" _ file.id %][%- IF file.version %]_[% file.version %][%- END %]">[% file.file_name %]</span></a><br><br>
76
  [%- END %]
77 69
        </td>
78 70
      </tr>
79 71
      <tr>
......
82 74
      <tr>
83 75
        <td><b>[%  LxERP.t8('Ordered, but not delivered (purchase)') %]</b></td><td colspan="3">[% LxERP.format_amount(ordered, 2) %] [% part.unit %]</td></tr>
84 76
      </tr>
85
      <tr>
86
        <td><b>[%  LxERP.t8('Reserved amount') %]</b></td><td colspan="3">[% LxERP.format_amount(part.stockqty - part.onhandqty, 2) %] [% part.unit %]</td></tr>
87
      </tr>
88 77
      <tr>
89 78
        <td><b>[%  LxERP.t8('Available amount') %]</b></td><td colspan="3">[% LxERP.format_amount(part.onhandqty, 2) %] [% part.unit %]</td></tr>
90 79
      </tr>

Auch abrufbar als: Unified diff