Bug 24161: Fix license statements
[srvgit] / Koha / Acquisition / Order.pm
1 package Koha::Acquisition::Order;
2
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18 use Modern::Perl;
19
20 use Carp qw( croak );
21
22 use Koha::Acquisition::Baskets;
23 use Koha::Acquisition::Funds;
24 use Koha::Acquisition::Invoices;
25 use Koha::Acquisition::Order::Claims;
26 use Koha::Database;
27 use Koha::DateUtils qw( dt_from_string output_pref );
28 use Koha::Biblios;
29 use Koha::Holds;
30 use Koha::Items;
31 use Koha::Subscriptions;
32
33 use base qw(Koha::Object);
34
35 =head1 NAME
36
37 Koha::Acquisition::Order Object class
38
39 =head1 API
40
41 =head2 Class methods
42
43 =head3 new
44
45 Overloaded I<new> method for backwards compatibility.
46
47 =cut
48
49 sub new {
50     my ( $self, $params ) = @_;
51
52     my $schema  = Koha::Database->new->schema;
53     my @columns = $schema->source('Aqorder')->columns;
54
55     my $values =
56       { map { exists $params->{$_} ? ( $_ => $params->{$_} ) : () } @columns };
57     return $self->SUPER::new($values);
58 }
59
60 =head3 store
61
62 Overloaded I<store> method for backwards compatibility.
63
64 =cut
65
66 sub store {
67     my ($self) = @_;
68
69     my $schema  = Koha::Database->new->schema;
70     # Override quantity for standing orders
71     $self->quantity(1) if ( $self->basketno && $schema->resultset('Aqbasket')->find( $self->basketno )->is_standing );
72
73     # if these parameters are missing, we can't continue
74     for my $key (qw( basketno quantity biblionumber budget_id )) {
75         croak "Cannot insert order: Mandatory parameter $key is missing"
76           unless $self->$key;
77     }
78
79     if (not defined $self->{created_by}) {
80         my $userenv = C4::Context->userenv;
81         if ($userenv) {
82             $self->created_by($userenv->{number});
83         }
84     }
85
86     $self->quantityreceived(0) unless $self->quantityreceived;
87     $self->entrydate(dt_from_string) unless $self->entrydate;
88
89     $self->ordernumber(undef) unless $self->ordernumber;
90     $self = $self->SUPER::store( $self );
91
92     unless ( $self->parent_ordernumber ) {
93         $self->set( { parent_ordernumber => $self->ordernumber } );
94         $self = $self->SUPER::store( $self );
95     }
96
97     return $self;
98 }
99
100 =head3 add_item
101
102   $order->add_item( $itemnumber );
103
104 Link an item to this order.
105
106 =cut
107
108 sub add_item {
109     my ( $self, $itemnumber )  = @_;
110
111     my $schema = Koha::Database->new->schema;
112     my $rs = $schema->resultset('AqordersItem');
113     $rs->create({ ordernumber => $self->ordernumber, itemnumber => $itemnumber });
114 }
115
116 =head3 basket
117
118     my $basket = $order->basket;
119
120 Returns the I<Koha::Acquisition::Basket> object for the basket associated
121 to the order.
122
123 =cut
124
125 sub basket {
126     my ( $self )  = @_;
127     my $basket_rs = $self->_result->basket;
128     return Koha::Acquisition::Basket->_new_from_dbic( $basket_rs );
129 }
130
131 =head3 fund
132
133     my $fund = $order->fund;
134
135 Returns the I<Koha::Acquisition::Fund> object for the fund (aqbudgets)
136 associated to the order.
137
138 =cut
139
140 sub fund {
141     my ( $self )  = @_;
142     my $fund_rs = $self->_result->fund;
143     return Koha::Acquisition::Fund->_new_from_dbic( $fund_rs );
144 }
145
146 =head3 invoice
147
148     my $invoice = $order->invoice;
149
150 Returns the I<Koha::Acquisition::Invoice> object for the invoice associated
151 to the order.
152
153 It returns B<undef> if no linked invoice is found.
154
155 =cut
156
157 sub invoice {
158     my ( $self )  = @_;
159     my $invoice_rs = $self->_result->invoice;
160     return unless $invoice_rs;
161     return Koha::Acquisition::Invoice->_new_from_dbic( $invoice_rs );
162 }
163
164 =head3 subscription
165
166     my $subscription = $order->subscription
167
168 Returns the I<Koha::Subscription> object for the subscription associated
169 to the order.
170
171 It returns B<undef> if no linked subscription is found.
172
173 =cut
174
175 sub subscription {
176     my ( $self )  = @_;
177     my $subscription_rs = $self->_result->subscription;
178     return unless $subscription_rs;
179     return Koha::Subscription->_new_from_dbic( $subscription_rs );
180 }
181
182 =head3 current_item_level_holds
183
184     my $holds = $order->current_item_level_holds;
185
186 Returns the current item-level holds associated to the order. It returns a I<Koha::Holds>
187 resultset.
188
189 =cut
190
191 sub current_item_level_holds {
192     my ($self) = @_;
193
194     my $items_rs     = $self->_result->aqorders_items;
195     my @item_numbers = $items_rs->get_column('itemnumber')->all;
196     my $biblio       = $self->biblio;
197
198     unless ( $biblio and @item_numbers ) {
199         return Koha::Holds->new->empty;
200     }
201
202     return $biblio->current_holds->search(
203         {
204             itemnumber => {
205                 -in => \@item_numbers
206             }
207         }
208     );
209 }
210
211 =head3 items
212
213     my $items = $order->items
214
215 Returns the items associated to the order.
216
217 =cut
218
219 sub items {
220     my ( $self )  = @_;
221     # aqorders_items is not a join table
222     # There is no FK on items (may have been deleted)
223     my $items_rs = $self->_result->aqorders_items;
224     my @itemnumbers = $items_rs->get_column( 'itemnumber' )->all;
225     return Koha::Items->search({ itemnumber => \@itemnumbers });
226 }
227
228 =head3 biblio
229
230     my $biblio = $order->biblio
231
232 Returns the bibliographic record associated to the order
233
234 =cut
235
236 sub biblio {
237     my ( $self ) = @_;
238     my $biblio_rs= $self->_result->biblio;
239     return unless $biblio_rs;
240     return Koha::Biblio->_new_from_dbic( $biblio_rs );
241 }
242
243 =head3 claims
244
245     my $claims = $order->claims
246
247 Return the claims history for this order
248
249 =cut
250
251 sub claims {
252     my ( $self ) = @_;
253     my $claims_rs = $self->_result->aqorders_claims;
254     return Koha::Acquisition::Order::Claims->_new_from_dbic( $claims_rs );
255 }
256
257 =head3 claim
258
259     my $claim = $order->claim
260
261 Do claim for this order
262
263 =cut
264
265 sub claim {
266     my ( $self ) = @_;
267     my $claim_rs = $self->_result->create_related('aqorders_claims', {});
268     return Koha::Acquisition::Order::Claim->_new_from_dbic($claim_rs);
269 }
270
271 =head3 claims_count
272
273 my $nb_of_claims = $order->claims_count;
274
275 This is the equivalent of $order->claims->count. Keeping it for retrocompatibilty.
276
277 =cut
278
279 sub claims_count {
280     my ( $self ) = @_;
281     return $self->claims->count;
282 }
283
284 =head3 claimed_date
285
286 my $last_claim_date = $order->claimed_date;
287
288 This is the equivalent of $order->claims->last->claimed_on. Keeping it for retrocompatibilty.
289
290 =cut
291
292 sub claimed_date {
293     my ( $self ) = @_;
294     my $last_claim = $self->claims->last;
295     return unless $last_claim;
296     return $last_claim->claimed_on;
297 }
298
299 =head3 duplicate_to
300
301     my $duplicated_order = $order->duplicate_to($basket, [$default_values]);
302
303 Duplicate an existing order and attach it to a basket. $default_values can be specified as a hashref
304 that contain default values for the different order's attributes.
305 Items will be duplicated as well but barcodes will be set to null.
306
307 =cut
308
309 sub duplicate_to {
310     my ( $self, $basket, $default_values ) = @_;
311     my $new_order;
312     $default_values //= {};
313     Koha::Database->schema->txn_do(
314         sub {
315             my $order_info = $self->unblessed;
316             undef $order_info->{ordernumber};
317             for my $field (
318                 qw(
319                 ordernumber
320                 received_on
321                 datereceived
322                 invoiceid
323                 datecancellationprinted
324                 cancellationreason
325                 purchaseordernumber
326                 claims_count
327                 claimed_date
328                 parent_ordernumber
329                 )
330               )
331             {
332                 undef $order_info->{$field};
333             }
334             $order_info->{placed_on}        = dt_from_string;
335             $order_info->{entrydate}        = dt_from_string;
336             $order_info->{orderstatus}      = 'new';
337             $order_info->{quantityreceived} = 0;
338             while ( my ( $field, $value ) = each %$default_values ) {
339                 $order_info->{$field} = $value;
340             }
341
342             my $userenv = C4::Context->userenv;
343             $order_info->{created_by} = $userenv->{number};
344             $order_info->{basketno} = $basket->basketno;
345
346             $new_order = Koha::Acquisition::Order->new($order_info)->store;
347
348             if ( ! $self->subscriptionid && $self->basket->effective_create_items eq 'ordering') { # Do copy items if not a subscription order AND if items are created on ordering
349                 my $items = $self->items;
350                 while ( my ($item) = $items->next ) {
351                     my $item_info = $item->unblessed;
352                     undef $item_info->{itemnumber};
353                     undef $item_info->{barcode};
354                     my $new_item = Koha::Item->new($item_info)->store;
355                     $new_order->add_item( $new_item->itemnumber );
356                 }
357             }
358         }
359     );
360     return $new_order;
361 }
362
363 =head3 to_api_mapping
364
365 This method returns the mapping for representing a Koha::Acquisition::Order object
366 on the API.
367
368 =cut
369
370 sub to_api_mapping {
371     return {
372         basketno                      => 'basket_id',
373         biblionumber                  => 'biblio_id',
374         budget_id                     => 'fund_id',
375         budgetdate                    => undef,                    # unused
376         cancellationreason            => 'cancellation_reason',
377         claimed_date                  => 'last_claim_date',
378         datecancellationprinted       => 'cancellation_date',
379         datereceived                  => 'date_received',
380         discount                      => 'discount_rate',
381         entrydate                     => 'entry_date',
382         freight                       => 'shipping_cost',
383         invoiceid                     => 'invoice_id',
384         line_item_id                  => undef,                    # EDIFACT related
385         listprice                     => 'list_price',
386         order_internalnote            => 'internal_note',
387         order_vendornote              => 'vendor_note',
388         ordernumber                   => 'order_id',
389         orderstatus                   => 'status',
390         parent_ordernumber            => 'parent_order_id',
391         purchaseordernumber           => undef,                    # obsolete
392         quantityreceived              => 'quantity_received',
393         replacementprice              => 'replacement_price',
394         sort1                         => 'statistics_1',
395         sort1_authcat                 => 'statistics_1_authcat',
396         sort2                         => 'statistics_2',
397         sort2_authcat                 => 'statistics_2_authcat',
398         subscriptionid                => 'subscription_id',
399         suppliers_reference_number    => undef,                    # EDIFACT related
400         suppliers_reference_qualifier => undef,                    # EDIFACT related
401         suppliers_report              => undef,                    # EDIFACT related
402         tax_rate_bak                  => undef,                    # unused
403         tax_value_bak                 => undef,                    # unused
404         uncertainprice                => 'uncertain_price',
405         unitprice                     => 'unit_price',
406         unitprice_tax_excluded        => 'unit_price_tax_excluded',
407         unitprice_tax_included        => 'unit_price_tax_included'
408     };
409 }
410
411 =head2 Internal methods
412
413 =head3 _type
414
415 =cut
416
417 sub _type {
418     return 'Aqorder';
419 }
420
421 1;