Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision dfe28d97

Von Werner Hahn vor etwa 1 Jahr hinzugefügt

  • ID dfe28d977ea3d65757b769066a88ddcd1ec4fcde
  • Vorgänger 3a2b956d
  • Nachfolger 4bd64342

DispositionsManager: Prototyp ohne Auftrag erstellen

Unterschiede anzeigen:

SL/Controller/DispositionsManager.pm
1
package SL::Controller::DispositionsManager;
2

  
3

  
4
use strict;
5

  
6
use parent qw(SL::Controller::Base);
7

  
8
use SL::DB::Part;
9
use SL::DB::PurchaseBasket;
10
use SL::Locale::String qw(t8);
11

  
12
sub action_list_parts {
13
  my ( $self ) = @_;
14

  
15
  my $query = <<SQL;
16
SELECT * FROM parts WHERE onhand <= rop AND rop != 0 AND id NOT IN( SELECT parts_id FROM purchase_basket) AND NOT obsolete
17
SQL
18

  
19
  my $parts = SL::DB::Manager::Part->get_objects_from_sql( sql => $query );
20
  $self->_setup_list_action_bar;
21
  $self->render('dispositionsmanager/list_parts', title => t8('Parts short onhand'), PARTS => $parts);
22

  
23

  
24
}
25

  
26
sub action_add_to_purchase_basket{
27
  my ( $self ) = @_;
28

  
29
  my $parts_to_add = delete($::form->{id}) || [];
30
  foreach my $id (@{ $parts_to_add }) {
31
    my $part = SL::DB::Manager::Part->get_first( query => [ id => $id ] );
32
    my $basket_part = SL::DB::PurchaseBasket->new(
33
                              parts_id    => $part->id,
34
                              qty         => $part->min_order_qty,
35
                              description => $part->description,
36
                            );
37
   $basket_part->save;
38
 }
39
 $self->action_show_basket;
40

  
41
}
42

  
43
sub action_show_basket {
44
  my ( $self ) = @_;
45

  
46
  $::request->{layout}->add_javascripts('kivi.DispositionsManager.js');
47
  my $basket = SL::DB::Manager::PurchaseBasket->get_all( query => [ cleared => 'F' ],  with_objects => [ 'parts', 'parts.makemodels' ]);
48
  $self->_setup_show_basket_action_bar;
49
  $self->render('dispositionsmanager/show_purchase_basket', PARTS => $basket );
50
}
51

  
52
sub action_transfer_to_purchase_order {
53
  my ( $self ) = @_;
54

  
55

  
56
}
57

  
58
sub _setup_list_action_bar {
59
  my ($self) = @_;
60
  for my $bar ($::request->layout->get('actionbar')) {
61
    $bar->add(
62
      action => [
63
        t8('Action'),
64
        submit   => [ '#form', { action => "DispositionsManager/add_to_purchase_basket" } ],
65
        tooltip  => t8('Add to purchase basket'),
66
      ],
67
    );
68
  }
69
}
70

  
71
sub _setup_show_basket_action_bar {
72
  my ($self) = @_;
73
  for my $bar ($::request->layout->get('actionbar')) {
74
    $bar->add(
75
      action => [
76
        t8('Reload'),
77
        submit   => [ '#form', { action => "DispositionsManager/show_basket" } ],
78
      ],
79
      action => [
80
        t8('Action'),
81
        submit   => [ '#form', { action => "DispositionsManager/transfer_to_purchase_order" } ],
82
        tooltip  => t8('Create purchase order'),
83
      ],
84
    );
85
  }
86
}
87
1;
88

  
89
__END__
90

  
91
=encoding utf-8
92

  
93
=head1 NAME
94

  
95
SL::Controller::DispositionsManager Controller to manage purchaseorders for parts
96

  
97
=head1 DESCRIPTION
98

  
99
This Controller shows a list of parts using the filter minimum stock (rop).
100
From this list it is possible to put parts in a purchase basket to order.
101
It's also possible to put parts from the parts edit form in the purchase basket.
102

  
103
From the purchase basket you can create a purchaseorder by using the filter vendor.
104
The quantity to order will be prefilled by the value min_qty_to_order from parts or
105
makemodel(vendor_parts) or default qty 1.
106

  
107
Tables:
108

  
109
=over 2
110

  
111
=item purchase_basket
112

  
113
=back
114

  
115
Depencies:
116

  
117
=over 2
118

  
119
=item parts
120

  
121
=item makemodels
122

  
123

  
124
=back
125

  
126
=head1 URL ACTIONS
127

  
128
=over 4
129

  
130
=item C<action_list_parts>
131

  
132
List the parts by the filter min stock (rop) and not in an open purchase order.
133

  
134
=item C<action_add_to_purchase_basket>
135

  
136
Adds one or more parts to the purchase basket.
137

  
138
=item C<action_show_basket>
139

  
140
Shows a list with parts wich are in the basket.
141
This List can be filtered by vendor. Then you can create a purchaseorder.
142

  
143
=item C<action_transfer_to_purchase_order>
144

  
145
Transfers the marked and by vendor filtered parts to a purchase order.
146
Deletes the entry in the purchasebasket.
147

  
148
=back
149

  
150
=head1 BUGS
151

  
152
None yet. :)
153

  
154
=head1 AUTHOR
155

  
156
W. Hahn E<lt>wh@futureworldsearch.netE<gt>
157

  
158
=cut
SL/Controller/Part.pm
513 513
                                  part_longdescription => '',
514 514
                                  lastcost             => 0,
515 515
                                  sortorder            => $position,
516
                                  min_order_qty        => '1',
516 517
                                 ) or die "Can't create MakeModel object";
517 518

  
518 519
  my $row_as_html = $self->p->render('part/_makemodel_row',
......
986 987

  
987 988
  my $position = 0;
988 989
  my $makemodels = delete($::form->{makemodels}) || [];
990
$main::lxdebug->dump(0, 'WH:MMFORM ', $makemodels);
989 991
  foreach my $makemodel ( @{$makemodels} ) {
990 992
    next unless $makemodel->{make};
991 993
    $position++;
......
1178 1180
  my $position = 0;
1179 1181
  my @makemodel_array = ();
1180 1182
  my $makemodels = delete($::form->{makemodels}) || [];
1183
$main::lxdebug->dump(0, 'WH:MM ', $makemodels);
1181 1184

  
1182 1185
  foreach my $makemodel ( @{$makemodels} ) {
1183 1186
    next unless $makemodel->{make};
......
1190 1193
                                    part_longdescription => $makemodel->{part_longdescription} || '',
1191 1194
                                    lastcost             => $::form->parse_amount(\%::myconfig, $makemodel->{lastcost_as_number} || 0),
1192 1195
                                    sortorder            => $position,
1196
                                    min_order_qty => $::form->parse_amount(\%::myconfig, $makemodel->{min_order_qty_as_number} || 0),
1193 1197
                                  ) or die "Can't create mm";
1194 1198
    # $mm->id($makemodel->{id}) if $makemodel->{id};
1195 1199
    push(@makemodel_array, $mm);
SL/DB/Helper/Mappings.pm
187 187
  project_roles                  => 'project_role',
188 188
  project_statuses               => 'project_status',
189 189
  project_types                  => 'project_type',
190
  purchase_basket                => 'purchase_basket',
190 191
  reclamations                   => 'Reclamation',
191 192
  reclamation_items              => 'ReclamationItem',
192 193
  reclamation_reasons            => 'ReclamationReason',
SL/DB/Manager/PurchaseBasket.pm
1
# This file has been auto-generated only because it didn't exist.
2
# Feel free to modify it at will; it will not be overwritten automatically.
3

  
4
package SL::DB::Manager::PurchaseBasket;
5

  
6
use strict;
7

  
8
use parent qw(SL::DB::Helper::Manager);
9

  
10
sub object_class { 'SL::DB::PurchaseBasket' }
11

  
12
__PACKAGE__->make_manager_methods;
13

  
14
1;
SL/DB/MetaSetup/MakeModel.pm
14 14
  lastcost             => { type => 'numeric', precision => 15, scale => 5 },
15 15
  lastupdate           => { type => 'date' },
16 16
  make                 => { type => 'integer' },
17
  min_order_qty        => { type => 'numeric', precision => 15, scale => 5 },
17 18
  model                => { type => 'text' },
18 19
  mtime                => { type => 'timestamp' },
19 20
  part_description     => { type => 'text' },
SL/DB/MetaSetup/PurchaseBasket.pm
1
# This file has been auto-generated. Do not modify it; it will be overwritten
2
# by rose_auto_create_model.pl automatically.
3
package SL::DB::PurchaseBasket;
4

  
5
use strict;
6

  
7
use parent qw(SL::DB::Object);
8

  
9
__PACKAGE__->meta->table('purchase_basket');
10

  
11
__PACKAGE__->meta->columns(
12
  cleared     => { type => 'boolean', default => 'false', not_null => 1 },
13
  description => { type => 'text' },
14
  id          => { type => 'serial', not_null => 1 },
15
  parts_id    => { type => 'integer' },
16
  qty         => { type => 'numeric', precision => 15, scale => 5 },
17
);
18

  
19
__PACKAGE__->meta->primary_key_columns([ 'id' ]);
20

  
21
__PACKAGE__->meta->foreign_keys(
22
  parts => {
23
    class       => 'SL::DB::Part',
24
    key_columns => { parts_id => 'id' },
25
  },
26
);
27

  
28
1;
29
;
SL/DB/Part.pm
12 12
use SL::DB::MetaSetup::Part;
13 13
use SL::DB::Manager::Part;
14 14
use SL::DB::Chart;
15
use SL::DB::Vendor;
15 16
use SL::DB::Helper::AttrHTML;
16 17
use SL::DB::Helper::AttrSorted;
17 18
use SL::DB::Helper::TransNumberGenerator;
......
578 579
  return 1;
579 580
}
580 581

  
582
sub vendor_dropdown {
583
  my ( $self ) = @_;
584

  
585
  my @vendor_dd;
586
  # $main::lxdebug->dump(0, 'WH:MakeModels ', $_[0]->makemodels);
587

  
588
  foreach my $mm ( @{$_[0]->makemodels} ){
589
    my $vendor = SL::DB::Manager::Vendor->get_first( where => [ id => $mm->make ] );
590
    my @tmp = ({ title => $vendor->name, value => $vendor->{id} });
591
    push @vendor_dd, @tmp;
592
  }
593
  return \@vendor_dd;
594
}
595

  
581 596
1;
582 597

  
583 598
__END__
SL/DB/PurchaseBasket.pm
1
# This file has been auto-generated only because it didn't exist.
2
# Feel free to modify it at will; it will not be overwritten automatically.
3

  
4
package SL::DB::PurchaseBasket;
5

  
6
use strict;
7

  
8
use SL::DB::MetaSetup::PurchaseBasket;
9
use SL::DB::Manager::PurchaseBasket;
10

  
11
__PACKAGE__->meta->initialize;
12

  
13

  
14
1;
js/kivi.DispositionsManager.js
1
namespace('kivi.DispositionsManager', function(ns) {
2
  ns.sort_vendors = function() {
3
    $("table tr").each(function(index) {
4
      if ( index !== 0 ) {
5
        $row = $(this);
6
    //    alert( $row.find('#vendor_id').val() + '!=' + $('#cv_id').val());
7
        if( $row.find('#vendor_id').val() != $('#cv_id').val()) {
8
          $row.remove();
9
        }
10
      }
11
    });
12
  }
13
});
menus/user/10-dispositionsmanager.yaml
1
---
2
- parent: ap
3
  id: ap_disp_manager
4
  name: Dispositionsmanager
5
  icon: rfq_add
6
  order: 150
7
  access: request_quotation_edit
8
- parent: ap_disp_manager
9
  id: ap_disp_manager_onhand
10
  name: List short onhand
11
  order: 160
12
  params:
13
    action: DispositionsManager/list_parts
14
- parent: ap_disp_manager
15
  id: ap_disp_manager_basket
16
  name: Show purchase basket
17
  order: 170
18
  params:
19
    action: DispositionsManager/show_basket
sql/Pg-upgrade2/purchase_basket.sql
1
-- @tag: purchase_basket
2
-- @description: Tabelle für den Dispostionsmanager
3
-- @depends: release_3_5_1
4
-- @ignore: 0
5

  
6
CREATE TABLE purchase_basket (
7
  id SERIAL PRIMARY KEY,
8
  parts_id INTEGER REFERENCES parts(id),
9
  qty NUMERIC(15,5),
10
  description text,
11
  cleared BOOLEAN NOT NULL DEFAULT FALSE
12
);
13

  
14
ALTER TABLE parts     ADD COLUMN min_order_qty NUMERIC(15,5);
15
ALTER TABLE makemodel ADD COLUMN min_order_qty NUMERIC(15,5);
templates/webpages/dispositionsmanager/list_parts.html
1
[%- USE HTML -%][%- USE LxERP -%][%- USE L -%][%- USE T8 -%]
2
[% USE Dumper %]
3
[%- INCLUDE 'common/flash.html' %]
4
<h1>[% title %]</h1>
5
<hr>
6
<h2>[% 'Short onhand' | $T8 %]</h2>
7
<form id="form">
8
  <table>
9
    <thead>
10
     <tr class="listheading">
11
       <th>[% L.checkbox_tag('check_all') %][% 'Purchasebasket' | $T8 %] </th>
12
       <th>[% 'Partnumber'                                      | $T8 %] </th>
13
       <th>[% 'Description'                                     | $T8 %] </th>
14
       <th>[% 'Onhand'                                          | $T8 %] </th>
15
       <th>[% 'Rop'                                             | $T8 %] </th>
16
       <th>[% 'Minimum order quantity'                          | $T8 %] </th>
17
     </tr>
18
    </thead>
19
    [% FOREACH part = PARTS %]
20
      [% IF !part.get_ordered_qty(part.id) %]
21
      <tr class="listrow">
22
        <td>[% IF part.makemodels.size %][% L.checkbox_tag('id[]', checked = '1',  value=part.id) %][% ELSE %][% 'No Vendor' | $T8 %][% END %]</td>
23
        <td>[% HTML.escape(part.partnumber) %] </td>
24
        <td>[% HTML.escape(part.description) %]</td>
25
        <td>[% part.onhand_as_number %]        </td>
26
        <td>[% part.rop_as_number %]           </td>
27
        <td>[% part.min_order_qty_as_number %] </td>
28
      </tr>
29
      [% END %]
30
    [% END %]
31
  </table>
32
</form>
33
<hr>
34
<h2>[% 'Short onhand Ordered' | $T8 %]</h2>
35
<table>
36
  <thead>
37
   <tr class="listheading">
38
     <th>[% 'Partnumber'       | $T8 %] </th>
39
     <th>[% 'Description'      | $T8 %] </th>
40
     <th>[% 'onhand'           | $T8 %] </th>
41
     <th>[% 'rop'              | $T8 %] </th>
42
     <th>[% 'Ordered purchase' | $T8 %] </th>
43
   </tr>
44
  </thead>
45
  [% FOREACH part = PARTS %]
46
    [% IF part.get_ordered_qty(part.id) %]
47
    <tr class="listrow">
48
      <td>[% HTML.escape(part.partnumber) %]  </td>
49
      <td>[% HTML.escape(part.description) %] </td>
50
      <td>[% part.onhand_as_number %]         </td>
51
      <td>[% part.rop_as_number %]            </td>
52
      <td>[% part.get_ordered_qty(part.id) %] </td>
53
    </tr>
54
    [% END %]
55
  [% END %]
56
</table>
57
<script type="text/javascript">
58
<!--
59

  
60
  kivi.DispositionsManager.sort_vendors();
61
$(function() {
62
  alert('hallo9');
63
  $('#check_all').checkall('INPUT[name^="id"]');
64
  kivi.DispositionsManager.sort_vendors();
65
});
66
-->
67
</script>
templates/webpages/dispositionsmanager/show_purchase_basket.html
1
[%- USE HTML -%][%- USE LxERP -%][%- USE L -%][%- USE T8 -%][% USE P %]
2
[% USE Dumper %]
3
[%- INCLUDE 'common/flash.html' %]
4
<h1>[% title %]</h1>
5
<hr>
6
[% # Dumper.dump_html(PARTS) %]
7
<form id="form">
8
[% P.customer_vendor.picker('vendor_id2', '', type='vendor', fat_set_item=1) %]<br>
9
<div>id  from change: <span id='change3'></span></div>
10
[% L.hidden_tag('cv_id', '') %]
11
  <table id="baskettable">
12
    <thead>
13
     <tr class="listheading">
14
       <th>[% L.checkbox_tag('check_all') %][% 'Purchasebasket' | $T8 %] </th>
15
       <th>[% 'Partnumber'                                      | $T8 %] </th>
16
       <th>[% 'Description'                                     | $T8 %] </th>
17
       <th>[% 'Onhand'                                          | $T8 %] </th>
18
       <th>[% 'Rop'                                             | $T8 %] </th>
19
       <th>[% 'Order quantity'                                  | $T8 %] </th>
20
       <th>[% 'Vendor'                                          | $T8 %] </th>
21
     </tr>
22
    </thead>
23
    <tbody>
24
    [% FOREACH part = PARTS %]
25
    [% SET select_size = part.parts.vendor_dropdown.size %]
26
      [% IF !part.part.get_ordered_qty(part.id) %]
27
      <tr class="listrow">
28
        <td>[% L.checkbox_tag('id[]', checked = '1',  value=part.id) %]</td>
29
        <td>[% HTML.escape(part.parts.partnumber) %] </td>
30
        <td>[% HTML.escape(part.parts.description) %]</td>
31
        <td>[% part.parts.onhand_as_number %]        </td>
32
        <td>[% part.parts.rop_as_number %]           </td>
33
        <td>[% part.parts.min_order_qty %]           </td>
34
        <td>[% L.select_tag('vendor_id', part.parts.vendor_dropdown, value_key = 'value', title_key = 'title', default = part.parts.makemodels.item(0).make, size = select_size, style='width: 350px;' ) %]</td>
35
      </tr>
36
      [% END %]
37
    [% END %]
38
    </tbody>
39
  </table>
40
</form>
41
<script type="text/javascript">
42
<!--
43

  
44
 $('#vendor_id2').change(function() { $('#change3').html($('#vendor_id2').val()) })
45
 $('#vendor_id2').on('set_item:CustomerVendorPicker', function(e,o) {
46
   $('#cv_id').val(o.id)
47
   kivi.DispositionsManager.sort_vendors();
48
 })
49
$(function() {
50
  $('#check_all').checkall('INPUT[name^="id"]');
51
});
52
-->
53
</script>
templates/webpages/part/_basic_data.html
178 178
           </td>
179 179
          </tr>
180 180
        [%- END %]
181
          <tr>
182
           <th align="right" nowrap="true">[% 'Minimum order Quantity' | $T8 %]</th>
183
           <td>[% L.input_tag("part.min_order_qty_as_number", SELF.part.min_order_qty_as_number, size=10, class="reformat_number numeric") %]</td>
184
          </tr>
181 185
          <tr>
182 186
           <th align="right" nowrap="true">[% 'Verrechnungseinheit' | $T8 %]</th>
183 187
           <td>[% L.input_tag("part.ve", SELF.part.ve, size=10) %]</td>

Auch abrufbar als: Unified diff