Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision a6a6121c

Von Sven Schöling vor mehr als 11 Jahren hinzugefügt

  • ID a6a6121c8a7b419bd4130c9374051dba76e4aac6
  • Vorgänger d820c116
  • Nachfolger 9d391728

DeliveryPlan Anpassungen für Filtered Helper

Unterschiede anzeigen:

SL/Controller/DeliveryPlan.pm
8 8
use SL::Controller::Helper::GetModels;
9 9
use SL::Controller::Helper::Paginated;
10 10
use SL::Controller::Helper::Sorted;
11
use SL::Controller::Helper::ParseFilter;
11
use SL::Controller::Helper::Filtered;
12 12
use SL::Controller::Helper::ReportGenerator;
13 13
use SL::Locale::String;
14 14

  
......
19 19
__PACKAGE__->run_before(sub { $::auth->assert('sales_order_edit'); });
20 20

  
21 21
__PACKAGE__->get_models_url_params('flat_filter');
22
__PACKAGE__->make_filtered(
23
  MODEL             => 'OrderItem',
24
  LAUNDER_TO        => 'filter'
25
);
22 26
__PACKAGE__->make_paginated(
23 27
  MODEL         => 'OrderItem',
24
  PAGINATE_ARGS => 'db_args',
25 28
  ONLY          => [ qw(list) ],
26 29
);
27 30

  
......
42 45
  customer          => t8('Customer'),
43 46
);
44 47

  
45
sub action_list {
46
  my ($self) = @_;
47

  
48
  $self->db_args($self->setup_for_list(filter => $::form->{filter}));
49
  $self->flat_filter({ map { $_->{key} => $_->{value} } $::form->flatten_variables('filter') });
50
  $self->make_filter_summary;
51

  
52
  $self->prepare_report;
53

  
54
  my $orderitems = $self->get_models(%{ $self->db_args });
55

  
56
  $self->report_generator_list_objects(report => $self->{report}, objects => $orderitems);
57
}
58

  
59
# private functions
60

  
61
sub setup_for_list {
62
  my ($self, %params) = @_;
63
  $self->{filter} = {};
64
  my %args = (
65
    parse_filter(
66
      $self->_pre_parse_filter($::form->{filter}, $self->{filter}),
67
      with_objects => [ 'order', 'order.customer', 'part' ],
68
      launder_to => $self->{filter},
69
    ),
70
  );
71

  
72
  $args{query} = [ @{ $args{query} || [] },
73
    (
74
      'order.customer_id' => { gt => 0 },
75
      'order.closed' => 0,
76
      or => [ 'order.quotation' => 0, 'order.quotation' => undef ],
77

  
78
      # filter by shipped_qty < qty, read from innermost to outermost
79
      'id' => [ \"
80
        -- 3. resolve the desired information about those
81
        SELECT oi.id FROM (
82
          -- 2. slice only part, orderitem and both quantities from it
83
          SELECT parts_id, trans_id, qty, SUM(doi_qty) AS doi_qty FROM (
84
            -- 1. join orderitems and deliverorder items via record_links.
85
            --    also add customer data to filter for sales_orders
86
            SELECT oi.parts_id, oi.trans_id, oi.id, oi.qty, doi.qty AS doi_qty
87
            FROM orderitems oi, oe, record_links rl, delivery_order_items doi
88
            WHERE
89
              oe.id = oi.trans_id AND
90
              oe.customer_id IS NOT NULL AND
91
              (oe.quotation = 'f' OR oe.quotation IS NULL) AND
92
              NOT oe.closed AND
93
              rl.from_id = oe.id AND
94
              rl.from_id = oi.trans_id AND
95
              oe.id = oi.trans_id AND
96
              rl.from_table = 'oe' AND
97
              rl.to_table = 'delivery_orders' AND
98
              rl.to_id = doi.delivery_order_id AND
99
              oi.parts_id = doi.parts_id
100
          ) tuples GROUP BY parts_id, trans_id, qty
101
        ) partials
102
        LEFT JOIN orderitems oi ON partials.parts_id = oi.parts_id AND partials.trans_id = oi.trans_id
103
        WHERE oi.qty > doi_qty
104

  
105
        UNION ALL
106

  
107
        -- 4. since the join over record_links fails for sales_orders wihtout any delivery order
108
        --    retrieve those without record_links at all
109
        SELECT oi.id FROM orderitems oi, oe
48
my $delivery_plan_query = [
49
  'order.customer_id' => { gt => 0 },
50
  'order.closed' => 0,
51
  or => [ 'order.quotation' => 0, 'order.quotation' => undef ],
52

  
53
  # filter by shipped_qty < qty, read from innermost to outermost
54
  'id' => [ \"
55
    -- 3. resolve the desired information about those
56
    SELECT oi.id FROM (
57
      -- 2. slice only part, orderitem and both quantities from it
58
      SELECT parts_id, trans_id, qty, SUM(doi_qty) AS doi_qty FROM (
59
        -- 1. join orderitems and deliverorder items via record_links.
60
        --    also add customer data to filter for sales_orders
61
        SELECT oi.parts_id, oi.trans_id, oi.id, oi.qty, doi.qty AS doi_qty
62
        FROM orderitems oi, oe, record_links rl, delivery_order_items doi
110 63
        WHERE
111 64
          oe.id = oi.trans_id AND
112 65
          oe.customer_id IS NOT NULL AND
113 66
          (oe.quotation = 'f' OR oe.quotation IS NULL) AND
114 67
          NOT oe.closed AND
115
          oi.trans_id NOT IN (
116
            SELECT from_id
117
            FROM record_links rl
118
            WHERE
119
              rl.from_table ='oe' AND
120
              rl.to_table = 'delivery_orders'
121
          )
122

  
123
        UNION ALL
124

  
125
        -- 5. In case someone deleted a line of the delivery_order there will be a record_link (4 fails)
126
        --    but there won't be a delivery_order_items to find (3 fails too). Search for orphaned orderitems this way
127
        SELECT oi.id FROM orderitems AS oi, oe, record_links AS rl
128
        WHERE
68
          rl.from_id = oe.id AND
69
          rl.from_id = oi.trans_id AND
70
          oe.id = oi.trans_id AND
129 71
          rl.from_table = 'oe' AND
130 72
          rl.to_table = 'delivery_orders' AND
73
          rl.to_id = doi.delivery_order_id AND
74
          oi.parts_id = doi.parts_id
75
      ) tuples GROUP BY parts_id, trans_id, qty
76
    ) partials
77
    LEFT JOIN orderitems oi ON partials.parts_id = oi.parts_id AND partials.trans_id = oi.trans_id
78
    WHERE oi.qty > doi_qty
79

  
80
    UNION ALL
81

  
82
    -- 4. since the join over record_links fails for sales_orders wihtout any delivery order
83
    --    retrieve those without record_links at all
84
    SELECT oi.id FROM orderitems oi, oe
85
    WHERE
86
      oe.id = oi.trans_id AND
87
      oe.customer_id IS NOT NULL AND
88
      (oe.quotation = 'f' OR oe.quotation IS NULL) AND
89
      NOT oe.closed AND
90
      oi.trans_id NOT IN (
91
        SELECT from_id
92
        FROM record_links rl
93
        WHERE
94
          rl.from_table ='oe' AND
95
          rl.to_table = 'delivery_orders'
96
      )
131 97

  
132
          oi.trans_id = rl.from_id AND
133
          oi.parts_id NOT IN (
134
            SELECT doi.parts_id FROM delivery_order_items AS doi WHERE doi.delivery_order_id = rl.to_id
135
          ) AND
98
    UNION ALL
136 99

  
137
          oe.id = oi.trans_id AND
100
    -- 5. In case someone deleted a line of the delivery_order there will be a record_link (4 fails)
101
    --    but there won't be a delivery_order_items to find (3 fails too). Search for orphaned orderitems this way
102
    SELECT oi.id FROM orderitems AS oi, oe, record_links AS rl
103
    WHERE
104
      rl.from_table = 'oe' AND
105
      rl.to_table = 'delivery_orders' AND
138 106

  
139
          oe.customer_id IS NOT NULL AND
140
          (oe.quotation = 'f' OR oe.quotation IS NULL) AND
141
          NOT oe.closed
142
      " ],
143
    )
144
  ];
107
      oi.trans_id = rl.from_id AND
108
      oi.parts_id NOT IN (
109
        SELECT doi.parts_id FROM delivery_order_items AS doi WHERE doi.delivery_order_id = rl.to_id
110
      ) AND
145 111

  
146
  return \%args;
112
      oe.id = oi.trans_id AND
113

  
114
      oe.customer_id IS NOT NULL AND
115
      (oe.quotation = 'f' OR oe.quotation IS NULL) AND
116
      NOT oe.closed
117
  " ],
118
];
119

  
120
sub action_list {
121
  my ($self) = @_;
122

  
123
  $self->make_filter_summary;
124

  
125
  my $orderitems = $self->get_models(query => $delivery_plan_query, with_objects => [ 'order', 'order.customer', 'part' ]);
126

  
127
  $self->prepare_report;
128
  $self->report_generator_list_objects(report => $self->{report}, objects => $orderitems);
147 129
}
148 130

  
131
# private functions
132
#
149 133
sub prepare_report {
150 134
  my ($self)      = @_;
151 135

  
......
209 193
    [ $filter->{order}{customer}{"customernumber:substr::ilike"}, $::locale->text('Customer Number')                                    ],
210 194
  );
211 195

  
212
  my @flags = (
213
    [ $filter->{part}{type}{part},     $::locale->text('Parts')      ],
214
    [ $filter->{part}{type}{service},  $::locale->text('Services')   ],
215
    [ $filter->{part}{type}{assembly}, $::locale->text('Assemblies') ],
196
  my %flags = (
197
    part     => $::locale->text('Parts'),
198
    service  => $::locale->text('Services'),
199
    assembly => $::locale->text('Assemblies'),
216 200
  );
201
  my @flags = map { $flags{$_} } @{ $filter->{part}{type} || [] };
217 202

  
218 203
  for (@flags) {
219
    push @filter_strings, "$_->[1]" if $_->[0];
204
    push @filter_strings, $_ if $_;
220 205
  }
221 206
  for (@filters) {
222 207
    push @filter_strings, "$_->[1]: $_->[0]" if $_->[0];
......
248 233
  }
249 234
}
250 235

  
251
# unfortunately ParseFilter can't handle compount filters.
252
# so we clone the original filter (still need that for serializing)
253
# rip out the options we know an replace them with the compound options.
254
# ParseFilter will take care of the prefixing then.
255
sub _pre_parse_filter {
256
  my ($self, $orig_filter, $launder_to) = @_;
257

  
258
  return undef unless $orig_filter;
259

  
260
  my $filter = clone($orig_filter);
261
  if ($filter->{part} && $filter->{part}{type}) {
262
    $launder_to->{part}{type} = delete $filter->{part}{type};
263
    my @part_filters = grep $_, map {
264
      $launder_to->{part}{type}{$_} ? SL::DB::Manager::Part->type_filter($_) : ()
265
    } qw(part service assembly);
266

  
267
    push @{ $filter->{and} }, or => [ @part_filters ] if @part_filters;
268
  }
269

  
270
  for my $op (qw(le ge)) {
271
    if ($filter->{"reqdate:date::$op"}) {
272
      $launder_to->{"reqdate_date__$op"} = delete $filter->{"reqdate:date::$op"};
273
      my $parsed_date = DateTime->from_lxoffice($launder_to->{"reqdate_date__$op"});
274
      push @{ $filter->{and} }, or => [
275
        'reqdate' => { $op => $parsed_date },
276
        and => [
277
          'reqdate' => undef,
278
          'order.reqdate' => { $op => $parsed_date },
279
        ]
280
      ] if $parsed_date;
281
    }
282
  }
283

  
284
  if (my $style = delete $filter->{searchstyle}) {
285
    $self->{searchstyle}       = $style;
286
    $launder_to->{searchstyle} = $style;
287
  }
288

  
289
  return $filter;
290
}
291

  
292 236
1;

Auch abrufbar als: Unified diff