Projekt

Allgemein

Profil

Herunterladen (4,49 KB) Statistiken
| Zweig: | Markierung: | Revision:
eebe8e90 Sven Schöling
package SL::PriceSource;

use strict;
use parent 'SL::DB::Object';
use Rose::Object::MakeMethods::Generic (
0409db7c Sven Schöling
scalar => [ qw(record_item record) ],
1c311d64 Sven Schöling
'array --get_set_init' => [ qw(all_price_sources) ],
eebe8e90 Sven Schöling
);

89b26688 Sven Schöling
use List::UtilsBy qw(min_by max_by);
eebe8e90 Sven Schöling
use SL::PriceSource::ALL;
use SL::PriceSource::Price;
use SL::Locale::String;

1c311d64 Sven Schöling
sub init_all_price_sources {
eebe8e90 Sven Schöling
my ($self) = @_;

1c311d64 Sven Schöling
[ map {
0409db7c Sven Schöling
$_->new(record_item => $self->record_item, record => $self->record)
1c311d64 Sven Schöling
} SL::PriceSource::ALL->all_enabled_price_sources ]
eebe8e90 Sven Schöling
}

sub price_from_source {
my ($self, $source) = @_;
my ($source_name, $spec) = split m{/}, $source, 2;

my $class = SL::PriceSource::ALL->price_source_class_by_name($source_name);

return $class
89b26688 Sven Schöling
? $class->new(record_item => $self->record_item, record => $self->record)->price_from_source($source, $spec)
eebe8e90 Sven Schöling
: empty_price();
}

sub available_prices {
map { $_->available_prices } $_[0]->all_price_sources;
}

89b26688 Sven Schöling
sub available_discounts {
67f06c1e Sven Schöling
return if $_[0]->record_item->part->not_discountable;
89b26688 Sven Schöling
map { $_->available_discounts } $_[0]->all_price_sources;
}

eebe8e90 Sven Schöling
sub best_price {
9f666261 Sven Schöling
min_by { $_->price } max_by { $_->priority } grep { $_->price > 0 } grep { $_ } map { $_->best_price } $_[0]->all_price_sources;
89b26688 Sven Schöling
}

sub best_discount {
9f666261 Sven Schöling
max_by { $_->discount } max_by { $_->priority } grep { $_->discount } grep { $_ } map { $_->best_discount } $_[0]->all_price_sources;
eebe8e90 Sven Schöling
}

sub empty_price {
SL::PriceSource::Price->new(
description => t8('None (PriceSource)'),
);
}

1;

__END__

=encoding utf-8

=head1 NAME

SL::PriceSource - mixin for price_sources in record items

418f0e70 Sven Schöling
=head1 DESCRIPTION
eebe8e90 Sven Schöling
418f0e70 Sven Schöling
PriceSource is an interface that allows generic algorithms to be plugged
together to calculate available prices for a position in a record.
eebe8e90 Sven Schöling
049e49fe Sven Schöling
Each algorithm can access details of the record to realize dependencies on
418f0e70 Sven Schöling
part, customer, vendor, date, quantity etc, which was previously not possible.
eebe8e90 Sven Schöling
fd6f0f82 Geoffrey Richardson
=head1 BACKGROUND AND PHILOSOPHY
eebe8e90 Sven Schöling
418f0e70 Sven Schöling
sql ledger and subsequently Lx-Office had three prices per part: sellprice,
listprice and lastcost. At the moment a part is loaded into a record, the
fd6f0f82 Geoffrey Richardson
applicable price is copied and after that it is free to be changed.
eebe8e90 Sven Schöling
fd6f0f82 Geoffrey Richardson
Later on additional things were added. Various types of discount, vendor pricelists
418f0e70 Sven Schöling
and the infamous price groups. The problem is not that those didn't work, the
fd6f0f82 Geoffrey Richardson
problem is, that they had to guess too much when to change a price with the
available price from the database, and when to leave the user entered price.
eebe8e90 Sven Schöling
418f0e70 Sven Schöling
Unrelated to that, users asked for more ways to store special prices, based on
qty (block pricing, bulk discount), based on date (special offers), based on
customers (special terms), up to full blown calculation modules.

On a third front sales personnel asked for ways to see what price options a
position in a quotation has, and wanted information available when a price
offer changed.

Price sources put that together by making some compromises:

=over 4

=item 1.

Only change the price on creation of a position or when asked to.

=item 2.

Either set the price from a price source and let it be read only, or use a free
price.

=item 3.

Save the origin of each price with the record so that the calculation can be
reproduced.

=item 4.

Make price calculation flexible and pluggable.

=back

The first point creates user security by never changing a price for them
without their explicit consent, eliminating all problems originating from
trying to be smart. The second and third one ensure that later on the
calculation can be repeated so that invalid prices can be caught (because for
example the special offer is no longer valid), and so that sales personnel have
information about rising or falling prices. The fourth point ensures that
049e49fe Sven Schöling
insular calculation processes can be developed independent of the core code.
418f0e70 Sven Schöling
=head1 INTERFACE METHODS

=over 4

=item C<new PARAMS>

C<PARAMS> must contain both C<record> and C<record_item>. C<record_item> does
not have to be registered in C<record>.

=item C<price_from_source>

Attempts to retrieve a formerly calculated price with the same conditions

=item C<available_prices>

Returns all available prices.

=item C<best_price>
eebe8e90 Sven Schöling
418f0e70 Sven Schöling
Attempts to get the best available price. returns L<empty_price> if no price is found.
eebe8e90 Sven Schöling
418f0e70 Sven Schöling
=item C<empty_price>
eebe8e90 Sven Schöling
418f0e70 Sven Schöling
A special empty price, that does not change the previously entered price, and
opens the price field to manual changes.
eebe8e90 Sven Schöling
418f0e70 Sven Schöling
=back
eebe8e90 Sven Schöling
418f0e70 Sven Schöling
=head1 SEE ALSO
eebe8e90 Sven Schöling
418f0e70 Sven Schöling
L<SL::PriceSource::Base>,
L<SL::PriceSource::Price>,
L<SL::PriceSource::ALL>
eebe8e90 Sven Schöling
=head1 BUGS

None yet. :)

=head1 AUTHOR

Sven Schoeling E<lt>s.schoeling@linet-services.deE<gt>

=cut