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 == 0
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 })
145 $self->add_message({ message => 'error_delbiblio' });
150 if ( ref($_) eq 'Koha::Exceptions::Object::CannotBeDeleted' ) {
151 my $object = $_->object;
152 if ( ref($object) eq 'Koha::Item' ) {
153 $self->add_message({ message => 'error_delitem' });
158 # Update order status
161 cancellationreason => $reason,
162 datecancellationprinted => \'NOW()',
163 orderstatus => 'cancelled',
172 $order->add_item( $itemnumber );
174 Link an item to this order.
179 my ( $self, $itemnumber ) = @_;
181 my $schema = Koha::Database->new->schema;
182 my $rs = $schema->resultset('AqordersItem');
183 $rs->create({ ordernumber => $self->ordernumber, itemnumber => $itemnumber });
188 my $basket = $order->basket;
190 Returns the I<Koha::Acquisition::Basket> object for the basket associated
197 my $basket_rs = $self->_result->basket;
198 return Koha::Acquisition::Basket->_new_from_dbic( $basket_rs );
203 my $fund = $order->fund;
205 Returns the I<Koha::Acquisition::Fund> object for the fund (aqbudgets)
206 associated to the order.
212 my $fund_rs = $self->_result->fund;
213 return Koha::Acquisition::Fund->_new_from_dbic( $fund_rs );
218 my $invoice = $order->invoice;
220 Returns the I<Koha::Acquisition::Invoice> object for the invoice associated
223 It returns B<undef> if no linked invoice is found.
229 my $invoice_rs = $self->_result->invoice;
230 return unless $invoice_rs;
231 return Koha::Acquisition::Invoice->_new_from_dbic( $invoice_rs );
236 my $subscription = $order->subscription
238 Returns the I<Koha::Subscription> object for the subscription associated
241 It returns B<undef> if no linked subscription is found.
247 my $subscription_rs = $self->_result->subscription;
248 return unless $subscription_rs;
249 return Koha::Subscription->_new_from_dbic( $subscription_rs );
252 =head3 current_item_level_holds
254 my $holds = $order->current_item_level_holds;
256 Returns the current item-level holds associated to the order. It returns a I<Koha::Holds>
261 sub current_item_level_holds {
264 my $items_rs = $self->_result->aqorders_items;
265 my @item_numbers = $items_rs->get_column('itemnumber')->all;
266 my $biblio = $self->biblio;
268 unless ( $biblio and @item_numbers ) {
269 return Koha::Holds->new->empty;
272 return $biblio->current_holds->search(
275 -in => \@item_numbers
283 my $items = $order->items
285 Returns the items associated to the order.
291 # aqorders_items is not a join table
292 # There is no FK on items (may have been deleted)
293 my $items_rs = $self->_result->aqorders_items;
294 my @itemnumbers = $items_rs->get_column( 'itemnumber' )->all;
295 return Koha::Items->search({ itemnumber => \@itemnumbers });
300 my $biblio = $order->biblio
302 Returns the bibliographic record associated to the order
308 my $biblio_rs= $self->_result->biblio;
309 return unless $biblio_rs;
310 return Koha::Biblio->_new_from_dbic( $biblio_rs );
315 my $claims = $order->claims
317 Return the claims history for this order
323 my $claims_rs = $self->_result->aqorders_claims;
324 return Koha::Acquisition::Order::Claims->_new_from_dbic( $claims_rs );
329 my $claim = $order->claim
331 Do claim for this order
337 my $claim_rs = $self->_result->create_related('aqorders_claims', {});
338 return Koha::Acquisition::Order::Claim->_new_from_dbic($claim_rs);
343 my $nb_of_claims = $order->claims_count;
345 This is the equivalent of $order->claims->count. Keeping it for retrocompatibilty.
351 return $self->claims->count;
356 my $last_claim_date = $order->claimed_date;
358 This is the equivalent of $order->claims->last->claimed_on. Keeping it for retrocompatibilty.
364 my $last_claim = $self->claims->last;
365 return unless $last_claim;
366 return $last_claim->claimed_on;
371 my $duplicated_order = $order->duplicate_to($basket, [$default_values]);
373 Duplicate an existing order and attach it to a basket. $default_values can be specified as a hashref
374 that contain default values for the different order's attributes.
375 Items will be duplicated as well but barcodes will be set to null.
380 my ( $self, $basket, $default_values ) = @_;
382 $default_values //= {};
383 Koha::Database->schema->txn_do(
385 my $order_info = $self->unblessed;
386 undef $order_info->{ordernumber};
393 datecancellationprinted
402 undef $order_info->{$field};
404 $order_info->{placed_on} = dt_from_string;
405 $order_info->{entrydate} = dt_from_string;
406 $order_info->{orderstatus} = 'new';
407 $order_info->{quantityreceived} = 0;
408 while ( my ( $field, $value ) = each %$default_values ) {
409 $order_info->{$field} = $value;
412 my $userenv = C4::Context->userenv;
413 $order_info->{created_by} = $userenv->{number};
414 $order_info->{basketno} = $basket->basketno;
416 $new_order = Koha::Acquisition::Order->new($order_info)->store;
418 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
419 my $items = $self->items;
420 while ( my ($item) = $items->next ) {
421 my $item_info = $item->unblessed;
422 undef $item_info->{itemnumber};
423 undef $item_info->{barcode};
424 my $new_item = Koha::Item->new($item_info)->store;
425 $new_order->add_item( $new_item->itemnumber );
433 =head3 to_api_mapping
435 This method returns the mapping for representing a Koha::Acquisition::Order object
442 basketno => 'basket_id',
443 biblionumber => 'biblio_id',
444 budget_id => 'fund_id',
445 budgetdate => undef, # unused
446 cancellationreason => 'cancellation_reason',
447 claimed_date => 'last_claim_date',
448 datecancellationprinted => 'cancellation_date',
449 datereceived => 'date_received',
450 discount => 'discount_rate',
451 entrydate => 'entry_date',
452 freight => 'shipping_cost',
453 invoiceid => 'invoice_id',
454 line_item_id => undef, # EDIFACT related
455 listprice => 'list_price',
456 order_internalnote => 'internal_note',
457 order_vendornote => 'vendor_note',
458 ordernumber => 'order_id',
459 orderstatus => 'status',
460 parent_ordernumber => 'parent_order_id',
461 purchaseordernumber => undef, # obsolete
462 quantityreceived => 'quantity_received',
463 replacementprice => 'replacement_price',
464 sort1 => 'statistics_1',
465 sort1_authcat => 'statistics_1_authcat',
466 sort2 => 'statistics_2',
467 sort2_authcat => 'statistics_2_authcat',
468 subscriptionid => 'subscription_id',
469 suppliers_reference_number => undef, # EDIFACT related
470 suppliers_reference_qualifier => undef, # EDIFACT related
471 suppliers_report => undef, # EDIFACT related
472 tax_rate_bak => undef, # unused
473 tax_value_bak => undef, # unused
474 uncertainprice => 'uncertain_price',
475 unitprice => 'unit_price',
476 unitprice_tax_excluded => 'unit_price_tax_excluded',
477 unitprice_tax_included => 'unit_price_tax_included'
481 =head2 Internal methods