Bug 15697 - [QA Followup] Apply change to NORMARC
[koha.git] / C4 / Acquisition.pm
blob4a83cb908f03240d41bf246b775eb02cbed21042
1 package C4::Acquisition;
3 # Copyright 2000-2002 Katipo Communications
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
21 use Modern::Perl;
22 use Carp;
23 use C4::Context;
24 use C4::Debug;
25 use C4::Suggestions;
26 use C4::Biblio;
27 use C4::Contract;
28 use C4::Debug;
29 use C4::Templates qw(gettemplate);
30 use Koha::DateUtils qw( dt_from_string output_pref );
31 use Koha::Acquisition::Order;
32 use Koha::Acquisition::Bookseller;
33 use Koha::Number::Price;
34 use Koha::Libraries;
36 use C4::Koha qw( subfield_is_koha_internal_p );
38 use MARC::Field;
39 use MARC::Record;
41 use Time::localtime;
42 use HTML::Entities;
44 use vars qw($VERSION @ISA @EXPORT);
46 BEGIN {
47 # set the version for version checking
48 $VERSION = 3.07.00.049;
49 require Exporter;
50 @ISA = qw(Exporter);
51 @EXPORT = qw(
52 &GetBasket &NewBasket &CloseBasket &ReopenBasket &DelBasket &ModBasket
53 &GetBasketAsCSV &GetBasketGroupAsCSV
54 &GetBasketsByBookseller &GetBasketsByBasketgroup
55 &GetBasketsInfosByBookseller
57 &GetBasketUsers &ModBasketUsers
58 &CanUserManageBasket
60 &ModBasketHeader
62 &ModBasketgroup &NewBasketgroup &DelBasketgroup &GetBasketgroup &CloseBasketgroup
63 &GetBasketgroups &ReOpenBasketgroup
65 &DelOrder &ModOrder &GetOrder &GetOrders &GetOrdersByBiblionumber
66 &GetLateOrders &GetOrderFromItemnumber
67 &SearchOrders &GetHistory &GetRecentAcqui
68 &ModReceiveOrder &CancelReceipt
69 &TransferOrder
70 &GetLastOrderNotReceivedFromSubscriptionid &GetLastOrderReceivedFromSubscriptionid
71 &ModItemOrder
73 &GetParcels
75 &GetInvoices
76 &GetInvoice
77 &GetInvoiceDetails
78 &AddInvoice
79 &ModInvoice
80 &CloseInvoice
81 &ReopenInvoice
82 &DelInvoice
83 &MergeInvoices
85 &GetItemnumbersFromOrder
87 &AddClaim
88 &GetBiblioCountByBasketno
90 &GetOrderUsers
91 &ModOrderUsers
92 &NotifyOrderUsers
94 &FillWithDefaultValues
102 sub GetOrderFromItemnumber {
103 my ($itemnumber) = @_;
104 my $dbh = C4::Context->dbh;
105 my $query = qq|
107 SELECT * from aqorders LEFT JOIN aqorders_items
108 ON ( aqorders.ordernumber = aqorders_items.ordernumber )
109 WHERE itemnumber = ? |;
111 my $sth = $dbh->prepare($query);
113 # $sth->trace(3);
115 $sth->execute($itemnumber);
117 my $order = $sth->fetchrow_hashref;
118 return ( $order );
122 # Returns the itemnumber(s) associated with the ordernumber given in parameter
123 sub GetItemnumbersFromOrder {
124 my ($ordernumber) = @_;
125 my $dbh = C4::Context->dbh;
126 my $query = "SELECT itemnumber FROM aqorders_items WHERE ordernumber=?";
127 my $sth = $dbh->prepare($query);
128 $sth->execute($ordernumber);
129 my @tab;
131 while (my $order = $sth->fetchrow_hashref) {
132 push @tab, $order->{'itemnumber'};
135 return @tab;
144 =head1 NAME
146 C4::Acquisition - Koha functions for dealing with orders and acquisitions
148 =head1 SYNOPSIS
150 use C4::Acquisition;
152 =head1 DESCRIPTION
154 The functions in this module deal with acquisitions, managing book
155 orders, basket and parcels.
157 =head1 FUNCTIONS
159 =head2 FUNCTIONS ABOUT BASKETS
161 =head3 GetBasket
163 $aqbasket = &GetBasket($basketnumber);
165 get all basket informations in aqbasket for a given basket
167 B<returns:> informations for a given basket returned as a hashref.
169 =cut
171 sub GetBasket {
172 my ($basketno) = @_;
173 my $dbh = C4::Context->dbh;
174 my $query = "
175 SELECT aqbasket.*,
176 concat( b.firstname,' ',b.surname) AS authorisedbyname
177 FROM aqbasket
178 LEFT JOIN borrowers b ON aqbasket.authorisedby=b.borrowernumber
179 WHERE basketno=?
181 my $sth=$dbh->prepare($query);
182 $sth->execute($basketno);
183 my $basket = $sth->fetchrow_hashref;
184 return ( $basket );
187 #------------------------------------------------------------#
189 =head3 NewBasket
191 $basket = &NewBasket( $booksellerid, $authorizedby, $basketname,
192 $basketnote, $basketbooksellernote, $basketcontractnumber, $deliveryplace, $billingplace );
194 Create a new basket in aqbasket table
196 =over
198 =item C<$booksellerid> is a foreign key in the aqbasket table
200 =item C<$authorizedby> is the username of who created the basket
202 =back
204 The other parameters are optional, see ModBasketHeader for more info on them.
206 =cut
208 sub NewBasket {
209 my ( $booksellerid, $authorisedby, $basketname, $basketnote,
210 $basketbooksellernote, $basketcontractnumber, $deliveryplace,
211 $billingplace ) = @_;
212 my $dbh = C4::Context->dbh;
213 my $query =
214 'INSERT INTO aqbasket (creationdate,booksellerid,authorisedby) '
215 . 'VALUES (now(),?,?)';
216 $dbh->do( $query, {}, $booksellerid, $authorisedby );
218 my $basket = $dbh->{mysql_insertid};
219 $basketname ||= q{}; # default to empty strings
220 $basketnote ||= q{};
221 $basketbooksellernote ||= q{};
222 ModBasketHeader( $basket, $basketname, $basketnote, $basketbooksellernote,
223 $basketcontractnumber, $booksellerid, $deliveryplace, $billingplace );
224 return $basket;
227 #------------------------------------------------------------#
229 =head3 CloseBasket
231 &CloseBasket($basketno);
233 close a basket (becomes unmodifiable, except for receives)
235 =cut
237 sub CloseBasket {
238 my ($basketno) = @_;
239 my $dbh = C4::Context->dbh;
240 $dbh->do('UPDATE aqbasket SET closedate=now() WHERE basketno=?', {}, $basketno );
242 $dbh->do( q{UPDATE aqorders SET orderstatus = 'ordered' WHERE basketno = ? AND orderstatus != 'complete'},
243 {}, $basketno);
244 return;
247 =head3 ReopenBasket
249 &ReopenBasket($basketno);
251 reopen a basket
253 =cut
255 sub ReopenBasket {
256 my ($basketno) = @_;
257 my $dbh = C4::Context->dbh;
258 $dbh->do( q{UPDATE aqbasket SET closedate=NULL WHERE basketno=?}, {}, $basketno );
260 $dbh->do( q{
261 UPDATE aqorders
262 SET orderstatus = 'new'
263 WHERE basketno = ?
264 AND orderstatus != 'complete'
265 }, {}, $basketno);
266 return;
269 #------------------------------------------------------------#
271 =head3 GetBasketAsCSV
273 &GetBasketAsCSV($basketno);
275 Export a basket as CSV
277 $cgi parameter is needed for column name translation
279 =cut
281 sub GetBasketAsCSV {
282 my ($basketno, $cgi) = @_;
283 my $basket = GetBasket($basketno);
284 my @orders = GetOrders($basketno);
285 my $contract = GetContract({
286 contractnumber => $basket->{'contractnumber'}
289 my $template = C4::Templates::gettemplate("acqui/csv/basket.tt", "intranet", $cgi);
291 my @rows;
292 foreach my $order (@orders) {
293 my $bd = GetBiblioData( $order->{'biblionumber'} );
294 my $row = {
295 contractname => $contract->{'contractname'},
296 ordernumber => $order->{'ordernumber'},
297 entrydate => $order->{'entrydate'},
298 isbn => $order->{'isbn'},
299 author => $bd->{'author'},
300 title => $bd->{'title'},
301 publicationyear => $bd->{'publicationyear'},
302 publishercode => $bd->{'publishercode'},
303 collectiontitle => $bd->{'collectiontitle'},
304 notes => $order->{'order_vendornote'},
305 quantity => $order->{'quantity'},
306 rrp => $order->{'rrp'},
307 deliveryplace => C4::Branch::GetBranchName( $basket->{'deliveryplace'} ),
308 billingplace => C4::Branch::GetBranchName( $basket->{'billingplace'} ),
310 foreach(qw(
311 contractname author title publishercode collectiontitle notes
312 deliveryplace billingplace
313 ) ) {
314 # Double the quotes to not be interpreted as a field end
315 $row->{$_} =~ s/"/""/g if $row->{$_};
317 push @rows, $row;
320 @rows = sort {
321 if(defined $a->{publishercode} and defined $b->{publishercode}) {
322 $a->{publishercode} cmp $b->{publishercode};
324 } @rows;
326 $template->param(rows => \@rows);
328 return $template->output;
332 =head3 GetBasketGroupAsCSV
334 &GetBasketGroupAsCSV($basketgroupid);
336 Export a basket group as CSV
338 $cgi parameter is needed for column name translation
340 =cut
342 sub GetBasketGroupAsCSV {
343 my ($basketgroupid, $cgi) = @_;
344 my $baskets = GetBasketsByBasketgroup($basketgroupid);
346 my $template = C4::Templates::gettemplate('acqui/csv/basketgroup.tt', 'intranet', $cgi);
348 my @rows;
349 for my $basket (@$baskets) {
350 my @orders = GetOrders( $basket->{basketno} );
351 my $contract = GetContract({
352 contractnumber => $basket->{contractnumber}
354 my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $basket->{booksellerid} });
355 my $basketgroup = GetBasketgroup( $$basket{basketgroupid} );
357 foreach my $order (@orders) {
358 my $bd = GetBiblioData( $order->{'biblionumber'} );
359 my $row = {
360 clientnumber => $bookseller->{accountnumber},
361 basketname => $basket->{basketname},
362 ordernumber => $order->{ordernumber},
363 author => $bd->{author},
364 title => $bd->{title},
365 publishercode => $bd->{publishercode},
366 publicationyear => $bd->{publicationyear},
367 collectiontitle => $bd->{collectiontitle},
368 isbn => $order->{isbn},
369 quantity => $order->{quantity},
370 rrp => $order->{rrp},
371 discount => $bookseller->{discount},
372 ecost => $order->{ecost},
373 notes => $order->{order_vendornote},
374 entrydate => $order->{entrydate},
375 booksellername => $bookseller->{name},
376 bookselleraddress => $bookseller->{address1},
377 booksellerpostal => $bookseller->{postal},
378 contractnumber => $contract->{contractnumber},
379 contractname => $contract->{contractname},
380 basketgroupdeliveryplace => C4::Branch::GetBranchName( $basketgroup->{deliveryplace} ),
381 basketgroupbillingplace => C4::Branch::GetBranchName( $basketgroup->{billingplace} ),
382 basketdeliveryplace => C4::Branch::GetBranchName( $basket->{deliveryplace} ),
383 basketbillingplace => C4::Branch::GetBranchName( $basket->{billingplace} ),
385 foreach(qw(
386 basketname author title publishercode collectiontitle notes
387 booksellername bookselleraddress booksellerpostal contractname
388 basketgroupdeliveryplace basketgroupbillingplace
389 basketdeliveryplace basketbillingplace
390 ) ) {
391 # Double the quotes to not be interpreted as a field end
392 $row->{$_} =~ s/"/""/g if $row->{$_};
394 push @rows, $row;
397 $template->param(rows => \@rows);
399 return $template->output;
403 =head3 CloseBasketgroup
405 &CloseBasketgroup($basketgroupno);
407 close a basketgroup
409 =cut
411 sub CloseBasketgroup {
412 my ($basketgroupno) = @_;
413 my $dbh = C4::Context->dbh;
414 my $sth = $dbh->prepare("
415 UPDATE aqbasketgroups
416 SET closed=1
417 WHERE id=?
419 $sth->execute($basketgroupno);
422 #------------------------------------------------------------#
424 =head3 ReOpenBaskergroup($basketgroupno)
426 &ReOpenBaskergroup($basketgroupno);
428 reopen a basketgroup
430 =cut
432 sub ReOpenBasketgroup {
433 my ($basketgroupno) = @_;
434 my $dbh = C4::Context->dbh;
435 my $sth = $dbh->prepare("
436 UPDATE aqbasketgroups
437 SET closed=0
438 WHERE id=?
440 $sth->execute($basketgroupno);
443 #------------------------------------------------------------#
446 =head3 DelBasket
448 &DelBasket($basketno);
450 Deletes the basket that has basketno field $basketno in the aqbasket table.
452 =over
454 =item C<$basketno> is the primary key of the basket in the aqbasket table.
456 =back
458 =cut
460 sub DelBasket {
461 my ( $basketno ) = @_;
462 my $query = "DELETE FROM aqbasket WHERE basketno=?";
463 my $dbh = C4::Context->dbh;
464 my $sth = $dbh->prepare($query);
465 $sth->execute($basketno);
466 return;
469 #------------------------------------------------------------#
471 =head3 ModBasket
473 &ModBasket($basketinfo);
475 Modifies a basket, using a hashref $basketinfo for the relevant information, only $basketinfo->{'basketno'} is required.
477 =over
479 =item C<$basketno> is the primary key of the basket in the aqbasket table.
481 =back
483 =cut
485 sub ModBasket {
486 my $basketinfo = shift;
487 my $query = "UPDATE aqbasket SET ";
488 my @params;
489 foreach my $key (keys %$basketinfo){
490 if ($key ne 'basketno'){
491 $query .= "$key=?, ";
492 push(@params, $basketinfo->{$key} || undef );
495 # get rid of the "," at the end of $query
496 if (substr($query, length($query)-2) eq ', '){
497 chop($query);
498 chop($query);
499 $query .= ' ';
501 $query .= "WHERE basketno=?";
502 push(@params, $basketinfo->{'basketno'});
503 my $dbh = C4::Context->dbh;
504 my $sth = $dbh->prepare($query);
505 $sth->execute(@params);
507 return;
510 #------------------------------------------------------------#
512 =head3 ModBasketHeader
514 &ModBasketHeader($basketno, $basketname, $note, $booksellernote, $contractnumber, $booksellerid);
516 Modifies a basket's header.
518 =over
520 =item C<$basketno> is the "basketno" field in the "aqbasket" table;
522 =item C<$basketname> is the "basketname" field in the "aqbasket" table;
524 =item C<$note> is the "note" field in the "aqbasket" table;
526 =item C<$booksellernote> is the "booksellernote" field in the "aqbasket" table;
528 =item C<$contractnumber> is the "contractnumber" (foreign) key in the "aqbasket" table.
530 =item C<$booksellerid> is the id (foreign) key in the "aqbooksellers" table for the vendor.
532 =item C<$deliveryplace> is the "deliveryplace" field in the aqbasket table.
534 =item C<$billingplace> is the "billingplace" field in the aqbasket table.
536 =back
538 =cut
540 sub ModBasketHeader {
541 my ($basketno, $basketname, $note, $booksellernote, $contractnumber, $booksellerid, $deliveryplace, $billingplace) = @_;
542 my $query = qq{
543 UPDATE aqbasket
544 SET basketname=?, note=?, booksellernote=?, booksellerid=?, deliveryplace=?, billingplace=?
545 WHERE basketno=?
548 my $dbh = C4::Context->dbh;
549 my $sth = $dbh->prepare($query);
550 $sth->execute($basketname, $note, $booksellernote, $booksellerid, $deliveryplace, $billingplace, $basketno);
552 if ( $contractnumber ) {
553 my $query2 ="UPDATE aqbasket SET contractnumber=? WHERE basketno=?";
554 my $sth2 = $dbh->prepare($query2);
555 $sth2->execute($contractnumber,$basketno);
557 return;
560 #------------------------------------------------------------#
562 =head3 GetBasketsByBookseller
564 @results = &GetBasketsByBookseller($booksellerid, $extra);
566 Returns a list of hashes of all the baskets that belong to bookseller 'booksellerid'.
568 =over
570 =item C<$booksellerid> is the 'id' field of the bookseller in the aqbooksellers table
572 =item C<$extra> is the extra sql parameters, can be
574 $extra->{groupby}: group baskets by column
575 ex. $extra->{groupby} = aqbasket.basketgroupid
576 $extra->{orderby}: order baskets by column
577 $extra->{limit}: limit number of results (can be helpful for pagination)
579 =back
581 =cut
583 sub GetBasketsByBookseller {
584 my ($booksellerid, $extra) = @_;
585 my $query = "SELECT * FROM aqbasket WHERE booksellerid=?";
586 if ($extra){
587 if ($extra->{groupby}) {
588 $query .= " GROUP by $extra->{groupby}";
590 if ($extra->{orderby}){
591 $query .= " ORDER by $extra->{orderby}";
593 if ($extra->{limit}){
594 $query .= " LIMIT $extra->{limit}";
597 my $dbh = C4::Context->dbh;
598 my $sth = $dbh->prepare($query);
599 $sth->execute($booksellerid);
600 return $sth->fetchall_arrayref({});
603 =head3 GetBasketsInfosByBookseller
605 my $baskets = GetBasketsInfosByBookseller($supplierid, $allbaskets);
607 The optional second parameter allbaskets is a boolean allowing you to
608 select all baskets from the supplier; by default only active baskets (open or
609 closed but still something to receive) are returned.
611 Returns in a arrayref of hashref all about booksellers baskets, plus:
612 total_biblios: Number of distinct biblios in basket
613 total_items: Number of items in basket
614 expected_items: Number of non-received items in basket
616 =cut
618 sub GetBasketsInfosByBookseller {
619 my ($supplierid, $allbaskets) = @_;
621 return unless $supplierid;
623 my $dbh = C4::Context->dbh;
624 my $query = q{
625 SELECT aqbasket.*,
626 SUM(aqorders.quantity) AS total_items,
627 SUM(
628 IF ( aqorders.orderstatus = 'cancelled', aqorders.quantity, 0 )
629 ) AS total_items_cancelled,
630 COUNT(DISTINCT aqorders.biblionumber) AS total_biblios,
631 SUM(
632 IF(aqorders.datereceived IS NULL
633 AND aqorders.datecancellationprinted IS NULL
634 , aqorders.quantity
635 , 0)
636 ) AS expected_items
637 FROM aqbasket
638 LEFT JOIN aqorders ON aqorders.basketno = aqbasket.basketno
639 WHERE booksellerid = ?};
641 unless ( $allbaskets ) {
642 $query.=" AND (closedate IS NULL OR (aqorders.quantity > aqorders.quantityreceived AND datecancellationprinted IS NULL))";
644 $query.=" GROUP BY aqbasket.basketno";
646 my $sth = $dbh->prepare($query);
647 $sth->execute($supplierid);
648 my $baskets = $sth->fetchall_arrayref({});
650 # Retrieve the number of biblios cancelled
651 my $cancelled_biblios = $dbh->selectall_hashref( q|
652 SELECT COUNT(DISTINCT(biblionumber)) AS total_biblios_cancelled, aqbasket.basketno
653 FROM aqbasket
654 LEFT JOIN aqorders ON aqorders.basketno = aqbasket.basketno
655 WHERE booksellerid = ?
656 AND aqorders.orderstatus = 'cancelled'
657 GROUP BY aqbasket.basketno
658 |, 'basketno', {}, $supplierid );
659 map {
660 $_->{total_biblios_cancelled} = $cancelled_biblios->{$_->{basketno}}{total_biblios_cancelled} || 0
661 } @$baskets;
663 return $baskets;
666 =head3 GetBasketUsers
668 $basketusers_ids = &GetBasketUsers($basketno);
670 Returns a list of all borrowernumbers that are in basket users list
672 =cut
674 sub GetBasketUsers {
675 my $basketno = shift;
677 return unless $basketno;
679 my $query = qq{
680 SELECT borrowernumber
681 FROM aqbasketusers
682 WHERE basketno = ?
684 my $dbh = C4::Context->dbh;
685 my $sth = $dbh->prepare($query);
686 $sth->execute($basketno);
687 my $results = $sth->fetchall_arrayref( {} );
689 my @borrowernumbers;
690 foreach (@$results) {
691 push @borrowernumbers, $_->{'borrowernumber'};
694 return @borrowernumbers;
697 =head3 ModBasketUsers
699 my @basketusers_ids = (1, 2, 3);
700 &ModBasketUsers($basketno, @basketusers_ids);
702 Delete all users from basket users list, and add users in C<@basketusers_ids>
703 to this users list.
705 =cut
707 sub ModBasketUsers {
708 my ($basketno, @basketusers_ids) = @_;
710 return unless $basketno;
712 my $dbh = C4::Context->dbh;
713 my $query = qq{
714 DELETE FROM aqbasketusers
715 WHERE basketno = ?
717 my $sth = $dbh->prepare($query);
718 $sth->execute($basketno);
720 $query = qq{
721 INSERT INTO aqbasketusers (basketno, borrowernumber)
722 VALUES (?, ?)
724 $sth = $dbh->prepare($query);
725 foreach my $basketuser_id (@basketusers_ids) {
726 $sth->execute($basketno, $basketuser_id);
728 return;
731 =head3 CanUserManageBasket
733 my $bool = CanUserManageBasket($borrower, $basket[, $userflags]);
734 my $bool = CanUserManageBasket($borrowernumber, $basketno[, $userflags]);
736 Check if a borrower can manage a basket, according to system preference
737 AcqViewBaskets, user permissions and basket properties (creator, users list,
738 branch).
740 First parameter can be either a borrowernumber or a hashref as returned by
741 C4::Members::GetMember.
743 Second parameter can be either a basketno or a hashref as returned by
744 C4::Acquisition::GetBasket.
746 The third parameter is optional. If given, it should be a hashref as returned
747 by C4::Auth::getuserflags. If not, getuserflags is called.
749 If user is authorised to manage basket, returns 1.
750 Otherwise returns 0.
752 =cut
754 sub CanUserManageBasket {
755 my ($borrower, $basket, $userflags) = @_;
757 if (!ref $borrower) {
758 $borrower = C4::Members::GetMember(borrowernumber => $borrower);
760 if (!ref $basket) {
761 $basket = GetBasket($basket);
764 return 0 unless ($basket and $borrower);
766 my $borrowernumber = $borrower->{borrowernumber};
767 my $basketno = $basket->{basketno};
769 my $AcqViewBaskets = C4::Context->preference('AcqViewBaskets');
771 if (!defined $userflags) {
772 my $dbh = C4::Context->dbh;
773 my $sth = $dbh->prepare("SELECT flags FROM borrowers WHERE borrowernumber = ?");
774 $sth->execute($borrowernumber);
775 my ($flags) = $sth->fetchrow_array;
776 $sth->finish;
778 $userflags = C4::Auth::getuserflags($flags, $borrower->{userid}, $dbh);
781 unless ($userflags->{superlibrarian}
782 || (ref $userflags->{acquisition} && $userflags->{acquisition}->{order_manage_all})
783 || (!ref $userflags->{acquisition} && $userflags->{acquisition}))
785 if (not exists $userflags->{acquisition}) {
786 return 0;
789 if ( (ref $userflags->{acquisition} && !$userflags->{acquisition}->{order_manage})
790 || (!ref $userflags->{acquisition} && !$userflags->{acquisition}) ) {
791 return 0;
794 if ($AcqViewBaskets eq 'user'
795 && $basket->{authorisedby} != $borrowernumber
796 && grep($borrowernumber, GetBasketUsers($basketno)) == 0) {
797 return 0;
800 if ($AcqViewBaskets eq 'branch' && defined $basket->{branch}
801 && $basket->{branch} ne $borrower->{branchcode}) {
802 return 0;
806 return 1;
809 #------------------------------------------------------------#
811 =head3 GetBasketsByBasketgroup
813 $baskets = &GetBasketsByBasketgroup($basketgroupid);
815 Returns a reference to all baskets that belong to basketgroup $basketgroupid.
817 =cut
819 sub GetBasketsByBasketgroup {
820 my $basketgroupid = shift;
821 my $query = qq{
822 SELECT *, aqbasket.booksellerid as booksellerid
823 FROM aqbasket
824 LEFT JOIN aqcontract USING(contractnumber) WHERE basketgroupid=?
826 my $dbh = C4::Context->dbh;
827 my $sth = $dbh->prepare($query);
828 $sth->execute($basketgroupid);
829 return $sth->fetchall_arrayref({});
832 #------------------------------------------------------------#
834 =head3 NewBasketgroup
836 $basketgroupid = NewBasketgroup(\%hashref);
838 Adds a basketgroup to the aqbasketgroups table, and add the initial baskets to it.
840 $hashref->{'booksellerid'} is the 'id' field of the bookseller in the aqbooksellers table,
842 $hashref->{'name'} is the 'name' field of the basketgroup in the aqbasketgroups table,
844 $hashref->{'basketlist'} is a list reference of the 'id's of the baskets that belong to this group,
846 $hashref->{'billingplace'} is the 'billingplace' field of the basketgroup in the aqbasketgroups table,
848 $hashref->{'deliveryplace'} is the 'deliveryplace' field of the basketgroup in the aqbasketgroups table,
850 $hashref->{'freedeliveryplace'} is the 'freedeliveryplace' field of the basketgroup in the aqbasketgroups table,
852 $hashref->{'deliverycomment'} is the 'deliverycomment' field of the basketgroup in the aqbasketgroups table,
854 $hashref->{'closed'} is the 'closed' field of the aqbasketgroups table, it is false if 0, true otherwise.
856 =cut
858 sub NewBasketgroup {
859 my $basketgroupinfo = shift;
860 die "booksellerid is required to create a basketgroup" unless $basketgroupinfo->{'booksellerid'};
861 my $query = "INSERT INTO aqbasketgroups (";
862 my @params;
863 foreach my $field (qw(name billingplace deliveryplace freedeliveryplace deliverycomment closed)) {
864 if ( defined $basketgroupinfo->{$field} ) {
865 $query .= "$field, ";
866 push(@params, $basketgroupinfo->{$field});
869 $query .= "booksellerid) VALUES (";
870 foreach (@params) {
871 $query .= "?, ";
873 $query .= "?)";
874 push(@params, $basketgroupinfo->{'booksellerid'});
875 my $dbh = C4::Context->dbh;
876 my $sth = $dbh->prepare($query);
877 $sth->execute(@params);
878 my $basketgroupid = $dbh->{'mysql_insertid'};
879 if( $basketgroupinfo->{'basketlist'} ) {
880 foreach my $basketno (@{$basketgroupinfo->{'basketlist'}}) {
881 my $query2 = "UPDATE aqbasket SET basketgroupid=? WHERE basketno=?";
882 my $sth2 = $dbh->prepare($query2);
883 $sth2->execute($basketgroupid, $basketno);
886 return $basketgroupid;
889 #------------------------------------------------------------#
891 =head3 ModBasketgroup
893 ModBasketgroup(\%hashref);
895 Modifies a basketgroup in the aqbasketgroups table, and add the baskets to it.
897 $hashref->{'id'} is the 'id' field of the basketgroup in the aqbasketgroup table, this parameter is mandatory,
899 $hashref->{'name'} is the 'name' field of the basketgroup in the aqbasketgroups table,
901 $hashref->{'basketlist'} is a list reference of the 'id's of the baskets that belong to this group,
903 $hashref->{'billingplace'} is the 'billingplace' field of the basketgroup in the aqbasketgroups table,
905 $hashref->{'deliveryplace'} is the 'deliveryplace' field of the basketgroup in the aqbasketgroups table,
907 $hashref->{'freedeliveryplace'} is the 'freedeliveryplace' field of the basketgroup in the aqbasketgroups table,
909 $hashref->{'deliverycomment'} is the 'deliverycomment' field of the basketgroup in the aqbasketgroups table,
911 $hashref->{'closed'} is the 'closed' field of the aqbasketgroups table, it is false if 0, true otherwise.
913 =cut
915 sub ModBasketgroup {
916 my $basketgroupinfo = shift;
917 die "basketgroup id is required to edit a basketgroup" unless $basketgroupinfo->{'id'};
918 my $dbh = C4::Context->dbh;
919 my $query = "UPDATE aqbasketgroups SET ";
920 my @params;
921 foreach my $field (qw(name billingplace deliveryplace freedeliveryplace deliverycomment closed)) {
922 if ( defined $basketgroupinfo->{$field} ) {
923 $query .= "$field=?, ";
924 push(@params, $basketgroupinfo->{$field});
927 chop($query);
928 chop($query);
929 $query .= " WHERE id=?";
930 push(@params, $basketgroupinfo->{'id'});
931 my $sth = $dbh->prepare($query);
932 $sth->execute(@params);
934 $sth = $dbh->prepare('UPDATE aqbasket SET basketgroupid = NULL WHERE basketgroupid = ?');
935 $sth->execute($basketgroupinfo->{'id'});
937 if($basketgroupinfo->{'basketlist'} && @{$basketgroupinfo->{'basketlist'}}){
938 $sth = $dbh->prepare("UPDATE aqbasket SET basketgroupid=? WHERE basketno=?");
939 foreach my $basketno (@{$basketgroupinfo->{'basketlist'}}) {
940 $sth->execute($basketgroupinfo->{'id'}, $basketno);
943 return;
946 #------------------------------------------------------------#
948 =head3 DelBasketgroup
950 DelBasketgroup($basketgroupid);
952 Deletes a basketgroup in the aqbasketgroups table, and removes the reference to it from the baskets,
954 =over
956 =item C<$basketgroupid> is the 'id' field of the basket in the aqbasketgroup table
958 =back
960 =cut
962 sub DelBasketgroup {
963 my $basketgroupid = shift;
964 die "basketgroup id is required to edit a basketgroup" unless $basketgroupid;
965 my $query = "DELETE FROM aqbasketgroups WHERE id=?";
966 my $dbh = C4::Context->dbh;
967 my $sth = $dbh->prepare($query);
968 $sth->execute($basketgroupid);
969 return;
972 #------------------------------------------------------------#
975 =head2 FUNCTIONS ABOUT ORDERS
977 =head3 GetBasketgroup
979 $basketgroup = &GetBasketgroup($basketgroupid);
981 Returns a reference to the hash containing all information about the basketgroup.
983 =cut
985 sub GetBasketgroup {
986 my $basketgroupid = shift;
987 die "basketgroup id is required to edit a basketgroup" unless $basketgroupid;
988 my $dbh = C4::Context->dbh;
989 my $result_set = $dbh->selectall_arrayref(
990 'SELECT * FROM aqbasketgroups WHERE id=?',
991 { Slice => {} },
992 $basketgroupid
994 return $result_set->[0]; # id is unique
997 #------------------------------------------------------------#
999 =head3 GetBasketgroups
1001 $basketgroups = &GetBasketgroups($booksellerid);
1003 Returns a reference to the array of all the basketgroups of bookseller $booksellerid.
1005 =cut
1007 sub GetBasketgroups {
1008 my $booksellerid = shift;
1009 die 'bookseller id is required to edit a basketgroup' unless $booksellerid;
1010 my $query = 'SELECT * FROM aqbasketgroups WHERE booksellerid=? ORDER BY id DESC';
1011 my $dbh = C4::Context->dbh;
1012 my $sth = $dbh->prepare($query);
1013 $sth->execute($booksellerid);
1014 return $sth->fetchall_arrayref({});
1017 #------------------------------------------------------------#
1019 =head2 FUNCTIONS ABOUT ORDERS
1021 =head3 GetOrders
1023 @orders = &GetOrders( $basketno, { orderby => 'biblio.title', cancelled => 0|1 } );
1025 Looks up the pending (non-cancelled) orders with the given basket
1026 number.
1028 If cancelled is set, only cancelled orders will be returned.
1030 =cut
1032 sub GetOrders {
1033 my ( $basketno, $params ) = @_;
1035 return () unless $basketno;
1037 my $orderby = $params->{orderby};
1038 my $cancelled = $params->{cancelled} || 0;
1040 my $dbh = C4::Context->dbh;
1041 my $query = q|
1042 SELECT biblio.*,biblioitems.*,
1043 aqorders.*,
1044 aqbudgets.*,
1046 $query .= $cancelled
1047 ? q|
1048 aqorders_transfers.ordernumber_to AS transferred_to,
1049 aqorders_transfers.timestamp AS transferred_to_timestamp
1051 : q|
1052 aqorders_transfers.ordernumber_from AS transferred_from,
1053 aqorders_transfers.timestamp AS transferred_from_timestamp
1055 $query .= q|
1056 FROM aqorders
1057 LEFT JOIN aqbudgets ON aqbudgets.budget_id = aqorders.budget_id
1058 LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber
1059 LEFT JOIN biblioitems ON biblioitems.biblionumber =biblio.biblionumber
1061 $query .= $cancelled
1062 ? q|
1063 LEFT JOIN aqorders_transfers ON aqorders_transfers.ordernumber_from = aqorders.ordernumber
1065 : q|
1066 LEFT JOIN aqorders_transfers ON aqorders_transfers.ordernumber_to = aqorders.ordernumber
1069 $query .= q|
1070 WHERE basketno=?
1073 if ($cancelled) {
1074 $orderby ||= q|biblioitems.publishercode, biblio.title|;
1075 $query .= q|
1076 AND (datecancellationprinted IS NOT NULL
1077 AND datecancellationprinted <> '0000-00-00')
1080 else {
1081 $orderby ||=
1082 q|aqorders.datecancellationprinted desc, aqorders.timestamp desc|;
1083 $query .= q|
1084 AND (datecancellationprinted IS NULL OR datecancellationprinted='0000-00-00')
1088 $query .= " ORDER BY $orderby";
1089 my $orders =
1090 $dbh->selectall_arrayref( $query, { Slice => {} }, $basketno );
1091 return @{$orders};
1095 #------------------------------------------------------------#
1097 =head3 GetOrdersByBiblionumber
1099 @orders = &GetOrdersByBiblionumber($biblionumber);
1101 Looks up the orders with linked to a specific $biblionumber, including
1102 cancelled orders and received orders.
1104 return :
1105 C<@orders> is an array of references-to-hash, whose keys are the
1106 fields from the aqorders, biblio, and biblioitems tables in the Koha database.
1108 =cut
1110 sub GetOrdersByBiblionumber {
1111 my $biblionumber = shift;
1112 return unless $biblionumber;
1113 my $dbh = C4::Context->dbh;
1114 my $query ="
1115 SELECT biblio.*,biblioitems.*,
1116 aqorders.*,
1117 aqbudgets.*
1118 FROM aqorders
1119 LEFT JOIN aqbudgets ON aqbudgets.budget_id = aqorders.budget_id
1120 LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber
1121 LEFT JOIN biblioitems ON biblioitems.biblionumber =biblio.biblionumber
1122 WHERE aqorders.biblionumber=?
1124 my $result_set =
1125 $dbh->selectall_arrayref( $query, { Slice => {} }, $biblionumber );
1126 return @{$result_set};
1130 #------------------------------------------------------------#
1132 =head3 GetOrder
1134 $order = &GetOrder($ordernumber);
1136 Looks up an order by order number.
1138 Returns a reference-to-hash describing the order. The keys of
1139 C<$order> are fields from the biblio, biblioitems, aqorders tables of the Koha database.
1141 =cut
1143 sub GetOrder {
1144 my ($ordernumber) = @_;
1145 return unless $ordernumber;
1147 my $dbh = C4::Context->dbh;
1148 my $query = qq{SELECT
1149 aqorders.*,
1150 biblio.title,
1151 biblio.author,
1152 aqbasket.basketname,
1153 borrowers.branchcode,
1154 biblioitems.publicationyear,
1155 biblio.copyrightdate,
1156 biblioitems.editionstatement,
1157 biblioitems.isbn,
1158 biblioitems.ean,
1159 biblio.seriestitle,
1160 biblioitems.publishercode,
1161 aqorders.rrp AS unitpricesupplier,
1162 aqorders.ecost AS unitpricelib,
1163 aqorders.claims_count AS claims_count,
1164 aqorders.claimed_date AS claimed_date,
1165 aqbudgets.budget_name AS budget,
1166 aqbooksellers.name AS supplier,
1167 aqbooksellers.id AS supplierid,
1168 biblioitems.publishercode AS publisher,
1169 ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) AS estimateddeliverydate,
1170 DATE(aqbasket.closedate) AS orderdate,
1171 aqorders.quantity - COALESCE(aqorders.quantityreceived,0) AS quantity_to_receive,
1172 (aqorders.quantity - COALESCE(aqorders.quantityreceived,0)) * aqorders.rrp AS subtotal,
1173 DATEDIFF(CURDATE( ),closedate) AS latesince
1174 FROM aqorders LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber
1175 LEFT JOIN biblioitems ON biblioitems.biblionumber = biblio.biblionumber
1176 LEFT JOIN aqbudgets ON aqorders.budget_id = aqbudgets.budget_id,
1177 aqbasket LEFT JOIN borrowers ON aqbasket.authorisedby = borrowers.borrowernumber
1178 LEFT JOIN aqbooksellers ON aqbasket.booksellerid = aqbooksellers.id
1179 WHERE aqorders.basketno = aqbasket.basketno
1180 AND ordernumber=?};
1181 my $result_set =
1182 $dbh->selectall_arrayref( $query, { Slice => {} }, $ordernumber );
1184 # result_set assumed to contain 1 match
1185 return $result_set->[0];
1188 =head3 GetLastOrderNotReceivedFromSubscriptionid
1190 $order = &GetLastOrderNotReceivedFromSubscriptionid($subscriptionid);
1192 Returns a reference-to-hash describing the last order not received for a subscription.
1194 =cut
1196 sub GetLastOrderNotReceivedFromSubscriptionid {
1197 my ( $subscriptionid ) = @_;
1198 my $dbh = C4::Context->dbh;
1199 my $query = qq|
1200 SELECT * FROM aqorders
1201 LEFT JOIN subscription
1202 ON ( aqorders.subscriptionid = subscription.subscriptionid )
1203 WHERE aqorders.subscriptionid = ?
1204 AND aqorders.datereceived IS NULL
1205 LIMIT 1
1207 my $result_set =
1208 $dbh->selectall_arrayref( $query, { Slice => {} }, $subscriptionid );
1210 # result_set assumed to contain 1 match
1211 return $result_set->[0];
1214 =head3 GetLastOrderReceivedFromSubscriptionid
1216 $order = &GetLastOrderReceivedFromSubscriptionid($subscriptionid);
1218 Returns a reference-to-hash describing the last order received for a subscription.
1220 =cut
1222 sub GetLastOrderReceivedFromSubscriptionid {
1223 my ( $subscriptionid ) = @_;
1224 my $dbh = C4::Context->dbh;
1225 my $query = qq|
1226 SELECT * FROM aqorders
1227 LEFT JOIN subscription
1228 ON ( aqorders.subscriptionid = subscription.subscriptionid )
1229 WHERE aqorders.subscriptionid = ?
1230 AND aqorders.datereceived =
1232 SELECT MAX( aqorders.datereceived )
1233 FROM aqorders
1234 LEFT JOIN subscription
1235 ON ( aqorders.subscriptionid = subscription.subscriptionid )
1236 WHERE aqorders.subscriptionid = ?
1237 AND aqorders.datereceived IS NOT NULL
1239 ORDER BY ordernumber DESC
1240 LIMIT 1
1242 my $result_set =
1243 $dbh->selectall_arrayref( $query, { Slice => {} }, $subscriptionid, $subscriptionid );
1245 # result_set assumed to contain 1 match
1246 return $result_set->[0];
1250 #------------------------------------------------------------#
1252 =head3 ModOrder
1254 &ModOrder(\%hashref);
1256 Modifies an existing order. Updates the order with order number
1257 $hashref->{'ordernumber'} and biblionumber $hashref->{'biblionumber'}. All
1258 other keys of the hash update the fields with the same name in the aqorders
1259 table of the Koha database.
1261 =cut
1263 sub ModOrder {
1264 my $orderinfo = shift;
1266 die "Ordernumber is required" if $orderinfo->{'ordernumber'} eq '' ;
1267 die "Biblionumber is required" if $orderinfo->{'biblionumber'} eq '';
1269 my $dbh = C4::Context->dbh;
1270 my @params;
1272 # update uncertainprice to an integer, just in case (under FF, checked boxes have the value "ON" by default)
1273 $orderinfo->{uncertainprice}=1 if $orderinfo->{uncertainprice};
1275 # delete($orderinfo->{'branchcode'});
1276 # the hash contains a lot of entries not in aqorders, so get the columns ...
1277 my $sth = $dbh->prepare("SELECT * FROM aqorders LIMIT 1;");
1278 $sth->execute;
1279 my $colnames = $sth->{NAME};
1280 #FIXME Be careful. If aqorders would have columns with diacritics,
1281 #you should need to decode what you get back from NAME.
1282 #See report 10110 and guided_reports.pl
1283 my $query = "UPDATE aqorders SET ";
1285 foreach my $orderinfokey (grep(!/ordernumber/, keys %$orderinfo)){
1286 # ... and skip hash entries that are not in the aqorders table
1287 # FIXME : probably not the best way to do it (would be better to have a correct hash)
1288 next unless grep(/^$orderinfokey$/, @$colnames);
1289 $query .= "$orderinfokey=?, ";
1290 push(@params, $orderinfo->{$orderinfokey});
1293 $query .= "timestamp=NOW() WHERE ordernumber=?";
1294 push(@params, $orderinfo->{'ordernumber'} );
1295 $sth = $dbh->prepare($query);
1296 $sth->execute(@params);
1297 return;
1300 #------------------------------------------------------------#
1302 =head3 ModItemOrder
1304 ModItemOrder($itemnumber, $ordernumber);
1306 Modifies the ordernumber of an item in aqorders_items.
1308 =cut
1310 sub ModItemOrder {
1311 my ($itemnumber, $ordernumber) = @_;
1313 return unless ($itemnumber and $ordernumber);
1315 my $dbh = C4::Context->dbh;
1316 my $query = qq{
1317 UPDATE aqorders_items
1318 SET ordernumber = ?
1319 WHERE itemnumber = ?
1321 my $sth = $dbh->prepare($query);
1322 return $sth->execute($ordernumber, $itemnumber);
1325 #------------------------------------------------------------#
1327 =head3 ModReceiveOrder
1329 &ModReceiveOrder({
1330 biblionumber => $biblionumber,
1331 ordernumber => $ordernumber,
1332 quantityreceived => $quantityreceived,
1333 user => $user,
1334 cost => $cost,
1335 ecost => $ecost,
1336 invoiceid => $invoiceid,
1337 rrp => $rrp,
1338 budget_id => $budget_id,
1339 datereceived => $datereceived,
1340 received_itemnumbers => \@received_itemnumbers,
1341 order_internalnote => $order_internalnote,
1342 order_vendornote => $order_vendornote,
1345 Updates an order, to reflect the fact that it was received, at least
1346 in part. All arguments not mentioned below update the fields with the
1347 same name in the aqorders table of the Koha database.
1349 If a partial order is received, splits the order into two.
1351 Updates the order with bibilionumber C<$biblionumber> and ordernumber
1352 C<$ordernumber>.
1354 =cut
1357 sub ModReceiveOrder {
1358 my ( $params ) = @_;
1359 my $biblionumber = $params->{biblionumber};
1360 my $ordernumber = $params->{ordernumber};
1361 my $quantrec = $params->{quantityreceived};
1362 my $user = $params->{user};
1363 my $cost = $params->{cost};
1364 my $ecost = $params->{ecost};
1365 my $invoiceid = $params->{invoiceid};
1366 my $rrp = $params->{rrp};
1367 my $budget_id = $params->{budget_id};
1368 my $datereceived = $params->{datereceived};
1369 my $received_items = $params->{received_items};
1370 my $order_internalnote = $params->{order_internalnote};
1371 my $order_vendornote = $params->{order_vendornote};
1373 my $dbh = C4::Context->dbh;
1374 $datereceived = output_pref(
1376 dt => ( $datereceived ? dt_from_string( $datereceived ) : dt_from_string ),
1377 dateformat => 'iso',
1378 dateonly => 1,
1381 my $suggestionid = GetSuggestionFromBiblionumber( $biblionumber );
1382 if ($suggestionid) {
1383 ModSuggestion( {suggestionid=>$suggestionid,
1384 STATUS=>'AVAILABLE',
1385 biblionumber=> $biblionumber}
1389 my $result_set = $dbh->selectall_arrayref(
1390 q{SELECT * FROM aqorders WHERE biblionumber=? AND aqorders.ordernumber=?},
1391 { Slice => {} }, $biblionumber, $ordernumber
1394 # we assume we have a unique order
1395 my $order = $result_set->[0];
1397 my $new_ordernumber = $ordernumber;
1398 if ( $order->{quantity} > $quantrec ) {
1399 # Split order line in two parts: the first is the original order line
1400 # without received items (the quantity is decreased),
1401 # the second part is a new order line with quantity=quantityrec
1402 # (entirely received)
1403 my $query = q|
1404 UPDATE aqorders
1405 SET quantity = ?,
1406 orderstatus = 'partial'|;
1407 $query .= q|, order_internalnote = ?| if defined $order_internalnote;
1408 $query .= q|, order_vendornote = ?| if defined $order_vendornote;
1409 $query .= q| WHERE ordernumber = ?|;
1410 my $sth = $dbh->prepare($query);
1412 $sth->execute(
1413 $order->{quantity} - $quantrec,
1414 ( defined $order_internalnote ? $order_internalnote : () ),
1415 ( defined $order_vendornote ? $order_vendornote : () ),
1416 $ordernumber
1419 delete $order->{'ordernumber'};
1420 $order->{'budget_id'} = ( $budget_id || $order->{'budget_id'} );
1421 $order->{'quantity'} = $quantrec;
1422 $order->{'quantityreceived'} = $quantrec;
1423 $order->{'datereceived'} = $datereceived;
1424 $order->{'invoiceid'} = $invoiceid;
1425 $order->{'unitprice'} = $cost;
1426 $order->{'rrp'} = $rrp;
1427 $order->{ecost} = $ecost;
1428 $order->{'orderstatus'} = 'complete';
1429 $new_ordernumber = Koha::Acquisition::Order->new($order)->insert->{ordernumber};
1431 if ($received_items) {
1432 foreach my $itemnumber (@$received_items) {
1433 ModItemOrder($itemnumber, $new_ordernumber);
1436 } else {
1437 my $query = q|
1438 update aqorders
1439 set quantityreceived=?,datereceived=?,invoiceid=?,
1440 unitprice=?,rrp=?,ecost=?,budget_id=?,orderstatus='complete'|;
1441 $query .= q|, order_internalnote = ?| if defined $order_internalnote;
1442 $query .= q|, order_vendornote = ?| if defined $order_vendornote;
1443 $query .= q| where biblionumber=? and ordernumber=?|;
1444 my $sth = $dbh->prepare( $query );
1445 $sth->execute(
1446 $quantrec,
1447 $datereceived,
1448 $invoiceid,
1449 $cost,
1450 $rrp,
1451 $ecost,
1452 ( $budget_id ? $budget_id : $order->{budget_id} ),
1453 ( defined $order_internalnote ? $order_internalnote : () ),
1454 ( defined $order_vendornote ? $order_vendornote : () ),
1455 $biblionumber,
1456 $ordernumber
1459 # All items have been received, sent a notification to users
1460 NotifyOrderUsers( $ordernumber );
1463 return ($datereceived, $new_ordernumber);
1466 =head3 CancelReceipt
1468 my $parent_ordernumber = CancelReceipt($ordernumber);
1470 Cancel an order line receipt and update the parent order line, as if no
1471 receipt was made.
1472 If items are created at receipt (AcqCreateItem = receiving) then delete
1473 these items.
1475 =cut
1477 sub CancelReceipt {
1478 my $ordernumber = shift;
1480 return unless $ordernumber;
1482 my $dbh = C4::Context->dbh;
1483 my $query = qq{
1484 SELECT datereceived, parent_ordernumber, quantity
1485 FROM aqorders
1486 WHERE ordernumber = ?
1488 my $sth = $dbh->prepare($query);
1489 $sth->execute($ordernumber);
1490 my $order = $sth->fetchrow_hashref;
1491 unless($order) {
1492 warn "CancelReceipt: order $ordernumber does not exist";
1493 return;
1495 unless($order->{'datereceived'}) {
1496 warn "CancelReceipt: order $ordernumber is not received";
1497 return;
1500 my $parent_ordernumber = $order->{'parent_ordernumber'};
1502 my @itemnumbers = GetItemnumbersFromOrder( $ordernumber );
1504 if($parent_ordernumber == $ordernumber || not $parent_ordernumber) {
1505 # The order line has no parent, just mark it as not received
1506 $query = qq{
1507 UPDATE aqorders
1508 SET quantityreceived = ?,
1509 datereceived = ?,
1510 invoiceid = ?,
1511 orderstatus = 'ordered'
1512 WHERE ordernumber = ?
1514 $sth = $dbh->prepare($query);
1515 $sth->execute(0, undef, undef, $ordernumber);
1516 _cancel_items_receipt( $ordernumber );
1517 } else {
1518 # The order line has a parent, increase parent quantity and delete
1519 # the order line.
1520 $query = qq{
1521 SELECT quantity, datereceived
1522 FROM aqorders
1523 WHERE ordernumber = ?
1525 $sth = $dbh->prepare($query);
1526 $sth->execute($parent_ordernumber);
1527 my $parent_order = $sth->fetchrow_hashref;
1528 unless($parent_order) {
1529 warn "Parent order $parent_ordernumber does not exist.";
1530 return;
1532 if($parent_order->{'datereceived'}) {
1533 warn "CancelReceipt: parent order is received.".
1534 " Can't cancel receipt.";
1535 return;
1537 $query = qq{
1538 UPDATE aqorders
1539 SET quantity = ?,
1540 orderstatus = 'ordered'
1541 WHERE ordernumber = ?
1543 $sth = $dbh->prepare($query);
1544 my $rv = $sth->execute(
1545 $order->{'quantity'} + $parent_order->{'quantity'},
1546 $parent_ordernumber
1548 unless($rv) {
1549 warn "Cannot update parent order line, so do not cancel".
1550 " receipt";
1551 return;
1553 _cancel_items_receipt( $ordernumber, $parent_ordernumber );
1554 # Delete order line
1555 $query = qq{
1556 DELETE FROM aqorders
1557 WHERE ordernumber = ?
1559 $sth = $dbh->prepare($query);
1560 $sth->execute($ordernumber);
1564 if(C4::Context->preference('AcqCreateItem') eq 'ordering') {
1565 my @affects = split q{\|}, C4::Context->preference("AcqItemSetSubfieldsWhenReceiptIsCancelled");
1566 if ( @affects ) {
1567 for my $in ( @itemnumbers ) {
1568 my $biblionumber = C4::Biblio::GetBiblionumberFromItemnumber( $in );
1569 my $frameworkcode = GetFrameworkCode($biblionumber);
1570 my ( $itemfield ) = GetMarcFromKohaField( 'items.itemnumber', $frameworkcode );
1571 my $item = C4::Items::GetMarcItem( $biblionumber, $in );
1572 for my $affect ( @affects ) {
1573 my ( $sf, $v ) = split q{=}, $affect, 2;
1574 foreach ( $item->field($itemfield) ) {
1575 $_->update( $sf => $v );
1578 C4::Items::ModItemFromMarc( $item, $biblionumber, $in );
1583 return $parent_ordernumber;
1586 sub _cancel_items_receipt {
1587 my ( $ordernumber, $parent_ordernumber ) = @_;
1588 $parent_ordernumber ||= $ordernumber;
1590 my @itemnumbers = GetItemnumbersFromOrder($ordernumber);
1591 if(C4::Context->preference('AcqCreateItem') eq 'receiving') {
1592 # Remove items that were created at receipt
1593 my $query = qq{
1594 DELETE FROM items, aqorders_items
1595 USING items, aqorders_items
1596 WHERE items.itemnumber = ? AND aqorders_items.itemnumber = ?
1598 my $dbh = C4::Context->dbh;
1599 my $sth = $dbh->prepare($query);
1600 foreach my $itemnumber (@itemnumbers) {
1601 $sth->execute($itemnumber, $itemnumber);
1603 } else {
1604 # Update items
1605 foreach my $itemnumber (@itemnumbers) {
1606 ModItemOrder($itemnumber, $parent_ordernumber);
1611 #------------------------------------------------------------#
1613 =head3 SearchOrders
1615 @results = &SearchOrders({
1616 ordernumber => $ordernumber,
1617 search => $search,
1618 biblionumber => $biblionumber,
1619 ean => $ean,
1620 booksellerid => $booksellerid,
1621 basketno => $basketno,
1622 owner => $owner,
1623 pending => $pending
1624 ordered => $ordered
1627 Searches for orders.
1629 C<$owner> Finds order for the logged in user.
1630 C<$pending> Finds pending orders. Ignores completed and cancelled orders.
1631 C<$ordered> Finds orders to receive only (status 'ordered' or 'partial').
1634 C<@results> is an array of references-to-hash with the keys are fields
1635 from aqorders, biblio, biblioitems and aqbasket tables.
1637 =cut
1639 sub SearchOrders {
1640 my ( $params ) = @_;
1641 my $ordernumber = $params->{ordernumber};
1642 my $search = $params->{search};
1643 my $ean = $params->{ean};
1644 my $booksellerid = $params->{booksellerid};
1645 my $basketno = $params->{basketno};
1646 my $basketname = $params->{basketname};
1647 my $basketgroupname = $params->{basketgroupname};
1648 my $owner = $params->{owner};
1649 my $pending = $params->{pending};
1650 my $ordered = $params->{ordered};
1651 my $biblionumber = $params->{biblionumber};
1652 my $budget_id = $params->{budget_id};
1654 my $dbh = C4::Context->dbh;
1655 my @args = ();
1656 my $query = q{
1657 SELECT aqbasket.basketno,
1658 borrowers.surname,
1659 borrowers.firstname,
1660 biblio.*,
1661 biblioitems.isbn,
1662 biblioitems.biblioitemnumber,
1663 aqbasket.authorisedby,
1664 aqbasket.booksellerid,
1665 aqbasket.closedate,
1666 aqbasket.creationdate,
1667 aqbasket.basketname,
1668 aqbasketgroups.id as basketgroupid,
1669 aqbasketgroups.name as basketgroupname,
1670 aqorders.*
1671 FROM aqorders
1672 LEFT JOIN aqbasket ON aqorders.basketno = aqbasket.basketno
1673 LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid = aqbasketgroups.id
1674 LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber
1675 LEFT JOIN biblio ON aqorders.biblionumber=biblio.biblionumber
1676 LEFT JOIN biblioitems ON biblioitems.biblionumber=biblio.biblionumber
1679 # If we search on ordernumber, we retrieve the transferred order if a transfer has been done.
1680 $query .= q{
1681 LEFT JOIN aqorders_transfers ON aqorders_transfers.ordernumber_to = aqorders.ordernumber
1682 } if $ordernumber;
1684 $query .= q{
1685 WHERE (datecancellationprinted is NULL)
1688 if ( $pending or $ordered ) {
1689 $query .= q{ AND (quantity > quantityreceived OR quantityreceived is NULL)};
1691 if ( $ordered ) {
1692 $query .= q{ AND aqorders.orderstatus IN ( "ordered", "partial" )};
1695 my $userenv = C4::Context->userenv;
1696 if ( C4::Context->preference("IndependentBranches") ) {
1697 unless ( C4::Context->IsSuperLibrarian() ) {
1698 $query .= q{
1699 AND (
1700 borrowers.branchcode = ?
1701 OR borrowers.branchcode = ''
1704 push @args, $userenv->{branch};
1708 if ( $ordernumber ) {
1709 $query .= ' AND ( aqorders.ordernumber = ? OR aqorders_transfers.ordernumber_from = ? ) ';
1710 push @args, ( $ordernumber, $ordernumber );
1712 if ( $biblionumber ) {
1713 $query .= 'AND aqorders.biblionumber = ?';
1714 push @args, $biblionumber;
1716 if( $search ) {
1717 $query .= ' AND (biblio.title LIKE ? OR biblio.author LIKE ? OR biblioitems.isbn LIKE ?)';
1718 push @args, ("%$search%","%$search%","%$search%");
1720 if ( $ean ) {
1721 $query .= ' AND biblioitems.ean = ?';
1722 push @args, $ean;
1724 if ( $booksellerid ) {
1725 $query .= 'AND aqbasket.booksellerid = ?';
1726 push @args, $booksellerid;
1728 if( $basketno ) {
1729 $query .= 'AND aqbasket.basketno = ?';
1730 push @args, $basketno;
1732 if( $basketname ) {
1733 $query .= 'AND aqbasket.basketname LIKE ?';
1734 push @args, "%$basketname%";
1736 if( $basketgroupname ) {
1737 $query .= ' AND aqbasketgroups.name LIKE ?';
1738 push @args, "%$basketgroupname%";
1741 if ( $owner ) {
1742 $query .= ' AND aqbasket.authorisedby=? ';
1743 push @args, $userenv->{'number'};
1746 if ( $budget_id ) {
1747 $query .= ' AND aqorders.budget_id = ?';
1748 push @args, $budget_id;
1751 $query .= ' ORDER BY aqbasket.basketno';
1753 my $sth = $dbh->prepare($query);
1754 $sth->execute(@args);
1755 return $sth->fetchall_arrayref({});
1758 #------------------------------------------------------------#
1760 =head3 DelOrder
1762 &DelOrder($biblionumber, $ordernumber);
1764 Cancel the order with the given order and biblio numbers. It does not
1765 delete any entries in the aqorders table, it merely marks them as
1766 cancelled.
1768 =cut
1770 sub DelOrder {
1771 my ( $bibnum, $ordernumber, $delete_biblio, $reason ) = @_;
1773 my $error;
1774 my $dbh = C4::Context->dbh;
1775 my $query = "
1776 UPDATE aqorders
1777 SET datecancellationprinted=now(), orderstatus='cancelled'
1779 if($reason) {
1780 $query .= ", cancellationreason = ? ";
1782 $query .= "
1783 WHERE biblionumber=? AND ordernumber=?
1785 my $sth = $dbh->prepare($query);
1786 if($reason) {
1787 $sth->execute($reason, $bibnum, $ordernumber);
1788 } else {
1789 $sth->execute( $bibnum, $ordernumber );
1791 $sth->finish;
1793 my @itemnumbers = GetItemnumbersFromOrder( $ordernumber );
1794 foreach my $itemnumber (@itemnumbers){
1795 my $delcheck = C4::Items::DelItemCheck( $dbh, $bibnum, $itemnumber );
1797 if($delcheck != 1) {
1798 $error->{'delitem'} = 1;
1802 if($delete_biblio) {
1803 # We get the number of remaining items
1804 my $itemcount = C4::Items::GetItemsCount($bibnum);
1806 # If there are no items left,
1807 if ( $itemcount == 0 ) {
1808 # We delete the record
1809 my $delcheck = DelBiblio($bibnum);
1811 if($delcheck) {
1812 $error->{'delbiblio'} = 1;
1817 return $error;
1820 =head3 TransferOrder
1822 my $newordernumber = TransferOrder($ordernumber, $basketno);
1824 Transfer an order line to a basket.
1825 Mark $ordernumber as cancelled with an internal note 'Cancelled and transferred
1826 to BOOKSELLER on DATE' and create new order with internal note
1827 'Transferred from BOOKSELLER on DATE'.
1828 Move all attached items to the new order.
1829 Received orders cannot be transferred.
1830 Return the ordernumber of created order.
1832 =cut
1834 sub TransferOrder {
1835 my ($ordernumber, $basketno) = @_;
1837 return unless ($ordernumber and $basketno);
1839 my $order = GetOrder( $ordernumber );
1840 return if $order->{datereceived};
1841 my $basket = GetBasket($basketno);
1842 return unless $basket;
1844 my $dbh = C4::Context->dbh;
1845 my ($query, $sth, $rv);
1847 $query = q{
1848 UPDATE aqorders
1849 SET datecancellationprinted = CAST(NOW() AS date), orderstatus = ?
1850 WHERE ordernumber = ?
1852 $sth = $dbh->prepare($query);
1853 $rv = $sth->execute('cancelled', $ordernumber);
1855 delete $order->{'ordernumber'};
1856 delete $order->{parent_ordernumber};
1857 $order->{'basketno'} = $basketno;
1859 my $newordernumber = Koha::Acquisition::Order->new($order)->insert->{ordernumber};
1861 $query = q{
1862 UPDATE aqorders_items
1863 SET ordernumber = ?
1864 WHERE ordernumber = ?
1866 $sth = $dbh->prepare($query);
1867 $sth->execute($newordernumber, $ordernumber);
1869 $query = q{
1870 INSERT INTO aqorders_transfers (ordernumber_from, ordernumber_to)
1871 VALUES (?, ?)
1873 $sth = $dbh->prepare($query);
1874 $sth->execute($ordernumber, $newordernumber);
1876 return $newordernumber;
1879 =head2 FUNCTIONS ABOUT PARCELS
1881 =head3 GetParcels
1883 $results = &GetParcels($bookseller, $order, $code, $datefrom, $dateto);
1885 get a lists of parcels.
1887 * Input arg :
1889 =over
1891 =item $bookseller
1892 is the bookseller this function has to get parcels.
1894 =item $order
1895 To know on what criteria the results list has to be ordered.
1897 =item $code
1898 is the booksellerinvoicenumber.
1900 =item $datefrom & $dateto
1901 to know on what date this function has to filter its search.
1903 =back
1905 * return:
1906 a pointer on a hash list containing parcel informations as such :
1908 =over
1910 =item Creation date
1912 =item Last operation
1914 =item Number of biblio
1916 =item Number of items
1918 =back
1920 =cut
1922 sub GetParcels {
1923 my ($bookseller,$order, $code, $datefrom, $dateto) = @_;
1924 my $dbh = C4::Context->dbh;
1925 my @query_params = ();
1926 my $strsth ="
1927 SELECT aqinvoices.invoicenumber,
1928 datereceived,purchaseordernumber,
1929 count(DISTINCT biblionumber) AS biblio,
1930 sum(quantity) AS itemsexpected,
1931 sum(quantityreceived) AS itemsreceived
1932 FROM aqorders LEFT JOIN aqbasket ON aqbasket.basketno = aqorders.basketno
1933 LEFT JOIN aqinvoices ON aqorders.invoiceid = aqinvoices.invoiceid
1934 WHERE aqbasket.booksellerid = ? and datereceived IS NOT NULL
1936 push @query_params, $bookseller;
1938 if ( defined $code ) {
1939 $strsth .= ' and aqinvoices.invoicenumber like ? ';
1940 # add a % to the end of the code to allow stemming.
1941 push @query_params, "$code%";
1944 if ( defined $datefrom ) {
1945 $strsth .= ' and datereceived >= ? ';
1946 push @query_params, $datefrom;
1949 if ( defined $dateto ) {
1950 $strsth .= 'and datereceived <= ? ';
1951 push @query_params, $dateto;
1954 $strsth .= "group by aqinvoices.invoicenumber,datereceived ";
1956 # can't use a placeholder to place this column name.
1957 # but, we could probably be checking to make sure it is a column that will be fetched.
1958 $strsth .= "order by $order " if ($order);
1960 my $sth = $dbh->prepare($strsth);
1962 $sth->execute( @query_params );
1963 my $results = $sth->fetchall_arrayref({});
1964 return @{$results};
1967 #------------------------------------------------------------#
1969 =head3 GetLateOrders
1971 @results = &GetLateOrders;
1973 Searches for bookseller with late orders.
1975 return:
1976 the table of supplier with late issues. This table is full of hashref.
1978 =cut
1980 sub GetLateOrders {
1981 my $delay = shift;
1982 my $supplierid = shift;
1983 my $branch = shift;
1984 my $estimateddeliverydatefrom = shift;
1985 my $estimateddeliverydateto = shift;
1987 my $dbh = C4::Context->dbh;
1989 #BEWARE, order of parenthesis and LEFT JOIN is important for speed
1990 my $dbdriver = C4::Context->config("db_scheme") || "mysql";
1992 my @query_params = ();
1993 my $select = "
1994 SELECT aqbasket.basketno,
1995 aqorders.ordernumber,
1996 DATE(aqbasket.closedate) AS orderdate,
1997 aqbasket.basketname AS basketname,
1998 aqbasket.basketgroupid AS basketgroupid,
1999 aqbasketgroups.name AS basketgroupname,
2000 aqorders.rrp AS unitpricesupplier,
2001 aqorders.ecost AS unitpricelib,
2002 aqorders.claims_count AS claims_count,
2003 aqorders.claimed_date AS claimed_date,
2004 aqbudgets.budget_name AS budget,
2005 borrowers.branchcode AS branch,
2006 aqbooksellers.name AS supplier,
2007 aqbooksellers.id AS supplierid,
2008 biblio.author, biblio.title,
2009 biblioitems.publishercode AS publisher,
2010 biblioitems.publicationyear,
2011 ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) AS estimateddeliverydate,
2013 my $from = "
2014 FROM
2015 aqorders LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber
2016 LEFT JOIN biblioitems ON biblioitems.biblionumber = biblio.biblionumber
2017 LEFT JOIN aqbudgets ON aqorders.budget_id = aqbudgets.budget_id,
2018 aqbasket LEFT JOIN borrowers ON aqbasket.authorisedby = borrowers.borrowernumber
2019 LEFT JOIN aqbooksellers ON aqbasket.booksellerid = aqbooksellers.id
2020 LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid = aqbasketgroups.id
2021 WHERE aqorders.basketno = aqbasket.basketno
2022 AND ( datereceived = ''
2023 OR datereceived IS NULL
2024 OR aqorders.quantityreceived < aqorders.quantity
2026 AND aqbasket.closedate IS NOT NULL
2027 AND (aqorders.datecancellationprinted IS NULL OR aqorders.datecancellationprinted='0000-00-00')
2029 my $having = "";
2030 if ($dbdriver eq "mysql") {
2031 $select .= "
2032 aqorders.quantity - COALESCE(aqorders.quantityreceived,0) AS quantity,
2033 (aqorders.quantity - COALESCE(aqorders.quantityreceived,0)) * aqorders.rrp AS subtotal,
2034 DATEDIFF(CAST(now() AS date),closedate) AS latesince
2036 if ( defined $delay ) {
2037 $from .= " AND (closedate <= DATE_SUB(CAST(now() AS date),INTERVAL ? DAY)) " ;
2038 push @query_params, $delay;
2040 $having = "
2041 HAVING quantity <> 0
2042 AND unitpricesupplier <> 0
2043 AND unitpricelib <> 0
2045 } else {
2046 # FIXME: account for IFNULL as above
2047 $select .= "
2048 aqorders.quantity AS quantity,
2049 aqorders.quantity * aqorders.rrp AS subtotal,
2050 (CAST(now() AS date) - closedate) AS latesince
2052 if ( defined $delay ) {
2053 $from .= " AND (closedate <= (CAST(now() AS date) -(INTERVAL ? DAY)) ";
2054 push @query_params, $delay;
2057 if (defined $supplierid) {
2058 $from .= ' AND aqbasket.booksellerid = ? ';
2059 push @query_params, $supplierid;
2061 if (defined $branch) {
2062 $from .= ' AND borrowers.branchcode LIKE ? ';
2063 push @query_params, $branch;
2066 if ( defined $estimateddeliverydatefrom or defined $estimateddeliverydateto ) {
2067 $from .= ' AND aqbooksellers.deliverytime IS NOT NULL ';
2069 if ( defined $estimateddeliverydatefrom ) {
2070 $from .= ' AND ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) >= ?';
2071 push @query_params, $estimateddeliverydatefrom;
2073 if ( defined $estimateddeliverydateto ) {
2074 $from .= ' AND ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) <= ?';
2075 push @query_params, $estimateddeliverydateto;
2077 if ( defined $estimateddeliverydatefrom and not defined $estimateddeliverydateto ) {
2078 $from .= ' AND ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) <= CAST(now() AS date)';
2080 if (C4::Context->preference("IndependentBranches")
2081 && !C4::Context->IsSuperLibrarian() ) {
2082 $from .= ' AND borrowers.branchcode LIKE ? ';
2083 push @query_params, C4::Context->userenv->{branch};
2085 $from .= " AND orderstatus <> 'cancelled' ";
2086 my $query = "$select $from $having\nORDER BY latesince, basketno, borrowers.branchcode, supplier";
2087 $debug and print STDERR "GetLateOrders query: $query\nGetLateOrders args: " . join(" ",@query_params);
2088 my $sth = $dbh->prepare($query);
2089 $sth->execute(@query_params);
2090 my @results;
2091 while (my $data = $sth->fetchrow_hashref) {
2092 push @results, $data;
2094 return @results;
2097 #------------------------------------------------------------#
2099 =head3 GetHistory
2101 \@order_loop = GetHistory( %params );
2103 Retreives some acquisition history information
2105 params:
2106 title
2107 author
2108 name
2109 isbn
2111 from_placed_on
2112 to_placed_on
2113 basket - search both basket name and number
2114 booksellerinvoicenumber
2115 basketgroupname
2116 budget
2117 orderstatus (note that orderstatus '' will retrieve orders
2118 of any status except cancelled)
2119 biblionumber
2120 get_canceled_order (if set to a true value, cancelled orders will
2121 be included)
2123 returns:
2124 $order_loop is a list of hashrefs that each look like this:
2126 'author' => 'Twain, Mark',
2127 'basketno' => '1',
2128 'biblionumber' => '215',
2129 'count' => 1,
2130 'creationdate' => 'MM/DD/YYYY',
2131 'datereceived' => undef,
2132 'ecost' => '1.00',
2133 'id' => '1',
2134 'invoicenumber' => undef,
2135 'name' => '',
2136 'ordernumber' => '1',
2137 'quantity' => 1,
2138 'quantityreceived' => undef,
2139 'title' => 'The Adventures of Huckleberry Finn'
2142 =cut
2144 sub GetHistory {
2145 # don't run the query if there are no parameters (list would be too long for sure !)
2146 croak "No search params" unless @_;
2147 my %params = @_;
2148 my $title = $params{title};
2149 my $author = $params{author};
2150 my $isbn = $params{isbn};
2151 my $ean = $params{ean};
2152 my $name = $params{name};
2153 my $from_placed_on = $params{from_placed_on};
2154 my $to_placed_on = $params{to_placed_on};
2155 my $basket = $params{basket};
2156 my $booksellerinvoicenumber = $params{booksellerinvoicenumber};
2157 my $basketgroupname = $params{basketgroupname};
2158 my $budget = $params{budget};
2159 my $orderstatus = $params{orderstatus};
2160 my $biblionumber = $params{biblionumber};
2161 my $get_canceled_order = $params{get_canceled_order} || 0;
2162 my $ordernumber = $params{ordernumber};
2163 my $search_children_too = $params{search_children_too} || 0;
2164 my $created_by = $params{created_by} || [];
2166 my @order_loop;
2167 my $total_qty = 0;
2168 my $total_qtyreceived = 0;
2169 my $total_price = 0;
2171 my $dbh = C4::Context->dbh;
2172 my $query ="
2173 SELECT
2174 COALESCE(biblio.title, deletedbiblio.title) AS title,
2175 COALESCE(biblio.author, deletedbiblio.author) AS author,
2176 COALESCE(biblioitems.isbn, deletedbiblioitems.isbn) AS isbn,
2177 COALESCE(biblioitems.ean, deletedbiblioitems.ean) AS ean,
2178 aqorders.basketno,
2179 aqbasket.basketname,
2180 aqbasket.basketgroupid,
2181 aqbasket.authorisedby,
2182 concat( borrowers.firstname,' ',borrowers.surname) AS authorisedbyname,
2183 aqbasketgroups.name as groupname,
2184 aqbooksellers.name,
2185 aqbasket.creationdate,
2186 aqorders.datereceived,
2187 aqorders.quantity,
2188 aqorders.quantityreceived,
2189 aqorders.ecost,
2190 aqorders.ordernumber,
2191 aqorders.invoiceid,
2192 aqinvoices.invoicenumber,
2193 aqbooksellers.id as id,
2194 aqorders.biblionumber,
2195 aqorders.orderstatus,
2196 aqorders.parent_ordernumber,
2197 aqbudgets.budget_name
2199 $query .= ", aqbudgets.budget_id AS budget" if defined $budget;
2200 $query .= "
2201 FROM aqorders
2202 LEFT JOIN aqbasket ON aqorders.basketno=aqbasket.basketno
2203 LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid=aqbasketgroups.id
2204 LEFT JOIN aqbooksellers ON aqbasket.booksellerid=aqbooksellers.id
2205 LEFT JOIN biblioitems ON biblioitems.biblionumber=aqorders.biblionumber
2206 LEFT JOIN biblio ON biblio.biblionumber=aqorders.biblionumber
2207 LEFT JOIN aqbudgets ON aqorders.budget_id=aqbudgets.budget_id
2208 LEFT JOIN aqinvoices ON aqorders.invoiceid = aqinvoices.invoiceid
2209 LEFT JOIN deletedbiblio ON deletedbiblio.biblionumber=aqorders.biblionumber
2210 LEFT JOIN deletedbiblioitems ON deletedbiblioitems.biblionumber=aqorders.biblionumber
2211 LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber
2214 $query .= " WHERE 1 ";
2216 unless ($get_canceled_order or (defined $orderstatus and $orderstatus eq 'cancelled')) {
2217 $query .= " AND (datecancellationprinted is NULL or datecancellationprinted='0000-00-00') ";
2220 my @query_params = ();
2222 if ( $biblionumber ) {
2223 $query .= " AND biblio.biblionumber = ?";
2224 push @query_params, $biblionumber;
2227 if ( $title ) {
2228 $query .= " AND biblio.title LIKE ? ";
2229 $title =~ s/\s+/%/g;
2230 push @query_params, "%$title%";
2233 if ( $author ) {
2234 $query .= " AND biblio.author LIKE ? ";
2235 push @query_params, "%$author%";
2238 if ( $isbn ) {
2239 $query .= " AND biblioitems.isbn LIKE ? ";
2240 push @query_params, "%$isbn%";
2242 if ( $ean ) {
2243 $query .= " AND biblioitems.ean = ? ";
2244 push @query_params, "$ean";
2246 if ( $name ) {
2247 $query .= " AND aqbooksellers.name LIKE ? ";
2248 push @query_params, "%$name%";
2251 if ( $budget ) {
2252 $query .= " AND aqbudgets.budget_id = ? ";
2253 push @query_params, "$budget";
2256 if ( $from_placed_on ) {
2257 $query .= " AND creationdate >= ? ";
2258 push @query_params, $from_placed_on;
2261 if ( $to_placed_on ) {
2262 $query .= " AND creationdate <= ? ";
2263 push @query_params, $to_placed_on;
2266 if ( defined $orderstatus and $orderstatus ne '') {
2267 $query .= " AND aqorders.orderstatus = ? ";
2268 push @query_params, "$orderstatus";
2271 if ($basket) {
2272 if ($basket =~ m/^\d+$/) {
2273 $query .= " AND aqorders.basketno = ? ";
2274 push @query_params, $basket;
2275 } else {
2276 $query .= " AND aqbasket.basketname LIKE ? ";
2277 push @query_params, "%$basket%";
2281 if ($booksellerinvoicenumber) {
2282 $query .= " AND aqinvoices.invoicenumber LIKE ? ";
2283 push @query_params, "%$booksellerinvoicenumber%";
2286 if ($basketgroupname) {
2287 $query .= " AND aqbasketgroups.name LIKE ? ";
2288 push @query_params, "%$basketgroupname%";
2291 if ($ordernumber) {
2292 $query .= " AND (aqorders.ordernumber = ? ";
2293 push @query_params, $ordernumber;
2294 if ($search_children_too) {
2295 $query .= " OR aqorders.parent_ordernumber = ? ";
2296 push @query_params, $ordernumber;
2298 $query .= ") ";
2301 if ( @$created_by ) {
2302 $query .= ' AND aqbasket.authorisedby IN ( ' . join( ',', ('?') x @$created_by ) . ')';
2303 push @query_params, @$created_by;
2307 if ( C4::Context->preference("IndependentBranches") ) {
2308 unless ( C4::Context->IsSuperLibrarian() ) {
2309 $query .= " AND (borrowers.branchcode = ? OR borrowers.branchcode ='' ) ";
2310 push @query_params, C4::Context->userenv->{branch};
2313 $query .= " ORDER BY id";
2315 return $dbh->selectall_arrayref( $query, { Slice => {} }, @query_params );
2318 =head2 GetRecentAcqui
2320 $results = GetRecentAcqui($days);
2322 C<$results> is a ref to a table which containts hashref
2324 =cut
2326 sub GetRecentAcqui {
2327 my $limit = shift;
2328 my $dbh = C4::Context->dbh;
2329 my $query = "
2330 SELECT *
2331 FROM biblio
2332 ORDER BY timestamp DESC
2333 LIMIT 0,".$limit;
2335 my $sth = $dbh->prepare($query);
2336 $sth->execute;
2337 my $results = $sth->fetchall_arrayref({});
2338 return $results;
2341 #------------------------------------------------------------#
2343 =head3 AddClaim
2345 &AddClaim($ordernumber);
2347 Add a claim for an order
2349 =cut
2351 sub AddClaim {
2352 my ($ordernumber) = @_;
2353 my $dbh = C4::Context->dbh;
2354 my $query = "
2355 UPDATE aqorders SET
2356 claims_count = claims_count + 1,
2357 claimed_date = CURDATE()
2358 WHERE ordernumber = ?
2360 my $sth = $dbh->prepare($query);
2361 $sth->execute($ordernumber);
2364 =head3 GetInvoices
2366 my @invoices = GetInvoices(
2367 invoicenumber => $invoicenumber,
2368 supplierid => $supplierid,
2369 suppliername => $suppliername,
2370 shipmentdatefrom => $shipmentdatefrom, # ISO format
2371 shipmentdateto => $shipmentdateto, # ISO format
2372 billingdatefrom => $billingdatefrom, # ISO format
2373 billingdateto => $billingdateto, # ISO format
2374 isbneanissn => $isbn_or_ean_or_issn,
2375 title => $title,
2376 author => $author,
2377 publisher => $publisher,
2378 publicationyear => $publicationyear,
2379 branchcode => $branchcode,
2380 order_by => $order_by
2383 Return a list of invoices that match all given criteria.
2385 $order_by is "column_name (asc|desc)", where column_name is any of
2386 'invoicenumber', 'booksellerid', 'shipmentdate', 'billingdate', 'closedate',
2387 'shipmentcost', 'shipmentcost_budgetid'.
2389 asc is the default if omitted
2391 =cut
2393 sub GetInvoices {
2394 my %args = @_;
2396 my @columns = qw(invoicenumber booksellerid shipmentdate billingdate
2397 closedate shipmentcost shipmentcost_budgetid);
2399 my $dbh = C4::Context->dbh;
2400 my $query = qq{
2401 SELECT aqinvoices.*, aqbooksellers.name AS suppliername,
2402 COUNT(
2403 DISTINCT IF(
2404 aqorders.datereceived IS NOT NULL,
2405 aqorders.biblionumber,
2406 NULL
2408 ) AS receivedbiblios,
2409 COUNT(
2410 DISTINCT IF(
2411 aqorders.subscriptionid IS NOT NULL,
2412 aqorders.subscriptionid,
2413 NULL
2415 ) AS is_linked_to_subscriptions,
2416 SUM(aqorders.quantityreceived) AS receiveditems
2417 FROM aqinvoices
2418 LEFT JOIN aqbooksellers ON aqbooksellers.id = aqinvoices.booksellerid
2419 LEFT JOIN aqorders ON aqorders.invoiceid = aqinvoices.invoiceid
2420 LEFT JOIN aqbasket ON aqbasket.basketno=aqorders.basketno
2421 LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber
2422 LEFT JOIN biblio ON aqorders.biblionumber = biblio.biblionumber
2423 LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
2424 LEFT JOIN subscription ON biblio.biblionumber = subscription.biblionumber
2427 my @bind_args;
2428 my @bind_strs;
2429 if($args{supplierid}) {
2430 push @bind_strs, " aqinvoices.booksellerid = ? ";
2431 push @bind_args, $args{supplierid};
2433 if($args{invoicenumber}) {
2434 push @bind_strs, " aqinvoices.invoicenumber LIKE ? ";
2435 push @bind_args, "%$args{invoicenumber}%";
2437 if($args{suppliername}) {
2438 push @bind_strs, " aqbooksellers.name LIKE ? ";
2439 push @bind_args, "%$args{suppliername}%";
2441 if($args{shipmentdatefrom}) {
2442 push @bind_strs, " aqinvoices.shipmentdate >= ? ";
2443 push @bind_args, $args{shipmentdatefrom};
2445 if($args{shipmentdateto}) {
2446 push @bind_strs, " aqinvoices.shipmentdate <= ? ";
2447 push @bind_args, $args{shipmentdateto};
2449 if($args{billingdatefrom}) {
2450 push @bind_strs, " aqinvoices.billingdate >= ? ";
2451 push @bind_args, $args{billingdatefrom};
2453 if($args{billingdateto}) {
2454 push @bind_strs, " aqinvoices.billingdate <= ? ";
2455 push @bind_args, $args{billingdateto};
2457 if($args{isbneanissn}) {
2458 push @bind_strs, " (biblioitems.isbn LIKE CONCAT('%', ?, '%') OR biblioitems.ean LIKE CONCAT('%', ?, '%') OR biblioitems.issn LIKE CONCAT('%', ?, '%') ) ";
2459 push @bind_args, $args{isbneanissn}, $args{isbneanissn}, $args{isbneanissn};
2461 if($args{title}) {
2462 push @bind_strs, " biblio.title LIKE CONCAT('%', ?, '%') ";
2463 push @bind_args, $args{title};
2465 if($args{author}) {
2466 push @bind_strs, " biblio.author LIKE CONCAT('%', ?, '%') ";
2467 push @bind_args, $args{author};
2469 if($args{publisher}) {
2470 push @bind_strs, " biblioitems.publishercode LIKE CONCAT('%', ?, '%') ";
2471 push @bind_args, $args{publisher};
2473 if($args{publicationyear}) {
2474 push @bind_strs, " ((biblioitems.publicationyear LIKE CONCAT('%', ?, '%')) OR (biblio.copyrightdate LIKE CONCAT('%', ?, '%'))) ";
2475 push @bind_args, $args{publicationyear}, $args{publicationyear};
2477 if($args{branchcode}) {
2478 push @bind_strs, " borrowers.branchcode = ? ";
2479 push @bind_args, $args{branchcode};
2482 $query .= " WHERE " . join(" AND ", @bind_strs) if @bind_strs;
2483 $query .= " GROUP BY aqinvoices.invoiceid ";
2485 if($args{order_by}) {
2486 my ($column, $direction) = split / /, $args{order_by};
2487 if(grep /^$column$/, @columns) {
2488 $direction ||= 'ASC';
2489 $query .= " ORDER BY $column $direction";
2493 my $sth = $dbh->prepare($query);
2494 $sth->execute(@bind_args);
2496 my $results = $sth->fetchall_arrayref({});
2497 return @$results;
2500 =head3 GetInvoice
2502 my $invoice = GetInvoice($invoiceid);
2504 Get informations about invoice with given $invoiceid
2506 Return a hash filled with aqinvoices.* fields
2508 =cut
2510 sub GetInvoice {
2511 my ($invoiceid) = @_;
2512 my $invoice;
2514 return unless $invoiceid;
2516 my $dbh = C4::Context->dbh;
2517 my $query = qq{
2518 SELECT *
2519 FROM aqinvoices
2520 WHERE invoiceid = ?
2522 my $sth = $dbh->prepare($query);
2523 $sth->execute($invoiceid);
2525 $invoice = $sth->fetchrow_hashref;
2526 return $invoice;
2529 =head3 GetInvoiceDetails
2531 my $invoice = GetInvoiceDetails($invoiceid)
2533 Return informations about an invoice + the list of related order lines
2535 Orders informations are in $invoice->{orders} (array ref)
2537 =cut
2539 sub GetInvoiceDetails {
2540 my ($invoiceid) = @_;
2542 if ( !defined $invoiceid ) {
2543 carp 'GetInvoiceDetails called without an invoiceid';
2544 return;
2547 my $dbh = C4::Context->dbh;
2548 my $query = q{
2549 SELECT aqinvoices.*, aqbooksellers.name AS suppliername
2550 FROM aqinvoices
2551 LEFT JOIN aqbooksellers ON aqinvoices.booksellerid = aqbooksellers.id
2552 WHERE invoiceid = ?
2554 my $sth = $dbh->prepare($query);
2555 $sth->execute($invoiceid);
2557 my $invoice = $sth->fetchrow_hashref;
2559 $query = q{
2560 SELECT aqorders.*,
2561 biblio.*,
2562 biblio.copyrightdate,
2563 biblioitems.publishercode,
2564 biblioitems.publicationyear,
2565 aqbasket.basketname,
2566 aqbasketgroups.id AS basketgroupid,
2567 aqbasketgroups.name AS basketgroupname
2568 FROM aqorders
2569 LEFT JOIN aqbasket ON aqorders.basketno = aqbasket.basketno
2570 LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid = aqbasketgroups.id
2571 LEFT JOIN biblio ON aqorders.biblionumber = biblio.biblionumber
2572 LEFT JOIN biblioitems ON aqorders.biblionumber = biblioitems.biblionumber
2573 WHERE invoiceid = ?
2575 $sth = $dbh->prepare($query);
2576 $sth->execute($invoiceid);
2577 $invoice->{orders} = $sth->fetchall_arrayref({});
2578 $invoice->{orders} ||= []; # force an empty arrayref if fetchall_arrayref fails
2580 return $invoice;
2583 =head3 AddInvoice
2585 my $invoiceid = AddInvoice(
2586 invoicenumber => $invoicenumber,
2587 booksellerid => $booksellerid,
2588 shipmentdate => $shipmentdate,
2589 billingdate => $billingdate,
2590 closedate => $closedate,
2591 shipmentcost => $shipmentcost,
2592 shipmentcost_budgetid => $shipmentcost_budgetid
2595 Create a new invoice and return its id or undef if it fails.
2597 =cut
2599 sub AddInvoice {
2600 my %invoice = @_;
2602 return unless(%invoice and $invoice{invoicenumber});
2604 my @columns = qw(invoicenumber booksellerid shipmentdate billingdate
2605 closedate shipmentcost shipmentcost_budgetid);
2607 my @set_strs;
2608 my @set_args;
2609 foreach my $key (keys %invoice) {
2610 if(0 < grep(/^$key$/, @columns)) {
2611 push @set_strs, "$key = ?";
2612 push @set_args, ($invoice{$key} || undef);
2616 my $rv;
2617 if(@set_args > 0) {
2618 my $dbh = C4::Context->dbh;
2619 my $query = "INSERT INTO aqinvoices SET ";
2620 $query .= join (",", @set_strs);
2621 my $sth = $dbh->prepare($query);
2622 $rv = $sth->execute(@set_args);
2623 if($rv) {
2624 $rv = $dbh->last_insert_id(undef, undef, 'aqinvoices', undef);
2627 return $rv;
2630 =head3 ModInvoice
2632 ModInvoice(
2633 invoiceid => $invoiceid, # Mandatory
2634 invoicenumber => $invoicenumber,
2635 booksellerid => $booksellerid,
2636 shipmentdate => $shipmentdate,
2637 billingdate => $billingdate,
2638 closedate => $closedate,
2639 shipmentcost => $shipmentcost,
2640 shipmentcost_budgetid => $shipmentcost_budgetid
2643 Modify an invoice, invoiceid is mandatory.
2645 Return undef if it fails.
2647 =cut
2649 sub ModInvoice {
2650 my %invoice = @_;
2652 return unless(%invoice and $invoice{invoiceid});
2654 my @columns = qw(invoicenumber booksellerid shipmentdate billingdate
2655 closedate shipmentcost shipmentcost_budgetid);
2657 my @set_strs;
2658 my @set_args;
2659 foreach my $key (keys %invoice) {
2660 if(0 < grep(/^$key$/, @columns)) {
2661 push @set_strs, "$key = ?";
2662 push @set_args, ($invoice{$key} || undef);
2666 my $dbh = C4::Context->dbh;
2667 my $query = "UPDATE aqinvoices SET ";
2668 $query .= join(",", @set_strs);
2669 $query .= " WHERE invoiceid = ?";
2671 my $sth = $dbh->prepare($query);
2672 $sth->execute(@set_args, $invoice{invoiceid});
2675 =head3 CloseInvoice
2677 CloseInvoice($invoiceid);
2679 Close an invoice.
2681 Equivalent to ModInvoice(invoiceid => $invoiceid, closedate => undef);
2683 =cut
2685 sub CloseInvoice {
2686 my ($invoiceid) = @_;
2688 return unless $invoiceid;
2690 my $dbh = C4::Context->dbh;
2691 my $query = qq{
2692 UPDATE aqinvoices
2693 SET closedate = CAST(NOW() AS DATE)
2694 WHERE invoiceid = ?
2696 my $sth = $dbh->prepare($query);
2697 $sth->execute($invoiceid);
2700 =head3 ReopenInvoice
2702 ReopenInvoice($invoiceid);
2704 Reopen an invoice
2706 Equivalent to ModInvoice(invoiceid => $invoiceid, closedate => output_pref({ dt=>dt_from_string, dateonly=>1, otputpref=>'iso' }))
2708 =cut
2710 sub ReopenInvoice {
2711 my ($invoiceid) = @_;
2713 return unless $invoiceid;
2715 my $dbh = C4::Context->dbh;
2716 my $query = qq{
2717 UPDATE aqinvoices
2718 SET closedate = NULL
2719 WHERE invoiceid = ?
2721 my $sth = $dbh->prepare($query);
2722 $sth->execute($invoiceid);
2725 =head3 DelInvoice
2727 DelInvoice($invoiceid);
2729 Delete an invoice if there are no items attached to it.
2731 =cut
2733 sub DelInvoice {
2734 my ($invoiceid) = @_;
2736 return unless $invoiceid;
2738 my $dbh = C4::Context->dbh;
2739 my $query = qq{
2740 SELECT COUNT(*)
2741 FROM aqorders
2742 WHERE invoiceid = ?
2744 my $sth = $dbh->prepare($query);
2745 $sth->execute($invoiceid);
2746 my $res = $sth->fetchrow_arrayref;
2747 if ( $res && $res->[0] == 0 ) {
2748 $query = qq{
2749 DELETE FROM aqinvoices
2750 WHERE invoiceid = ?
2752 my $sth = $dbh->prepare($query);
2753 return ( $sth->execute($invoiceid) > 0 );
2755 return;
2758 =head3 MergeInvoices
2760 MergeInvoices($invoiceid, \@sourceids);
2762 Merge the invoices identified by the IDs in \@sourceids into
2763 the invoice identified by $invoiceid.
2765 =cut
2767 sub MergeInvoices {
2768 my ($invoiceid, $sourceids) = @_;
2770 return unless $invoiceid;
2771 foreach my $sourceid (@$sourceids) {
2772 next if $sourceid == $invoiceid;
2773 my $source = GetInvoiceDetails($sourceid);
2774 foreach my $order (@{$source->{'orders'}}) {
2775 $order->{'invoiceid'} = $invoiceid;
2776 ModOrder($order);
2778 DelInvoice($source->{'invoiceid'});
2780 return;
2783 =head3 GetBiblioCountByBasketno
2785 $biblio_count = &GetBiblioCountByBasketno($basketno);
2787 Looks up the biblio's count that has basketno value $basketno
2789 Returns a quantity
2791 =cut
2793 sub GetBiblioCountByBasketno {
2794 my ($basketno) = @_;
2795 my $dbh = C4::Context->dbh;
2796 my $query = "
2797 SELECT COUNT( DISTINCT( biblionumber ) )
2798 FROM aqorders
2799 WHERE basketno = ?
2800 AND (datecancellationprinted IS NULL OR datecancellationprinted='0000-00-00')
2803 my $sth = $dbh->prepare($query);
2804 $sth->execute($basketno);
2805 return $sth->fetchrow;
2808 # This is *not* the good way to calcul prices
2809 # But it's how it works at the moment into Koha
2810 # This will be fixed later.
2811 # Note this subroutine should be moved to Koha::Acquisition::Order
2812 # Will do when a DBIC decision will be taken.
2813 sub populate_order_with_prices {
2814 my ($params) = @_;
2816 my $order = $params->{order};
2817 my $booksellerid = $params->{booksellerid};
2818 return unless $booksellerid;
2820 my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $booksellerid });
2822 my $receiving = $params->{receiving};
2823 my $ordering = $params->{ordering};
2824 my $discount = $order->{discount};
2825 $discount /= 100 if $discount > 1;
2827 $order->{rrp} = Koha::Number::Price->new( $order->{rrp} )->round;
2828 $order->{ecost} = Koha::Number::Price->new( $order->{ecost} )->round;
2829 if ($ordering) {
2830 if ( $bookseller->{listincgst} ) {
2831 $order->{rrpgsti} = $order->{rrp};
2832 $order->{rrpgste} = Koha::Number::Price->new(
2833 $order->{rrpgsti} / ( 1 + $order->{gstrate} ) )->round;
2834 $order->{ecostgsti} = $order->{ecost};
2835 $order->{ecostgste} = Koha::Number::Price->new(
2836 $order->{ecost} / ( 1 + $order->{gstrate} ) )->round;
2837 $order->{gstvalue} = Koha::Number::Price->new(
2838 ( $order->{ecostgsti} - $order->{ecostgste} ) *
2839 $order->{quantity} )->round;
2840 $order->{totalgste} = $order->{ecostgste} * $order->{quantity};
2841 $order->{totalgsti} = $order->{ecostgsti} * $order->{quantity};
2843 else {
2844 $order->{rrpgste} = $order->{rrp};
2845 $order->{rrpgsti} = Koha::Number::Price->new(
2846 $order->{rrp} * ( 1 + $order->{gstrate} ) )->round;
2847 $order->{ecostgste} = $order->{ecost};
2848 $order->{ecostgsti} = Koha::Number::Price->new(
2849 $order->{ecost} * ( 1 + $order->{gstrate} ) )->round;
2850 $order->{gstvalue} = Koha::Number::Price->new(
2851 ( $order->{ecostgsti} - $order->{ecostgste} ) *
2852 $order->{quantity} )->round;
2853 $order->{totalgste} = $order->{ecostgste} * $order->{quantity};
2854 $order->{totalgsti} = $order->{ecostgsti} * $order->{quantity};
2858 if ($receiving) {
2859 if ( $bookseller->{listincgst} ) {
2860 $order->{unitpricegsti} = Koha::Number::Price->new( $order->{unitprice} )->round;
2861 $order->{unitpricegste} = Koha::Number::Price->new(
2862 $order->{unitpricegsti} / ( 1 + $order->{gstrate} ) )->round;
2864 else {
2865 $order->{unitpricegste} = Koha::Number::Price->new( $order->{unitprice} )->round;
2866 $order->{unitpricegsti} = Koha::Number::Price->new(
2867 $order->{unitpricegste} * ( 1 + $order->{gstrate} ) )->round;
2869 $order->{gstvalue} = Koha::Number::Price->new(
2870 ( $order->{unitpricegsti} - $order->{unitpricegste} )
2871 * $order->{quantityreceived} )->round;
2873 $order->{totalgste} = $order->{unitpricegste} * $order->{quantity};
2874 $order->{totalgsti} = $order->{unitpricegsti} * $order->{quantity};
2877 return $order;
2880 =head3 GetOrderUsers
2882 $order_users_ids = &GetOrderUsers($ordernumber);
2884 Returns a list of all borrowernumbers that are in order users list
2886 =cut
2888 sub GetOrderUsers {
2889 my ($ordernumber) = @_;
2891 return unless $ordernumber;
2893 my $query = q|
2894 SELECT borrowernumber
2895 FROM aqorder_users
2896 WHERE ordernumber = ?
2898 my $dbh = C4::Context->dbh;
2899 my $sth = $dbh->prepare($query);
2900 $sth->execute($ordernumber);
2901 my $results = $sth->fetchall_arrayref( {} );
2903 my @borrowernumbers;
2904 foreach (@$results) {
2905 push @borrowernumbers, $_->{'borrowernumber'};
2908 return @borrowernumbers;
2911 =head3 ModOrderUsers
2913 my @order_users_ids = (1, 2, 3);
2914 &ModOrderUsers($ordernumber, @basketusers_ids);
2916 Delete all users from order users list, and add users in C<@order_users_ids>
2917 to this users list.
2919 =cut
2921 sub ModOrderUsers {
2922 my ( $ordernumber, @order_users_ids ) = @_;
2924 return unless $ordernumber;
2926 my $dbh = C4::Context->dbh;
2927 my $query = q|
2928 DELETE FROM aqorder_users
2929 WHERE ordernumber = ?
2931 my $sth = $dbh->prepare($query);
2932 $sth->execute($ordernumber);
2934 $query = q|
2935 INSERT INTO aqorder_users (ordernumber, borrowernumber)
2936 VALUES (?, ?)
2938 $sth = $dbh->prepare($query);
2939 foreach my $order_user_id (@order_users_ids) {
2940 $sth->execute( $ordernumber, $order_user_id );
2944 sub NotifyOrderUsers {
2945 my ($ordernumber) = @_;
2947 my @borrowernumbers = GetOrderUsers($ordernumber);
2948 return unless @borrowernumbers;
2950 my $order = GetOrder( $ordernumber );
2951 for my $borrowernumber (@borrowernumbers) {
2952 my $borrower = C4::Members::GetMember( borrowernumber => $borrowernumber );
2953 my $library = Koha::Libraries->find( $borrower->{branchcode} )->unblessed;
2954 my $biblio = C4::Biblio::GetBiblio( $order->{biblionumber} );
2955 my $letter = C4::Letters::GetPreparedLetter(
2956 module => 'acquisition',
2957 letter_code => 'ACQ_NOTIF_ON_RECEIV',
2958 branchcode => $library->{branchcode},
2959 tables => {
2960 'branches' => $library,
2961 'borrowers' => $borrower,
2962 'biblio' => $biblio,
2963 'aqorders' => $order,
2966 if ( $letter ) {
2967 C4::Letters::EnqueueLetter(
2969 letter => $letter,
2970 borrowernumber => $borrowernumber,
2971 LibraryName => C4::Context->preference("LibraryName"),
2972 message_transport_type => 'email',
2974 ) or warn "can't enqueue letter $letter";
2979 =head3 FillWithDefaultValues
2981 FillWithDefaultValues( $marc_record );
2983 This will update the record with default value defined in the ACQ framework.
2984 For all existing fields, if a default value exists and there are no subfield, it will be created.
2985 If the field does not exist, it will be created too.
2987 =cut
2989 sub FillWithDefaultValues {
2990 my ($record) = @_;
2991 my $tagslib = C4::Biblio::GetMarcStructure( 1, 'ACQ' );
2992 if ($tagslib) {
2993 my ($itemfield) =
2994 C4::Biblio::GetMarcFromKohaField( 'items.itemnumber', '' );
2995 for my $tag ( sort keys %$tagslib ) {
2996 next unless $tag;
2997 next if $tag == $itemfield;
2998 for my $subfield ( sort keys %{ $tagslib->{$tag} } ) {
2999 next if ( subfield_is_koha_internal_p($subfield) );
3000 my $defaultvalue = $tagslib->{$tag}{$subfield}{defaultvalue};
3001 if ( defined $defaultvalue and $defaultvalue ne '' ) {
3002 my @fields = $record->field($tag);
3003 if (@fields) {
3004 for my $field (@fields) {
3005 unless ( defined $field->subfield($subfield) ) {
3006 $field->add_subfields(
3007 $subfield => $defaultvalue );
3011 else {
3012 $record->insert_fields_ordered(
3013 MARC::Field->new(
3014 $tag, '', '', $subfield => $defaultvalue
3025 __END__
3027 =head1 AUTHOR
3029 Koha Development Team <http://koha-community.org/>
3031 =cut