Bug 24545: 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::Database;
26 use Koha::DateUtils qw( dt_from_string output_pref );
27 use Koha::Biblios;
28 use Koha::Items;
29 use Koha::Subscriptions;
30
31 use base qw(Koha::Object);
32
33 =head1 NAME
34
35 Koha::Acquisition::Order Object class
36
37 =head1 API
38
39 =head2 Class methods
40
41 =head3 new
42
43 Overloaded I<new> method for backwards compatibility.
44
45 =cut
46
47 sub new {
48     my ( $self, $params ) = @_;
49
50     my $schema  = Koha::Database->new->schema;
51     my @columns = $schema->source('Aqorder')->columns;
52
53     my $values =
54       { map { exists $params->{$_} ? ( $_ => $params->{$_} ) : () } @columns };
55     return $self->SUPER::new($values);
56 }
57
58 =head3 store
59
60 Overloaded I<store> method for backwards compatibility.
61
62 =cut
63
64 sub store {
65     my ($self) = @_;
66
67     my $schema  = Koha::Database->new->schema;
68     # Override quantity for standing orders
69     $self->quantity(1) if ( $self->basketno && $schema->resultset('Aqbasket')->find( $self->basketno )->is_standing );
70
71     # if these parameters are missing, we can't continue
72     for my $key (qw( basketno quantity biblionumber budget_id )) {
73         croak "Cannot insert order: Mandatory parameter $key is missing"
74           unless $self->$key;
75     }
76
77     if (not defined $self->{created_by}) {
78         my $userenv = C4::Context->userenv;
79         if ($userenv) {
80             $self->created_by($userenv->{number});
81         }
82     }
83
84     $self->quantityreceived(0) unless $self->quantityreceived;
85     $self->entrydate(dt_from_string) unless $self->entrydate;
86
87     $self->ordernumber(undef) unless $self->ordernumber;
88     $self = $self->SUPER::store( $self );
89
90     unless ( $self->parent_ordernumber ) {
91         $self->set( { parent_ordernumber => $self->ordernumber } );
92         $self = $self->SUPER::store( $self );
93     }
94
95     return $self;
96 }
97
98 =head3 add_item
99
100   $order->add_item( $itemnumber );
101
102 Link an item to this order.
103
104 =cut
105
106 sub add_item {
107     my ( $self, $itemnumber )  = @_;
108
109     my $schema = Koha::Database->new->schema;
110     my $rs = $schema->resultset('AqordersItem');
111     $rs->create({ ordernumber => $self->ordernumber, itemnumber => $itemnumber });
112 }
113
114 =head3 basket
115
116     my $basket = $order->basket;
117
118 Returns the I<Koha::Acquisition::Basket> object for the basket associated
119 to the order.
120
121 =cut
122
123 sub basket {
124     my ( $self )  = @_;
125     my $basket_rs = $self->_result->basket;
126     return Koha::Acquisition::Basket->_new_from_dbic( $basket_rs );
127 }
128
129 =head3 fund
130
131     my $fund = $order->fund;
132
133 Returns the I<Koha::Acquisition::Fund> object for the fund (aqbudgets)
134 associated to the order.
135
136 =cut
137
138 sub fund {
139     my ( $self )  = @_;
140     my $fund_rs = $self->_result->fund;
141     return Koha::Acquisition::Fund->_new_from_dbic( $fund_rs );
142 }
143
144 =head3 invoice
145
146     my $invoice = $order->invoice;
147
148 Returns the I<Koha::Acquisition::Invoice> object for the invoice associated
149 to the order.
150
151 It returns B<undef> if no linked invoice is found.
152
153 =cut
154
155 sub invoice {
156     my ( $self )  = @_;
157     my $invoice_rs = $self->_result->invoice;
158     return unless $invoice_rs;
159     return Koha::Acquisition::Invoice->_new_from_dbic( $invoice_rs );
160 }
161
162 =head3 subscription
163
164     my $subscription = $order->subscription
165
166 Returns the I<Koha::Subscription> object for the subscription associated
167 to the order.
168
169 It returns B<undef> if no linked subscription is found.
170
171 =cut
172
173 sub subscription {
174     my ( $self )  = @_;
175     my $subscription_rs = $self->_result->subscription;
176     return unless $subscription_rs;
177     return Koha::Subscription->_new_from_dbic( $subscription_rs );
178 }
179
180 =head3 current_item_level_holds
181
182     my $holds = $order->current_item_level_holds;
183
184 Returns the current item-level holds associated to the order. It returns a I<Koha::Holds>
185 resultset in scalar context or a list of I<Koha::Hold> objects in list context.
186
187 It returns B<undef> if no I<biblio> or no I<items> are linked to the order.
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
197     return unless @item_numbers;
198
199     my $biblio = $self->biblio;
200     return unless $biblio;
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 duplicate_to
244
245     my $duplicated_order = $order->duplicate_to($basket, [$default_values]);
246
247 Duplicate an existing order and attach it to a basket. $default_values can be specified as a hashref
248 that contain default values for the different order's attributes.
249 Items will be duplicated as well but barcodes will be set to null.
250
251 =cut
252
253 sub duplicate_to {
254     my ( $self, $basket, $default_values ) = @_;
255     my $new_order;
256     $default_values //= {};
257     Koha::Database->schema->txn_do(
258         sub {
259             my $order_info = $self->unblessed;
260             undef $order_info->{ordernumber};
261             for my $field (
262                 qw(
263                 ordernumber
264                 received_on
265                 datereceived
266                 invoiceid
267                 datecancellationprinted
268                 cancellationreason
269                 purchaseordernumber
270                 claims_count
271                 claimed_date
272                 parent_ordernumber
273                 )
274               )
275             {
276                 undef $order_info->{$field};
277             }
278             $order_info->{placed_on}        = dt_from_string;
279             $order_info->{entrydate}        = dt_from_string;
280             $order_info->{orderstatus}      = 'new';
281             $order_info->{quantityreceived} = 0;
282             while ( my ( $field, $value ) = each %$default_values ) {
283                 $order_info->{$field} = $value;
284             }
285
286             my $userenv = C4::Context->userenv;
287             $order_info->{created_by} = $userenv->{number};
288             $order_info->{basketno} = $basket->basketno;
289
290             $new_order = Koha::Acquisition::Order->new($order_info)->store;
291
292             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
293                 my $items = $self->items;
294                 while ( my ($item) = $items->next ) {
295                     my $item_info = $item->unblessed;
296                     undef $item_info->{itemnumber};
297                     undef $item_info->{barcode};
298                     my $new_item = Koha::Item->new($item_info)->store;
299                     $new_order->add_item( $new_item->itemnumber );
300                 }
301             }
302         }
303     );
304     return $new_order;
305 }
306
307 =head3 to_api_mapping
308
309 This method returns the mapping for representing a Koha::Acquisition::Order object
310 on the API.
311
312 =cut
313
314 sub to_api_mapping {
315     return {
316         basketno                      => 'basket_id',
317         biblionumber                  => 'biblio_id',
318         budget_id                     => 'fund_id',
319         budgetdate                    => undef,                    # unused
320         cancellationreason            => 'cancellation_reason',
321         claimed_date                  => 'last_claim_date',
322         datecancellationprinted       => 'cancellation_date',
323         datereceived                  => 'date_received',
324         discount                      => 'discount_rate',
325         entrydate                     => 'entry_date',
326         freight                       => 'shipping_cost',
327         invoiceid                     => 'invoice_id',
328         line_item_id                  => undef,                    # EDIFACT related
329         listprice                     => 'list_price',
330         order_internalnote            => 'internal_note',
331         order_vendornote              => 'vendor_note',
332         ordernumber                   => 'order_id',
333         orderstatus                   => 'status',
334         parent_ordernumber            => 'parent_order_id',
335         purchaseordernumber           => undef,                    # obsolete
336         quantityreceived              => 'quantity_received',
337         replacementprice              => 'replacement_price',
338         sort1                         => 'statistics_1',
339         sort1_authcat                 => 'statistics_1_authcat',
340         sort2                         => 'statistics_2',
341         sort2_authcat                 => 'statistics_2_authcat',
342         subscriptionid                => 'subscription_id',
343         suppliers_reference_number    => undef,                    # EDIFACT related
344         suppliers_reference_qualifier => undef,                    # EDIFACT related
345         suppliers_report              => undef,                    # EDIFACT related
346         tax_rate_bak                  => undef,                    # unused
347         tax_value_bak                 => undef,                    # unused
348         uncertainprice                => 'uncertain_price',
349         unitprice                     => 'unit_price',
350         unitprice_tax_excluded        => 'unit_price_tax_excluded',
351         unitprice_tax_included        => 'unit_price_tax_included'
352     };
353 }
354
355 =head2 Internal methods
356
357 =head3 _type
358
359 =cut
360
361 sub _type {
362     return 'Aqorder';
363 }
364
365 1;