kivitendo/SL/PriceSource/Base.pm @ 79b7fc43
eebe8e90 | Sven Schöling | package SL::PriceSource::Base;
|
||
use strict;
|
||||
use parent qw(SL::DB::Object);
|
||||
use Rose::Object::MakeMethods::Generic (
|
||||
scalar => [ qw(record_item record) ],
|
||||
);
|
||||
sub name { die 'name needs to be implemented' }
|
||||
sub description { die 'description needs to be implemented' }
|
||||
sub available_prices { die 'available_prices needs to be implemented' }
|
||||
89b26688 | Sven Schöling | sub available_discounts { die 'available_discounts needs to be implemented' }
|
||
eebe8e90 | Sven Schöling | sub best_price { die 'best_price needs to be implemented' }
|
||
89b26688 | Sven Schöling | sub best_discounts { die 'best_discounts needs to be implemented' }
|
||
eebe8e90 | Sven Schöling | sub price_from_source { die 'price_from_source needs to be implemented:' . "@_" }
|
||
sub part {
|
||||
$_[0]->record_item->part;
|
||||
}
|
||||
89b26688 | Sven Schöling | sub customer_vendor {
|
||
$_[0]->record->is_sales ? $_[0]->record->customer : $_[0]->record->vendor;
|
||||
}
|
||||
eebe8e90 | Sven Schöling | 1;
|
||
__END__
|
||||
=encoding utf-8
|
||||
=head1 NAME
|
||||
418f0e70 | Sven Schöling | SL::PriceSource::Base - this is the base class for price source adapters
|
||
eebe8e90 | Sven Schöling | |||
=head1 SYNOPSIS
|
||||
418f0e70 | Sven Schöling | # working example adapter:
|
||
package SL::PriceSource::FiveOnEverything;
|
||||
eebe8e90 | Sven Schöling | |||
418f0e70 | Sven Schöling | use parent qw(SL::PriceSource::Base);
|
||
# used as internal identifier
|
||||
sub name { 'simple' }
|
||||
# used in frontend to signal where this comes from
|
||||
sub description { t8('Simple') }
|
||||
my $price = SL::PriceSource::Price->new(
|
||||
price => 5,
|
||||
description => t8('Only today 5$ on everything!'),
|
||||
price_source => $self,
|
||||
);
|
||||
# give list of prices that this
|
||||
sub available_prices {
|
||||
return ($price);
|
||||
eebe8e90 | Sven Schöling | }
|
||
418f0e70 | Sven Schöling | sub best_price {
|
||
return $price;
|
||||
}
|
||||
eebe8e90 | Sven Schöling | |||
418f0e70 | Sven Schöling | sub price_from_source {
|
||
return $price;
|
||||
}
|
||||
eebe8e90 | Sven Schöling | |||
=head1 DESCRIPTION
|
||||
418f0e70 | Sven Schöling | See L<SL::PriceSource> for information about the mechanism.
|
||
This is the base class for a price source algorithm. To play well, you'll have
|
||||
to implement a number of interface methods and be aware of a number of corner
|
||||
conditions.
|
||||
=head1 AVAILABLE METHODS
|
||||
=over 4
|
||||
=item C<record_item>
|
||||
=item C<record>
|
||||
C<record> can be any one of L<SL::DB::Order>, L<SL::DB::DeliveryOrder>,
|
||||
L<SL::DB::Invoice>, L<SL::DB::PurchaseInvoice>. C<record_item> is of the
|
||||
corresponding position type.
|
||||
You can assume that both are filled with all information available at the time.
|
||||
C<part> and C<customer>/C<vendor> as well as C<is_sales> can be relied upon. You must NOT
|
||||
rely on both being linked together, in particular
|
||||
$self->record_item->record # don't do that
|
||||
eebe8e90 | Sven Schöling | |||
418f0e70 | Sven Schöling | is not guaranteed to work.
|
||
eebe8e90 | Sven Schöling | |||
418f0e70 | Sven Schöling | Also these are copies and not the original documents. Do not try to change
|
||
anything and do not save those.
|
||||
=item C<part>
|
||||
Shortcut to C<< record_item->part >>
|
||||
89b26688 | Sven Schöling | =item C<customer_vendor>
|
||
Shortcut to C<< record->is_sales ? record->customer : record->vendor >>
|
||||
418f0e70 | Sven Schöling | =back
|
||
eebe8e90 | Sven Schöling | |||
=head1 INTERFACE METHODS
|
||||
=over 4
|
||||
=item C<name>
|
||||
418f0e70 | Sven Schöling | Must return a unique internal name. Must be entered in
|
||
L<SL::PriceSource::ALL>.
|
||||
eebe8e90 | Sven Schöling | |||
=item C<description>
|
||||
418f0e70 | Sven Schöling | Must return a translated name to be used in frontend. Will be used, to
|
||
distinguish the origin of different prices.
|
||||
=item C<available_prices>
|
||||
eebe8e90 | Sven Schöling | |||
418f0e70 | Sven Schöling | Must return a list of all prices that you algorithm can recommend the user
|
||
for the current situation. Each price must have a unique spec that can be used
|
||||
to recreate it later. Try to be brief, no one needs 20 different price
|
||||
suggestions.
|
||||
eebe8e90 | Sven Schöling | |||
89b26688 | Sven Schöling | =item C<available_discounts>
|
||
Must return a list of all prices that you algorithm can recommend the user
|
||||
for the current situation. Each discount must have a unique spec that can be
|
||||
used to recreate it later. Try to be brief, no one needs 20 different discount
|
||||
suggestions.
|
||||
418f0e70 | Sven Schöling | =item C<best_price>
|
||
eebe8e90 | Sven Schöling | |||
418f0e70 | Sven Schöling | Must return what you think of as the best matching price in your
|
||
C<available_prices>. This does not have to be the lowest price, but it will be
|
||||
compared later to other price sources, and the lowest will be set.
|
||||
eebe8e90 | Sven Schöling | |||
89b26688 | Sven Schöling | =item C<best_discount>
|
||
Must return what you think of as the best matching discount in your
|
||||
C<available_discounts>. This does not have to be the highest discount, but it
|
||||
will be compared later to other price sources, and the highest will be set.
|
||||
418f0e70 | Sven Schöling | =item C<price_from_source SOURCE, SPEC>
|
||
eebe8e90 | Sven Schöling | |||
89b26688 | Sven Schöling | Must recreate the price or discount from C<SPEC> and return. For reference, the
|
||
complete C<SOURCE> entry from C<record_item.active_price_source> or
|
||||
C<record_item.active_discount_source> is included.
|
||||
eebe8e90 | Sven Schöling | |||
418f0e70 | Sven Schöling | Note that constraints from the rest of the C<record> do not apply anymore. If
|
||
information needed for the retrieval can be deleted elsewhere, then you must
|
||||
guard against that.
|
||||
eebe8e90 | Sven Schöling | |||
418f0e70 | Sven Schöling | If the price for the same coditions changed, return the new price. It will be
|
||
presented as an option to the user if the record is still editable.
|
||||
eebe8e90 | Sven Schöling | |||
418f0e70 | Sven Schöling | If the price is not valid anymore or not reconstructable, return a price with
|
||
C<price_source> and C<spec> set to the same values as before but with
|
||||
C<invalid> or C<missing> set.
|
||||
eebe8e90 | Sven Schöling | |||
=back
|
||||
418f0e70 | Sven Schöling | =head1 TRAPS AND CORNER CASES
|
||
=over 4
|
||||
=item *
|
||||
Be aware that all 8 types of record will be passed to your algorithm. If you
|
||||
don't serve some of them, just return emptry lists on C<available_prices> and
|
||||
C<best_price>
|
||||
=item *
|
||||
Information in C<record> might be missing. Especially on newly or automatically
|
||||
created records there might be fields not set at all.
|
||||
=item *
|
||||
Records will not be calculated. If you need tax data or position totals, you
|
||||
need to invoke that for yourself.
|
||||
=item *
|
||||
Accessor methods might not be present in some of the record types.
|
||||
=item *
|
||||
You do not need to do price factor and row discount calculation. These will be
|
||||
done automatically afterwards. You do have to include customer/vendor discount
|
||||
if your price interacts with those.
|
||||
=item *
|
||||
The price field in purchase records is still C<sellprice>.
|
||||
=item *
|
||||
C<source> and C<spec> are tainted. If you store data directly in C<spec>, sanitize.
|
||||
049e49fe | Sven Schöling | =back
|
||
418f0e70 | Sven Schöling | =head1 SEE ALSO
|
||
L<SL::PriceSource>,
|
||||
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
|