Revision 049e49fe
Von Sven Schöling vor etwa 10 Jahren hinzugefügt
SL/Controller/PriceSource.pm | ||
---|---|---|
1 |
package SL::Controller::PriceSource; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use parent qw(SL::Controller::Base); |
|
6 |
|
|
7 |
use List::MoreUtils qw(any uniq apply); |
|
8 |
use SL::ClientJS; |
|
9 |
use SL::Locale::String qw(t8); |
|
10 |
use SL::PriceSource; |
|
11 |
|
|
12 |
use Rose::Object::MakeMethods::Generic |
|
13 |
( |
|
14 |
scalar => [ qw(record_item) ], |
|
15 |
'scalar --get_set_init' => [ qw(js record) ], |
|
16 |
); |
|
17 |
|
|
18 |
__PACKAGE__->run_before('check_auth'); |
|
19 |
|
|
20 |
# |
|
21 |
# actions |
|
22 |
# |
|
23 |
|
|
24 |
sub action_price_popup { |
|
25 |
my ($self) = @_; |
|
26 |
|
|
27 |
my $record_item = _make_record_item($::form->{row}); |
|
28 |
|
|
29 |
$self->render_price_dialog($record_item); |
|
30 |
} |
|
31 |
|
|
32 |
sub render_price_dialog { |
|
33 |
my ($self, $record_item) = @_; |
|
34 |
|
|
35 |
my $price_source = SL::PriceSource->new(record_item => $record_item, record => $self->record); |
|
36 |
|
|
37 |
$self->js |
|
38 |
->run( |
|
39 |
'kivi.io.price_chooser_dialog', |
|
40 |
t8('Available Prices'), |
|
41 |
$self->render('oe/price_sources_dialog', { output => 0 }, price_source => $price_source) |
|
42 |
) |
|
43 |
->reinit_widgets; |
|
44 |
|
|
45 |
# if (@errors) { |
|
46 |
# $self->js->text('#dialog_flash_error_content', join ' ', @errors); |
|
47 |
# $self->js->show('#dialog_flash_error'); |
|
48 |
# } |
|
49 |
|
|
50 |
$self->js->render($self); |
|
51 |
} |
|
52 |
|
|
53 |
|
|
54 |
# |
|
55 |
# internal stuff |
|
56 |
# |
|
57 |
|
|
58 |
sub check_auth { |
|
59 |
$::auth->assert('edit_prices'); |
|
60 |
} |
|
61 |
|
|
62 |
sub init_js { |
|
63 |
SL::ClientJS->new |
|
64 |
} |
|
65 |
|
|
66 |
sub init_record { |
|
67 |
_make_record(); |
|
68 |
} |
|
69 |
|
|
70 |
sub _make_record_item { |
|
71 |
my ($row) = @_; |
|
72 |
|
|
73 |
my $class = { |
|
74 |
sales_order => 'OrderItem', |
|
75 |
purchase_oder => 'OrderItem', |
|
76 |
sales_quotation => 'OrderItem', |
|
77 |
request_quotation => 'OrderItem', |
|
78 |
invoice => 'InvoiceItem', |
|
79 |
purchase_invoice => 'InvoiceItem', |
|
80 |
purchase_delivery_order => 'DeliveryOrderItem', |
|
81 |
sales_delivery_order => 'DeliveryOrderItem', |
|
82 |
}->{$::form->{type}}; |
|
83 |
|
|
84 |
return unless $class; |
|
85 |
|
|
86 |
$class = 'SL::DB::' . $class; |
|
87 |
|
|
88 |
eval "require $class"; |
|
89 |
|
|
90 |
my $obj = $::form->{"orderitems_id_$row"} |
|
91 |
? $class->meta->convention_manager->auto_manager_class_name->find_by(id => $::form->{"orderitems_id_$row"}) |
|
92 |
: $class->new; |
|
93 |
|
|
94 |
for my $method (apply { s/_$row$// } grep { /_$row$/ } keys %$::form) { |
|
95 |
next unless $obj->meta->column($method); |
|
96 |
if ($obj->meta->column($method)->isa('Rose::DB::Object::Metadata::Column::Date')) { |
|
97 |
$obj->${\"$method\_as_date"}($::form->{"$method\_$row"}); |
|
98 |
} elsif ((ref $obj->meta->column($method)) =~ /^Rose::DB::Object::Metadata::Column::(?:Numeric|Float|DoublePrecsion)$/) { |
|
99 |
$obj->${\"$method\_as_number"}($::form->{"$method\_$row"}); |
|
100 |
} else { |
|
101 |
$obj->$method($::form->{"$method\_$row"}); |
|
102 |
} |
|
103 |
} |
|
104 |
|
|
105 |
if ($::form->{"id_$row"}) { |
|
106 |
$obj->part(SL::DB::Part->load_cached($::form->{"id_$row"})); |
|
107 |
} |
|
108 |
|
|
109 |
return $obj; |
|
110 |
} |
|
111 |
|
|
112 |
sub _make_record { |
|
113 |
my ($with_items) = @_; |
|
114 |
|
|
115 |
my $class = { |
|
116 |
sales_order => 'Order', |
|
117 |
purchase_oder => 'Order', |
|
118 |
sales_quotation => 'Order', |
|
119 |
request_quotation => 'Order', |
|
120 |
purchase_delivery_order => 'DeliveryOrder', |
|
121 |
sales_delivery_order => 'DeliveryOrder', |
|
122 |
}->{$::form->{type}}; |
|
123 |
|
|
124 |
if ($::form->{type} eq 'invoice') { |
|
125 |
$class = $::form->{vc} eq 'customer' ? 'Invoice' |
|
126 |
: $::form->{vc} eq 'vendor' ? 'PurchaseInvoice' |
|
127 |
: do { die 'unknown invoice type' }; |
|
128 |
} |
|
129 |
|
|
130 |
return unless $class; |
|
131 |
|
|
132 |
$class = 'SL::DB::' . $class; |
|
133 |
|
|
134 |
eval "require $class"; |
|
135 |
|
|
136 |
my $obj = $::form->{id} |
|
137 |
? $class->meta->convention_manager->auto_manager_class_name->find_by(id => $::form->{id}) |
|
138 |
: $class->new; |
|
139 |
|
|
140 |
for my $method (keys %$::form) { |
|
141 |
next unless $obj->can($method); |
|
142 |
next unless $obj->meta->column($method); |
|
143 |
|
|
144 |
if ($obj->meta->column($method)->isa('Rose::DB::Object::Metadata::Column::Date')) { |
|
145 |
$obj->${\"$method\_as_date"}($::form->{$method}); |
|
146 |
} elsif ((ref $obj->meta->column($method)) =~ /^Rose::DB::Object::Metadata::Column::(?:Numeric|Float|DoublePrecsion)$/) { |
|
147 |
$obj->${\"$method\_as\_number"}($::form->{$method}); |
|
148 |
} else { |
|
149 |
$obj->$method($::form->{$method}); |
|
150 |
} |
|
151 |
} |
|
152 |
|
|
153 |
if ($with_items) { |
|
154 |
my @items; |
|
155 |
for my $i (1 .. $::form->{rowcount}) { |
|
156 |
next unless $::form->{"id_$i"}; |
|
157 |
push @items, _make_record_item($i) |
|
158 |
} |
|
159 |
|
|
160 |
$obj->items(@items) if @items; |
|
161 |
} |
|
162 |
|
|
163 |
return $obj; |
|
164 |
} |
|
165 |
|
|
166 |
1; |
|
167 |
|
SL/PriceSource.pm | ||
---|---|---|
59 | 59 |
PriceSource is an interface that allows generic algorithms to be plugged |
60 | 60 |
together to calculate available prices for a position in a record. |
61 | 61 |
|
62 |
Each algorithm can access details of the record to realize dependancies on
|
|
62 |
Each algorithm can access details of the record to realize dependencies on
|
|
63 | 63 |
part, customer, vendor, date, quantity etc, which was previously not possible. |
64 | 64 |
|
65 | 65 |
=head1 BACKGROUND AND PHILOSOPY |
... | ... | |
111 | 111 |
calculation can be repeated so that invalid prices can be caught (because for |
112 | 112 |
example the special offer is no longer valid), and so that sales personnel have |
113 | 113 |
information about rising or falling prices. The fourth point ensures that |
114 |
insular calculation processes can be developed independant of the core code.
|
|
114 |
insular calculation processes can be developed independent of the core code.
|
|
115 | 115 |
|
116 | 116 |
=head1 INTERFACE METHODS |
117 | 117 |
|
SL/PriceSource/Base.pm | ||
---|---|---|
183 | 183 |
|
184 | 184 |
C<source> and C<spec> are tainted. If you store data directly in C<spec>, sanitize. |
185 | 185 |
|
186 |
=back |
|
187 |
|
|
186 | 188 |
=head1 SEE ALSO |
187 | 189 |
|
188 | 190 |
L<SL::PriceSource>, |
bin/mozilla/do.pl | ||
---|---|---|
323 | 323 |
|
324 | 324 |
$form->{follow_up_trans_info} = $form->{donumber} .'('. $follow_up_vc .')'; |
325 | 325 |
|
326 |
$::request->{layout}->use_javascript(map { "${_}.js" } qw(kivi.SalesPurchase ckeditor/ckeditor ckeditor/adapters/jquery)); |
|
326 |
$::request->{layout}->use_javascript(map { "${_}.js" } qw(kivi.SalesPurchase ckeditor/ckeditor ckeditor/adapters/jquery kivi.io));
|
|
327 | 327 |
|
328 | 328 |
$form->header(); |
329 | 329 |
# Fix für Bug 1082 Erwartet wird: 'abteilungsNAME--abteilungsID' |
bin/mozilla/io.pl | ||
---|---|---|
44 | 44 |
use SL::CVar; |
45 | 45 |
use SL::Common; |
46 | 46 |
use SL::CT; |
47 |
use SL::Locale::String qw(t8); |
|
47 | 48 |
use SL::IC; |
48 | 49 |
use SL::IO; |
49 | 50 |
use SL::PriceSource; |
... | ... | |
325 | 326 |
if ($form->{"id_${i}"}) { |
326 | 327 |
my $price_source = SL::PriceSource->new(record_item => $record_item, record => $record); |
327 | 328 |
my $price = $price_source->price_from_source($::form->{"active_price_source_$i"}); |
328 |
$::form->{price_sources}[$i] = $price_source; |
|
329 |
$column_data{price_source} .= $cgi->button(-value => $price->full_description, -onClick => "toggle_price_source($i)"); |
|
329 |
$column_data{price_source} .= $cgi->button(-value => $price->full_description, -onClick => "kivi.io.price_chooser($i)"); |
|
330 |
if ($price->source) { |
|
331 |
$column_data{price_source} .= ' ' . $cgi->img({src => 'image/flag-red.png', alt => $price->invalid, title => $price->invalid }) if $price->invalid; |
|
332 |
$column_data{price_source} .= ' ' . $cgi->img({src => 'image/flag-red.png', alt => $price->missing, title => $price->missing }) if $price->missing; |
|
333 |
$column_data{price_source} .= ' ' . $cgi->img({src => 'image/up.png', alt => t8('This price has since gone up'), title => t8('This price has since gone up' ) }) if $price->price > $record_item->sellprice; |
|
334 |
$column_data{price_source} .= ' ' . $cgi->img({src => 'image/down.png', alt => t8('This price has since gone down'), title => t8('This price has since gone down') }) if $price->price < $record_item->sellprice; |
|
335 |
$column_data{price_source} .= ' ' . $cgi->img({src => 'image/ok.png', alt => t8('There is a better price available'), title => t8('There is a better price available') }) if $price->source ne $price_source->best_price->source; |
|
336 |
} |
|
330 | 337 |
} |
331 | 338 |
|
332 | 339 |
if ($is_delivery_order) { |
... | ... | |
702 | 709 |
price_old price_new unit_old ordnumber donumber |
703 | 710 |
transdate longdescription basefactor marge_total marge_percent |
704 | 711 |
marge_price_factor lastcost price_factor_id partnotes |
705 |
stock_out stock_in has_sernumber reqdate orderitems_id); |
|
712 |
stock_out stock_in has_sernumber reqdate orderitems_id |
|
713 |
active_price_source); |
|
706 | 714 |
|
707 | 715 |
my $ic_cvar_configs = CVar->get_configs(module => 'IC'); |
708 | 716 |
push @flds, map { "ic_cvar_$_->{name}" } @{ $ic_cvar_configs }; |
... | ... | |
1931 | 1939 |
next unless $obj->meta->column($method); |
1932 | 1940 |
if ($obj->meta->column($method)->isa('Rose::DB::Object::Metadata::Column::Date')) { |
1933 | 1941 |
$obj->${\"$method\_as_date"}($::form->{"$method\_$row"}); |
1934 |
} elsif ((ref $obj->meta->column($method)) =~ /^Rose::DB::Object::Metadata::Column::(?:Numeric|Float|DoublePrecsion)$/) { |
|
1935 |
$obj->${\"$method\_as\_number"}($::form->{$method}); |
|
1936 | 1942 |
} else { |
1937 | 1943 |
$obj->$method($::form->{"$method\_$row"}); |
1938 | 1944 |
} |
... | ... | |
1978 | 1984 |
if ($obj->meta->column($method)->isa('Rose::DB::Object::Metadata::Column::Date')) { |
1979 | 1985 |
$obj->${\"$method\_as_date"}($::form->{$method}); |
1980 | 1986 |
} elsif ((ref $obj->meta->column($method)) =~ /^Rose::DB::Object::Metadata::Column::(?:Numeric|Float|DoublePrecsion)$/) { |
1981 |
$obj->${\"$method\_as\_number"}($::form->{$method});
|
|
1987 |
$obj->${\"$method\_as_number"}($::form->{$method}); |
|
1982 | 1988 |
} else { |
1983 | 1989 |
$obj->$method($::form->{$method}); |
1984 | 1990 |
} |
bin/mozilla/ir.pl | ||
---|---|---|
335 | 335 |
), @custom_hiddens, |
336 | 336 |
map { $_.'_rate', $_.'_description', $_.'_taxnumber' } split / /, $form->{taxaccounts}]; |
337 | 337 |
|
338 |
$::request->{layout}->use_javascript(map { "${_}.js" } qw(kivi.SalesPurchase ckeditor/ckeditor ckeditor/adapters/jquery)); |
|
338 |
$::request->{layout}->use_javascript(map { "${_}.js" } qw(kivi.SalesPurchase ckeditor/ckeditor ckeditor/adapters/jquery kivi.io));
|
|
339 | 339 |
|
340 | 340 |
$form->header(); |
341 | 341 |
|
bin/mozilla/is.pl | ||
---|---|---|
385 | 385 |
), @custom_hiddens, |
386 | 386 |
map { $_.'_rate', $_.'_description', $_.'_taxnumber' } split / /, $form->{taxaccounts}]; |
387 | 387 |
|
388 |
$::request->{layout}->use_javascript(map { "${_}.js" } qw(kivi.SalesPurchase ckeditor/ckeditor ckeditor/adapters/jquery)); |
|
388 |
$::request->{layout}->use_javascript(map { "${_}.js" } qw(kivi.SalesPurchase ckeditor/ckeditor ckeditor/adapters/jquery kivi.io));
|
|
389 | 389 |
|
390 | 390 |
$form->header(); |
391 | 391 |
|
bin/mozilla/oe.pl | ||
---|---|---|
465 | 465 |
} |
466 | 466 |
} |
467 | 467 |
|
468 |
$::request->{layout}->use_javascript(map { "${_}.js" } qw(kivi.SalesPurchase show_form_details show_history show_vc_details ckeditor/ckeditor ckeditor/adapters/jquery)); |
|
468 |
$::request->{layout}->use_javascript(map { "${_}.js" } qw(kivi.SalesPurchase show_form_details show_history show_vc_details ckeditor/ckeditor ckeditor/adapters/jquery kivi.io));
|
|
469 | 469 |
|
470 | 470 |
$form->header; |
471 | 471 |
if ($form->{CFDD_shipto} && $form->{CFDD_shipto_id} ) { |
js/kivi.io.js | ||
---|---|---|
1 |
namespace('kivi.io', function(ns) { |
|
2 |
var $dialog; |
|
3 |
|
|
4 |
ns.price_chooser_dialog = function(title, html) { |
|
5 |
var id = 'jqueryui_popup_dialog'; |
|
6 |
var dialog_params = { |
|
7 |
id: id, |
|
8 |
width: 800, |
|
9 |
height: 500, |
|
10 |
modal: true, |
|
11 |
close: function(event, ui) { $dialog.remove(); }, |
|
12 |
}; |
|
13 |
|
|
14 |
$('#' + id).remove(); |
|
15 |
|
|
16 |
$dialog = $('<div style="display:none" id="' + id + '"></div>').appendTo('body'); |
|
17 |
$dialog.attr('title', title); |
|
18 |
$dialog.html(html); |
|
19 |
$dialog.dialog(dialog_params); |
|
20 |
|
|
21 |
$('.cancel').click(ns.close_dialog); |
|
22 |
|
|
23 |
return true; |
|
24 |
}; |
|
25 |
|
|
26 |
ns.close_dialog = function() { |
|
27 |
$dialog.dialog("close"); |
|
28 |
} |
|
29 |
|
|
30 |
ns.price_chooser = function(i) { |
|
31 |
var form = $('form').serializeArray(); |
|
32 |
form.push( { name: 'action', value: 'PriceSource/price_popup' } |
|
33 |
, { name: 'row', value: i } |
|
34 |
); |
|
35 |
|
|
36 |
$.post('controller.pl', form, function(data) { |
|
37 |
kivi.eval_json_result(data); |
|
38 |
}); |
|
39 |
} |
|
40 |
|
|
41 |
ns.update_price_source = function(row, source, price_str) { |
|
42 |
$('#active_price_source_' + row).val(source); |
|
43 |
if (price_str) $('#sellprice_' + row).val(price_str); |
|
44 |
$('#update_button').click(); |
|
45 |
} |
|
46 |
}); |
locale/de/all | ||
---|---|---|
291 | 291 |
'Automatic deletion of leading, trailing and excessive (repetitive) spaces in part description and part notes. Affects the CSV import as well.' => 'Automatisches Löschen von voran-/nachgestellten und aufeinanderfolgenden Leerzeichen in Artikelbeschreibungen und -bemerkungen. Betrifft auch den CSV-Import.', |
292 | 292 |
'Automatically created invoice for fee and interest for dunning %s' => 'Automatisch erzeugte Rechnung für Gebühren und Zinsen zu Mahnung %s', |
293 | 293 |
'Available' => 'Verfügbar', |
294 |
'Available Prices' => 'Mögliche Preise', |
|
294 | 295 |
'Available qty' => 'Lagerbestand', |
295 | 296 |
'BALANCE SHEET' => 'BILANZ', |
296 | 297 |
'BIC' => 'BIC', |
... | ... | |
340 | 341 |
'Beratername' => 'Beratername', |
341 | 342 |
'Beraternummer' => 'Beraternummer', |
342 | 343 |
'Best Before' => 'Mindesthaltbarkeit', |
344 |
'Best Price' => 'Bester Preis', |
|
343 | 345 |
'Bilanz' => 'Bilanz', |
344 | 346 |
'Billable amount' => 'Abrechenbarer Betrag', |
345 | 347 |
'Billed amount' => 'Abgerechneter Betrag', |
... | ... | |
2628 | 2630 |
'There are still transfers not matching the qty of the delivery order. Stock operations can not be changed later. Do you really want to proceed?' => 'Einige der Lagerbewegungen sind nicht vollständig und Lagerbewegungen können nachträglich nicht mehr verändert werden. Wollen Sie wirklich fortfahren?', |
2629 | 2631 |
'There are undefined currencies in your system.' => 'In Ihrer Datenbank wurden Währungen benutzt, die nicht ordnungsgemäß in den Währungen eingetragen wurden.', |
2630 | 2632 |
'There are usually three ways to install Perl modules.' => 'Es gibt normalerweise drei Arten, ein Perlmodul zu installieren.', |
2633 |
'There is a better price available' => 'Es ist ein besserer Preis verfügbar', |
|
2631 | 2634 |
'There is already a taxkey 0 with tax rate not 0.' => 'Es existiert bereits ein Steuerschlüssel mit Steuersatz ungleich 0%.', |
2632 | 2635 |
'There is an inconsistancy in your database.' => 'In Ihrer Datenbank sind Unstimmigkeiten vorhanden.', |
2633 | 2636 |
'There is at least one sales or purchase invoice for which kivitendo recorded an inventory transaction with taxkeys even though no tax was recorded.' => 'Es gibt mindestens eine Verkaufs- oder Einkaufsrechnung, für die kivitendo eine Warenbestandsbuchung ohne dazugehörige Steuerbuchung durchgeführt hat.', |
... | ... | |
2663 | 2666 |
'This option controls the method used for profit determination.' => 'Dieser Parameter legt die Berechnungsmethode für die Gewinnermittlung fest.', |
2664 | 2667 |
'This option controls the posting and calculation behavior for the accounting method.' => 'Dieser Parameter steuert die Buchungs- und Berechnungsmethoden für die Versteuerungsart.', |
2665 | 2668 |
'This partnumber is not unique. You should change it.' => 'Diese Artikelnummer ist nicht eindeutig. Bitte wählen Sie eine andere.', |
2669 |
'This price has since gone down' => 'Dieser Preis ist mittlerweile niedriger', |
|
2670 |
'This price has since gone up' => 'Dieser Preis ist mittlerweile höher', |
|
2666 | 2671 |
'This requirement spec is currently linked to the following project:' => 'Dieses Pflichtenheft ist mit dem folgenden Projekt verknüpft:', |
2667 | 2672 |
'This requirement spec is currently not linked to a project.' => 'Dieses Pflichtenheft ist noch nicht mit einem Projekt verknüpft.', |
2668 | 2673 |
'This requires you to manually correct entries for which an automatic conversion failed and to check those for which it succeeded.' => 'Dies erfordert, dass Sie diejenigen Einträge manuell korrigieren, für die die automatische Umstellung fehlschlug, sowie dass Sie diejenigen überprüfen, für die die Umstellung erfolgreich war.', |
... | ... | |
2770 | 2775 |
'Unsupported image type (supported types: #1)' => 'Nicht unterstützter Bildtyp (unterstützte Typen: #1)', |
2771 | 2776 |
'Until' => 'Bis', |
2772 | 2777 |
'Update' => 'Erneuern', |
2778 |
'Update Price' => 'Preis übernehmen', |
|
2773 | 2779 |
'Update Prices' => 'Preise aktualisieren', |
2774 | 2780 |
'Update SKR04: new tax account 3804 (19%)' => 'Update SKR04: neues Steuerkonto 3804 (19%) für innergemeinschaftlichen Erwerb', |
2775 | 2781 |
'Update prices' => 'Preise aktualisieren', |
templates/webpages/oe/_price_sources_row.html | ||
---|---|---|
1 |
[%- USE T8 %] |
|
2 |
[%- USE HTML %] |
|
3 |
[%- USE L %] |
|
4 |
[%- USE LxERP %] |
|
5 |
<tr class="listrow[% i % 2 %]" id="row[% i %]_3" style='display:none'> |
|
6 |
<td colspan="[% row.colspan %]"> |
|
7 |
<span class="[% IF !row.obj.active_price_source %]bold[% END %]"> |
|
8 |
[% L.radio_button_tag('active_price_source_' _ i, label=LxERP.t8('None (PriceSource)'), checked=!row.obj.active_price_source, value='', onChange='update_price_source(' _ i _ ', \'\')') %] |
|
9 |
</span> |
|
10 |
[%- FOREACH price IN price_sources.$i.available_prices %] |
|
11 |
<div class="[% IF price.source == row.obj.active_price_source %]bold[% END %]"> |
|
12 |
[% L.radio_button_tag('active_price_source_' _ i, value=price.source, checked=price.source == row.obj.active_price_source, label=LxERP.format_amount(price.price, 2) _ ' (' _ price.full_description _ ')', onChange='update_price_source(' _ i _ ', \'' _ price.source _ '\', \'' _ LxERP.format_amount(price.price, -2) _ '\')' ) %] |
|
13 |
</div> |
|
14 |
[%- END %] |
|
15 |
</td> |
|
16 |
</tr> |
templates/webpages/oe/price_sources_dialog.html | ||
---|---|---|
1 |
[%- USE T8 %] |
|
2 |
[%- USE HTML %] |
|
3 |
[%- USE L %] |
|
4 |
[%- USE LxERP %] |
|
5 |
[% SET best_price = price_source.best_price %] |
|
6 |
<table> |
|
7 |
<tr class='listheading'> |
|
8 |
<th></th> |
|
9 |
<th>[% 'Price Source' | $T8 %]</th> |
|
10 |
<th>[% 'Price' | $T8 %]</th> |
|
11 |
<th>[% 'Best Price' | $T8 %]</th> |
|
12 |
</tr> |
|
13 |
<tr class='listrow'> |
|
14 |
[%- IF price_source.record_item.active_price_source %] |
|
15 |
<td>[% L.button_tag('kivi.io.update_price_source(' _ FORM.row _ ', \'\')', LxERP.t8('Select')) %]</td> |
|
16 |
[%- ELSE %] |
|
17 |
<td><b>[% 'Selected' | $T8 %]</b></td> |
|
18 |
[%- END %] |
|
19 |
<td>[% 'None (PriceSource)' | $T8 %]</td> |
|
20 |
<td>-</td> |
|
21 |
<td></td> |
|
22 |
</tr> |
|
23 |
[%- FOREACH price IN price_source.available_prices %] |
|
24 |
<tr class='listrow'> |
|
25 |
[%- IF price_source.record_item.active_price_source != price.source %] |
|
26 |
<td>[% L.button_tag('kivi.io.update_price_source(' _ FORM.row _ ', \'' _ price.source _ '\', \'' _ LxERP.format_amount(price.price, -2) _ '\')', LxERP.t8('Select')) %]</td> |
|
27 |
[%- ELSIF price_source.record_item.sellprice_as_number != price.price_as_number %] |
|
28 |
<td>[% L.button_tag('kivi.io.update_price_source(' _ FORM.row _ ', \'' _ price.source _ '\', \'' _ LxERP.format_amount(price.price, -2) _ '\')', LxERP.t8('Update Price')) %]</td> |
|
29 |
[%- ELSE %] |
|
30 |
<td><b>[% 'Selected' | $T8 %]</b></td> |
|
31 |
[% END %] |
|
32 |
<td>[% price.full_description | html %]</td> |
|
33 |
<td>[% price.price_as_number %]</td> |
|
34 |
[% IF price.source == best_price.source %] |
|
35 |
<td align='center'>•</td> |
|
36 |
[% ELSE %] |
|
37 |
<td></td> |
|
38 |
[% END %] |
|
39 |
</tr> |
|
40 |
[%- END %] |
|
41 |
</table> |
templates/webpages/oe/sales_order.html | ||
---|---|---|
75 | 75 |
|
76 | 76 |
</td> |
77 | 77 |
</tr> |
78 |
[% PROCESS 'oe/_price_sources_row.html' i = loop.count %] |
|
79 | 78 |
[%- END %] |
80 | 79 |
|
81 | 80 |
</table> |
... | ... | |
95 | 94 |
[% END %] |
96 | 95 |
}, 1); |
97 | 96 |
}); |
98 |
function toggle_price_source(row) { |
|
99 |
$('#row' + row + '_3').toggle(); |
|
100 |
} |
|
101 |
function update_price_source(row, source, price_str){ |
|
102 |
$('#active_price_source_' + row).val(source); |
|
103 |
if (price_str) $('#sellprice_' + row).val(price_str); |
|
104 |
$('#update_button').click(); |
|
105 |
} |
|
106 | 97 |
</script> |
107 | 98 |
|
108 | 99 |
</td> |
Auch abrufbar als: Unified diff
PriceSource: Preisselektion auf Popup umgestellt.
- Logik für geänderte Preise implementiert
- Visualisierung verbessert
- fix für emptied rows
- nachricht wenn invalid und missing
- benachrichtigung für höher/niedriger
- js ausgelagert
- best price benachrichtigung
noch offene bugs:
- preise mit mehr als 2 stellen werden abgeschnitten
- interaktive preise noch nicht möglich
- symbol für "besser preis" ist nicht schön
- beide make_record_item implementierungen sind leicht unterschiedlich
- pricesource controller grösstenteils ungetestet
- performance ist im moment mies