Revision b213d89c
Von Sven Schöling vor mehr als 12 Jahren hinzugefügt
SL/Controller/DeliveryPlan.pm | ||
---|---|---|
1 |
package SL::Controller::DeliveryPlan; |
|
2 | ||
3 |
use strict; |
|
4 |
use parent qw(SL::Controller::Base); |
|
5 | ||
6 |
use Clone qw(clone); |
|
7 |
use SL::DB::OrderItem; |
|
8 |
use SL::Controller::Helper::ParseFilter; |
|
9 |
use SL::Controller::Helper::ReportGenerator; |
|
10 | ||
11 |
__PACKAGE__->run_before(sub { $::auth->assert('sales_order_edit'); }); |
|
12 | ||
13 |
sub action_list { |
|
14 |
my ($self) = @_; |
|
15 |
my %list_params = ( |
|
16 |
sort_by => $::form->{sort_by} || 'reqdate', |
|
17 |
sort_dir => $::form->{sort_dir}, |
|
18 |
filter => $::form->{filter}, |
|
19 |
page => $::form->{page}, |
|
20 |
); |
|
21 | ||
22 |
my $db_args = $self->setup_for_list(%list_params); |
|
23 |
$self->{pages} = SL::DB::Manager::OrderItem->paginate(%list_params, args => $db_args); |
|
24 |
$self->{flat_filter} = { map { $_->{key} => $_->{value} } $::form->flatten_variables('filter') }; |
|
25 | ||
26 |
my $top = $::form->parse_html_template('delivery_plan/report_top', { FORM => $::form, SELF => $self }); |
|
27 |
my $bottom = $::form->parse_html_template('delivery_plan/report_bottom', { SELF => $self }); |
|
28 | ||
29 |
$self->prepare_report( |
|
30 |
report_generator_options => { |
|
31 |
raw_top_info_text => $top, |
|
32 |
raw_bottom_info_text => $bottom, |
|
33 |
controller_class => 'DeliveryPlan', |
|
34 |
}, |
|
35 |
report_generator_export_options => [ |
|
36 |
'list', qw(filter sort_by sort_dir), |
|
37 |
], |
|
38 |
db_args => $db_args, |
|
39 |
); |
|
40 | ||
41 |
$self->{orderitems} = SL::DB::Manager::OrderItem->get_all(%$db_args); |
|
42 | ||
43 |
$self->list_objects; |
|
44 |
} |
|
45 | ||
46 |
# private functions |
|
47 | ||
48 |
sub setup_for_list { |
|
49 |
my ($self, %params) = @_; |
|
50 |
$self->{filter} = {}; |
|
51 |
my %args = ( |
|
52 |
parse_filter( |
|
53 |
$self->_pre_parse_filter($::form->{filter}, $self->{filter}), |
|
54 |
with_objects => [ 'order', 'order.customer', 'part' ], |
|
55 |
launder_to => $self->{filter}, |
|
56 |
), |
|
57 |
sort_by => $self->set_sort_params(%params), |
|
58 |
page => $params{page}, |
|
59 |
); |
|
60 | ||
61 |
$args{query} = [ @{ $args{query} || [] }, |
|
62 |
( |
|
63 |
'order.customer_id' => { gt => 0 }, |
|
64 |
'order.closed' => 0, |
|
65 |
or => [ 'order.quotation' => 0, 'order.quotation' => undef ], |
|
66 | ||
67 |
# filter by shipped_qty < qty, read from innermost to outermost |
|
68 |
'id' => [ \" |
|
69 |
-- 3. resolve the desired information about those |
|
70 |
SELECT oi.id FROM ( |
|
71 |
-- 2. slice only part, orderitem and both quantities from it |
|
72 |
SELECT parts_id, trans_id, qty, SUM(doi_qty) AS doi_qty FROM ( |
|
73 |
-- 1. join orderitems and deliverorder items via record_links. |
|
74 |
-- also add customer data to filter for sales_orders |
|
75 |
SELECT oi.parts_id, oi.trans_id, oi.id, oi.qty, doi.qty AS doi_qty |
|
76 |
FROM orderitems oi, oe, record_links rl, delivery_order_items doi |
|
77 |
WHERE |
|
78 |
oe.id = oi.trans_id AND |
|
79 |
oe.customer_id IS NOT NULL AND |
|
80 |
(oe.quotation = 'f' OR oe.quotation IS NULL) AND |
|
81 |
NOT oe.closed AND |
|
82 |
rl.from_id = oe.id AND |
|
83 |
rl.from_id = oi.trans_id AND |
|
84 |
oe.id = oi.trans_id AND |
|
85 |
rl.from_table = 'oe' AND |
|
86 |
rl.to_table = 'delivery_orders' AND |
|
87 |
rl.to_id = doi.delivery_order_id AND |
|
88 |
oi.parts_id = doi.parts_id |
|
89 |
) tuples GROUP BY parts_id, trans_id, qty |
|
90 |
) partials |
|
91 |
LEFT JOIN orderitems oi ON partials.parts_id = oi.parts_id AND partials.trans_id = oi.trans_id |
|
92 |
WHERE oi.qty > doi_qty |
|
93 | ||
94 |
UNION ALL |
|
95 | ||
96 |
-- 4. since the join over record_links fails for sales_orders wihtout any delivery order |
|
97 |
-- retrieve those without record_links at all |
|
98 |
SELECT oi.id FROM orderitems oi, oe |
|
99 |
WHERE |
|
100 |
oe.id = oi.trans_id AND |
|
101 |
oe.customer_id IS NOT NULL AND |
|
102 |
(oe.quotation = 'f' OR oe.quotation IS NULL) AND |
|
103 |
NOT oe.closed AND |
|
104 |
oi.trans_id NOT IN ( |
|
105 |
SELECT from_id |
|
106 |
FROM record_links rl |
|
107 |
WHERE |
|
108 |
rl.from_table ='oe' AND |
|
109 |
rl.to_table = 'delivery_orders' |
|
110 |
) |
|
111 |
" ], |
|
112 |
) |
|
113 |
]; |
|
114 | ||
115 |
return \%args; |
|
116 |
} |
|
117 | ||
118 |
sub set_sort_params { |
|
119 |
my ($self, %params) = @_; |
|
120 |
my $sort_str; |
|
121 |
($self->{sort_by}, $self->{sort_dir}, $sort_str) = |
|
122 |
SL::DB::Manager::OrderItem->make_sort_string(%params); |
|
123 |
return $sort_str; |
|
124 |
} |
|
125 | ||
126 |
sub prepare_report { |
|
127 |
my ($self, %params) = @_; |
|
128 | ||
129 |
my $objects = $params{objects} || []; |
|
130 |
my $report = SL::ReportGenerator->new(\%::myconfig, $::form); |
|
131 |
$self->{report} = $report; |
|
132 | ||
133 |
my @columns = qw(reqdate customer ordnumber partnumber description qty shipped_qty); |
|
134 |
my @visible = qw(reqdate partnumber description qty shipped_qty ordnumber customer); |
|
135 |
my @sortable = qw(reqdate partnumber description ordnumber customer); |
|
136 | ||
137 |
my %column_defs = ( |
|
138 |
reqdate => { text => $::locale->text('Reqdate'), |
|
139 |
sub => sub { $_[0]->reqdate_as_date || $_[0]->order->reqdate_as_date }}, |
|
140 |
description => { text => $::locale->text('Description'), |
|
141 |
sub => sub { $_[0]->description }, |
|
142 |
obj_link => sub { $self->link_to($_[0]->part) }}, |
|
143 |
partnumber => { text => $::locale->text('Part Number'), |
|
144 |
sub => sub { $_[0]->part->partnumber }, |
|
145 |
obj_link => sub { $self->link_to($_[0]->part) }}, |
|
146 |
qty => { text => $::locale->text('Qty'), |
|
147 |
sub => sub { $_[0]->qty_as_number . ' ' . $_[0]->unit }}, |
|
148 |
shipped_qty => { text => $::locale->text('shipped'), |
|
149 |
sub => sub { $::form->format_amount(\%::myconfig, $_[0]->shipped_qty, 2) . ' ' . $_[0]->unit }}, |
|
150 |
ordnumber => { text => $::locale->text('Order'), |
|
151 |
sub => sub { $_[0]->order->ordnumber }, |
|
152 |
obj_link => sub { $self->link_to($_[0]->order) }}, |
|
153 |
customer => { text => $::locale->text('Customer'), |
|
154 |
sub => sub { $_[0]->order->customer->name }, |
|
155 |
obj_link => sub { $self->link_to($_[0]->order->customer) }}, |
|
156 |
); |
|
157 | ||
158 | ||
159 |
for my $col (@sortable) { |
|
160 |
$column_defs{$col}{link} = $self->url_for( |
|
161 |
action => 'list', |
|
162 |
sort_by => $col, |
|
163 |
sort_dir => ($self->{sort_by} eq $col ? 1 - $self->{sort_dir} : $self->{sort_dir}), |
|
164 |
page => $self->{pages}{cur}, |
|
165 |
%{ $self->{flat_filter} }, |
|
166 |
); |
|
167 |
} |
|
168 | ||
169 |
map { $column_defs{$_}->{visible} = 1 } @visible; |
|
170 | ||
171 |
$report->set_columns(%column_defs); |
|
172 |
$report->set_column_order(@columns); |
|
173 |
$report->set_options(allow_pdf_export => 1, allow_csv_export => 1); |
|
174 |
$report->set_sort_indicator(%params); |
|
175 |
$report->set_export_options(@{ $params{report_generator_export_options} || [] }); |
|
176 |
$report->set_options( |
|
177 |
%{ $params{report_generator_options} || {} }, |
|
178 |
output_format => 'HTML', |
|
179 |
top_info_text => $::locale->text('Delivery Plan for currently outstanding sales orders'), |
|
180 |
title => $::locale->text('Delivery Plan'), |
|
181 |
); |
|
182 |
$report->set_options_from_form; |
|
183 | ||
184 |
SL::DB::Manager::OrderItem->disable_paginating(args => $params{db_args}) if $report->{options}{output_format} =~ /^(pdf|csv)$/i; |
|
185 | ||
186 |
$self->{report_data} = { |
|
187 |
column_defs => \%column_defs, |
|
188 |
columns => \@columns, |
|
189 |
visible => \@visible, |
|
190 |
sortable => \@sortable, |
|
191 |
}; |
|
192 |
} |
|
193 | ||
194 |
sub list_objects { |
|
195 |
my ($self) = @_; |
|
196 |
my $column_defs = $self->{report_data}{column_defs}; |
|
197 |
for my $obj (@{ $self->{orderitems} || [] }) { |
|
198 |
$self->{report}->add_data({ |
|
199 |
map { |
|
200 |
$_ => { |
|
201 |
data => $column_defs->{$_}{sub} ? $column_defs->{$_}{sub}->($obj) |
|
202 |
: $obj->can($_) ? $obj->$_ |
|
203 |
: $obj->{$_}, |
|
204 |
link => $column_defs->{$_}{obj_link} ? $column_defs->{$_}{obj_link}->($obj) : '', |
|
205 |
}, |
|
206 |
} @{ $self->{report_data}{columns} || {} } |
|
207 |
}); |
|
208 |
} |
|
209 | ||
210 |
return $self->{report}->generate_with_headers; |
|
211 |
} |
|
212 | ||
213 |
sub link_to { |
|
214 |
my ($self, $object, %params) = @_; |
|
215 | ||
216 |
return unless $object; |
|
217 |
my $action = $params{action} || 'edit'; |
|
218 | ||
219 |
if ($object->isa('SL::DB::Order')) { |
|
220 |
my $type = $object->type; |
|
221 |
my $vc = $object->is_sales ? 'customer' : 'vendor'; |
|
222 |
my $id = $object->id; |
|
223 | ||
224 |
return "oe.pl?action=$action&type=$type&vc=$vc&id=$id"; |
|
225 |
} |
|
226 |
if ($object->isa('SL::DB::Part')) { |
|
227 |
my $id = $object->id; |
|
228 |
return "ic.pl?action=$action&id=$id"; |
|
229 |
} |
|
230 |
if ($object->isa('SL::DB::Customer')) { |
|
231 |
my $id = $object->id; |
|
232 |
return "ct.pl?action=$action&id=$id&db=customer"; |
|
233 |
} |
|
234 |
} |
|
235 | ||
236 |
# unfortunately ParseFilter can't handle compount filters. |
|
237 |
# so we clone the original filter (still need that for serializing) |
|
238 |
# rip out the options we know an replace them with the compound options. |
|
239 |
# ParseFilter will take care of the prefixing then. |
|
240 |
sub _pre_parse_filter { |
|
241 |
my ($self, $orig_filter, $launder_to) = @_; |
|
242 | ||
243 |
return undef unless $orig_filter; |
|
244 | ||
245 |
my $filter = clone($orig_filter); |
|
246 |
if ($filter->{part} && $filter->{part}{type}) { |
|
247 |
$launder_to->{part}{type} = delete $filter->{part}{type}; |
|
248 |
my @part_filters = grep $_, map { |
|
249 |
$launder_to->{part}{type}{$_} ? SL::DB::Manager::Part->type_filter($_) : () |
|
250 |
} qw(part service assembly); |
|
251 | ||
252 |
push @{ $filter->{and} }, or => [ @part_filters ] if @part_filters; |
|
253 |
} |
|
254 | ||
255 |
if ($filter->{'reqdate:date::le'}) { |
|
256 |
$launder_to->{'reqdate_date__le'} = delete $filter->{'reqdate:date::le'}; |
|
257 |
my $parsed_date = DateTime->from_lxoffice($launder_to->{'reqdate_date__le'}); |
|
258 |
push @{ $filter->{and} }, or => [ |
|
259 |
'reqdate' => { le => $parsed_date }, |
|
260 |
and => [ |
|
261 |
'reqdate' => undef, |
|
262 |
'order.reqdate' => { le => $parsed_date }, |
|
263 |
] |
|
264 |
] if $parsed_date; |
|
265 |
} |
|
266 | ||
267 |
return $filter; |
|
268 |
} |
|
269 | ||
270 |
1; |
SL/DB/OrderItem.pm | ||
---|---|---|
68 | 68 |
qty => [ 'qty' ], |
69 | 69 |
ordnumber => [ 'order.ordnumber' ], |
70 | 70 |
customer => [ 'lower(customer.name)', ], |
71 |
position => [ 'trans_id' ], |
|
72 |
reqdate => [ 'COALESCE(orderitems.reqdate, order.transdate)' ],
|
|
71 |
position => [ 'trans_id', 'runningnumber' ],
|
|
72 |
reqdate => [ 'COALESCE(orderitems.reqdate, order.reqdate)' ],
|
|
73 | 73 |
orddate => [ 'order.orddate' ], |
74 | 74 |
sellprice => [ 'sellprice' ], |
75 | 75 |
discount => [ 'discount' ], |
76 |
transdate => [ 'transdate::date', 'order.reqdate' ], |
|
76 | 77 |
}, |
77 | 78 |
default => [ 'position', 1 ], |
78 | 79 |
nulls => { } |
SL/InstallationCheck.pm | ||
---|---|---|
11 | 11 |
@required_modules = ( |
12 | 12 |
{ name => "parent", url => "http://search.cpan.org/~corion/", debian => 'libparent-perl' }, |
13 | 13 |
{ name => "Archive::Zip", version => '1.16', url => "http://search.cpan.org/~adamk/", debian => 'libarchive-zip-perl' }, |
14 |
{ name => "Clone", url => "http://search.cpan.org/~rdf/", debian => 'libclone-perl' }, |
|
14 | 15 |
{ name => "Config::Std", url => "http://search.cpan.org/~dconway/", debian => 'libconfig-std-perl' }, |
15 | 16 |
{ name => "DateTime", url => "http://search.cpan.org/~drolsky/", debian => 'libdatetime-perl' }, |
16 | 17 |
{ name => "DBI", version => '1.50', url => "http://search.cpan.org/~timb/", debian => 'libdbi-perl' }, |
locale/de/all | ||
---|---|---|
208 | 208 |
'Article type (see below)' => 'Artikeltyp (siehe unten)', |
209 | 209 |
'As a result, the saved onhand values of the present goods can be stored into a warehouse designated by you, or will be reset for a proper warehouse tracking' => 'Als Konsequenz können die gespeicherten Mengen entweder in ein Lager überführt werden, oder für eine frische Lagerverwaltung resettet werden.', |
210 | 210 |
'Assemblies' => 'Erzeugnisse', |
211 |
'Assembly' => 'Erzeugnis', |
|
211 | 212 |
'Assembly Description' => 'Erzeugnis-Beschreibung', |
212 | 213 |
'Assembly Number' => 'Erzeugnis-Nummer', |
213 | 214 |
'Assembly Number missing!' => 'Erzeugnisnummer fehlt!', |
... | ... | |
592 | 593 |
'Delivery Order created' => 'Lieferschein erstellt', |
593 | 594 |
'Delivery Order deleted!' => 'Lieferschein gelöscht!', |
594 | 595 |
'Delivery Orders' => 'Lieferscheine', |
596 |
'Delivery Orders for this document' => 'Lieferscheine für dieses Dokument', |
|
597 |
'Delivery Plan' => 'Lieferplan', |
|
598 |
'Delivery Plan for currently outstanding sales orders' => 'Lieferplan für offene Verkaufsaufträge', |
|
599 |
'Delivery information deleted.' => 'Lieferinformation gelöscht.', |
|
600 |
'Delivery information saved.' => 'Lieferinformation gespeichert.', |
|
595 | 601 |
'Department' => 'Abteilung', |
596 | 602 |
'Department 1' => 'Abteilung (1)', |
597 | 603 |
'Department 2' => 'Abteilung (2)', |
... | ... | |
903 | 909 |
'Help Template Variables' => 'Hilfe zu Dokumenten-Variablen', |
904 | 910 |
'Help on column names' => 'Hilfe zu Spaltennamen', |
905 | 911 |
'Here\'s an example command line:' => 'Hier ist eine Kommandozeile, die als Beispiel dient:', |
912 |
'Hide Filter' => 'Filter verbergen', |
|
906 | 913 |
'Hide by default' => 'Standardmäßig verstecken', |
907 | 914 |
'Hide help text' => 'Hilfetext verbergen', |
908 | 915 |
'History' => 'Historie', |
... | ... | |
1518 | 1525 |
'Requested execution date from' => 'Gewünschtes Ausführungsdatum von', |
1519 | 1526 |
'Requested execution date to' => 'Gewünschtes Ausführungsdatum bis', |
1520 | 1527 |
'Required by' => 'Lieferdatum', |
1528 |
'Reset' => 'Zurücksetzen', |
|
1521 | 1529 |
'Restore Dataset' => 'Datenbank wiederherstellen', |
1522 | 1530 |
'Revenue' => 'Erlöskonto', |
1523 | 1531 |
'Revenue Account' => 'Erlöskonto', |
... | ... | |
1635 | 1643 |
'Shopartikel' => 'Shopartikel', |
1636 | 1644 |
'Short' => 'Knapp', |
1637 | 1645 |
'Show' => 'Zeigen', |
1646 |
'Show Filter' => 'Filter zeigen', |
|
1638 | 1647 |
'Show Salesman' => 'Verkäufer anzeigen', |
1639 | 1648 |
'Show TODO list' => 'Aufgabenliste anzeigen', |
1640 | 1649 |
'Show by default' => 'Standardmäßig anzeigen', |
menu.ini | ||
---|---|---|
166 | 166 |
module=dn.pl |
167 | 167 |
action=search |
168 | 168 | |
169 |
[AR--Reports--Delivery Plan] |
|
170 |
ACCESS=sales_order_edit |
|
171 |
module=controller.pl |
|
172 |
action=DeliveryPlan/list |
|
169 | 173 | |
170 | 174 |
[AP] |
171 | 175 |
templates/webpages/delivery_plan/_filter.html | ||
---|---|---|
1 |
[%- USE T8 %] |
|
2 |
[%- USE L %] |
|
3 |
[%- USE LxERP %] |
|
4 |
[%- USE HTML %] |
|
5 |
<form action='controller.pl' method='post'> |
|
6 |
<div class='filter_toggle'> |
|
7 |
<a href='#' onClick='javascript:$(".filter_toggle").toggle()'>[% 'Show Filter' | $T8 %]</a> |
|
8 |
[% SELF.filter_summary %] |
|
9 |
</div> |
|
10 |
<div class='filter_toggle' style='display:none'> |
|
11 |
<a href='#' onClick='javascript:$(".filter_toggle").toggle()'>[% 'Hide Filter' | $T8 %]</a> |
|
12 |
<table id='filter_table'> |
|
13 |
<tr> |
|
14 |
<th align="right">[% 'Number' | $T8 %]</th> |
|
15 |
<td>[% L.input_tag('filter.order.ordnumber:substr::ilike', filter.order.ordnumber_substr__ilike, size = 20) %]</td> |
|
16 |
</tr> |
|
17 |
<tr> |
|
18 |
<th align="right">[% 'Part Number' | $T8 %]</th> |
|
19 |
<td>[% L.input_tag('filter.part.partnumber:substr::ilike', filter.part.partnumber_substr__ilike, size = 20) %]</td> |
|
20 |
</tr> |
|
21 |
<tr> |
|
22 |
<th align="right">[% 'Part Description' | $T8 %]</th> |
|
23 |
<td>[% L.input_tag('filter.description:substr::ilike', filter.description_substr__ilike, size = 20) %]</td> |
|
24 |
</tr> |
|
25 |
<tr> |
|
26 |
<th align="right">[% 'Delivery Date' | $T8 %]</th> |
|
27 |
<td>[% L.date_tag('filter.reqdate:date::le', filter.reqdate_date__le, cal_align = 'BR') %]</td> |
|
28 |
</tr> |
|
29 |
<tr> |
|
30 |
<th align="right">[% 'Quantity' | $T8 %]</th> |
|
31 |
<td>[% L.input_tag('filter.qty:number', filter.qty_number, size = 20) %]</td> |
|
32 |
</tr> |
|
33 |
<tr> |
|
34 |
<th align="right">[% 'Customer' | $T8 %]</th> |
|
35 |
<td>[% L.input_tag('filter.order.customer.name:substr::ilike', filter.order.customer.name_substr__ilike, size = 20) %]</td> |
|
36 |
</tr> |
|
37 |
<tr> |
|
38 |
<th align="right">[% 'Type' | $T8 %]</th> |
|
39 |
<td> |
|
40 |
[% L.checkbox_tag('filter.part.type.part', checked=filter.part.type.part, label=LxERP.t8('Part')) %] |
|
41 |
[% L.checkbox_tag('filter.part.type.service', checked=filter.part.type.service, label=LxERP.t8('Service')) %] |
|
42 |
[% L.checkbox_tag('filter.part.type.assembly', checked=filter.part.type.assembly, label=LxERP.t8('Assembly')) %] |
|
43 |
</td> |
|
44 |
</tr> |
|
45 |
</table> |
|
46 | ||
47 |
[% L.hidden_tag('action', 'DeliveryPlan/dispatch') %] |
|
48 |
[% L.hidden_tag('sort_by', FORM.sort_by) %] |
|
49 |
[% L.hidden_tag('sort_dir', FORM.sort_dir) %] |
|
50 |
[% L.hidden_tag('page', FORM.page) %] |
|
51 |
[% L.input_tag('action_list', LxERP.t8('Continue'), type = 'submit', class='submit')%] |
|
52 | ||
53 | ||
54 |
<a href='#' onClick='javascript:$("#filter_table input").attr("value","");$("#filter_table option").attr("selected","")'>[% 'Reset' | $T8 %]</a> |
|
55 | ||
56 |
</div> |
|
57 | ||
58 |
</form> |
templates/webpages/delivery_plan/_list.html | ||
---|---|---|
1 |
[% USE HTML %][% USE T8 %][% USE L %][% USE LxERP %] |
|
2 | ||
3 |
[% BLOCK header %] |
|
4 |
[% SET new_sort_dir = SELF.sort_by == sort_by ? 1 - SELF.sort_dir : SELF.sort_dir %] |
|
5 |
<th width="[% size %]%"> |
|
6 |
<a href="[% SELF.url_for(action => 'list') %]&sort_by=[% sort_by %]&sort_dir=[% new_sort_dir %]&page=[% FORM.page %]"> |
|
7 |
[%- title %] |
|
8 |
[%- IF SELF.sort_by == sort_by %] |
|
9 |
<img src="image/[% IF SELF.sort_dir %]down[% ELSE %]up[% END %].png" border="0"> |
|
10 |
[%- END %] |
|
11 |
</a> |
|
12 |
</th> |
|
13 |
[% END %] |
|
14 | ||
15 |
<div id="orders"> |
|
16 |
[%- IF !SELF.orderitems.size %] |
|
17 |
<p>[%- 'There are no outstanding deliveries at the moment.' | $T8 %]</p> |
|
18 |
[%- ELSE %] |
|
19 | ||
20 |
<table width=100%> |
|
21 |
<tr class="listheading"> |
|
22 |
[% PROCESS header title=LxERP.t8('Date') sort_by='transdate', size=15 %] |
|
23 |
[% PROCESS header title=LxERP.t8('Description') sort_by='description', size=15 %] |
|
24 |
[% PROCESS header title=LxERP.t8('Part Number') sort_by='partnumber', size=15 %] |
|
25 |
[% PROCESS header title=LxERP.t8('Qty') sort_by='qty', size=10 %] |
|
26 |
[% PROCESS header title=LxERP.t8('Order') sort_by='ordnumber', size=10 %] |
|
27 |
[% PROCESS header title=LxERP.t8('Customer') sort_by='customer', size=10 %] |
|
28 |
</tr> |
|
29 | ||
30 |
[%- FOREACH row = SELF.orderitems %] |
|
31 |
<tr class="listrow[% loop.count % 2 %]"> |
|
32 |
<td>[% row.transdate ? row.transdate : row.order.reqdate_as_date %]</td> |
|
33 |
<td>[% row.part.partnumber | html %]</td> |
|
34 |
<td>[% row.description | html %]</td> |
|
35 |
<td class='numeric'>[% LxERP.format_amount(row.qty, 2) | html %]</td> |
|
36 |
<td>[% row.order.ordnumber | html %]</td> |
|
37 |
<td>[% row.order.customer.name | html %]</td> |
|
38 |
</tr> |
|
39 |
[%- END %] |
|
40 |
</table> |
|
41 |
<p align=right>[% PROCESS 'common/paginate.html' pages=SELF.pages, base_url=SELF.url_for(action='list', sort_dir=SELF.sort_dir, sort_by=SELF.sort_by) %]</p> |
|
42 | ||
43 |
[%- END %] |
|
44 |
</div> |
templates/webpages/delivery_plan/list.html | ||
---|---|---|
1 |
[%- USE T8 %] |
|
2 | ||
3 |
<h1>[% 'Delivery Plan' | $T8 %]</h1> |
|
4 | ||
5 |
[%- PROCESS 'delivery_plan/_filter.html' filter=FORM.filter %] |
|
6 |
<hr> |
|
7 |
[%- PROCESS 'delivery_plan/_list.html' %] |
templates/webpages/delivery_plan/report_bottom.html | ||
---|---|---|
1 |
[% SET report_bottom_url_args = {} %] |
|
2 |
[% report_bottom_url_args.import(SELF.flat_filter) %] |
|
3 |
[% report_bottom_url_args.import({action='list', sort_dir=SELF.sort_dir, sort_by=SELF.sort_by}) %] |
|
4 |
<p align=right>[% PROCESS 'common/paginate.html' pages=SELF.pages, base_url=SELF.url_for(report_bottom_url_args) %]</p> |
templates/webpages/delivery_plan/report_top.html | ||
---|---|---|
1 |
[%- USE L %] |
|
2 |
[%- PROCESS 'delivery_plan/_filter.html' filter=SELF.filter %] |
|
3 |
<hr> |
Auch abrufbar als: Unified diff
DeliveryPlan
Erste Version squashed (überspringt 10 Commits, in denen das Query unbrauchbar langsam ist)