Revision 259a5727
Von Sven Schöling vor fast 7 Jahren hinzugefügt
SL/PriceSource.pm | ||
---|---|---|
4 | 4 |
use parent 'SL::DB::Object'; |
5 | 5 |
use Rose::Object::MakeMethods::Generic ( |
6 | 6 |
scalar => [ qw(record_item record) ], |
7 |
'array --get_set_init' => [ qw(all_price_sources) ], |
|
7 |
'scalar --get_set_init' => [ qw( |
|
8 |
best_price best_discount |
|
9 |
) ], |
|
10 |
'array --get_set_init' => [ qw( |
|
11 |
all_price_sources |
|
12 |
available_prices available_discounts |
|
13 |
) ], |
|
8 | 14 |
); |
9 | 15 |
|
10 | 16 |
use List::UtilsBy qw(min_by max_by); |
... | ... | |
16 | 22 |
my ($self) = @_; |
17 | 23 |
|
18 | 24 |
[ map { |
19 |
$_->new(record_item => $self->record_item, record => $self->record)
|
|
25 |
$self->price_source_by_class($_);
|
|
20 | 26 |
} SL::PriceSource::ALL->all_enabled_price_sources ] |
21 | 27 |
} |
22 | 28 |
|
29 |
sub price_source_by_class { |
|
30 |
my ($self, $class) = @_; |
|
31 |
return unless $class; |
|
32 |
|
|
33 |
$self->{price_source_by_name}{$class} //= |
|
34 |
$class->new(record_item => $self->record_item, record => $self->record); |
|
35 |
} |
|
36 |
|
|
23 | 37 |
sub price_from_source { |
24 | 38 |
my ($self, $source) = @_; |
25 |
my ($source_name, $spec) = split m{/}, $source, 2;
|
|
39 |
return empty_price() if !$source;
|
|
26 | 40 |
|
27 |
my $class = SL::PriceSource::ALL->price_source_class_by_name($source_name); |
|
41 |
${ $self->{price_from_source} //= {} }{$source} //= do { |
|
42 |
my ($source_name, $spec) = split m{/}, $source, 2; |
|
43 |
my $class = SL::PriceSource::ALL->price_source_class_by_name($source_name); |
|
44 |
my $source_object = $self->price_source_by_class($class); |
|
28 | 45 |
|
29 |
return $class |
|
30 |
? $class->new(record_item => $self->record_item, record => $self->record)->price_from_source($source, $spec) |
|
31 |
: empty_price(); |
|
46 |
$source_object |
|
47 |
? $source_object->price_from_source($source, $spec) |
|
48 |
: empty_price(); |
|
49 |
} |
|
32 | 50 |
} |
33 | 51 |
|
34 | 52 |
sub discount_from_source { |
35 | 53 |
my ($self, $source) = @_; |
36 |
my ($source_name, $spec) = split m{/}, $source, 2;
|
|
54 |
return empty_discount() if !$source;
|
|
37 | 55 |
|
38 |
my $class = SL::PriceSource::ALL->price_source_class_by_name($source_name); |
|
56 |
${ $self->{discount_from_source} //= {} }{$source} //= do { |
|
57 |
my ($source_name, $spec) = split m{/}, $source, 2; |
|
58 |
my $class = SL::PriceSource::ALL->price_source_class_by_name($source_name); |
|
59 |
my $source_object = $self->price_source_by_class($class); |
|
39 | 60 |
|
40 |
return $class |
|
41 |
? $class->new(record_item => $self->record_item, record => $self->record)->discount_from_source($source, $spec) |
|
42 |
: empty_discount(); |
|
61 |
$source_object |
|
62 |
? $source_object->discount_from_source($source, $spec) |
|
63 |
: empty_discount(); |
|
64 |
} |
|
43 | 65 |
} |
44 | 66 |
|
45 |
sub available_prices { |
|
46 |
map { $_->available_prices } $_[0]->all_price_sources;
|
|
67 |
sub init_available_prices {
|
|
68 |
[ map { $_->available_prices } $_[0]->all_price_sources ];
|
|
47 | 69 |
} |
48 | 70 |
|
49 |
sub available_discounts { |
|
50 |
return if $_[0]->record_item->part->not_discountable; |
|
51 |
map { $_->available_discounts } $_[0]->all_price_sources;
|
|
71 |
sub init_available_discounts {
|
|
72 |
return [] if $_[0]->record_item->part->not_discountable;
|
|
73 |
[ map { $_->available_discounts } $_[0]->all_price_sources ];
|
|
52 | 74 |
} |
53 | 75 |
|
54 |
sub best_price { |
|
76 |
sub init_best_price {
|
|
55 | 77 |
min_by { $_->price } max_by { $_->priority } grep { $_->price > 0 } grep { $_ } map { $_->best_price } $_[0]->all_price_sources; |
56 | 78 |
} |
57 | 79 |
|
58 |
sub best_discount { |
|
80 |
sub init_best_discount {
|
|
59 | 81 |
max_by { $_->discount } max_by { $_->priority } grep { $_->discount } grep { $_ } map { $_->best_discount } $_[0]->all_price_sources; |
60 | 82 |
} |
61 | 83 |
|
Auch abrufbar als: Unified diff
PriceSource: Objekte cachen.
Im Moment werden die einzelnen Worker im normalen Workflow mehrfach
angelegt, einmal für die verfügbaren, und dann noch einmal für den
besten und zum wiederherstellen der existierenden.
Für größere Belege wird das merklich, und bei komplexen
Implementationen, die auf die Datenbank zugreifen müssen, sogar mehrere
Sekunden.
Diese Patch ist der erste in einer Reihe, die es erlauben optional
Preisquellen
1. nicht unnötig zu erstellen
2. in sich cachen zu lassen
3. vorberechnen zu lassen und damit horizontal zu cachen
3. die Berechnungen in einen Ajax Call zu verzögern