PriceSource: Preisselektion auf Popup umgestellt.
[kivitendo-erp.git] / SL / PriceSource / Base.pm
1 package SL::PriceSource::Base;
2
3 use strict;
4
5 use parent qw(SL::DB::Object);
6 use Rose::Object::MakeMethods::Generic (
7   scalar => [ qw(record_item record) ],
8 );
9
10 sub name { die 'name needs to be implemented' }
11
12 sub description { die 'description needs to be implemented' }
13
14 sub available_prices { die 'available_prices needs to be implemented' }
15
16 sub best_price { die 'best_price needs to be implemented' }
17
18 sub price_from_source { die 'price_from_source needs to be implemented:' . "@_" }
19
20 sub part {
21   $_[0]->record_item->part;
22 }
23
24 1;
25
26 __END__
27
28 =encoding utf-8
29
30 =head1 NAME
31
32 SL::PriceSource::Base - this is the base class for price source adapters
33
34 =head1 SYNOPSIS
35
36   # working example adapter:
37   package SL::PriceSource::FiveOnEverything;
38
39   use parent qw(SL::PriceSource::Base);
40
41   # used as internal identifier
42   sub name { 'simple' }
43
44   # used in frontend to signal where this comes from
45   sub description { t8('Simple') }
46
47   my $price = SL::PriceSource::Price->new(
48     price        => 5,
49     description  => t8('Only today 5$ on everything!'),
50     price_source => $self,
51   );
52
53   # give list of prices that this
54   sub available_prices {
55     return ($price);
56   }
57
58   sub best_price {
59     return $price;
60   }
61
62   sub price_from_source {
63     return $price;
64   }
65
66 =head1 DESCRIPTION
67
68 See L<SL::PriceSource> for information about the mechanism.
69
70 This is the base class for a price source algorithm. To play well, you'll have
71 to implement a number of interface methods and be aware of a number of corner
72 conditions.
73
74 =head1 AVAILABLE METHODS
75
76 =over 4
77
78 =item C<record_item>
79
80 =item C<record>
81
82 C<record> can be any one of L<SL::DB::Order>, L<SL::DB::DeliveryOrder>,
83 L<SL::DB::Invoice>, L<SL::DB::PurchaseInvoice>. C<record_item> is of the
84 corresponding position type.
85
86 You can assume that both are filled with all information available at the time.
87 C<part> and C<customer>/C<vendor> as well as C<is_sales> can be relied upon. You must NOT
88 rely on both being linked together, in particular
89
90   $self->record_item->record   # don't do that
91
92 is not guaranteed to work.
93
94 Also these are copies and not the original documents. Do not try to change
95 anything and do not save those.
96
97 =item C<part>
98
99 Shortcut to C<< record_item->part >>
100
101 =back
102
103 =head1 INTERFACE METHODS
104
105 =over 4
106
107 =item C<name>
108
109 Must return a unique internal name. Must be entered in
110 L<SL::PriceSource::ALL>.
111
112 =item C<description>
113
114 Must return a translated name to be used in frontend. Will be used, to
115 distinguish the origin of different prices.
116
117 =item C<available_prices>
118
119 Must return a list of all prices that you algorithm can recommend the user
120 for the current situation. Each price must have a unique spec that can be used
121 to recreate it later. Try to be brief, no one needs 20 different price
122 suggestions.
123
124 =item C<best_price>
125
126 Must return what you think of as the best matching price in your
127 C<available_prices>. This does not have to be the lowest price, but it will be
128 compared later to other price sources, and the lowest will be set.
129
130 =item C<price_from_source SOURCE, SPEC>
131
132 Must recreate the price from C<SPEC> and return. For reference, the complete
133 C<SOURCE> entry from C<record_item.active_price_source> is included.
134
135 Note that constraints from the rest of the C<record> do not apply anymore. If
136 information needed for the retrieval can be deleted elsewhere, then you must
137 guard against that.
138
139 If the price for the same coditions changed, return the new price. It will be
140 presented as an option to the user if the record is still editable.
141
142 If the price is not valid anymore or not reconstructable, return a price with
143 C<price_source> and C<spec> set to the same values as before but with
144 C<invalid> or C<missing> set.
145
146 =back
147
148 =head1 TRAPS AND CORNER CASES
149
150 =over 4
151
152 =item *
153
154 Be aware that all 8 types of record will be passed to your algorithm. If you
155 don't serve some of them, just return emptry lists on C<available_prices> and
156 C<best_price>
157
158 =item *
159
160 Information in C<record> might be missing. Especially on newly or automatically
161 created records there might be fields not set at all.
162
163 =item *
164
165 Records will not be calculated. If you need tax data or position totals, you
166 need to invoke that for yourself.
167
168 =item *
169
170 Accessor methods might not be present in some of the record types.
171
172 =item *
173
174 You do not need to do price factor and row discount calculation. These will be
175 done automatically afterwards. You do have to include customer/vendor discount
176 if your price interacts with those.
177
178 =item *
179
180 The price field in purchase records is still C<sellprice>.
181
182 =item *
183
184 C<source> and C<spec> are tainted. If you store data directly in C<spec>, sanitize.
185
186 =back
187
188 =head1 SEE ALSO
189
190 L<SL::PriceSource>,
191 L<SL::PriceSource::Price>,
192 L<SL::PriceSource::ALL>
193
194 =head1 BUGS
195
196 None yet. :)
197
198 =head1 AUTHOR
199
200 Sven Schoeling E<lt>s.schoeling@linet-services.deE<gt>
201
202 =cut