Bug 25297: Consistent return value in K::A::Order->current_item_level_holds
[koha.git] / Koha / Acquisition / Order.pm
blob5135a3372d5b7d876a2735f1c4a6c5470ec4ef0e
1 package Koha::Acquisition::Order;
3 # This file is part of Koha.
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.
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.
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>.
18 use Modern::Perl;
20 use Carp qw( croak );
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::Holds;
29 use Koha::Items;
30 use Koha::Subscriptions;
32 use base qw(Koha::Object);
34 =head1 NAME
36 Koha::Acquisition::Order Object class
38 =head1 API
40 =head2 Class methods
42 =head3 new
44 Overloaded I<new> method for backwards compatibility.
46 =cut
48 sub new {
49 my ( $self, $params ) = @_;
51 my $schema = Koha::Database->new->schema;
52 my @columns = $schema->source('Aqorder')->columns;
54 my $values =
55 { map { exists $params->{$_} ? ( $_ => $params->{$_} ) : () } @columns };
56 return $self->SUPER::new($values);
59 =head3 store
61 Overloaded I<store> method for backwards compatibility.
63 =cut
65 sub store {
66 my ($self) = @_;
68 my $schema = Koha::Database->new->schema;
69 # Override quantity for standing orders
70 $self->quantity(1) if ( $self->basketno && $schema->resultset('Aqbasket')->find( $self->basketno )->is_standing );
72 # if these parameters are missing, we can't continue
73 for my $key (qw( basketno quantity biblionumber budget_id )) {
74 croak "Cannot insert order: Mandatory parameter $key is missing"
75 unless $self->$key;
78 if (not defined $self->{created_by}) {
79 my $userenv = C4::Context->userenv;
80 if ($userenv) {
81 $self->created_by($userenv->{number});
85 $self->quantityreceived(0) unless $self->quantityreceived;
86 $self->entrydate(dt_from_string) unless $self->entrydate;
88 $self->ordernumber(undef) unless $self->ordernumber;
89 $self = $self->SUPER::store( $self );
91 unless ( $self->parent_ordernumber ) {
92 $self->set( { parent_ordernumber => $self->ordernumber } );
93 $self = $self->SUPER::store( $self );
96 return $self;
99 =head3 add_item
101 $order->add_item( $itemnumber );
103 Link an item to this order.
105 =cut
107 sub add_item {
108 my ( $self, $itemnumber ) = @_;
110 my $schema = Koha::Database->new->schema;
111 my $rs = $schema->resultset('AqordersItem');
112 $rs->create({ ordernumber => $self->ordernumber, itemnumber => $itemnumber });
115 =head3 basket
117 my $basket = $order->basket;
119 Returns the I<Koha::Acquisition::Basket> object for the basket associated
120 to the order.
122 =cut
124 sub basket {
125 my ( $self ) = @_;
126 my $basket_rs = $self->_result->basket;
127 return Koha::Acquisition::Basket->_new_from_dbic( $basket_rs );
130 =head3 fund
132 my $fund = $order->fund;
134 Returns the I<Koha::Acquisition::Fund> object for the fund (aqbudgets)
135 associated to the order.
137 =cut
139 sub fund {
140 my ( $self ) = @_;
141 my $fund_rs = $self->_result->fund;
142 return Koha::Acquisition::Fund->_new_from_dbic( $fund_rs );
145 =head3 invoice
147 my $invoice = $order->invoice;
149 Returns the I<Koha::Acquisition::Invoice> object for the invoice associated
150 to the order.
152 It returns B<undef> if no linked invoice is found.
154 =cut
156 sub invoice {
157 my ( $self ) = @_;
158 my $invoice_rs = $self->_result->invoice;
159 return unless $invoice_rs;
160 return Koha::Acquisition::Invoice->_new_from_dbic( $invoice_rs );
163 =head3 subscription
165 my $subscription = $order->subscription
167 Returns the I<Koha::Subscription> object for the subscription associated
168 to the order.
170 It returns B<undef> if no linked subscription is found.
172 =cut
174 sub subscription {
175 my ( $self ) = @_;
176 my $subscription_rs = $self->_result->subscription;
177 return unless $subscription_rs;
178 return Koha::Subscription->_new_from_dbic( $subscription_rs );
181 =head3 current_item_level_holds
183 my $holds = $order->current_item_level_holds;
185 Returns the current item-level holds associated to the order. It returns a I<Koha::Holds>
186 resultset.
188 =cut
190 sub current_item_level_holds {
191 my ($self) = @_;
193 my $items_rs = $self->_result->aqorders_items;
194 my @item_numbers = $items_rs->get_column('itemnumber')->all;
195 my $biblio = $self->biblio;
197 unless ( $biblio and @item_numbers ) {
198 return Koha::Holds->new->empty;
201 return $biblio->current_holds->search(
203 itemnumber => {
204 -in => \@item_numbers
210 =head3 items
212 my $items = $order->items
214 Returns the items associated to the order.
216 =cut
218 sub items {
219 my ( $self ) = @_;
220 # aqorders_items is not a join table
221 # There is no FK on items (may have been deleted)
222 my $items_rs = $self->_result->aqorders_items;
223 my @itemnumbers = $items_rs->get_column( 'itemnumber' )->all;
224 return Koha::Items->search({ itemnumber => \@itemnumbers });
227 =head3 biblio
229 my $biblio = $order->biblio
231 Returns the bibliographic record associated to the order
233 =cut
235 sub biblio {
236 my ( $self ) = @_;
237 my $biblio_rs= $self->_result->biblio;
238 return unless $biblio_rs;
239 return Koha::Biblio->_new_from_dbic( $biblio_rs );
242 =head3 duplicate_to
244 my $duplicated_order = $order->duplicate_to($basket, [$default_values]);
246 Duplicate an existing order and attach it to a basket. $default_values can be specified as a hashref
247 that contain default values for the different order's attributes.
248 Items will be duplicated as well but barcodes will be set to null.
250 =cut
252 sub duplicate_to {
253 my ( $self, $basket, $default_values ) = @_;
254 my $new_order;
255 $default_values //= {};
256 Koha::Database->schema->txn_do(
257 sub {
258 my $order_info = $self->unblessed;
259 undef $order_info->{ordernumber};
260 for my $field (
262 ordernumber
263 received_on
264 datereceived
265 invoiceid
266 datecancellationprinted
267 cancellationreason
268 purchaseordernumber
269 claims_count
270 claimed_date
271 parent_ordernumber
275 undef $order_info->{$field};
277 $order_info->{placed_on} = dt_from_string;
278 $order_info->{entrydate} = dt_from_string;
279 $order_info->{orderstatus} = 'new';
280 $order_info->{quantityreceived} = 0;
281 while ( my ( $field, $value ) = each %$default_values ) {
282 $order_info->{$field} = $value;
285 my $userenv = C4::Context->userenv;
286 $order_info->{created_by} = $userenv->{number};
287 $order_info->{basketno} = $basket->basketno;
289 $new_order = Koha::Acquisition::Order->new($order_info)->store;
291 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
292 my $items = $self->items;
293 while ( my ($item) = $items->next ) {
294 my $item_info = $item->unblessed;
295 undef $item_info->{itemnumber};
296 undef $item_info->{barcode};
297 my $new_item = Koha::Item->new($item_info)->store;
298 $new_order->add_item( $new_item->itemnumber );
303 return $new_order;
306 =head3 to_api_mapping
308 This method returns the mapping for representing a Koha::Acquisition::Order object
309 on the API.
311 =cut
313 sub to_api_mapping {
314 return {
315 basketno => 'basket_id',
316 biblionumber => 'biblio_id',
317 budget_id => 'fund_id',
318 budgetdate => undef, # unused
319 cancellationreason => 'cancellation_reason',
320 claimed_date => 'last_claim_date',
321 datecancellationprinted => 'cancellation_date',
322 datereceived => 'date_received',
323 discount => 'discount_rate',
324 entrydate => 'entry_date',
325 freight => 'shipping_cost',
326 invoiceid => 'invoice_id',
327 line_item_id => undef, # EDIFACT related
328 listprice => 'list_price',
329 order_internalnote => 'internal_note',
330 order_vendornote => 'vendor_note',
331 ordernumber => 'order_id',
332 orderstatus => 'status',
333 parent_ordernumber => 'parent_order_id',
334 purchaseordernumber => undef, # obsolete
335 quantityreceived => 'quantity_received',
336 replacementprice => 'replacement_price',
337 sort1 => 'statistics_1',
338 sort1_authcat => 'statistics_1_authcat',
339 sort2 => 'statistics_2',
340 sort2_authcat => 'statistics_2_authcat',
341 subscriptionid => 'subscription_id',
342 suppliers_reference_number => undef, # EDIFACT related
343 suppliers_reference_qualifier => undef, # EDIFACT related
344 suppliers_report => undef, # EDIFACT related
345 tax_rate_bak => undef, # unused
346 tax_value_bak => undef, # unused
347 uncertainprice => 'uncertain_price',
348 unitprice => 'unit_price',
349 unitprice_tax_excluded => 'unit_price_tax_excluded',
350 unitprice_tax_included => 'unit_price_tax_included'
354 =head2 Internal methods
356 =head3 _type
358 =cut
360 sub _type {
361 return 'Aqorder';