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>.
23 use C4::Biblio qw(DelBiblio);
25 use Koha::Acquisition::Baskets;
26 use Koha::Acquisition::Funds;
27 use Koha::Acquisition::Invoices;
28 use Koha::Acquisition::Order::Claims;
30 use Koha::DateUtils qw( dt_from_string output_pref );
31 use Koha::Exceptions::Object;
35 use Koha::Subscriptions;
37 use base qw(Koha::Object);
41 Koha::Acquisition::Order Object class
49 Overloaded I<new> method for backwards compatibility.
54 my ( $self, $params ) = @_;
56 my $schema = Koha::Database->new->schema;
57 my @columns = $schema->source('Aqorder')->columns;
60 { map { exists $params->{$_} ? ( $_ => $params->{$_} ) : () } @columns };
61 return $self->SUPER::new($values);
66 Overloaded I<store> method for backwards compatibility.
73 my $schema = Koha::Database->new->schema;
74 # Override quantity for standing orders
75 $self->quantity(1) if ( $self->basketno && $schema->resultset('Aqbasket')->find( $self->basketno )->is_standing );
77 # if these parameters are missing, we can't continue
78 for my $key (qw( basketno quantity biblionumber budget_id )) {
79 croak "Cannot insert order: Mandatory parameter $key is missing"
83 if (not defined $self->{created_by}) {
84 my $userenv = C4::Context->userenv;
86 $self->created_by($userenv->{number});
90 $self->quantityreceived(0) unless $self->quantityreceived;
91 $self->entrydate(dt_from_string) unless $self->entrydate;
93 $self->ordernumber(undef) unless $self->ordernumber;
94 $self = $self->SUPER::store( $self );
96 unless ( $self->parent_ordernumber ) {
97 $self->set( { parent_ordernumber => $self->ordernumber } );
98 $self = $self->SUPER::store( $self );
107 { [ reason => $reason,
108 delete_biblio => $delete_biblio ]
112 This method marks an order as cancelled, optionally using the I<reason> parameter.
113 As the order is cancelled, the (eventual) items linked to it are removed.
114 If I<delete_biblio> is passed, it will try to remove the linked biblio.
116 If either the items or biblio removal fails, an error message is added to the object
117 so the caller can take appropriate actions.
122 my ($self, $params) = @_;
124 my $delete_biblio = $params->{delete_biblio};
125 my $reason = $params->{reason};
128 # Delete the related items
129 $self->items->safe_delete;
131 my $biblio = $self->biblio;
132 if ( $biblio and $delete_biblio ) {
134 if ( $biblio->active_orders->count - 1 == 0 # minus ourself
135 and $biblio->subscriptions->count == 0
136 and $biblio->items->count == 0 )
139 my $error = DelBiblio( $biblio->id );
140 $self->add_message({ message => 'error_delbiblio', error => $error })
144 $self->add_message({ message => 'error_delbiblio' });
149 if ( ref($_) eq 'Koha::Exceptions::Object::CannotBeDeleted' ) {
150 my $object = $_->object;
151 if ( ref($object) eq 'Koha::Item' ) {
152 $self->add_message({ message => 'error_delitem' });
157 # Update order status
160 cancellationreason => $reason,
161 datecancellationprinted => \'NOW()',
162 orderstatus => 'cancelled',
171 $order->add_item( $itemnumber );
173 Link an item to this order.
178 my ( $self, $itemnumber ) = @_;
180 my $schema = Koha::Database->new->schema;
181 my $rs = $schema->resultset('AqordersItem');
182 $rs->create({ ordernumber => $self->ordernumber, itemnumber => $itemnumber });
187 my $basket = $order->basket;
189 Returns the I<Koha::Acquisition::Basket> object for the basket associated
196 my $basket_rs = $self->_result->basket;
197 return Koha::Acquisition::Basket->_new_from_dbic( $basket_rs );
202 my $fund = $order->fund;
204 Returns the I<Koha::Acquisition::Fund> object for the fund (aqbudgets)
205 associated to the order.
211 my $fund_rs = $self->_result->fund;
212 return Koha::Acquisition::Fund->_new_from_dbic( $fund_rs );
217 my $invoice = $order->invoice;
219 Returns the I<Koha::Acquisition::Invoice> object for the invoice associated
222 It returns B<undef> if no linked invoice is found.
228 my $invoice_rs = $self->_result->invoice;
229 return unless $invoice_rs;
230 return Koha::Acquisition::Invoice->_new_from_dbic( $invoice_rs );
235 my $subscription = $order->subscription
237 Returns the I<Koha::Subscription> object for the subscription associated
240 It returns B<undef> if no linked subscription is found.
246 my $subscription_rs = $self->_result->subscription;
247 return unless $subscription_rs;
248 return Koha::Subscription->_new_from_dbic( $subscription_rs );
251 =head3 current_item_level_holds
253 my $holds = $order->current_item_level_holds;
255 Returns the current item-level holds associated to the order. It returns a I<Koha::Holds>
260 sub current_item_level_holds {
263 my $items_rs = $self->_result->aqorders_items;
264 my @item_numbers = $items_rs->get_column('itemnumber')->all;
265 my $biblio = $self->biblio;
267 unless ( $biblio and @item_numbers ) {
268 return Koha::Holds->new->empty;
271 return $biblio->current_holds->search(
274 -in => \@item_numbers
282 my $items = $order->items
284 Returns the items associated to the order.
290 # aqorders_items is not a join table
291 # There is no FK on items (may have been deleted)
292 my $items_rs = $self->_result->aqorders_items;
293 my @itemnumbers = $items_rs->get_column( 'itemnumber' )->all;
294 return Koha::Items->search({ itemnumber => \@itemnumbers });
299 my $biblio = $order->biblio
301 Returns the bibliographic record associated to the order
307 my $biblio_rs= $self->_result->biblio;
308 return unless $biblio_rs;
309 return Koha::Biblio->_new_from_dbic( $biblio_rs );
314 my $claims = $order->claims
316 Return the claims history for this order
322 my $claims_rs = $self->_result->aqorders_claims;
323 return Koha::Acquisition::Order::Claims->_new_from_dbic( $claims_rs );
328 my $claim = $order->claim
330 Do claim for this order
336 my $claim_rs = $self->_result->create_related('aqorders_claims', {});
337 return Koha::Acquisition::Order::Claim->_new_from_dbic($claim_rs);
342 my $nb_of_claims = $order->claims_count;
344 This is the equivalent of $order->claims->count. Keeping it for retrocompatibilty.
350 return $self->claims->count;
355 my $last_claim_date = $order->claimed_date;
357 This is the equivalent of $order->claims->last->claimed_on. Keeping it for retrocompatibilty.
363 my $last_claim = $self->claims->last;
364 return unless $last_claim;
365 return $last_claim->claimed_on;
370 my $duplicated_order = $order->duplicate_to($basket, [$default_values]);
372 Duplicate an existing order and attach it to a basket. $default_values can be specified as a hashref
373 that contain default values for the different order's attributes.
374 Items will be duplicated as well but barcodes will be set to null.
379 my ( $self, $basket, $default_values ) = @_;
381 $default_values //= {};
382 Koha::Database->schema->txn_do(
384 my $order_info = $self->unblessed;
385 undef $order_info->{ordernumber};
392 datecancellationprinted
401 undef $order_info->{$field};
403 $order_info->{placed_on} = dt_from_string;
404 $order_info->{entrydate} = dt_from_string;
405 $order_info->{orderstatus} = 'new';
406 $order_info->{quantityreceived} = 0;
407 while ( my ( $field, $value ) = each %$default_values ) {
408 $order_info->{$field} = $value;
411 my $userenv = C4::Context->userenv;
412 $order_info->{created_by} = $userenv->{number};
413 $order_info->{basketno} = $basket->basketno;
415 $new_order = Koha::Acquisition::Order->new($order_info)->store;
417 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
418 my $items = $self->items;
419 while ( my ($item) = $items->next ) {
420 my $item_info = $item->unblessed;
421 undef $item_info->{itemnumber};
422 undef $item_info->{barcode};
423 my $new_item = Koha::Item->new($item_info)->store;
424 $new_order->add_item( $new_item->itemnumber );
432 =head3 to_api_mapping
434 This method returns the mapping for representing a Koha::Acquisition::Order object
441 basketno => 'basket_id',
442 biblionumber => 'biblio_id',
443 budget_id => 'fund_id',
444 budgetdate => undef, # unused
445 cancellationreason => 'cancellation_reason',
446 claimed_date => 'last_claim_date',
447 datecancellationprinted => 'cancellation_date',
448 datereceived => 'date_received',
449 discount => 'discount_rate',
450 entrydate => 'entry_date',
451 freight => 'shipping_cost',
452 invoiceid => 'invoice_id',
453 line_item_id => undef, # EDIFACT related
454 listprice => 'list_price',
455 order_internalnote => 'internal_note',
456 order_vendornote => 'vendor_note',
457 ordernumber => 'order_id',
458 orderstatus => 'status',
459 parent_ordernumber => 'parent_order_id',
460 purchaseordernumber => undef, # obsolete
461 quantityreceived => 'quantity_received',
462 replacementprice => 'replacement_price',
463 sort1 => 'statistics_1',
464 sort1_authcat => 'statistics_1_authcat',
465 sort2 => 'statistics_2',
466 sort2_authcat => 'statistics_2_authcat',
467 subscriptionid => 'subscription_id',
468 suppliers_reference_number => undef, # EDIFACT related
469 suppliers_reference_qualifier => undef, # EDIFACT related
470 suppliers_report => undef, # EDIFACT related
471 tax_rate_bak => undef, # unused
472 tax_value_bak => undef, # unused
473 uncertainprice => 'uncertain_price',
474 unitprice => 'unit_price',
475 unitprice_tax_excluded => 'unit_price_tax_excluded',
476 unitprice_tax_included => 'unit_price_tax_included'
480 =head2 Internal methods