Revision 62f21410
Von Martin Helmling martin.helmling@octosoft.eu vor etwa 7 Jahren hinzugefügt
SL/Controller/Part.pm | ||
---|---|---|
24 | 24 |
use Rose::Object::MakeMethods::Generic ( |
25 | 25 |
'scalar --get_set_init' => [ qw(parts models part p warehouses multi_items_models |
26 | 26 |
makemodels shops_not_assigned |
27 |
customerprices |
|
27 | 28 |
orphaned |
28 | 29 |
assortment assortment_items assembly assembly_items |
29 | 30 |
all_pricegroups all_translations all_partsgroups all_units |
... | ... | |
455 | 456 |
->render; |
456 | 457 |
} |
457 | 458 |
|
459 |
sub action_add_customerprice_row { |
|
460 |
my ($self) = @_; |
|
461 |
|
|
462 |
my $customer_id = $::form->{add_customerprice}; |
|
463 |
|
|
464 |
my $customer = SL::DB::Manager::Customer->find_by(id => $customer_id) |
|
465 |
or return $self->js->error(t8("No customer selected or found!"))->render; |
|
466 |
|
|
467 |
if (grep { $customer_id == $_->customer_id } @{ $self->customerprices }) { |
|
468 |
$self->js->flash('info', t8("This customer has already been added.")); |
|
469 |
} |
|
470 |
|
|
471 |
my $position = scalar @{ $self->customerprices } + 1; |
|
472 |
|
|
473 |
my $cu = SL::DB::PartCustomerPrice->new( |
|
474 |
customer_id => $customer->id, |
|
475 |
customer_partnumber => '', |
|
476 |
price => 0, |
|
477 |
sortorder => $position, |
|
478 |
) or die "Can't create Customerprice object"; |
|
479 |
|
|
480 |
my $row_as_html = $self->p->render( |
|
481 |
'part/_customerprice_row', |
|
482 |
customerprice => $cu, |
|
483 |
listrow => $position % 2 ? 0 |
|
484 |
: 1, |
|
485 |
); |
|
486 |
|
|
487 |
$self->js->append('#customerprice_rows', $row_as_html) # append in tbody |
|
488 |
->val('.add_customerprice_input', '') |
|
489 |
->run('kivi.Part.focus_last_customerprice_input')->render; |
|
490 |
} |
|
491 |
|
|
458 | 492 |
sub action_reorder_items { |
459 | 493 |
my ($self) = @_; |
460 | 494 |
|
... | ... | |
713 | 747 |
$self->part->prices([]); |
714 | 748 |
$self->parse_form_prices; |
715 | 749 |
|
750 |
$self->parse_form_customerprices; |
|
716 | 751 |
$self->parse_form_makemodels; |
717 | 752 |
} |
718 | 753 |
|
... | ... | |
782 | 817 |
}; |
783 | 818 |
} |
784 | 819 |
|
820 |
sub parse_form_customerprices { |
|
821 |
my ($self) = @_; |
|
822 |
|
|
823 |
my $customerprices_map; |
|
824 |
if ( $self->part->customerprices ) { # check for new parts or parts without customerprices |
|
825 |
$customerprices_map = { map { $_->id => Rose::DB::Object::Helpers::clone($_) } @{$self->part->customerprices} }; |
|
826 |
}; |
|
827 |
|
|
828 |
$self->part->customerprices([]); |
|
829 |
|
|
830 |
my $position = 0; |
|
831 |
my $customerprices = delete($::form->{customerprices}) || []; |
|
832 |
foreach my $customerprice ( @{$customerprices} ) { |
|
833 |
next unless $customerprice->{customer_id}; |
|
834 |
$position++; |
|
835 |
my $customer = SL::DB::Manager::Customer->find_by(id => $customerprice->{customer_id}) || die "Can't find customer from id"; |
|
836 |
|
|
837 |
my $cu = SL::DB::PartCustomerPrice->new( # parts_id => $self->part->id, # will be assigned by row add_customerprices |
|
838 |
id => $customerprice->{id}, |
|
839 |
customer_id => $customerprice->{customer_id}, |
|
840 |
customer_partnumber => $customerprice->{customer_partnumber} || '', |
|
841 |
price => $::form->parse_amount(\%::myconfig, $customerprice->{price_as_number}), |
|
842 |
sortorder => $position, |
|
843 |
); |
|
844 |
if ($customerprices_map->{$cu->id} && !$customerprices_map->{$cu->id}->lastupdate && $customerprices_map->{$cu->id}->price == 0 && $cu->price == 0) { |
|
845 |
# lastupdate isn't set, original price is 0 and new lastcost is 0 |
|
846 |
# don't change lastupdate |
|
847 |
} elsif ( !$customerprices_map->{$cu->id} && $cu->price == 0 ) { |
|
848 |
# new customerprice, no lastcost entered, leave lastupdate empty |
|
849 |
} elsif ($customerprices_map->{$cu->id} && $customerprices_map->{$cu->id}->price == $cu->price) { |
|
850 |
# price hasn't changed, use original lastupdate |
|
851 |
$cu->lastupdate($customerprices_map->{$cu->id}->lastupdate); |
|
852 |
} else { |
|
853 |
$cu->lastupdate(DateTime->now); |
|
854 |
}; |
|
855 |
$self->part->add_customerprices($cu); |
|
856 |
}; |
|
857 |
} |
|
858 |
|
|
785 | 859 |
sub build_bin_select { |
786 | 860 |
$_[0]->p->select_tag('part.bin_id', [ $_[0]->warehouse->bins ], |
787 | 861 |
title_key => 'description', |
... | ... | |
806 | 880 |
# used by edit, save, delete and add |
807 | 881 |
|
808 | 882 |
if ( $::form->{part}{id} ) { |
809 |
return SL::DB::Part->new(id => $::form->{part}{id})->load(with => [ qw(makemodels prices translations partsgroup shop_parts shop_parts.shop) ]); |
|
883 |
return SL::DB::Part->new(id => $::form->{part}{id})->load(with => [ qw(makemodels customerprices prices translations partsgroup shop_parts shop_parts.shop) ]);
|
|
810 | 884 |
} else { |
811 | 885 |
die "part_type missing" unless $::form->{part}{part_type}; |
812 | 886 |
return SL::DB::Part->new(part_type => $::form->{part}{part_type}); |
... | ... | |
885 | 959 |
return \@makemodel_array; |
886 | 960 |
} |
887 | 961 |
|
962 |
sub init_customerprices { |
|
963 |
my ($self) = @_; |
|
964 |
|
|
965 |
my $position = 0; |
|
966 |
my @customerprice_array = (); |
|
967 |
my $customerprices = delete($::form->{customerprices}) || []; |
|
968 |
|
|
969 |
foreach my $customerprice ( @{$customerprices} ) { |
|
970 |
next unless $customerprice->{customer_id}; |
|
971 |
$position++; |
|
972 |
my $cu = SL::DB::PartCustomerPrice->new( # parts_id => $self->part->id, # will be assigned by row add_customerprices |
|
973 |
id => $customerprice->{id}, |
|
974 |
customer_partnumber => $customerprice->{customer_partnumber}, |
|
975 |
customer_id => $customerprice->{customer_id} || '', |
|
976 |
price => $::form->parse_amount(\%::myconfig, $customerprice->{price_as_number} || 0), |
|
977 |
sortorder => $position, |
|
978 |
) or die "Can't create cu"; |
|
979 |
# $cu->id($customerprice->{id}) if $customerprice->{id}; |
|
980 |
push(@customerprice_array, $cu); |
|
981 |
}; |
|
982 |
return \@customerprice_array; |
|
983 |
} |
|
984 |
|
|
888 | 985 |
sub init_assembly_items { |
889 | 986 |
my ($self) = @_; |
890 | 987 |
my $position = 0; |
SL/DB/Helper/ALL.pm | ||
---|---|---|
75 | 75 |
use SL::DB::OrderItem; |
76 | 76 |
use SL::DB::Part; |
77 | 77 |
use SL::DB::PartClassification; |
78 |
use SL::DB::PartCustomerPrice; |
|
78 | 79 |
use SL::DB::PartsGroup; |
79 | 80 |
use SL::DB::PartsPriceHistory; |
80 | 81 |
use SL::DB::PaymentTerm; |
SL/DB/Helper/Mappings.pm | ||
---|---|---|
157 | 157 |
parts => 'part', |
158 | 158 |
partsgroup => 'parts_group', |
159 | 159 |
part_classifications => 'PartClassification', |
160 |
part_customer_prices => 'PartCustomerPrice', |
|
160 | 161 |
parts_price_history => 'PartsPriceHistory', |
161 | 162 |
payment_terms => 'payment_term', |
162 | 163 |
periodic_invoices => 'periodic_invoice', |
SL/DB/Manager/PartCustomerPrice.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::PartCustomerPrice; |
|
5 |
|
|
6 |
use strict; |
|
7 |
|
|
8 |
use SL::DB::Helper::Manager; |
|
9 |
use base qw(SL::DB::Helper::Manager); |
|
10 |
|
|
11 |
sub object_class { 'SL::DB::PartCustomerPrice' } |
|
12 |
|
|
13 |
__PACKAGE__->make_manager_methods; |
|
14 |
|
|
15 |
1; |
SL/DB/MetaSetup/Part.pm | ||
---|---|---|
37 | 37 |
payment_id => { type => 'integer' }, |
38 | 38 |
price_factor_id => { type => 'integer' }, |
39 | 39 |
priceupdate => { type => 'date', default => 'now' }, |
40 |
rop => { type => 'float', scale => 4 }, |
|
40 |
rop => { type => 'float', precision => 4, scale => 4 },
|
|
41 | 41 |
sellprice => { type => 'numeric', precision => 15, scale => 5 }, |
42 | 42 |
shop => { type => 'boolean', default => 'false' }, |
43 | 43 |
stockable => { type => 'boolean', default => 'false' }, |
44 | 44 |
unit => { type => 'varchar', length => 20, not_null => 1 }, |
45 | 45 |
ve => { type => 'integer' }, |
46 | 46 |
warehouse_id => { type => 'integer' }, |
47 |
weight => { type => 'float', scale => 4 }, |
|
47 |
weight => { type => 'float', precision => 4, scale => 4 },
|
|
48 | 48 |
); |
49 | 49 |
|
50 | 50 |
__PACKAGE__->meta->primary_key_columns([ 'id' ]); |
SL/DB/MetaSetup/PartCustomerPrice.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::PartCustomerPrice; |
|
4 |
|
|
5 |
use strict; |
|
6 |
|
|
7 |
use parent qw(SL::DB::Object); |
|
8 |
|
|
9 |
__PACKAGE__->meta->table('part_customer_prices'); |
|
10 |
|
|
11 |
__PACKAGE__->meta->columns( |
|
12 |
customer_id => { type => 'integer', not_null => 1 }, |
|
13 |
customer_partnumber => { type => 'text', default => '' }, |
|
14 |
id => { type => 'serial', not_null => 1 }, |
|
15 |
lastupdate => { type => 'date', default => 'now()' }, |
|
16 |
parts_id => { type => 'integer', not_null => 1 }, |
|
17 |
price => { type => 'numeric', default => '0', precision => 15, scale => 5 }, |
|
18 |
sortorder => { type => 'integer', default => '0' }, |
|
19 |
); |
|
20 |
|
|
21 |
__PACKAGE__->meta->primary_key_columns([ 'id' ]); |
|
22 |
|
|
23 |
__PACKAGE__->meta->allow_inline_column_values(1); |
|
24 |
|
|
25 |
__PACKAGE__->meta->foreign_keys( |
|
26 |
customer => { |
|
27 |
class => 'SL::DB::Customer', |
|
28 |
key_columns => { customer_id => 'id' }, |
|
29 |
}, |
|
30 |
|
|
31 |
parts => { |
|
32 |
class => 'SL::DB::Part', |
|
33 |
key_columns => { parts_id => 'id' }, |
|
34 |
}, |
|
35 |
); |
|
36 |
|
|
37 |
1; |
|
38 |
; |
SL/DB/Part.pm | ||
---|---|---|
37 | 37 |
manager_args => { sort_by => 'sortorder' }, |
38 | 38 |
column_map => { id => 'parts_id' }, |
39 | 39 |
}, |
40 |
customerprices => { |
|
41 |
type => 'one to many', |
|
42 |
class => 'SL::DB::PartCustomerPrice', |
|
43 |
column_map => { id => 'parts_id' }, |
|
44 |
}, |
|
40 | 45 |
translations => { |
41 | 46 |
type => 'one to many', |
42 | 47 |
class => 'SL::DB::Translation', |
SL/DB/PartCustomerPrice.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::PartCustomerPrice; |
|
5 |
|
|
6 |
use strict; |
|
7 |
|
|
8 |
use SL::DB::MetaSetup::PartCustomerPrice; |
|
9 |
use SL::DB::Manager::PartCustomerPrice; |
|
10 |
|
|
11 |
__PACKAGE__->meta->initialize; |
|
12 |
|
|
13 |
1; |
SL/IR.pm | ||
---|---|---|
49 | 49 |
use SL::MoreCommon; |
50 | 50 |
use SL::DB::Default; |
51 | 51 |
use SL::DB::TaxZone; |
52 |
use SL::DB::MakeModel; |
|
52 | 53 |
use SL::DB; |
53 | 54 |
use SL::Presenter::Part qw(type_abbreviation classification_abbreviation); |
54 | 55 |
use List::Util qw(min); |
... | ... | |
1377 | 1378 |
$stw->finish(); |
1378 | 1379 |
chop $ref->{taxaccounts}; |
1379 | 1380 |
|
1380 |
$ref->{onhand} *= 1; |
|
1381 |
## vendor_id ggf beim ersten mal noch nicht gesetzt nur vendor <name>--<id> |
|
1382 |
($form->{vendor}, $form->{vendor_id}) = split(/--/, $form->{vendor}) if ! $form->{vendor_id}; |
|
1381 | 1383 |
|
1384 |
if ( $form->{vendor_id} ) { |
|
1385 |
my $mm = SL::DB::Manager::MakeModel->get_first( |
|
1386 |
query => [ parts_id => $ref->{id} , make => $form->{vendor_id} ] ); |
|
1387 |
if ( $mm ) { |
|
1388 |
$::lxdebug->message(LXDebug->DEBUG2(), "mm id=".$mm->{id}." price=".$mm->{lastcost}); |
|
1389 |
$ref->{lastcost} = $mm->{lastcost}; |
|
1390 |
} |
|
1391 |
} |
|
1392 |
|
|
1393 |
$ref->{onhand} *= 1; |
|
1382 | 1394 |
push @{ $form->{item_list} }, $ref; |
1383 | 1395 |
|
1384 | 1396 |
} |
SL/IS.pm | ||
---|---|---|
2435 | 2435 |
last; |
2436 | 2436 |
} |
2437 | 2437 |
} |
2438 |
## customer_id ggf beim ersten mal noch nicht gesetzt nur customer <name>--<id> |
|
2439 |
($form->{customer}, $form->{customer_id}) = split(/--/, $form->{customer}) if ! $form->{customer_id}; |
|
2440 |
if ( $form->{customer_id} ) { |
|
2441 |
my $cprice = SL::DB::Manager::PartCustomerPrice->get_first( |
|
2442 |
query => [ parts_id => $ref->{id} , customer_id => $form->{customer_id} ] ); |
|
2443 |
if ( $cprice ) { |
|
2444 |
$::lxdebug->message(LXDebug->DEBUG2(), "cprice id=".$cprice->{id}." price=".$cprice->{price}); |
|
2445 |
$ref->{sellprice} = $cprice->{price}; |
|
2446 |
} |
|
2447 |
} |
|
2438 | 2448 |
|
2439 | 2449 |
$ref->{onhand} *= 1; |
2440 |
|
|
2441 | 2450 |
push @{ $form->{item_list} }, $ref; |
2442 | 2451 |
} |
2443 | 2452 |
$sth->finish; |
SL/PriceSource/ALL.pm | ||
---|---|---|
4 | 4 |
use SL::PriceSource::Pricegroup; |
5 | 5 |
use SL::PriceSource::MasterData; |
6 | 6 |
use SL::PriceSource::Makemodel; |
7 |
use SL::PriceSource::CustomerPrice; |
|
7 | 8 |
use SL::PriceSource::Customer; |
8 | 9 |
use SL::PriceSource::Vendor; |
9 | 10 |
use SL::PriceSource::Business; |
... | ... | |
15 | 16 |
vendor_discount => 'SL::PriceSource::Vendor', |
16 | 17 |
pricegroup => 'SL::PriceSource::Pricegroup', |
17 | 18 |
makemodel => 'SL::PriceSource::Makemodel', |
19 |
customerprice => 'SL::PriceSource::CustomerPrice', |
|
18 | 20 |
business => 'SL::PriceSource::Business', |
19 | 21 |
price_rules => 'SL::PriceSource::PriceRules', |
20 | 22 |
); |
... | ... | |
25 | 27 |
vendor_discount |
26 | 28 |
pricegroup |
27 | 29 |
makemodel |
30 |
customerprice |
|
28 | 31 |
business |
29 | 32 |
price_rules |
30 | 33 |
); |
SL/PriceSource/CustomerPrice.pm | ||
---|---|---|
1 |
package SL::PriceSource::CustomerPrice; |
|
2 |
|
|
3 |
use strict; |
|
4 |
use parent qw(SL::PriceSource::Base); |
|
5 |
|
|
6 |
use SL::PriceSource::Price; |
|
7 |
use SL::Locale::String; |
|
8 |
use SL::DB::PartCustomerPrice; |
|
9 |
# use List::UtilsBy qw(min_by max_by); |
|
10 |
|
|
11 |
sub name { 'customer_price' } |
|
12 |
|
|
13 |
sub description { t8('Customer specific Price') } |
|
14 |
|
|
15 |
sub available_prices { |
|
16 |
my ($self, %params) = @_; |
|
17 |
|
|
18 |
return () if !$self->part; |
|
19 |
return () if !$self->record->is_sales; |
|
20 |
|
|
21 |
map { $self->make_price_from_customerprice($_) } |
|
22 |
grep { $_->customer_id == $self->record->customer_id } |
|
23 |
$self->part->customerprices; |
|
24 |
} |
|
25 |
|
|
26 |
sub available_discounts { } |
|
27 |
|
|
28 |
sub price_from_source { |
|
29 |
my ($self, $source, $spec) = @_; |
|
30 |
|
|
31 |
my $customerprice = SL::DB::Manager::PartCustomerPrice->find_by(id => $spec); |
|
32 |
|
|
33 |
return $self->make_price_from_customerprice($customerprice); |
|
34 |
|
|
35 |
} |
|
36 |
|
|
37 |
sub best_price { |
|
38 |
my ($self, %params) = @_; |
|
39 |
|
|
40 |
return () if !$self->record->is_sales; |
|
41 |
|
|
42 |
# min_by { $_->price } $self->available_prices; |
|
43 |
# max_by { $_->price } $self->available_prices; |
|
44 |
&available_prices; |
|
45 |
|
|
46 |
} |
|
47 |
|
|
48 |
sub best_discount { } |
|
49 |
|
|
50 |
sub make_price_from_customerprice { |
|
51 |
my ($self, $customerprice) = @_; |
|
52 |
|
|
53 |
return SL::PriceSource::Price->new( |
|
54 |
price => $customerprice->price, |
|
55 |
spec => $customerprice->id, |
|
56 |
description => $customerprice->customer_partnumber, |
|
57 |
price_source => $self, |
|
58 |
); |
|
59 |
} |
|
60 |
|
|
61 |
|
|
62 |
1; |
bin/mozilla/ic.pl | ||
---|---|---|
281 | 281 |
description => $locale->text('Part Description') . ": '$form->{description}'", |
282 | 282 |
make => $locale->text('Make') . ": '$form->{make}'", |
283 | 283 |
model => $locale->text('Model') . ": '$form->{model}'", |
284 |
customername => $locale->text('Customer') . ": '$form->{customername}'", |
|
285 |
customernumber=> $locale->text('Customer Part Number').": '$form->{customernumber}'", |
|
284 | 286 |
drawing => $locale->text('Drawing') . ": '$form->{drawing}'", |
285 | 287 |
microfiche => $locale->text('Microfiche') . ": '$form->{microfiche}'", |
286 | 288 |
l_soldtotal => $locale->text('Qty in Selected Records'), |
bin/mozilla/is.pl | ||
---|---|---|
776 | 776 |
# ask if it is a part or service item |
777 | 777 |
|
778 | 778 |
if ( $form->{"partsgroup_$i"} |
779 |
&& ($form->{"partsnumber_$i"} eq "")
|
|
779 |
&& ($form->{"partnumber_$i" } eq "")
|
|
780 | 780 |
&& ($form->{"description_$i"} eq "")) { |
781 | 781 |
$form->{rowcount}--; |
782 | 782 |
$form->{"discount_$i"} = ""; |
... | ... | |
784 | 784 |
|
785 | 785 |
} else { |
786 | 786 |
$form->{"id_$i"} = 0; |
787 |
if ( $form->{is_wrong_ptype} > 0 ) { |
|
788 |
$form->{"partnumber_$i"} = ""; |
|
789 |
$form->{"description_$i"} = ""; |
|
790 |
} |
|
787 | 791 |
new_item(); |
788 | 792 |
} |
789 | 793 |
} |
js/kivi.Part.js | ||
---|---|---|
253 | 253 |
$("#makemodel_rows tr:last").find('input[type=text]').filter(':visible:first').focus(); |
254 | 254 |
}; |
255 | 255 |
|
256 |
|
|
257 |
// customerprice |
|
258 |
ns.customerprice_renumber_positions = function() { |
|
259 |
$('.customerprice_row [name="position"]').each(function(idx, elt) { |
|
260 |
$(elt).html(idx+1); |
|
261 |
}); |
|
262 |
}; |
|
263 |
|
|
264 |
ns.delete_customerprice_row = function(clicked) { |
|
265 |
var row = $(clicked).closest('tr'); |
|
266 |
$(row).remove(); |
|
267 |
|
|
268 |
ns.customerprice_renumber_positions(); |
|
269 |
}; |
|
270 |
|
|
271 |
ns.add_customerprice_row = function() { |
|
272 |
if ($('#add_customerpriceid').val() === '') return; |
|
273 |
|
|
274 |
var data = $('#customerprice_table :input').serializeArray(); |
|
275 |
data.push({ name: 'action', value: 'Part/add_customerprice_row' }); |
|
276 |
|
|
277 |
$.post("controller.pl", data, kivi.eval_json_result); |
|
278 |
}; |
|
279 |
|
|
280 |
ns.focus_last_customerprice_input = function () { |
|
281 |
$("#customerprice_rows tr:last").find('input[type=text]').filter(':visible:first').focus(); |
|
282 |
}; |
|
283 |
|
|
284 |
|
|
256 | 285 |
ns.reload_bin_selection = function() { |
257 | 286 |
$.post("controller.pl", { action: 'Part/warehouse_changed', warehouse_id: function(){ return $('#part_warehouse_id').val() } }, kivi.eval_json_result); |
258 | 287 |
} |
... | ... | |
734 | 763 |
} |
735 | 764 |
}); |
736 | 765 |
|
766 |
$('.add_customerprice_input').keydown(function(event) { |
|
767 |
if(event.keyCode == 13) { |
|
768 |
event.preventDefault(); |
|
769 |
ns.add_customerprice_row(); |
|
770 |
return false; |
|
771 |
} |
|
772 |
}); |
|
773 |
|
|
737 | 774 |
$('#part_warehouse_id').change(kivi.Part.reload_bin_selection); |
738 | 775 |
|
739 | 776 |
ns.init(); |
locale/de/all | ||
---|---|---|
807 | 807 |
'Customer Name' => 'Kundenname', |
808 | 808 |
'Customer Number' => 'Kundennummer', |
809 | 809 |
'Customer Order Number' => 'Bestellnummer des Kunden', |
810 |
'Customer Part Number' => 'Kunden-Art-Nr.', |
|
811 |
'Customer Price' => 'Kundenpreis', |
|
810 | 812 |
'Customer deleted!' => 'Kunde gelöscht!', |
811 | 813 |
'Customer details' => 'Kundendetails', |
812 | 814 |
'Customer missing!' => 'Kundenname fehlt!', |
813 | 815 |
'Customer not found' => 'Kunde nicht gefunden', |
814 | 816 |
'Customer saved' => 'Kunde gespeichert', |
815 | 817 |
'Customer saved!' => 'Kunde gespeichert!', |
818 |
'Customer specific Price' => 'Kundenpreis', |
|
816 | 819 |
'Customer type' => 'Kundentyp', |
817 | 820 |
'Customer variables' => 'Kundenvariablen', |
818 | 821 |
'Customer\'s Mandate Date of Signature' => 'Mandatsunterschriftsdatum des Kunden', |
... | ... | |
1960 | 1963 |
'No contra account selected!' => 'Kein Gegenkonto ausgewählt!', |
1961 | 1964 |
'No custom data exports have been created yet.' => 'Es wurden noch keine benutzerdefinierten Datenexporte angelegt.', |
1962 | 1965 |
'No customer has been selected yet.' => 'Es wurde noch kein Kunde ausgewählt.', |
1966 |
'No customer selected or found!' => 'Kein Kunde selektiert oder keinen gefunden!', |
|
1963 | 1967 |
'No data was found.' => 'Es wurden keine Daten gefunden.', |
1964 | 1968 |
'No default currency' => 'Keine Standardwährung', |
1965 | 1969 |
'No default value' => 'Kein Standardwert', |
... | ... | |
2206 | 2210 |
'Payable account' => 'Verbindlichkeitskonto', |
2207 | 2211 |
'Payables' => 'Verbindlichkeiten', |
2208 | 2212 |
'Payment' => 'Zahlungsausgang', |
2209 |
'Payment / Delivery Options' => 'Zahlungs- und Lieferoptionen',
|
|
2213 |
'Payment / Delivery Options' => '', |
|
2210 | 2214 |
'Payment Reminder' => 'Zahlungserinnerung', |
2211 | 2215 |
'Payment Terms' => 'Zahlungsbedingungen', |
2212 | 2216 |
'Payment Terms missing in row ' => 'Zahlungsfrist fehlt in Zeile ', |
... | ... | |
3442 | 3446 |
'This Price Rule is no longer valid' => 'Diese Preisregel ist nicht mehr gültig', |
3443 | 3447 |
'This can be done with the following query:' => 'Dies kann mit der folgenden Datenbankabfrage erreicht werden:', |
3444 | 3448 |
'This could have happened for two reasons:' => 'Dies kann aus zwei Gründen geschehen sein:', |
3449 |
'This customer has already been added.' => 'Für diesen Kunden ist bereits ein Preis hinzugefügt.', |
|
3445 | 3450 |
'This customer number is already in use.' => 'Diese Kundennummer wird bereits verwendet.', |
3446 | 3451 |
'This discount has since gone down' => 'Dieser Rabatt ist mittlerweile niedriger', |
3447 | 3452 |
'This discount has since gone up' => 'Dieser Rabatt ist mittlerweile höher', |
sql/Pg-upgrade2/create_part_customerprices.sql | ||
---|---|---|
1 |
-- @tag: create_part_customerprices |
|
2 |
-- @description: VK-Preis für jeden Kunden speichern und das Datum der Eingabe |
|
3 |
-- @depends: release_3_5_1 |
|
4 |
|
|
5 |
CREATE TABLE part_customer_prices ( |
|
6 |
id SERIAL PRIMARY KEY, |
|
7 |
parts_id integer NOT NULL, |
|
8 |
customer_id integer NOT NULL, |
|
9 |
customer_partnumber text DEFAULT '', |
|
10 |
price numeric(15,5) DEFAULT 0, |
|
11 |
sortorder integer DEFAULT 0, |
|
12 |
lastupdate date DEFAULT now(), |
|
13 |
|
|
14 |
FOREIGN KEY (parts_id) REFERENCES parts (id), |
|
15 |
FOREIGN KEY (customer_id) REFERENCES customer (id) |
|
16 |
); |
|
17 |
CREATE INDEX part_customer_prices_parts_id_key ON part_customer_prices USING btree (parts_id); |
|
18 |
CREATE INDEX part_customer_prices_customer_id_key ON part_customer_prices USING btree (customer_id); |
templates/webpages/part/_basic_data.html | ||
---|---|---|
223 | 223 |
[% PROCESS 'part/_pricegroup_prices.html' %] |
224 | 224 |
</div> |
225 | 225 |
|
226 |
<div id="customerprices"> |
|
227 |
[% PROCESS 'part/_customerprices.html' %] |
|
228 |
</div> |
|
226 | 229 |
[%- UNLESS SELF.part.is_assembly %] |
227 | 230 |
<div id="makemodel"> |
228 | 231 |
[% PROCESS 'part/_makemodel.html' %] |
templates/webpages/part/_customerprice_row.html | ||
---|---|---|
1 |
[%- USE T8 %] |
|
2 |
[%- USE L %] |
|
3 |
[%- USE HTML %] |
|
4 |
[%- USE LxERP %] |
|
5 |
<tr class="listrow[% listrow % 2 %] customerprice_row"> |
|
6 |
<td style='display:none'> |
|
7 |
[% L.hidden_tag("customerprices[+].customer_id", customerprice.customer_id) %] |
|
8 |
[% L.hidden_tag("customerprices[].id" , customerprice.id) %] |
|
9 |
</td> |
|
10 |
<td align="center"> |
|
11 |
[%- L.button_tag("kivi.Part.delete_customerprice_row(this)", |
|
12 |
LxERP.t8("X")) %] [% # , confirm=LxERP.t8("Are you sure?")) %] |
|
13 |
</td> |
|
14 |
<td><span name="position" class="numeric">[% HTML.escape(customerprice.sortorder) %]</span></td> |
|
15 |
<td align="center"> |
|
16 |
<img src="image/updown.png" alt="[%- LxERP.t8('reorder item') %]" class="dragdrop"> |
|
17 |
</td> |
|
18 |
<td>[% customerprice.customer.customernumber | html %]</td> |
|
19 |
<td>[% customerprice.customer.name | html %] </td> |
|
20 |
<td>[% L.input_tag('customerprices[].customer_partnumber', customerprice.customer_partnumber, size=30 ) %]</td> |
|
21 |
<td>[% L.input_tag('customerprices[].price_as_number' , customerprice.price_as_number , size=15 , class="reformat_number numeric") %]</td> |
|
22 |
<td>[% L.hidden_tag('customerprices[].lastupdate' , customerprice.lastupdate.to_kivitendo) %][% customerprice.lastupdate.to_kivitendo | html %]</td> |
|
23 |
</tr> |
templates/webpages/part/_customerprices.html | ||
---|---|---|
1 |
[%- USE T8 %] |
|
2 |
[%- USE L %] |
|
3 |
[%- USE HTML %] |
|
4 |
[%- USE LxERP %] |
|
5 |
<tr> |
|
6 |
</tr> |
|
7 |
<tr> |
|
8 |
<td> |
|
9 |
<table id="customerprice_table"> |
|
10 |
<thead> |
|
11 |
<th class="listheading" style='text-align:center' nowrap width="1"><img src="image/close.png" alt="[%- LxERP.t8('delete item') %]"></th> |
|
12 |
<th class="listheading">[% 'position' | $T8 %]</th> |
|
13 |
<th class="listheading" style='text-align:center' nowrap width="1"><img src="image/updown.png" alt="[%- LxERP.t8('reorder item') %]"></th> |
|
14 |
<th class="listheading" style='width:12em'>[% 'Customer Number' | $T8 %]</th> |
|
15 |
<th class="listheading">[% 'Customer' | $T8 %]</th> |
|
16 |
<th class="listheading">[% 'Customer Part Number' | $T8 %]</th> |
|
17 |
<th class="listheading">[% 'Customer Price' | $T8 %]</th> |
|
18 |
<th class="listheading">[% 'Updated' | $T8 %]</th> |
|
19 |
</thead> |
|
20 |
<tbody id="customerprice_rows"> |
|
21 |
[% SET listrow = 0 %] |
|
22 |
[%- FOREACH customerprice = SELF.part.customerprices %] |
|
23 |
[% listrow = listrow + 1 %] |
|
24 |
[% PROCESS 'part/_customerprice_row.html' customerprice=customerprice listrow=listrow %] |
|
25 |
[%- END %] |
|
26 |
</tbody> |
|
27 |
<tbody> |
|
28 |
<tr> |
|
29 |
<td></td> |
|
30 |
<td></td> |
|
31 |
<td></td> |
|
32 |
<td align="right">[% 'Customer' | $T8 %]</td> |
|
33 |
<td rowspan="2">[% P.customer_vendor.customer_picker('add_customerprice', '', style='width: 300px', class="add_customerprice_input") %]</td> |
|
34 |
<td rowspan="2" align="right">[% L.button_tag('kivi.Part.add_customerprice_row()', LxERP.t8('Add')) %]</td> |
|
35 |
</tr> |
|
36 |
</tbody> |
|
37 |
</table> |
|
38 |
</td> |
|
39 |
</tr> |
|
40 |
[% L.sortable_element('#customerprice_rows') %] |
|
41 |
|
|
42 |
<script type="text/javascript"> |
|
43 |
$(function() { |
|
44 |
|
|
45 |
$('#customerprice_rows').on('sortstop', function(event, ui) { |
|
46 |
kivi.Part.customerprice_renumber_positions(); |
|
47 |
}); |
|
48 |
|
|
49 |
}) |
|
50 |
</script> |
templates/webpages/part/_makemodel.html | ||
---|---|---|
12 | 12 |
<th class="listheading" style='text-align:center' nowrap width="1"><img src="image/close.png" alt="[%- LxERP.t8('delete item') %]"></th> |
13 | 13 |
<th class="listheading">[% 'position' | $T8 %]</th> |
14 | 14 |
<th class="listheading" style='text-align:center' nowrap width="1"><img src="image/updown.png" alt="[%- LxERP.t8('reorder item') %]"></th> |
15 |
<th class="listheading">[% 'Vendor Number' | $T8 %]</th> |
|
15 |
<th class="listheading" style='width:12em'>[% 'Vendor Number' | $T8 %]</th>
|
|
16 | 16 |
<th class="listheading">[% 'Vendor' | $T8 %]</th> |
17 | 17 |
<th class="listheading">[% 'Model' | $T8 %]</th> |
18 | 18 |
<th class="listheading">[% 'Last Cost' | $T8 %]</th> |
Auch abrufbar als: Unified diff
Kunden-Spezifische Artikeleigenschaften
neue Tabelle "PartCustomerPrices" mit SL/DB Dateien
in Artikelstammdaten eingebaut,
in Preisquellen analog zu den Lieferantenpreisen nun Kundenpreise eingebaut
(Unklar ist was bei Kundenpreisen der beste Preis ist !)
Analog zu Lieferanten "make" und "model" aus kundenspezifischen Daten
"customer" und "custnumber" zum Drucken pro Artikel anbieten