Bug 13909: (QA followup) fix references to get_chargeable_units
[koha.git] / C4 / Acquisition.pm
blob0bb34c66efa5529883227c170065c99a61bb3a39
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 under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
10 # version.
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License along
17 # with Koha; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 use Modern::Perl;
22 use Carp;
23 use C4::Context;
24 use C4::Debug;
25 use C4::Dates qw(format_date format_date_in_iso);
26 use MARC::Record;
27 use C4::Suggestions;
28 use C4::Biblio;
29 use C4::Contract;
30 use C4::Debug;
31 use C4::Templates qw(gettemplate);
32 use Koha::DateUtils qw( dt_from_string output_pref );
33 use Koha::Acquisition::Order;
34 use Koha::Acquisition::Bookseller;
35 use Koha::Number::Price;
37 use Time::localtime;
38 use HTML::Entities;
40 use vars qw($VERSION @ISA @EXPORT);
42 BEGIN {
43 # set the version for version checking
44 $VERSION = 3.07.00.049;
45 require Exporter;
46 @ISA = qw(Exporter);
47 @EXPORT = qw(
48 &GetBasket &NewBasket &CloseBasket &ReopenBasket &DelBasket &ModBasket
49 &GetBasketAsCSV &GetBasketGroupAsCSV
50 &GetBasketsByBookseller &GetBasketsByBasketgroup
51 &GetBasketsInfosByBookseller
53 &GetBasketUsers &ModBasketUsers
54 &CanUserManageBasket
56 &ModBasketHeader
58 &ModBasketgroup &NewBasketgroup &DelBasketgroup &GetBasketgroup &CloseBasketgroup
59 &GetBasketgroups &ReOpenBasketgroup
61 &DelOrder &ModOrder &GetOrder &GetOrders &GetOrdersByBiblionumber
62 &GetLateOrders &GetOrderFromItemnumber
63 &SearchOrders &GetHistory &GetRecentAcqui
64 &ModReceiveOrder &CancelReceipt
65 &GetCancelledOrders &TransferOrder
66 &GetLastOrderNotReceivedFromSubscriptionid &GetLastOrderReceivedFromSubscriptionid
67 &ModItemOrder
69 &GetParcels
71 &GetInvoices
72 &GetInvoice
73 &GetInvoiceDetails
74 &AddInvoice
75 &ModInvoice
76 &CloseInvoice
77 &ReopenInvoice
78 &DelInvoice
79 &MergeInvoices
81 &GetItemnumbersFromOrder
83 &AddClaim
84 &GetBiblioCountByBasketno
86 &GetOrderUsers
87 &ModOrderUsers
88 &NotifyOrderUsers
96 sub GetOrderFromItemnumber {
97 my ($itemnumber) = @_;
98 my $dbh = C4::Context->dbh;
99 my $query = qq|
101 SELECT * from aqorders LEFT JOIN aqorders_items
102 ON ( aqorders.ordernumber = aqorders_items.ordernumber )
103 WHERE itemnumber = ? |;
105 my $sth = $dbh->prepare($query);
107 # $sth->trace(3);
109 $sth->execute($itemnumber);
111 my $order = $sth->fetchrow_hashref;
112 return ( $order );
116 # Returns the itemnumber(s) associated with the ordernumber given in parameter
117 sub GetItemnumbersFromOrder {
118 my ($ordernumber) = @_;
119 my $dbh = C4::Context->dbh;
120 my $query = "SELECT itemnumber FROM aqorders_items WHERE ordernumber=?";
121 my $sth = $dbh->prepare($query);
122 $sth->execute($ordernumber);
123 my @tab;
125 while (my $order = $sth->fetchrow_hashref) {
126 push @tab, $order->{'itemnumber'};
129 return @tab;
138 =head1 NAME
140 C4::Acquisition - Koha functions for dealing with orders and acquisitions
142 =head1 SYNOPSIS
144 use C4::Acquisition;
146 =head1 DESCRIPTION
148 The functions in this module deal with acquisitions, managing book
149 orders, basket and parcels.
151 =head1 FUNCTIONS
153 =head2 FUNCTIONS ABOUT BASKETS
155 =head3 GetBasket
157 $aqbasket = &GetBasket($basketnumber);
159 get all basket informations in aqbasket for a given basket
161 B<returns:> informations for a given basket returned as a hashref.
163 =cut
165 sub GetBasket {
166 my ($basketno) = @_;
167 my $dbh = C4::Context->dbh;
168 my $query = "
169 SELECT aqbasket.*,
170 concat( b.firstname,' ',b.surname) AS authorisedbyname
171 FROM aqbasket
172 LEFT JOIN borrowers b ON aqbasket.authorisedby=b.borrowernumber
173 WHERE basketno=?
175 my $sth=$dbh->prepare($query);
176 $sth->execute($basketno);
177 my $basket = $sth->fetchrow_hashref;
178 return ( $basket );
181 #------------------------------------------------------------#
183 =head3 NewBasket
185 $basket = &NewBasket( $booksellerid, $authorizedby, $basketname,
186 $basketnote, $basketbooksellernote, $basketcontractnumber, $deliveryplace, $billingplace );
188 Create a new basket in aqbasket table
190 =over
192 =item C<$booksellerid> is a foreign key in the aqbasket table
194 =item C<$authorizedby> is the username of who created the basket
196 =back
198 The other parameters are optional, see ModBasketHeader for more info on them.
200 =cut
202 sub NewBasket {
203 my ( $booksellerid, $authorisedby, $basketname, $basketnote,
204 $basketbooksellernote, $basketcontractnumber, $deliveryplace,
205 $billingplace ) = @_;
206 my $dbh = C4::Context->dbh;
207 my $query =
208 'INSERT INTO aqbasket (creationdate,booksellerid,authorisedby) '
209 . 'VALUES (now(),?,?)';
210 $dbh->do( $query, {}, $booksellerid, $authorisedby );
212 my $basket = $dbh->{mysql_insertid};
213 $basketname ||= q{}; # default to empty strings
214 $basketnote ||= q{};
215 $basketbooksellernote ||= q{};
216 ModBasketHeader( $basket, $basketname, $basketnote, $basketbooksellernote,
217 $basketcontractnumber, $booksellerid, $deliveryplace, $billingplace );
218 return $basket;
221 #------------------------------------------------------------#
223 =head3 CloseBasket
225 &CloseBasket($basketno);
227 close a basket (becomes unmodifiable, except for receives)
229 =cut
231 sub CloseBasket {
232 my ($basketno) = @_;
233 my $dbh = C4::Context->dbh;
234 my $query = "
235 UPDATE aqbasket
236 SET closedate=now()
237 WHERE basketno=?
239 my $sth = $dbh->prepare($query);
240 $sth->execute($basketno);
242 my @orders = GetOrders($basketno);
243 foreach my $order (@orders) {
244 $query = qq{
245 UPDATE aqorders
246 SET orderstatus = 'ordered'
247 WHERE ordernumber = ?;
249 $sth = $dbh->prepare($query);
250 $sth->execute($order->{'ordernumber'});
254 =head3 ReopenBasket
256 &ReopenBasket($basketno);
258 reopen a basket
260 =cut
262 sub ReopenBasket {
263 my ($basketno) = @_;
264 my $dbh = C4::Context->dbh;
265 my $query = "
266 UPDATE aqbasket
267 SET closedate=NULL
268 WHERE basketno=?
270 my $sth = $dbh->prepare($query);
271 $sth->execute($basketno);
273 my @orders = GetOrders($basketno);
274 foreach my $order (@orders) {
275 $query = qq{
276 UPDATE aqorders
277 SET orderstatus = 'new'
278 WHERE ordernumber = ?;
280 $sth = $dbh->prepare($query);
281 $sth->execute($order->{'ordernumber'});
285 #------------------------------------------------------------#
287 =head3 GetBasketAsCSV
289 &GetBasketAsCSV($basketno);
291 Export a basket as CSV
293 $cgi parameter is needed for column name translation
295 =cut
297 sub GetBasketAsCSV {
298 my ($basketno, $cgi) = @_;
299 my $basket = GetBasket($basketno);
300 my @orders = GetOrders($basketno);
301 my $contract = GetContract({
302 contractnumber => $basket->{'contractnumber'}
305 my $template = C4::Templates::gettemplate("acqui/csv/basket.tt", "intranet", $cgi);
307 my @rows;
308 foreach my $order (@orders) {
309 my $bd = GetBiblioData( $order->{'biblionumber'} );
310 my $row = {
311 contractname => $contract->{'contractname'},
312 ordernumber => $order->{'ordernumber'},
313 entrydate => $order->{'entrydate'},
314 isbn => $order->{'isbn'},
315 author => $bd->{'author'},
316 title => $bd->{'title'},
317 publicationyear => $bd->{'publicationyear'},
318 publishercode => $bd->{'publishercode'},
319 collectiontitle => $bd->{'collectiontitle'},
320 notes => $order->{'order_vendornote'},
321 quantity => $order->{'quantity'},
322 rrp => $order->{'rrp'},
323 deliveryplace => C4::Branch::GetBranchName( $basket->{'deliveryplace'} ),
324 billingplace => C4::Branch::GetBranchName( $basket->{'billingplace'} ),
326 foreach(qw(
327 contractname author title publishercode collectiontitle notes
328 deliveryplace billingplace
329 ) ) {
330 # Double the quotes to not be interpreted as a field end
331 $row->{$_} =~ s/"/""/g if $row->{$_};
333 push @rows, $row;
336 @rows = sort {
337 if(defined $a->{publishercode} and defined $b->{publishercode}) {
338 $a->{publishercode} cmp $b->{publishercode};
340 } @rows;
342 $template->param(rows => \@rows);
344 return $template->output;
348 =head3 GetBasketGroupAsCSV
350 &GetBasketGroupAsCSV($basketgroupid);
352 Export a basket group as CSV
354 $cgi parameter is needed for column name translation
356 =cut
358 sub GetBasketGroupAsCSV {
359 my ($basketgroupid, $cgi) = @_;
360 my $baskets = GetBasketsByBasketgroup($basketgroupid);
362 my $template = C4::Templates::gettemplate('acqui/csv/basketgroup.tt', 'intranet', $cgi);
364 my @rows;
365 for my $basket (@$baskets) {
366 my @orders = GetOrders( $basket->{basketno} );
367 my $contract = GetContract({
368 contractnumber => $basket->{contractnumber}
370 my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $basket->{booksellerid} });
371 my $basketgroup = GetBasketgroup( $$basket{basketgroupid} );
373 foreach my $order (@orders) {
374 my $bd = GetBiblioData( $order->{'biblionumber'} );
375 my $row = {
376 clientnumber => $bookseller->{accountnumber},
377 basketname => $basket->{basketname},
378 ordernumber => $order->{ordernumber},
379 author => $bd->{author},
380 title => $bd->{title},
381 publishercode => $bd->{publishercode},
382 publicationyear => $bd->{publicationyear},
383 collectiontitle => $bd->{collectiontitle},
384 isbn => $order->{isbn},
385 quantity => $order->{quantity},
386 rrp => $order->{rrp},
387 discount => $bookseller->{discount},
388 ecost => $order->{ecost},
389 notes => $order->{order_vendornote},
390 entrydate => $order->{entrydate},
391 booksellername => $bookseller->{name},
392 bookselleraddress => $bookseller->{address1},
393 booksellerpostal => $bookseller->{postal},
394 contractnumber => $contract->{contractnumber},
395 contractname => $contract->{contractname},
396 basketgroupdeliveryplace => C4::Branch::GetBranchName( $basketgroup->{deliveryplace} ),
397 basketgroupbillingplace => C4::Branch::GetBranchName( $basketgroup->{billingplace} ),
398 basketdeliveryplace => C4::Branch::GetBranchName( $basket->{deliveryplace} ),
399 basketbillingplace => C4::Branch::GetBranchName( $basket->{billingplace} ),
401 foreach(qw(
402 basketname author title publishercode collectiontitle notes
403 booksellername bookselleraddress booksellerpostal contractname
404 basketgroupdeliveryplace basketgroupbillingplace
405 basketdeliveryplace basketbillingplace
406 ) ) {
407 # Double the quotes to not be interpreted as a field end
408 $row->{$_} =~ s/"/""/g if $row->{$_};
410 push @rows, $row;
413 $template->param(rows => \@rows);
415 return $template->output;
419 =head3 CloseBasketgroup
421 &CloseBasketgroup($basketgroupno);
423 close a basketgroup
425 =cut
427 sub CloseBasketgroup {
428 my ($basketgroupno) = @_;
429 my $dbh = C4::Context->dbh;
430 my $sth = $dbh->prepare("
431 UPDATE aqbasketgroups
432 SET closed=1
433 WHERE id=?
435 $sth->execute($basketgroupno);
438 #------------------------------------------------------------#
440 =head3 ReOpenBaskergroup($basketgroupno)
442 &ReOpenBaskergroup($basketgroupno);
444 reopen a basketgroup
446 =cut
448 sub ReOpenBasketgroup {
449 my ($basketgroupno) = @_;
450 my $dbh = C4::Context->dbh;
451 my $sth = $dbh->prepare("
452 UPDATE aqbasketgroups
453 SET closed=0
454 WHERE id=?
456 $sth->execute($basketgroupno);
459 #------------------------------------------------------------#
462 =head3 DelBasket
464 &DelBasket($basketno);
466 Deletes the basket that has basketno field $basketno in the aqbasket table.
468 =over
470 =item C<$basketno> is the primary key of the basket in the aqbasket table.
472 =back
474 =cut
476 sub DelBasket {
477 my ( $basketno ) = @_;
478 my $query = "DELETE FROM aqbasket WHERE basketno=?";
479 my $dbh = C4::Context->dbh;
480 my $sth = $dbh->prepare($query);
481 $sth->execute($basketno);
482 return;
485 #------------------------------------------------------------#
487 =head3 ModBasket
489 &ModBasket($basketinfo);
491 Modifies a basket, using a hashref $basketinfo for the relevant information, only $basketinfo->{'basketno'} is required.
493 =over
495 =item C<$basketno> is the primary key of the basket in the aqbasket table.
497 =back
499 =cut
501 sub ModBasket {
502 my $basketinfo = shift;
503 my $query = "UPDATE aqbasket SET ";
504 my @params;
505 foreach my $key (keys %$basketinfo){
506 if ($key ne 'basketno'){
507 $query .= "$key=?, ";
508 push(@params, $basketinfo->{$key} || undef );
511 # get rid of the "," at the end of $query
512 if (substr($query, length($query)-2) eq ', '){
513 chop($query);
514 chop($query);
515 $query .= ' ';
517 $query .= "WHERE basketno=?";
518 push(@params, $basketinfo->{'basketno'});
519 my $dbh = C4::Context->dbh;
520 my $sth = $dbh->prepare($query);
521 $sth->execute(@params);
523 return;
526 #------------------------------------------------------------#
528 =head3 ModBasketHeader
530 &ModBasketHeader($basketno, $basketname, $note, $booksellernote, $contractnumber, $booksellerid);
532 Modifies a basket's header.
534 =over
536 =item C<$basketno> is the "basketno" field in the "aqbasket" table;
538 =item C<$basketname> is the "basketname" field in the "aqbasket" table;
540 =item C<$note> is the "note" field in the "aqbasket" table;
542 =item C<$booksellernote> is the "booksellernote" field in the "aqbasket" table;
544 =item C<$contractnumber> is the "contractnumber" (foreign) key in the "aqbasket" table.
546 =item C<$booksellerid> is the id (foreign) key in the "aqbooksellers" table for the vendor.
548 =item C<$deliveryplace> is the "deliveryplace" field in the aqbasket table.
550 =item C<$billingplace> is the "billingplace" field in the aqbasket table.
552 =back
554 =cut
556 sub ModBasketHeader {
557 my ($basketno, $basketname, $note, $booksellernote, $contractnumber, $booksellerid, $deliveryplace, $billingplace) = @_;
558 my $query = qq{
559 UPDATE aqbasket
560 SET basketname=?, note=?, booksellernote=?, booksellerid=?, deliveryplace=?, billingplace=?
561 WHERE basketno=?
564 my $dbh = C4::Context->dbh;
565 my $sth = $dbh->prepare($query);
566 $sth->execute($basketname, $note, $booksellernote, $booksellerid, $deliveryplace, $billingplace, $basketno);
568 if ( $contractnumber ) {
569 my $query2 ="UPDATE aqbasket SET contractnumber=? WHERE basketno=?";
570 my $sth2 = $dbh->prepare($query2);
571 $sth2->execute($contractnumber,$basketno);
573 return;
576 #------------------------------------------------------------#
578 =head3 GetBasketsByBookseller
580 @results = &GetBasketsByBookseller($booksellerid, $extra);
582 Returns a list of hashes of all the baskets that belong to bookseller 'booksellerid'.
584 =over
586 =item C<$booksellerid> is the 'id' field of the bookseller in the aqbooksellers table
588 =item C<$extra> is the extra sql parameters, can be
590 $extra->{groupby}: group baskets by column
591 ex. $extra->{groupby} = aqbasket.basketgroupid
592 $extra->{orderby}: order baskets by column
593 $extra->{limit}: limit number of results (can be helpful for pagination)
595 =back
597 =cut
599 sub GetBasketsByBookseller {
600 my ($booksellerid, $extra) = @_;
601 my $query = "SELECT * FROM aqbasket WHERE booksellerid=?";
602 if ($extra){
603 if ($extra->{groupby}) {
604 $query .= " GROUP by $extra->{groupby}";
606 if ($extra->{orderby}){
607 $query .= " ORDER by $extra->{orderby}";
609 if ($extra->{limit}){
610 $query .= " LIMIT $extra->{limit}";
613 my $dbh = C4::Context->dbh;
614 my $sth = $dbh->prepare($query);
615 $sth->execute($booksellerid);
616 return $sth->fetchall_arrayref({});
619 =head3 GetBasketsInfosByBookseller
621 my $baskets = GetBasketsInfosByBookseller($supplierid, $allbaskets);
623 The optional second parameter allbaskets is a boolean allowing you to
624 select all baskets from the supplier; by default only active baskets (open or
625 closed but still something to receive) are returned.
627 Returns in a arrayref of hashref all about booksellers baskets, plus:
628 total_biblios: Number of distinct biblios in basket
629 total_items: Number of items in basket
630 expected_items: Number of non-received items in basket
632 =cut
634 sub GetBasketsInfosByBookseller {
635 my ($supplierid, $allbaskets) = @_;
637 return unless $supplierid;
639 my $dbh = C4::Context->dbh;
640 my $query = q{
641 SELECT aqbasket.*,
642 SUM(aqorders.quantity) AS total_items,
643 SUM(
644 IF ( aqorders.orderstatus = 'cancelled', aqorders.quantity, 0 )
645 ) AS total_items_cancelled,
646 COUNT(DISTINCT aqorders.biblionumber) AS total_biblios,
647 SUM(
648 IF(aqorders.datereceived IS NULL
649 AND aqorders.datecancellationprinted IS NULL
650 , aqorders.quantity
651 , 0)
652 ) AS expected_items
653 FROM aqbasket
654 LEFT JOIN aqorders ON aqorders.basketno = aqbasket.basketno
655 WHERE booksellerid = ?};
657 unless ( $allbaskets ) {
658 $query.=" AND (closedate IS NULL OR (aqorders.quantity > aqorders.quantityreceived AND datecancellationprinted IS NULL))";
660 $query.=" GROUP BY aqbasket.basketno";
662 my $sth = $dbh->prepare($query);
663 $sth->execute($supplierid);
664 my $baskets = $sth->fetchall_arrayref({});
666 # Retrieve the number of biblios cancelled
667 my $cancelled_biblios = $dbh->selectall_hashref( q|
668 SELECT COUNT(DISTINCT(biblionumber)) AS total_biblios_cancelled, aqbasket.basketno
669 FROM aqbasket
670 LEFT JOIN aqorders ON aqorders.basketno = aqbasket.basketno
671 WHERE booksellerid = ?
672 AND aqorders.orderstatus = 'cancelled'
673 GROUP BY aqbasket.basketno
674 |, 'basketno', {}, $supplierid );
675 map {
676 $_->{total_biblios_cancelled} = $cancelled_biblios->{$_->{basketno}}{total_biblios_cancelled} || 0
677 } @$baskets;
679 return $baskets;
682 =head3 GetBasketUsers
684 $basketusers_ids = &GetBasketUsers($basketno);
686 Returns a list of all borrowernumbers that are in basket users list
688 =cut
690 sub GetBasketUsers {
691 my $basketno = shift;
693 return unless $basketno;
695 my $query = qq{
696 SELECT borrowernumber
697 FROM aqbasketusers
698 WHERE basketno = ?
700 my $dbh = C4::Context->dbh;
701 my $sth = $dbh->prepare($query);
702 $sth->execute($basketno);
703 my $results = $sth->fetchall_arrayref( {} );
705 my @borrowernumbers;
706 foreach (@$results) {
707 push @borrowernumbers, $_->{'borrowernumber'};
710 return @borrowernumbers;
713 =head3 ModBasketUsers
715 my @basketusers_ids = (1, 2, 3);
716 &ModBasketUsers($basketno, @basketusers_ids);
718 Delete all users from basket users list, and add users in C<@basketusers_ids>
719 to this users list.
721 =cut
723 sub ModBasketUsers {
724 my ($basketno, @basketusers_ids) = @_;
726 return unless $basketno;
728 my $dbh = C4::Context->dbh;
729 my $query = qq{
730 DELETE FROM aqbasketusers
731 WHERE basketno = ?
733 my $sth = $dbh->prepare($query);
734 $sth->execute($basketno);
736 $query = qq{
737 INSERT INTO aqbasketusers (basketno, borrowernumber)
738 VALUES (?, ?)
740 $sth = $dbh->prepare($query);
741 foreach my $basketuser_id (@basketusers_ids) {
742 $sth->execute($basketno, $basketuser_id);
744 return;
747 =head3 CanUserManageBasket
749 my $bool = CanUserManageBasket($borrower, $basket[, $userflags]);
750 my $bool = CanUserManageBasket($borrowernumber, $basketno[, $userflags]);
752 Check if a borrower can manage a basket, according to system preference
753 AcqViewBaskets, user permissions and basket properties (creator, users list,
754 branch).
756 First parameter can be either a borrowernumber or a hashref as returned by
757 C4::Members::GetMember.
759 Second parameter can be either a basketno or a hashref as returned by
760 C4::Acquisition::GetBasket.
762 The third parameter is optional. If given, it should be a hashref as returned
763 by C4::Auth::getuserflags. If not, getuserflags is called.
765 If user is authorised to manage basket, returns 1.
766 Otherwise returns 0.
768 =cut
770 sub CanUserManageBasket {
771 my ($borrower, $basket, $userflags) = @_;
773 if (!ref $borrower) {
774 $borrower = C4::Members::GetMember(borrowernumber => $borrower);
776 if (!ref $basket) {
777 $basket = GetBasket($basket);
780 return 0 unless ($basket and $borrower);
782 my $borrowernumber = $borrower->{borrowernumber};
783 my $basketno = $basket->{basketno};
785 my $AcqViewBaskets = C4::Context->preference('AcqViewBaskets');
787 if (!defined $userflags) {
788 my $dbh = C4::Context->dbh;
789 my $sth = $dbh->prepare("SELECT flags FROM borrowers WHERE borrowernumber = ?");
790 $sth->execute($borrowernumber);
791 my ($flags) = $sth->fetchrow_array;
792 $sth->finish;
794 $userflags = C4::Auth::getuserflags($flags, $borrower->{userid}, $dbh);
797 unless ($userflags->{superlibrarian}
798 || (ref $userflags->{acquisition} && $userflags->{acquisition}->{order_manage_all})
799 || (!ref $userflags->{acquisition} && $userflags->{acquisition}))
801 if (not exists $userflags->{acquisition}) {
802 return 0;
805 if ( (ref $userflags->{acquisition} && !$userflags->{acquisition}->{order_manage})
806 || (!ref $userflags->{acquisition} && !$userflags->{acquisition}) ) {
807 return 0;
810 if ($AcqViewBaskets eq 'user'
811 && $basket->{authorisedby} != $borrowernumber
812 && grep($borrowernumber, GetBasketUsers($basketno)) == 0) {
813 return 0;
816 if ($AcqViewBaskets eq 'branch' && defined $basket->{branch}
817 && $basket->{branch} ne $borrower->{branchcode}) {
818 return 0;
822 return 1;
825 #------------------------------------------------------------#
827 =head3 GetBasketsByBasketgroup
829 $baskets = &GetBasketsByBasketgroup($basketgroupid);
831 Returns a reference to all baskets that belong to basketgroup $basketgroupid.
833 =cut
835 sub GetBasketsByBasketgroup {
836 my $basketgroupid = shift;
837 my $query = qq{
838 SELECT *, aqbasket.booksellerid as booksellerid
839 FROM aqbasket
840 LEFT JOIN aqcontract USING(contractnumber) WHERE basketgroupid=?
842 my $dbh = C4::Context->dbh;
843 my $sth = $dbh->prepare($query);
844 $sth->execute($basketgroupid);
845 return $sth->fetchall_arrayref({});
848 #------------------------------------------------------------#
850 =head3 NewBasketgroup
852 $basketgroupid = NewBasketgroup(\%hashref);
854 Adds a basketgroup to the aqbasketgroups table, and add the initial baskets to it.
856 $hashref->{'booksellerid'} is the 'id' field of the bookseller in the aqbooksellers table,
858 $hashref->{'name'} is the 'name' field of the basketgroup in the aqbasketgroups table,
860 $hashref->{'basketlist'} is a list reference of the 'id's of the baskets that belong to this group,
862 $hashref->{'billingplace'} is the 'billingplace' field of the basketgroup in the aqbasketgroups table,
864 $hashref->{'deliveryplace'} is the 'deliveryplace' field of the basketgroup in the aqbasketgroups table,
866 $hashref->{'freedeliveryplace'} is the 'freedeliveryplace' field of the basketgroup in the aqbasketgroups table,
868 $hashref->{'deliverycomment'} is the 'deliverycomment' field of the basketgroup in the aqbasketgroups table,
870 $hashref->{'closed'} is the 'closed' field of the aqbasketgroups table, it is false if 0, true otherwise.
872 =cut
874 sub NewBasketgroup {
875 my $basketgroupinfo = shift;
876 die "booksellerid is required to create a basketgroup" unless $basketgroupinfo->{'booksellerid'};
877 my $query = "INSERT INTO aqbasketgroups (";
878 my @params;
879 foreach my $field (qw(name billingplace deliveryplace freedeliveryplace deliverycomment closed)) {
880 if ( defined $basketgroupinfo->{$field} ) {
881 $query .= "$field, ";
882 push(@params, $basketgroupinfo->{$field});
885 $query .= "booksellerid) VALUES (";
886 foreach (@params) {
887 $query .= "?, ";
889 $query .= "?)";
890 push(@params, $basketgroupinfo->{'booksellerid'});
891 my $dbh = C4::Context->dbh;
892 my $sth = $dbh->prepare($query);
893 $sth->execute(@params);
894 my $basketgroupid = $dbh->{'mysql_insertid'};
895 if( $basketgroupinfo->{'basketlist'} ) {
896 foreach my $basketno (@{$basketgroupinfo->{'basketlist'}}) {
897 my $query2 = "UPDATE aqbasket SET basketgroupid=? WHERE basketno=?";
898 my $sth2 = $dbh->prepare($query2);
899 $sth2->execute($basketgroupid, $basketno);
902 return $basketgroupid;
905 #------------------------------------------------------------#
907 =head3 ModBasketgroup
909 ModBasketgroup(\%hashref);
911 Modifies a basketgroup in the aqbasketgroups table, and add the baskets to it.
913 $hashref->{'id'} is the 'id' field of the basketgroup in the aqbasketgroup table, this parameter is mandatory,
915 $hashref->{'name'} is the 'name' field of the basketgroup in the aqbasketgroups table,
917 $hashref->{'basketlist'} is a list reference of the 'id's of the baskets that belong to this group,
919 $hashref->{'billingplace'} is the 'billingplace' field of the basketgroup in the aqbasketgroups table,
921 $hashref->{'deliveryplace'} is the 'deliveryplace' field of the basketgroup in the aqbasketgroups table,
923 $hashref->{'freedeliveryplace'} is the 'freedeliveryplace' field of the basketgroup in the aqbasketgroups table,
925 $hashref->{'deliverycomment'} is the 'deliverycomment' field of the basketgroup in the aqbasketgroups table,
927 $hashref->{'closed'} is the 'closed' field of the aqbasketgroups table, it is false if 0, true otherwise.
929 =cut
931 sub ModBasketgroup {
932 my $basketgroupinfo = shift;
933 die "basketgroup id is required to edit a basketgroup" unless $basketgroupinfo->{'id'};
934 my $dbh = C4::Context->dbh;
935 my $query = "UPDATE aqbasketgroups SET ";
936 my @params;
937 foreach my $field (qw(name billingplace deliveryplace freedeliveryplace deliverycomment closed)) {
938 if ( defined $basketgroupinfo->{$field} ) {
939 $query .= "$field=?, ";
940 push(@params, $basketgroupinfo->{$field});
943 chop($query);
944 chop($query);
945 $query .= " WHERE id=?";
946 push(@params, $basketgroupinfo->{'id'});
947 my $sth = $dbh->prepare($query);
948 $sth->execute(@params);
950 $sth = $dbh->prepare('UPDATE aqbasket SET basketgroupid = NULL WHERE basketgroupid = ?');
951 $sth->execute($basketgroupinfo->{'id'});
953 if($basketgroupinfo->{'basketlist'} && @{$basketgroupinfo->{'basketlist'}}){
954 $sth = $dbh->prepare("UPDATE aqbasket SET basketgroupid=? WHERE basketno=?");
955 foreach my $basketno (@{$basketgroupinfo->{'basketlist'}}) {
956 $sth->execute($basketgroupinfo->{'id'}, $basketno);
959 return;
962 #------------------------------------------------------------#
964 =head3 DelBasketgroup
966 DelBasketgroup($basketgroupid);
968 Deletes a basketgroup in the aqbasketgroups table, and removes the reference to it from the baskets,
970 =over
972 =item C<$basketgroupid> is the 'id' field of the basket in the aqbasketgroup table
974 =back
976 =cut
978 sub DelBasketgroup {
979 my $basketgroupid = shift;
980 die "basketgroup id is required to edit a basketgroup" unless $basketgroupid;
981 my $query = "DELETE FROM aqbasketgroups WHERE id=?";
982 my $dbh = C4::Context->dbh;
983 my $sth = $dbh->prepare($query);
984 $sth->execute($basketgroupid);
985 return;
988 #------------------------------------------------------------#
991 =head2 FUNCTIONS ABOUT ORDERS
993 =head3 GetBasketgroup
995 $basketgroup = &GetBasketgroup($basketgroupid);
997 Returns a reference to the hash containing all information about the basketgroup.
999 =cut
1001 sub GetBasketgroup {
1002 my $basketgroupid = shift;
1003 die "basketgroup id is required to edit a basketgroup" unless $basketgroupid;
1004 my $dbh = C4::Context->dbh;
1005 my $result_set = $dbh->selectall_arrayref(
1006 'SELECT * FROM aqbasketgroups WHERE id=?',
1007 { Slice => {} },
1008 $basketgroupid
1010 return $result_set->[0]; # id is unique
1013 #------------------------------------------------------------#
1015 =head3 GetBasketgroups
1017 $basketgroups = &GetBasketgroups($booksellerid);
1019 Returns a reference to the array of all the basketgroups of bookseller $booksellerid.
1021 =cut
1023 sub GetBasketgroups {
1024 my $booksellerid = shift;
1025 die 'bookseller id is required to edit a basketgroup' unless $booksellerid;
1026 my $query = 'SELECT * FROM aqbasketgroups WHERE booksellerid=? ORDER BY id DESC';
1027 my $dbh = C4::Context->dbh;
1028 my $sth = $dbh->prepare($query);
1029 $sth->execute($booksellerid);
1030 return $sth->fetchall_arrayref({});
1033 #------------------------------------------------------------#
1035 =head2 FUNCTIONS ABOUT ORDERS
1037 =head3 GetOrders
1039 @orders = &GetOrders($basketnumber, $orderby);
1041 Looks up the pending (non-cancelled) orders with the given basket
1042 number. If C<$booksellerID> is non-empty, only orders from that seller
1043 are returned.
1045 return :
1046 C<&basket> returns a two-element array. C<@orders> is an array of
1047 references-to-hash, whose keys are the fields from the aqorders,
1048 biblio, and biblioitems tables in the Koha database.
1050 =cut
1052 sub GetOrders {
1053 my ( $basketno, $orderby ) = @_;
1054 return () unless $basketno;
1055 my $dbh = C4::Context->dbh;
1056 my $query ="
1057 SELECT biblio.*,biblioitems.*,
1058 aqorders.*,
1059 aqbudgets.*,
1060 aqorders_transfers.ordernumber_from AS transferred_from,
1061 aqorders_transfers.timestamp AS transferred_from_timestamp
1062 FROM aqorders
1063 LEFT JOIN aqbudgets ON aqbudgets.budget_id = aqorders.budget_id
1064 LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber
1065 LEFT JOIN biblioitems ON biblioitems.biblionumber =biblio.biblionumber
1066 LEFT JOIN aqorders_transfers ON aqorders_transfers.ordernumber_to = aqorders.ordernumber
1067 WHERE basketno=?
1068 AND (datecancellationprinted IS NULL OR datecancellationprinted='0000-00-00')
1071 $orderby = "biblioitems.publishercode,biblio.title" unless $orderby;
1072 $query .= " ORDER BY $orderby";
1073 my $result_set =
1074 $dbh->selectall_arrayref( $query, { Slice => {} }, $basketno );
1075 return @{$result_set};
1079 #------------------------------------------------------------#
1081 =head3 GetOrdersByBiblionumber
1083 @orders = &GetOrdersByBiblionumber($biblionumber);
1085 Looks up the orders with linked to a specific $biblionumber, including
1086 cancelled orders and received orders.
1088 return :
1089 C<@orders> is an array of references-to-hash, whose keys are the
1090 fields from the aqorders, biblio, and biblioitems tables in the Koha database.
1092 =cut
1094 sub GetOrdersByBiblionumber {
1095 my $biblionumber = shift;
1096 return unless $biblionumber;
1097 my $dbh = C4::Context->dbh;
1098 my $query ="
1099 SELECT biblio.*,biblioitems.*,
1100 aqorders.*,
1101 aqbudgets.*
1102 FROM aqorders
1103 LEFT JOIN aqbudgets ON aqbudgets.budget_id = aqorders.budget_id
1104 LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber
1105 LEFT JOIN biblioitems ON biblioitems.biblionumber =biblio.biblionumber
1106 WHERE aqorders.biblionumber=?
1108 my $result_set =
1109 $dbh->selectall_arrayref( $query, { Slice => {} }, $biblionumber );
1110 return @{$result_set};
1114 #------------------------------------------------------------#
1116 =head3 GetOrder
1118 $order = &GetOrder($ordernumber);
1120 Looks up an order by order number.
1122 Returns a reference-to-hash describing the order. The keys of
1123 C<$order> are fields from the biblio, biblioitems, aqorders tables of the Koha database.
1125 =cut
1127 sub GetOrder {
1128 my ($ordernumber) = @_;
1129 return unless $ordernumber;
1131 my $dbh = C4::Context->dbh;
1132 my $query = qq{SELECT
1133 aqorders.*,
1134 biblio.title,
1135 biblio.author,
1136 aqbasket.basketname,
1137 borrowers.branchcode,
1138 biblioitems.publicationyear,
1139 biblio.copyrightdate,
1140 biblioitems.editionstatement,
1141 biblioitems.isbn,
1142 biblioitems.ean,
1143 biblio.seriestitle,
1144 biblioitems.publishercode,
1145 aqorders.rrp AS unitpricesupplier,
1146 aqorders.ecost AS unitpricelib,
1147 aqorders.claims_count AS claims_count,
1148 aqorders.claimed_date AS claimed_date,
1149 aqbudgets.budget_name AS budget,
1150 aqbooksellers.name AS supplier,
1151 aqbooksellers.id AS supplierid,
1152 biblioitems.publishercode AS publisher,
1153 ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) AS estimateddeliverydate,
1154 DATE(aqbasket.closedate) AS orderdate,
1155 aqorders.quantity - COALESCE(aqorders.quantityreceived,0) AS quantity_to_receive,
1156 (aqorders.quantity - COALESCE(aqorders.quantityreceived,0)) * aqorders.rrp AS subtotal,
1157 DATEDIFF(CURDATE( ),closedate) AS latesince
1158 FROM aqorders LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber
1159 LEFT JOIN biblioitems ON biblioitems.biblionumber = biblio.biblionumber
1160 LEFT JOIN aqbudgets ON aqorders.budget_id = aqbudgets.budget_id,
1161 aqbasket LEFT JOIN borrowers ON aqbasket.authorisedby = borrowers.borrowernumber
1162 LEFT JOIN aqbooksellers ON aqbasket.booksellerid = aqbooksellers.id
1163 WHERE aqorders.basketno = aqbasket.basketno
1164 AND ordernumber=?};
1165 my $result_set =
1166 $dbh->selectall_arrayref( $query, { Slice => {} }, $ordernumber );
1168 # result_set assumed to contain 1 match
1169 return $result_set->[0];
1172 =head3 GetLastOrderNotReceivedFromSubscriptionid
1174 $order = &GetLastOrderNotReceivedFromSubscriptionid($subscriptionid);
1176 Returns a reference-to-hash describing the last order not received for a subscription.
1178 =cut
1180 sub GetLastOrderNotReceivedFromSubscriptionid {
1181 my ( $subscriptionid ) = @_;
1182 my $dbh = C4::Context->dbh;
1183 my $query = qq|
1184 SELECT * FROM aqorders
1185 LEFT JOIN subscription
1186 ON ( aqorders.subscriptionid = subscription.subscriptionid )
1187 WHERE aqorders.subscriptionid = ?
1188 AND aqorders.datereceived IS NULL
1189 LIMIT 1
1191 my $result_set =
1192 $dbh->selectall_arrayref( $query, { Slice => {} }, $subscriptionid );
1194 # result_set assumed to contain 1 match
1195 return $result_set->[0];
1198 =head3 GetLastOrderReceivedFromSubscriptionid
1200 $order = &GetLastOrderReceivedFromSubscriptionid($subscriptionid);
1202 Returns a reference-to-hash describing the last order received for a subscription.
1204 =cut
1206 sub GetLastOrderReceivedFromSubscriptionid {
1207 my ( $subscriptionid ) = @_;
1208 my $dbh = C4::Context->dbh;
1209 my $query = qq|
1210 SELECT * FROM aqorders
1211 LEFT JOIN subscription
1212 ON ( aqorders.subscriptionid = subscription.subscriptionid )
1213 WHERE aqorders.subscriptionid = ?
1214 AND aqorders.datereceived =
1216 SELECT MAX( aqorders.datereceived )
1217 FROM aqorders
1218 LEFT JOIN subscription
1219 ON ( aqorders.subscriptionid = subscription.subscriptionid )
1220 WHERE aqorders.subscriptionid = ?
1221 AND aqorders.datereceived IS NOT NULL
1223 ORDER BY ordernumber DESC
1224 LIMIT 1
1226 my $result_set =
1227 $dbh->selectall_arrayref( $query, { Slice => {} }, $subscriptionid, $subscriptionid );
1229 # result_set assumed to contain 1 match
1230 return $result_set->[0];
1234 #------------------------------------------------------------#
1236 =head3 ModOrder
1238 &ModOrder(\%hashref);
1240 Modifies an existing order. Updates the order with order number
1241 $hashref->{'ordernumber'} and biblionumber $hashref->{'biblionumber'}. All
1242 other keys of the hash update the fields with the same name in the aqorders
1243 table of the Koha database.
1245 =cut
1247 sub ModOrder {
1248 my $orderinfo = shift;
1250 die "Ordernumber is required" if $orderinfo->{'ordernumber'} eq '' ;
1251 die "Biblionumber is required" if $orderinfo->{'biblionumber'} eq '';
1253 my $dbh = C4::Context->dbh;
1254 my @params;
1256 # update uncertainprice to an integer, just in case (under FF, checked boxes have the value "ON" by default)
1257 $orderinfo->{uncertainprice}=1 if $orderinfo->{uncertainprice};
1259 # delete($orderinfo->{'branchcode'});
1260 # the hash contains a lot of entries not in aqorders, so get the columns ...
1261 my $sth = $dbh->prepare("SELECT * FROM aqorders LIMIT 1;");
1262 $sth->execute;
1263 my $colnames = $sth->{NAME};
1264 #FIXME Be careful. If aqorders would have columns with diacritics,
1265 #you should need to decode what you get back from NAME.
1266 #See report 10110 and guided_reports.pl
1267 my $query = "UPDATE aqorders SET ";
1269 foreach my $orderinfokey (grep(!/ordernumber/, keys %$orderinfo)){
1270 # ... and skip hash entries that are not in the aqorders table
1271 # FIXME : probably not the best way to do it (would be better to have a correct hash)
1272 next unless grep(/^$orderinfokey$/, @$colnames);
1273 $query .= "$orderinfokey=?, ";
1274 push(@params, $orderinfo->{$orderinfokey});
1277 $query .= "timestamp=NOW() WHERE ordernumber=?";
1278 push(@params, $orderinfo->{'ordernumber'} );
1279 $sth = $dbh->prepare($query);
1280 $sth->execute(@params);
1281 return;
1284 #------------------------------------------------------------#
1286 =head3 ModItemOrder
1288 ModItemOrder($itemnumber, $ordernumber);
1290 Modifies the ordernumber of an item in aqorders_items.
1292 =cut
1294 sub ModItemOrder {
1295 my ($itemnumber, $ordernumber) = @_;
1297 return unless ($itemnumber and $ordernumber);
1299 my $dbh = C4::Context->dbh;
1300 my $query = qq{
1301 UPDATE aqorders_items
1302 SET ordernumber = ?
1303 WHERE itemnumber = ?
1305 my $sth = $dbh->prepare($query);
1306 return $sth->execute($ordernumber, $itemnumber);
1309 #------------------------------------------------------------#
1311 =head3 GetCancelledOrders
1313 my @orders = GetCancelledOrders($basketno, $orderby);
1315 Returns cancelled orders for a basket
1317 =cut
1319 sub GetCancelledOrders {
1320 my ( $basketno, $orderby ) = @_;
1322 return () unless $basketno;
1324 my $dbh = C4::Context->dbh;
1325 my $query = "
1326 SELECT
1327 biblio.*,
1328 biblioitems.*,
1329 aqorders.*,
1330 aqbudgets.*,
1331 aqorders_transfers.ordernumber_to AS transferred_to,
1332 aqorders_transfers.timestamp AS transferred_to_timestamp
1333 FROM aqorders
1334 LEFT JOIN aqbudgets ON aqbudgets.budget_id = aqorders.budget_id
1335 LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber
1336 LEFT JOIN biblioitems ON biblioitems.biblionumber = biblio.biblionumber
1337 LEFT JOIN aqorders_transfers ON aqorders_transfers.ordernumber_from = aqorders.ordernumber
1338 WHERE basketno = ?
1339 AND (datecancellationprinted IS NOT NULL
1340 AND datecancellationprinted <> '0000-00-00')
1343 $orderby = "aqorders.datecancellationprinted desc, aqorders.timestamp desc"
1344 unless $orderby;
1345 $query .= " ORDER BY $orderby";
1346 my $sth = $dbh->prepare($query);
1347 $sth->execute($basketno);
1348 my $results = $sth->fetchall_arrayref( {} );
1350 return @$results;
1354 #------------------------------------------------------------#
1356 =head3 ModReceiveOrder
1358 &ModReceiveOrder({
1359 biblionumber => $biblionumber,
1360 ordernumber => $ordernumber,
1361 quantityreceived => $quantityreceived,
1362 user => $user,
1363 cost => $cost,
1364 ecost => $ecost,
1365 invoiceid => $invoiceid,
1366 rrp => $rrp,
1367 budget_id => $budget_id,
1368 datereceived => $datereceived,
1369 received_itemnumbers => \@received_itemnumbers,
1370 order_internalnote => $order_internalnote,
1371 order_vendornote => $order_vendornote,
1374 Updates an order, to reflect the fact that it was received, at least
1375 in part. All arguments not mentioned below update the fields with the
1376 same name in the aqorders table of the Koha database.
1378 If a partial order is received, splits the order into two.
1380 Updates the order with bibilionumber C<$biblionumber> and ordernumber
1381 C<$ordernumber>.
1383 =cut
1386 sub ModReceiveOrder {
1387 my ( $params ) = @_;
1388 my $biblionumber = $params->{biblionumber};
1389 my $ordernumber = $params->{ordernumber};
1390 my $quantrec = $params->{quantityreceived};
1391 my $user = $params->{user};
1392 my $cost = $params->{cost};
1393 my $ecost = $params->{ecost};
1394 my $invoiceid = $params->{invoiceid};
1395 my $rrp = $params->{rrp};
1396 my $budget_id = $params->{budget_id};
1397 my $datereceived = $params->{datereceived};
1398 my $received_items = $params->{received_items};
1399 my $order_internalnote = $params->{order_internalnote};
1400 my $order_vendornote = $params->{order_vendornote};
1402 my $dbh = C4::Context->dbh;
1403 $datereceived = C4::Dates->output('iso') unless $datereceived;
1404 my $suggestionid = GetSuggestionFromBiblionumber( $biblionumber );
1405 if ($suggestionid) {
1406 ModSuggestion( {suggestionid=>$suggestionid,
1407 STATUS=>'AVAILABLE',
1408 biblionumber=> $biblionumber}
1412 my $result_set = $dbh->selectall_arrayref(
1413 q{SELECT * FROM aqorders WHERE biblionumber=? AND aqorders.ordernumber=?},
1414 { Slice => {} }, $biblionumber, $ordernumber
1417 # we assume we have a unique order
1418 my $order = $result_set->[0];
1420 my $new_ordernumber = $ordernumber;
1421 if ( $order->{quantity} > $quantrec ) {
1422 # Split order line in two parts: the first is the original order line
1423 # without received items (the quantity is decreased),
1424 # the second part is a new order line with quantity=quantityrec
1425 # (entirely received)
1426 my $query = q|
1427 UPDATE aqorders
1428 SET quantity = ?,
1429 orderstatus = 'partial'|;
1430 $query .= q|, order_internalnote = ?| if defined $order_internalnote;
1431 $query .= q|, order_vendornote = ?| if defined $order_vendornote;
1432 $query .= q| WHERE ordernumber = ?|;
1433 my $sth = $dbh->prepare($query);
1435 $sth->execute(
1436 $order->{quantity} - $quantrec,
1437 ( defined $order_internalnote ? $order_internalnote : () ),
1438 ( defined $order_vendornote ? $order_vendornote : () ),
1439 $ordernumber
1442 delete $order->{'ordernumber'};
1443 $order->{'budget_id'} = ( $budget_id || $order->{'budget_id'} );
1444 $order->{'quantity'} = $quantrec;
1445 $order->{'quantityreceived'} = $quantrec;
1446 $order->{'datereceived'} = $datereceived;
1447 $order->{'invoiceid'} = $invoiceid;
1448 $order->{'unitprice'} = $cost;
1449 $order->{'rrp'} = $rrp;
1450 $order->{ecost} = $ecost;
1451 $order->{'orderstatus'} = 'complete';
1452 $new_ordernumber = Koha::Acquisition::Order->new($order)->insert->{ordernumber};
1454 if ($received_items) {
1455 foreach my $itemnumber (@$received_items) {
1456 ModItemOrder($itemnumber, $new_ordernumber);
1459 } else {
1460 my $query = q|
1461 update aqorders
1462 set quantityreceived=?,datereceived=?,invoiceid=?,
1463 unitprice=?,rrp=?,ecost=?,budget_id=?,orderstatus='complete'|;
1464 $query .= q|, order_internalnote = ?| if defined $order_internalnote;
1465 $query .= q|, order_vendornote = ?| if defined $order_vendornote;
1466 $query .= q| where biblionumber=? and ordernumber=?|;
1467 my $sth = $dbh->prepare( $query );
1468 $sth->execute(
1469 $quantrec,
1470 $datereceived,
1471 $invoiceid,
1472 $cost,
1473 $rrp,
1474 $ecost,
1475 ( $budget_id ? $budget_id : $order->{budget_id} ),
1476 ( defined $order_internalnote ? $order_internalnote : () ),
1477 ( defined $order_vendornote ? $order_vendornote : () ),
1478 $biblionumber,
1479 $ordernumber
1482 # All items have been received, sent a notification to users
1483 NotifyOrderUsers( $ordernumber );
1486 return ($datereceived, $new_ordernumber);
1489 =head3 CancelReceipt
1491 my $parent_ordernumber = CancelReceipt($ordernumber);
1493 Cancel an order line receipt and update the parent order line, as if no
1494 receipt was made.
1495 If items are created at receipt (AcqCreateItem = receiving) then delete
1496 these items.
1498 =cut
1500 sub CancelReceipt {
1501 my $ordernumber = shift;
1503 return unless $ordernumber;
1505 my $dbh = C4::Context->dbh;
1506 my $query = qq{
1507 SELECT datereceived, parent_ordernumber, quantity
1508 FROM aqorders
1509 WHERE ordernumber = ?
1511 my $sth = $dbh->prepare($query);
1512 $sth->execute($ordernumber);
1513 my $order = $sth->fetchrow_hashref;
1514 unless($order) {
1515 warn "CancelReceipt: order $ordernumber does not exist";
1516 return;
1518 unless($order->{'datereceived'}) {
1519 warn "CancelReceipt: order $ordernumber is not received";
1520 return;
1523 my $parent_ordernumber = $order->{'parent_ordernumber'};
1525 my @itemnumbers = GetItemnumbersFromOrder( $ordernumber );
1527 if($parent_ordernumber == $ordernumber || not $parent_ordernumber) {
1528 # The order line has no parent, just mark it as not received
1529 $query = qq{
1530 UPDATE aqorders
1531 SET quantityreceived = ?,
1532 datereceived = ?,
1533 invoiceid = ?,
1534 orderstatus = 'ordered'
1535 WHERE ordernumber = ?
1537 $sth = $dbh->prepare($query);
1538 $sth->execute(0, undef, undef, $ordernumber);
1539 _cancel_items_receipt( $ordernumber );
1540 } else {
1541 # The order line has a parent, increase parent quantity and delete
1542 # the order line.
1543 $query = qq{
1544 SELECT quantity, datereceived
1545 FROM aqorders
1546 WHERE ordernumber = ?
1548 $sth = $dbh->prepare($query);
1549 $sth->execute($parent_ordernumber);
1550 my $parent_order = $sth->fetchrow_hashref;
1551 unless($parent_order) {
1552 warn "Parent order $parent_ordernumber does not exist.";
1553 return;
1555 if($parent_order->{'datereceived'}) {
1556 warn "CancelReceipt: parent order is received.".
1557 " Can't cancel receipt.";
1558 return;
1560 $query = qq{
1561 UPDATE aqorders
1562 SET quantity = ?,
1563 orderstatus = 'ordered'
1564 WHERE ordernumber = ?
1566 $sth = $dbh->prepare($query);
1567 my $rv = $sth->execute(
1568 $order->{'quantity'} + $parent_order->{'quantity'},
1569 $parent_ordernumber
1571 unless($rv) {
1572 warn "Cannot update parent order line, so do not cancel".
1573 " receipt";
1574 return;
1576 _cancel_items_receipt( $ordernumber, $parent_ordernumber );
1577 # Delete order line
1578 $query = qq{
1579 DELETE FROM aqorders
1580 WHERE ordernumber = ?
1582 $sth = $dbh->prepare($query);
1583 $sth->execute($ordernumber);
1587 if(C4::Context->preference('AcqCreateItem') eq 'ordering') {
1588 my @affects = split q{\|}, C4::Context->preference("AcqItemSetSubfieldsWhenReceiptIsCancelled");
1589 if ( @affects ) {
1590 for my $in ( @itemnumbers ) {
1591 my $biblionumber = C4::Biblio::GetBiblionumberFromItemnumber( $in );
1592 my $frameworkcode = GetFrameworkCode($biblionumber);
1593 my ( $itemfield ) = GetMarcFromKohaField( 'items.itemnumber', $frameworkcode );
1594 my $item = C4::Items::GetMarcItem( $biblionumber, $in );
1595 for my $affect ( @affects ) {
1596 my ( $sf, $v ) = split q{=}, $affect, 2;
1597 foreach ( $item->field($itemfield) ) {
1598 $_->update( $sf => $v );
1601 C4::Items::ModItemFromMarc( $item, $biblionumber, $in );
1606 return $parent_ordernumber;
1609 sub _cancel_items_receipt {
1610 my ( $ordernumber, $parent_ordernumber ) = @_;
1611 $parent_ordernumber ||= $ordernumber;
1613 my @itemnumbers = GetItemnumbersFromOrder($ordernumber);
1614 if(C4::Context->preference('AcqCreateItem') eq 'receiving') {
1615 # Remove items that were created at receipt
1616 my $query = qq{
1617 DELETE FROM items, aqorders_items
1618 USING items, aqorders_items
1619 WHERE items.itemnumber = ? AND aqorders_items.itemnumber = ?
1621 my $dbh = C4::Context->dbh;
1622 my $sth = $dbh->prepare($query);
1623 foreach my $itemnumber (@itemnumbers) {
1624 $sth->execute($itemnumber, $itemnumber);
1626 } else {
1627 # Update items
1628 foreach my $itemnumber (@itemnumbers) {
1629 ModItemOrder($itemnumber, $parent_ordernumber);
1634 #------------------------------------------------------------#
1636 =head3 SearchOrders
1638 @results = &SearchOrders({
1639 ordernumber => $ordernumber,
1640 search => $search,
1641 biblionumber => $biblionumber,
1642 ean => $ean,
1643 booksellerid => $booksellerid,
1644 basketno => $basketno,
1645 owner => $owner,
1646 pending => $pending
1647 ordered => $ordered
1650 Searches for orders.
1652 C<$owner> Finds order for the logged in user.
1653 C<$pending> Finds pending orders. Ignores completed and cancelled orders.
1654 C<$ordered> Finds orders to receive only (status 'ordered' or 'partial').
1657 C<@results> is an array of references-to-hash with the keys are fields
1658 from aqorders, biblio, biblioitems and aqbasket tables.
1660 =cut
1662 sub SearchOrders {
1663 my ( $params ) = @_;
1664 my $ordernumber = $params->{ordernumber};
1665 my $search = $params->{search};
1666 my $ean = $params->{ean};
1667 my $booksellerid = $params->{booksellerid};
1668 my $basketno = $params->{basketno};
1669 my $basketname = $params->{basketname};
1670 my $basketgroupname = $params->{basketgroupname};
1671 my $owner = $params->{owner};
1672 my $pending = $params->{pending};
1673 my $ordered = $params->{ordered};
1674 my $biblionumber = $params->{biblionumber};
1675 my $budget_id = $params->{budget_id};
1677 my $dbh = C4::Context->dbh;
1678 my @args = ();
1679 my $query = q{
1680 SELECT aqbasket.basketno,
1681 borrowers.surname,
1682 borrowers.firstname,
1683 biblio.*,
1684 biblioitems.isbn,
1685 biblioitems.biblioitemnumber,
1686 aqbasket.authorisedby,
1687 aqbasket.booksellerid,
1688 aqbasket.closedate,
1689 aqbasket.creationdate,
1690 aqbasket.basketname,
1691 aqbasketgroups.id as basketgroupid,
1692 aqbasketgroups.name as basketgroupname,
1693 aqorders.*
1694 FROM aqorders
1695 LEFT JOIN aqbasket ON aqorders.basketno = aqbasket.basketno
1696 LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid = aqbasketgroups.id
1697 LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber
1698 LEFT JOIN biblio ON aqorders.biblionumber=biblio.biblionumber
1699 LEFT JOIN biblioitems ON biblioitems.biblionumber=biblio.biblionumber
1702 # If we search on ordernumber, we retrieve the transfered order if a transfer has been done.
1703 $query .= q{
1704 LEFT JOIN aqorders_transfers ON aqorders_transfers.ordernumber_to = aqorders.ordernumber
1705 } if $ordernumber;
1707 $query .= q{
1708 WHERE (datecancellationprinted is NULL)
1711 if ( $pending or $ordered ) {
1712 $query .= q{ AND (quantity > quantityreceived OR quantityreceived is NULL)};
1714 if ( $ordered ) {
1715 $query .= q{ AND aqorders.orderstatus IN ( "ordered", "partial" )};
1718 my $userenv = C4::Context->userenv;
1719 if ( C4::Context->preference("IndependentBranches") ) {
1720 unless ( C4::Context->IsSuperLibrarian() ) {
1721 $query .= q{
1722 AND (
1723 borrowers.branchcode = ?
1724 OR borrowers.branchcode = ''
1727 push @args, $userenv->{branch};
1731 if ( $ordernumber ) {
1732 $query .= ' AND ( aqorders.ordernumber = ? OR aqorders_transfers.ordernumber_from = ? ) ';
1733 push @args, ( $ordernumber, $ordernumber );
1735 if ( $biblionumber ) {
1736 $query .= 'AND aqorders.biblionumber = ?';
1737 push @args, $biblionumber;
1739 if( $search ) {
1740 $query .= ' AND (biblio.title LIKE ? OR biblio.author LIKE ? OR biblioitems.isbn LIKE ?)';
1741 push @args, ("%$search%","%$search%","%$search%");
1743 if ( $ean ) {
1744 $query .= ' AND biblioitems.ean = ?';
1745 push @args, $ean;
1747 if ( $booksellerid ) {
1748 $query .= 'AND aqbasket.booksellerid = ?';
1749 push @args, $booksellerid;
1751 if( $basketno ) {
1752 $query .= 'AND aqbasket.basketno = ?';
1753 push @args, $basketno;
1755 if( $basketname ) {
1756 $query .= 'AND aqbasket.basketname LIKE ?';
1757 push @args, "%$basketname%";
1759 if( $basketgroupname ) {
1760 $query .= ' AND aqbasketgroups.name LIKE ?';
1761 push @args, "%$basketgroupname%";
1764 if ( $owner ) {
1765 $query .= ' AND aqbasket.authorisedby=? ';
1766 push @args, $userenv->{'number'};
1769 if ( $budget_id ) {
1770 $query .= ' AND aqorders.budget_id = ?';
1771 push @args, $budget_id;
1774 $query .= ' ORDER BY aqbasket.basketno';
1776 my $sth = $dbh->prepare($query);
1777 $sth->execute(@args);
1778 return $sth->fetchall_arrayref({});
1781 #------------------------------------------------------------#
1783 =head3 DelOrder
1785 &DelOrder($biblionumber, $ordernumber);
1787 Cancel the order with the given order and biblio numbers. It does not
1788 delete any entries in the aqorders table, it merely marks them as
1789 cancelled.
1791 =cut
1793 sub DelOrder {
1794 my ( $bibnum, $ordernumber, $delete_biblio, $reason ) = @_;
1796 my $error;
1797 my $dbh = C4::Context->dbh;
1798 my $query = "
1799 UPDATE aqorders
1800 SET datecancellationprinted=now(), orderstatus='cancelled'
1802 if($reason) {
1803 $query .= ", cancellationreason = ? ";
1805 $query .= "
1806 WHERE biblionumber=? AND ordernumber=?
1808 my $sth = $dbh->prepare($query);
1809 if($reason) {
1810 $sth->execute($reason, $bibnum, $ordernumber);
1811 } else {
1812 $sth->execute( $bibnum, $ordernumber );
1814 $sth->finish;
1816 my @itemnumbers = GetItemnumbersFromOrder( $ordernumber );
1817 foreach my $itemnumber (@itemnumbers){
1818 my $delcheck = C4::Items::DelItemCheck( $dbh, $bibnum, $itemnumber );
1820 if($delcheck != 1) {
1821 $error->{'delitem'} = 1;
1825 if($delete_biblio) {
1826 # We get the number of remaining items
1827 my $itemcount = C4::Items::GetItemsCount($bibnum);
1829 # If there are no items left,
1830 if ( $itemcount == 0 ) {
1831 # We delete the record
1832 my $delcheck = DelBiblio($bibnum);
1834 if($delcheck) {
1835 $error->{'delbiblio'} = 1;
1840 return $error;
1843 =head3 TransferOrder
1845 my $newordernumber = TransferOrder($ordernumber, $basketno);
1847 Transfer an order line to a basket.
1848 Mark $ordernumber as cancelled with an internal note 'Cancelled and transfered
1849 to BOOKSELLER on DATE' and create new order with internal note
1850 'Transfered from BOOKSELLER on DATE'.
1851 Move all attached items to the new order.
1852 Received orders cannot be transfered.
1853 Return the ordernumber of created order.
1855 =cut
1857 sub TransferOrder {
1858 my ($ordernumber, $basketno) = @_;
1860 return unless ($ordernumber and $basketno);
1862 my $order = GetOrder( $ordernumber );
1863 return if $order->{datereceived};
1864 my $basket = GetBasket($basketno);
1865 return unless $basket;
1867 my $dbh = C4::Context->dbh;
1868 my ($query, $sth, $rv);
1870 $query = q{
1871 UPDATE aqorders
1872 SET datecancellationprinted = CAST(NOW() AS date)
1873 WHERE ordernumber = ?
1875 $sth = $dbh->prepare($query);
1876 $rv = $sth->execute($ordernumber);
1878 delete $order->{'ordernumber'};
1879 delete $order->{parent_ordernumber};
1880 $order->{'basketno'} = $basketno;
1882 my $newordernumber = Koha::Acquisition::Order->new($order)->insert->{ordernumber};
1884 $query = q{
1885 UPDATE aqorders_items
1886 SET ordernumber = ?
1887 WHERE ordernumber = ?
1889 $sth = $dbh->prepare($query);
1890 $sth->execute($newordernumber, $ordernumber);
1892 $query = q{
1893 INSERT INTO aqorders_transfers (ordernumber_from, ordernumber_to)
1894 VALUES (?, ?)
1896 $sth = $dbh->prepare($query);
1897 $sth->execute($ordernumber, $newordernumber);
1899 return $newordernumber;
1902 =head2 FUNCTIONS ABOUT PARCELS
1904 =head3 GetParcels
1906 $results = &GetParcels($bookseller, $order, $code, $datefrom, $dateto);
1908 get a lists of parcels.
1910 * Input arg :
1912 =over
1914 =item $bookseller
1915 is the bookseller this function has to get parcels.
1917 =item $order
1918 To know on what criteria the results list has to be ordered.
1920 =item $code
1921 is the booksellerinvoicenumber.
1923 =item $datefrom & $dateto
1924 to know on what date this function has to filter its search.
1926 =back
1928 * return:
1929 a pointer on a hash list containing parcel informations as such :
1931 =over
1933 =item Creation date
1935 =item Last operation
1937 =item Number of biblio
1939 =item Number of items
1941 =back
1943 =cut
1945 sub GetParcels {
1946 my ($bookseller,$order, $code, $datefrom, $dateto) = @_;
1947 my $dbh = C4::Context->dbh;
1948 my @query_params = ();
1949 my $strsth ="
1950 SELECT aqinvoices.invoicenumber,
1951 datereceived,purchaseordernumber,
1952 count(DISTINCT biblionumber) AS biblio,
1953 sum(quantity) AS itemsexpected,
1954 sum(quantityreceived) AS itemsreceived
1955 FROM aqorders LEFT JOIN aqbasket ON aqbasket.basketno = aqorders.basketno
1956 LEFT JOIN aqinvoices ON aqorders.invoiceid = aqinvoices.invoiceid
1957 WHERE aqbasket.booksellerid = ? and datereceived IS NOT NULL
1959 push @query_params, $bookseller;
1961 if ( defined $code ) {
1962 $strsth .= ' and aqinvoices.invoicenumber like ? ';
1963 # add a % to the end of the code to allow stemming.
1964 push @query_params, "$code%";
1967 if ( defined $datefrom ) {
1968 $strsth .= ' and datereceived >= ? ';
1969 push @query_params, $datefrom;
1972 if ( defined $dateto ) {
1973 $strsth .= 'and datereceived <= ? ';
1974 push @query_params, $dateto;
1977 $strsth .= "group by aqinvoices.invoicenumber,datereceived ";
1979 # can't use a placeholder to place this column name.
1980 # but, we could probably be checking to make sure it is a column that will be fetched.
1981 $strsth .= "order by $order " if ($order);
1983 my $sth = $dbh->prepare($strsth);
1985 $sth->execute( @query_params );
1986 my $results = $sth->fetchall_arrayref({});
1987 return @{$results};
1990 #------------------------------------------------------------#
1992 =head3 GetLateOrders
1994 @results = &GetLateOrders;
1996 Searches for bookseller with late orders.
1998 return:
1999 the table of supplier with late issues. This table is full of hashref.
2001 =cut
2003 sub GetLateOrders {
2004 my $delay = shift;
2005 my $supplierid = shift;
2006 my $branch = shift;
2007 my $estimateddeliverydatefrom = shift;
2008 my $estimateddeliverydateto = shift;
2010 my $dbh = C4::Context->dbh;
2012 #BEWARE, order of parenthesis and LEFT JOIN is important for speed
2013 my $dbdriver = C4::Context->config("db_scheme") || "mysql";
2015 my @query_params = ();
2016 my $select = "
2017 SELECT aqbasket.basketno,
2018 aqorders.ordernumber,
2019 DATE(aqbasket.closedate) AS orderdate,
2020 aqbasket.basketname AS basketname,
2021 aqbasket.basketgroupid AS basketgroupid,
2022 aqbasketgroups.name AS basketgroupname,
2023 aqorders.rrp AS unitpricesupplier,
2024 aqorders.ecost AS unitpricelib,
2025 aqorders.claims_count AS claims_count,
2026 aqorders.claimed_date AS claimed_date,
2027 aqbudgets.budget_name AS budget,
2028 borrowers.branchcode AS branch,
2029 aqbooksellers.name AS supplier,
2030 aqbooksellers.id AS supplierid,
2031 biblio.author, biblio.title,
2032 biblioitems.publishercode AS publisher,
2033 biblioitems.publicationyear,
2034 ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) AS estimateddeliverydate,
2036 my $from = "
2037 FROM
2038 aqorders LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber
2039 LEFT JOIN biblioitems ON biblioitems.biblionumber = biblio.biblionumber
2040 LEFT JOIN aqbudgets ON aqorders.budget_id = aqbudgets.budget_id,
2041 aqbasket LEFT JOIN borrowers ON aqbasket.authorisedby = borrowers.borrowernumber
2042 LEFT JOIN aqbooksellers ON aqbasket.booksellerid = aqbooksellers.id
2043 LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid = aqbasketgroups.id
2044 WHERE aqorders.basketno = aqbasket.basketno
2045 AND ( datereceived = ''
2046 OR datereceived IS NULL
2047 OR aqorders.quantityreceived < aqorders.quantity
2049 AND aqbasket.closedate IS NOT NULL
2050 AND (aqorders.datecancellationprinted IS NULL OR aqorders.datecancellationprinted='0000-00-00')
2052 my $having = "";
2053 if ($dbdriver eq "mysql") {
2054 $select .= "
2055 aqorders.quantity - COALESCE(aqorders.quantityreceived,0) AS quantity,
2056 (aqorders.quantity - COALESCE(aqorders.quantityreceived,0)) * aqorders.rrp AS subtotal,
2057 DATEDIFF(CAST(now() AS date),closedate) AS latesince
2059 if ( defined $delay ) {
2060 $from .= " AND (closedate <= DATE_SUB(CAST(now() AS date),INTERVAL ? DAY)) " ;
2061 push @query_params, $delay;
2063 $having = "
2064 HAVING quantity <> 0
2065 AND unitpricesupplier <> 0
2066 AND unitpricelib <> 0
2068 } else {
2069 # FIXME: account for IFNULL as above
2070 $select .= "
2071 aqorders.quantity AS quantity,
2072 aqorders.quantity * aqorders.rrp AS subtotal,
2073 (CAST(now() AS date) - closedate) AS latesince
2075 if ( defined $delay ) {
2076 $from .= " AND (closedate <= (CAST(now() AS date) -(INTERVAL ? DAY)) ";
2077 push @query_params, $delay;
2080 if (defined $supplierid) {
2081 $from .= ' AND aqbasket.booksellerid = ? ';
2082 push @query_params, $supplierid;
2084 if (defined $branch) {
2085 $from .= ' AND borrowers.branchcode LIKE ? ';
2086 push @query_params, $branch;
2089 if ( defined $estimateddeliverydatefrom or defined $estimateddeliverydateto ) {
2090 $from .= ' AND aqbooksellers.deliverytime IS NOT NULL ';
2092 if ( defined $estimateddeliverydatefrom ) {
2093 $from .= ' AND ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) >= ?';
2094 push @query_params, $estimateddeliverydatefrom;
2096 if ( defined $estimateddeliverydateto ) {
2097 $from .= ' AND ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) <= ?';
2098 push @query_params, $estimateddeliverydateto;
2100 if ( defined $estimateddeliverydatefrom and not defined $estimateddeliverydateto ) {
2101 $from .= ' AND ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) <= CAST(now() AS date)';
2103 if (C4::Context->preference("IndependentBranches")
2104 && !C4::Context->IsSuperLibrarian() ) {
2105 $from .= ' AND borrowers.branchcode LIKE ? ';
2106 push @query_params, C4::Context->userenv->{branch};
2108 $from .= " AND orderstatus <> 'cancelled' ";
2109 my $query = "$select $from $having\nORDER BY latesince, basketno, borrowers.branchcode, supplier";
2110 $debug and print STDERR "GetLateOrders query: $query\nGetLateOrders args: " . join(" ",@query_params);
2111 my $sth = $dbh->prepare($query);
2112 $sth->execute(@query_params);
2113 my @results;
2114 while (my $data = $sth->fetchrow_hashref) {
2115 push @results, $data;
2117 return @results;
2120 #------------------------------------------------------------#
2122 =head3 GetHistory
2124 \@order_loop = GetHistory( %params );
2126 Retreives some acquisition history information
2128 params:
2129 title
2130 author
2131 name
2132 isbn
2134 from_placed_on
2135 to_placed_on
2136 basket - search both basket name and number
2137 booksellerinvoicenumber
2138 basketgroupname
2139 budget
2140 orderstatus (note that orderstatus '' will retrieve orders
2141 of any status except cancelled)
2142 biblionumber
2143 get_canceled_order (if set to a true value, cancelled orders will
2144 be included)
2146 returns:
2147 $order_loop is a list of hashrefs that each look like this:
2149 'author' => 'Twain, Mark',
2150 'basketno' => '1',
2151 'biblionumber' => '215',
2152 'count' => 1,
2153 'creationdate' => 'MM/DD/YYYY',
2154 'datereceived' => undef,
2155 'ecost' => '1.00',
2156 'id' => '1',
2157 'invoicenumber' => undef,
2158 'name' => '',
2159 'ordernumber' => '1',
2160 'quantity' => 1,
2161 'quantityreceived' => undef,
2162 'title' => 'The Adventures of Huckleberry Finn'
2165 =cut
2167 sub GetHistory {
2168 # don't run the query if there are no parameters (list would be too long for sure !)
2169 croak "No search params" unless @_;
2170 my %params = @_;
2171 my $title = $params{title};
2172 my $author = $params{author};
2173 my $isbn = $params{isbn};
2174 my $ean = $params{ean};
2175 my $name = $params{name};
2176 my $from_placed_on = $params{from_placed_on};
2177 my $to_placed_on = $params{to_placed_on};
2178 my $basket = $params{basket};
2179 my $booksellerinvoicenumber = $params{booksellerinvoicenumber};
2180 my $basketgroupname = $params{basketgroupname};
2181 my $budget = $params{budget};
2182 my $orderstatus = $params{orderstatus};
2183 my $biblionumber = $params{biblionumber};
2184 my $get_canceled_order = $params{get_canceled_order} || 0;
2185 my $ordernumber = $params{ordernumber};
2186 my $search_children_too = $params{search_children_too} || 0;
2187 my $created_by = $params{created_by} || [];
2189 my @order_loop;
2190 my $total_qty = 0;
2191 my $total_qtyreceived = 0;
2192 my $total_price = 0;
2194 my $dbh = C4::Context->dbh;
2195 my $query ="
2196 SELECT
2197 COALESCE(biblio.title, deletedbiblio.title) AS title,
2198 COALESCE(biblio.author, deletedbiblio.author) AS author,
2199 COALESCE(biblioitems.isbn, deletedbiblioitems.isbn) AS isbn,
2200 COALESCE(biblioitems.ean, deletedbiblioitems.ean) AS ean,
2201 aqorders.basketno,
2202 aqbasket.basketname,
2203 aqbasket.basketgroupid,
2204 aqbasket.authorisedby,
2205 concat( borrowers.firstname,' ',borrowers.surname) AS authorisedbyname,
2206 aqbasketgroups.name as groupname,
2207 aqbooksellers.name,
2208 aqbasket.creationdate,
2209 aqorders.datereceived,
2210 aqorders.quantity,
2211 aqorders.quantityreceived,
2212 aqorders.ecost,
2213 aqorders.ordernumber,
2214 aqorders.invoiceid,
2215 aqinvoices.invoicenumber,
2216 aqbooksellers.id as id,
2217 aqorders.biblionumber,
2218 aqorders.orderstatus,
2219 aqorders.parent_ordernumber,
2220 aqbudgets.budget_name
2222 $query .= ", aqbudgets.budget_id AS budget" if defined $budget;
2223 $query .= "
2224 FROM aqorders
2225 LEFT JOIN aqbasket ON aqorders.basketno=aqbasket.basketno
2226 LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid=aqbasketgroups.id
2227 LEFT JOIN aqbooksellers ON aqbasket.booksellerid=aqbooksellers.id
2228 LEFT JOIN biblioitems ON biblioitems.biblionumber=aqorders.biblionumber
2229 LEFT JOIN biblio ON biblio.biblionumber=aqorders.biblionumber
2230 LEFT JOIN aqbudgets ON aqorders.budget_id=aqbudgets.budget_id
2231 LEFT JOIN aqinvoices ON aqorders.invoiceid = aqinvoices.invoiceid
2232 LEFT JOIN deletedbiblio ON deletedbiblio.biblionumber=aqorders.biblionumber
2233 LEFT JOIN deletedbiblioitems ON deletedbiblioitems.biblionumber=aqorders.biblionumber
2234 LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber
2237 $query .= " WHERE 1 ";
2239 unless ($get_canceled_order or (defined $orderstatus and $orderstatus eq 'cancelled')) {
2240 $query .= " AND (datecancellationprinted is NULL or datecancellationprinted='0000-00-00') ";
2243 my @query_params = ();
2245 if ( $biblionumber ) {
2246 $query .= " AND biblio.biblionumber = ?";
2247 push @query_params, $biblionumber;
2250 if ( $title ) {
2251 $query .= " AND biblio.title LIKE ? ";
2252 $title =~ s/\s+/%/g;
2253 push @query_params, "%$title%";
2256 if ( $author ) {
2257 $query .= " AND biblio.author LIKE ? ";
2258 push @query_params, "%$author%";
2261 if ( $isbn ) {
2262 $query .= " AND biblioitems.isbn LIKE ? ";
2263 push @query_params, "%$isbn%";
2265 if ( $ean ) {
2266 $query .= " AND biblioitems.ean = ? ";
2267 push @query_params, "$ean";
2269 if ( $name ) {
2270 $query .= " AND aqbooksellers.name LIKE ? ";
2271 push @query_params, "%$name%";
2274 if ( $budget ) {
2275 $query .= " AND aqbudgets.budget_id = ? ";
2276 push @query_params, "$budget";
2279 if ( $from_placed_on ) {
2280 $query .= " AND creationdate >= ? ";
2281 push @query_params, $from_placed_on;
2284 if ( $to_placed_on ) {
2285 $query .= " AND creationdate <= ? ";
2286 push @query_params, $to_placed_on;
2289 if ( defined $orderstatus and $orderstatus ne '') {
2290 $query .= " AND aqorders.orderstatus = ? ";
2291 push @query_params, "$orderstatus";
2294 if ($basket) {
2295 if ($basket =~ m/^\d+$/) {
2296 $query .= " AND aqorders.basketno = ? ";
2297 push @query_params, $basket;
2298 } else {
2299 $query .= " AND aqbasket.basketname LIKE ? ";
2300 push @query_params, "%$basket%";
2304 if ($booksellerinvoicenumber) {
2305 $query .= " AND aqinvoices.invoicenumber LIKE ? ";
2306 push @query_params, "%$booksellerinvoicenumber%";
2309 if ($basketgroupname) {
2310 $query .= " AND aqbasketgroups.name LIKE ? ";
2311 push @query_params, "%$basketgroupname%";
2314 if ($ordernumber) {
2315 $query .= " AND (aqorders.ordernumber = ? ";
2316 push @query_params, $ordernumber;
2317 if ($search_children_too) {
2318 $query .= " OR aqorders.parent_ordernumber = ? ";
2319 push @query_params, $ordernumber;
2321 $query .= ") ";
2324 if ( @$created_by ) {
2325 $query .= ' AND aqbasket.authorisedby IN ( ' . join( ',', ('?') x @$created_by ) . ')';
2326 push @query_params, @$created_by;
2330 if ( C4::Context->preference("IndependentBranches") ) {
2331 unless ( C4::Context->IsSuperLibrarian() ) {
2332 $query .= " AND (borrowers.branchcode = ? OR borrowers.branchcode ='' ) ";
2333 push @query_params, C4::Context->userenv->{branch};
2336 $query .= " ORDER BY id";
2338 return $dbh->selectall_arrayref( $query, { Slice => {} }, @query_params );
2341 =head2 GetRecentAcqui
2343 $results = GetRecentAcqui($days);
2345 C<$results> is a ref to a table which containts hashref
2347 =cut
2349 sub GetRecentAcqui {
2350 my $limit = shift;
2351 my $dbh = C4::Context->dbh;
2352 my $query = "
2353 SELECT *
2354 FROM biblio
2355 ORDER BY timestamp DESC
2356 LIMIT 0,".$limit;
2358 my $sth = $dbh->prepare($query);
2359 $sth->execute;
2360 my $results = $sth->fetchall_arrayref({});
2361 return $results;
2364 #------------------------------------------------------------#
2366 =head3 AddClaim
2368 &AddClaim($ordernumber);
2370 Add a claim for an order
2372 =cut
2374 sub AddClaim {
2375 my ($ordernumber) = @_;
2376 my $dbh = C4::Context->dbh;
2377 my $query = "
2378 UPDATE aqorders SET
2379 claims_count = claims_count + 1,
2380 claimed_date = CURDATE()
2381 WHERE ordernumber = ?
2383 my $sth = $dbh->prepare($query);
2384 $sth->execute($ordernumber);
2387 =head3 GetInvoices
2389 my @invoices = GetInvoices(
2390 invoicenumber => $invoicenumber,
2391 supplierid => $supplierid,
2392 suppliername => $suppliername,
2393 shipmentdatefrom => $shipmentdatefrom, # ISO format
2394 shipmentdateto => $shipmentdateto, # ISO format
2395 billingdatefrom => $billingdatefrom, # ISO format
2396 billingdateto => $billingdateto, # ISO format
2397 isbneanissn => $isbn_or_ean_or_issn,
2398 title => $title,
2399 author => $author,
2400 publisher => $publisher,
2401 publicationyear => $publicationyear,
2402 branchcode => $branchcode,
2403 order_by => $order_by
2406 Return a list of invoices that match all given criteria.
2408 $order_by is "column_name (asc|desc)", where column_name is any of
2409 'invoicenumber', 'booksellerid', 'shipmentdate', 'billingdate', 'closedate',
2410 'shipmentcost', 'shipmentcost_budgetid'.
2412 asc is the default if omitted
2414 =cut
2416 sub GetInvoices {
2417 my %args = @_;
2419 my @columns = qw(invoicenumber booksellerid shipmentdate billingdate
2420 closedate shipmentcost shipmentcost_budgetid);
2422 my $dbh = C4::Context->dbh;
2423 my $query = qq{
2424 SELECT aqinvoices.*, aqbooksellers.name AS suppliername,
2425 COUNT(
2426 DISTINCT IF(
2427 aqorders.datereceived IS NOT NULL,
2428 aqorders.biblionumber,
2429 NULL
2431 ) AS receivedbiblios,
2432 COUNT(
2433 DISTINCT IF(
2434 aqorders.subscriptionid IS NOT NULL,
2435 aqorders.subscriptionid,
2436 NULL
2438 ) AS is_linked_to_subscriptions,
2439 SUM(aqorders.quantityreceived) AS receiveditems
2440 FROM aqinvoices
2441 LEFT JOIN aqbooksellers ON aqbooksellers.id = aqinvoices.booksellerid
2442 LEFT JOIN aqorders ON aqorders.invoiceid = aqinvoices.invoiceid
2443 LEFT JOIN aqbasket ON aqbasket.basketno=aqorders.basketno
2444 LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber
2445 LEFT JOIN biblio ON aqorders.biblionumber = biblio.biblionumber
2446 LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
2447 LEFT JOIN subscription ON biblio.biblionumber = subscription.biblionumber
2450 my @bind_args;
2451 my @bind_strs;
2452 if($args{supplierid}) {
2453 push @bind_strs, " aqinvoices.booksellerid = ? ";
2454 push @bind_args, $args{supplierid};
2456 if($args{invoicenumber}) {
2457 push @bind_strs, " aqinvoices.invoicenumber LIKE ? ";
2458 push @bind_args, "%$args{invoicenumber}%";
2460 if($args{suppliername}) {
2461 push @bind_strs, " aqbooksellers.name LIKE ? ";
2462 push @bind_args, "%$args{suppliername}%";
2464 if($args{shipmentdatefrom}) {
2465 push @bind_strs, " aqinvoices.shipmentdate >= ? ";
2466 push @bind_args, $args{shipmentdatefrom};
2468 if($args{shipmentdateto}) {
2469 push @bind_strs, " aqinvoices.shipmentdate <= ? ";
2470 push @bind_args, $args{shipmentdateto};
2472 if($args{billingdatefrom}) {
2473 push @bind_strs, " aqinvoices.billingdate >= ? ";
2474 push @bind_args, $args{billingdatefrom};
2476 if($args{billingdateto}) {
2477 push @bind_strs, " aqinvoices.billingdate <= ? ";
2478 push @bind_args, $args{billingdateto};
2480 if($args{isbneanissn}) {
2481 push @bind_strs, " (biblioitems.isbn LIKE CONCAT('%', ?, '%') OR biblioitems.ean LIKE CONCAT('%', ?, '%') OR biblioitems.issn LIKE CONCAT('%', ?, '%') ) ";
2482 push @bind_args, $args{isbneanissn}, $args{isbneanissn}, $args{isbneanissn};
2484 if($args{title}) {
2485 push @bind_strs, " biblio.title LIKE CONCAT('%', ?, '%') ";
2486 push @bind_args, $args{title};
2488 if($args{author}) {
2489 push @bind_strs, " biblio.author LIKE CONCAT('%', ?, '%') ";
2490 push @bind_args, $args{author};
2492 if($args{publisher}) {
2493 push @bind_strs, " biblioitems.publishercode LIKE CONCAT('%', ?, '%') ";
2494 push @bind_args, $args{publisher};
2496 if($args{publicationyear}) {
2497 push @bind_strs, " ((biblioitems.publicationyear LIKE CONCAT('%', ?, '%')) OR (biblio.copyrightdate LIKE CONCAT('%', ?, '%'))) ";
2498 push @bind_args, $args{publicationyear}, $args{publicationyear};
2500 if($args{branchcode}) {
2501 push @bind_strs, " borrowers.branchcode = ? ";
2502 push @bind_args, $args{branchcode};
2505 $query .= " WHERE " . join(" AND ", @bind_strs) if @bind_strs;
2506 $query .= " GROUP BY aqinvoices.invoiceid ";
2508 if($args{order_by}) {
2509 my ($column, $direction) = split / /, $args{order_by};
2510 if(grep /^$column$/, @columns) {
2511 $direction ||= 'ASC';
2512 $query .= " ORDER BY $column $direction";
2516 my $sth = $dbh->prepare($query);
2517 $sth->execute(@bind_args);
2519 my $results = $sth->fetchall_arrayref({});
2520 return @$results;
2523 =head3 GetInvoice
2525 my $invoice = GetInvoice($invoiceid);
2527 Get informations about invoice with given $invoiceid
2529 Return a hash filled with aqinvoices.* fields
2531 =cut
2533 sub GetInvoice {
2534 my ($invoiceid) = @_;
2535 my $invoice;
2537 return unless $invoiceid;
2539 my $dbh = C4::Context->dbh;
2540 my $query = qq{
2541 SELECT *
2542 FROM aqinvoices
2543 WHERE invoiceid = ?
2545 my $sth = $dbh->prepare($query);
2546 $sth->execute($invoiceid);
2548 $invoice = $sth->fetchrow_hashref;
2549 return $invoice;
2552 =head3 GetInvoiceDetails
2554 my $invoice = GetInvoiceDetails($invoiceid)
2556 Return informations about an invoice + the list of related order lines
2558 Orders informations are in $invoice->{orders} (array ref)
2560 =cut
2562 sub GetInvoiceDetails {
2563 my ($invoiceid) = @_;
2565 if ( !defined $invoiceid ) {
2566 carp 'GetInvoiceDetails called without an invoiceid';
2567 return;
2570 my $dbh = C4::Context->dbh;
2571 my $query = q{
2572 SELECT aqinvoices.*, aqbooksellers.name AS suppliername
2573 FROM aqinvoices
2574 LEFT JOIN aqbooksellers ON aqinvoices.booksellerid = aqbooksellers.id
2575 WHERE invoiceid = ?
2577 my $sth = $dbh->prepare($query);
2578 $sth->execute($invoiceid);
2580 my $invoice = $sth->fetchrow_hashref;
2582 $query = q{
2583 SELECT aqorders.*,
2584 biblio.*,
2585 biblio.copyrightdate,
2586 biblioitems.publishercode,
2587 biblioitems.publicationyear,
2588 aqbasket.basketname,
2589 aqbasketgroups.id AS basketgroupid,
2590 aqbasketgroups.name AS basketgroupname
2591 FROM aqorders
2592 LEFT JOIN aqbasket ON aqorders.basketno = aqbasket.basketno
2593 LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid = aqbasketgroups.id
2594 LEFT JOIN biblio ON aqorders.biblionumber = biblio.biblionumber
2595 LEFT JOIN biblioitems ON aqorders.biblionumber = biblioitems.biblionumber
2596 WHERE invoiceid = ?
2598 $sth = $dbh->prepare($query);
2599 $sth->execute($invoiceid);
2600 $invoice->{orders} = $sth->fetchall_arrayref({});
2601 $invoice->{orders} ||= []; # force an empty arrayref if fetchall_arrayref fails
2603 return $invoice;
2606 =head3 AddInvoice
2608 my $invoiceid = AddInvoice(
2609 invoicenumber => $invoicenumber,
2610 booksellerid => $booksellerid,
2611 shipmentdate => $shipmentdate,
2612 billingdate => $billingdate,
2613 closedate => $closedate,
2614 shipmentcost => $shipmentcost,
2615 shipmentcost_budgetid => $shipmentcost_budgetid
2618 Create a new invoice and return its id or undef if it fails.
2620 =cut
2622 sub AddInvoice {
2623 my %invoice = @_;
2625 return unless(%invoice and $invoice{invoicenumber});
2627 my @columns = qw(invoicenumber booksellerid shipmentdate billingdate
2628 closedate shipmentcost shipmentcost_budgetid);
2630 my @set_strs;
2631 my @set_args;
2632 foreach my $key (keys %invoice) {
2633 if(0 < grep(/^$key$/, @columns)) {
2634 push @set_strs, "$key = ?";
2635 push @set_args, ($invoice{$key} || undef);
2639 my $rv;
2640 if(@set_args > 0) {
2641 my $dbh = C4::Context->dbh;
2642 my $query = "INSERT INTO aqinvoices SET ";
2643 $query .= join (",", @set_strs);
2644 my $sth = $dbh->prepare($query);
2645 $rv = $sth->execute(@set_args);
2646 if($rv) {
2647 $rv = $dbh->last_insert_id(undef, undef, 'aqinvoices', undef);
2650 return $rv;
2653 =head3 ModInvoice
2655 ModInvoice(
2656 invoiceid => $invoiceid, # Mandatory
2657 invoicenumber => $invoicenumber,
2658 booksellerid => $booksellerid,
2659 shipmentdate => $shipmentdate,
2660 billingdate => $billingdate,
2661 closedate => $closedate,
2662 shipmentcost => $shipmentcost,
2663 shipmentcost_budgetid => $shipmentcost_budgetid
2666 Modify an invoice, invoiceid is mandatory.
2668 Return undef if it fails.
2670 =cut
2672 sub ModInvoice {
2673 my %invoice = @_;
2675 return unless(%invoice and $invoice{invoiceid});
2677 my @columns = qw(invoicenumber booksellerid shipmentdate billingdate
2678 closedate shipmentcost shipmentcost_budgetid);
2680 my @set_strs;
2681 my @set_args;
2682 foreach my $key (keys %invoice) {
2683 if(0 < grep(/^$key$/, @columns)) {
2684 push @set_strs, "$key = ?";
2685 push @set_args, ($invoice{$key} || undef);
2689 my $dbh = C4::Context->dbh;
2690 my $query = "UPDATE aqinvoices SET ";
2691 $query .= join(",", @set_strs);
2692 $query .= " WHERE invoiceid = ?";
2694 my $sth = $dbh->prepare($query);
2695 $sth->execute(@set_args, $invoice{invoiceid});
2698 =head3 CloseInvoice
2700 CloseInvoice($invoiceid);
2702 Close an invoice.
2704 Equivalent to ModInvoice(invoiceid => $invoiceid, closedate => undef);
2706 =cut
2708 sub CloseInvoice {
2709 my ($invoiceid) = @_;
2711 return unless $invoiceid;
2713 my $dbh = C4::Context->dbh;
2714 my $query = qq{
2715 UPDATE aqinvoices
2716 SET closedate = CAST(NOW() AS DATE)
2717 WHERE invoiceid = ?
2719 my $sth = $dbh->prepare($query);
2720 $sth->execute($invoiceid);
2723 =head3 ReopenInvoice
2725 ReopenInvoice($invoiceid);
2727 Reopen an invoice
2729 Equivalent to ModInvoice(invoiceid => $invoiceid, closedate => C4::Dates->new()->output('iso'))
2731 =cut
2733 sub ReopenInvoice {
2734 my ($invoiceid) = @_;
2736 return unless $invoiceid;
2738 my $dbh = C4::Context->dbh;
2739 my $query = qq{
2740 UPDATE aqinvoices
2741 SET closedate = NULL
2742 WHERE invoiceid = ?
2744 my $sth = $dbh->prepare($query);
2745 $sth->execute($invoiceid);
2748 =head3 DelInvoice
2750 DelInvoice($invoiceid);
2752 Delete an invoice if there are no items attached to it.
2754 =cut
2756 sub DelInvoice {
2757 my ($invoiceid) = @_;
2759 return unless $invoiceid;
2761 my $dbh = C4::Context->dbh;
2762 my $query = qq{
2763 SELECT COUNT(*)
2764 FROM aqorders
2765 WHERE invoiceid = ?
2767 my $sth = $dbh->prepare($query);
2768 $sth->execute($invoiceid);
2769 my $res = $sth->fetchrow_arrayref;
2770 if ( $res && $res->[0] == 0 ) {
2771 $query = qq{
2772 DELETE FROM aqinvoices
2773 WHERE invoiceid = ?
2775 my $sth = $dbh->prepare($query);
2776 return ( $sth->execute($invoiceid) > 0 );
2778 return;
2781 =head3 MergeInvoices
2783 MergeInvoices($invoiceid, \@sourceids);
2785 Merge the invoices identified by the IDs in \@sourceids into
2786 the invoice identified by $invoiceid.
2788 =cut
2790 sub MergeInvoices {
2791 my ($invoiceid, $sourceids) = @_;
2793 return unless $invoiceid;
2794 foreach my $sourceid (@$sourceids) {
2795 next if $sourceid == $invoiceid;
2796 my $source = GetInvoiceDetails($sourceid);
2797 foreach my $order (@{$source->{'orders'}}) {
2798 $order->{'invoiceid'} = $invoiceid;
2799 ModOrder($order);
2801 DelInvoice($source->{'invoiceid'});
2803 return;
2806 =head3 GetBiblioCountByBasketno
2808 $biblio_count = &GetBiblioCountByBasketno($basketno);
2810 Looks up the biblio's count that has basketno value $basketno
2812 Returns a quantity
2814 =cut
2816 sub GetBiblioCountByBasketno {
2817 my ($basketno) = @_;
2818 my $dbh = C4::Context->dbh;
2819 my $query = "
2820 SELECT COUNT( DISTINCT( biblionumber ) )
2821 FROM aqorders
2822 WHERE basketno = ?
2823 AND (datecancellationprinted IS NULL OR datecancellationprinted='0000-00-00')
2826 my $sth = $dbh->prepare($query);
2827 $sth->execute($basketno);
2828 return $sth->fetchrow;
2831 # This is *not* the good way to calcul prices
2832 # But it's how it works at the moment into Koha
2833 # This will be fixed later.
2834 # Note this subroutine should be moved to Koha::Acquisition::Order
2835 # Will do when a DBIC decision will be taken.
2836 sub populate_order_with_prices {
2837 my ($params) = @_;
2839 my $order = $params->{order};
2840 my $booksellerid = $params->{booksellerid};
2841 return unless $booksellerid;
2843 my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $booksellerid });
2845 my $receiving = $params->{receiving};
2846 my $ordering = $params->{ordering};
2847 my $discount = $order->{discount};
2848 $discount /= 100 if $discount > 1;
2850 $order->{rrp} = Koha::Number::Price->new( $order->{rrp} )->round;
2851 $order->{ecost} = Koha::Number::Price->new( $order->{ecost} )->round;
2852 if ($ordering) {
2853 if ( $bookseller->{listincgst} ) {
2854 $order->{rrpgsti} = $order->{rrp};
2855 $order->{rrpgste} = Koha::Number::Price->new(
2856 $order->{rrpgsti} / ( 1 + $order->{gstrate} ) )->round;
2857 $order->{ecostgsti} = $order->{ecost};
2858 $order->{ecostgste} = Koha::Number::Price->new(
2859 $order->{ecost} / ( 1 + $order->{gstrate} ) )->round;
2860 $order->{gstvalue} = Koha::Number::Price->new(
2861 ( $order->{ecostgsti} - $order->{ecostgste} ) *
2862 $order->{quantity} )->round;
2863 $order->{totalgste} = $order->{ecostgste} * $order->{quantity};
2864 $order->{totalgsti} = $order->{ecostgsti} * $order->{quantity};
2866 else {
2867 $order->{rrpgste} = $order->{rrp};
2868 $order->{rrpgsti} = Koha::Number::Price->new(
2869 $order->{rrp} * ( 1 + $order->{gstrate} ) )->round;
2870 $order->{ecostgste} = $order->{ecost};
2871 $order->{ecostgsti} = Koha::Number::Price->new(
2872 $order->{ecost} * ( 1 + $order->{gstrate} ) )->round;
2873 $order->{gstvalue} = Koha::Number::Price->new(
2874 ( $order->{ecostgsti} - $order->{ecostgste} ) *
2875 $order->{quantity} )->round;
2876 $order->{totalgste} = $order->{ecostgste} * $order->{quantity};
2877 $order->{totalgsti} = $order->{ecostgsti} * $order->{quantity};
2881 if ($receiving) {
2882 if ( $bookseller->{listincgst} ) {
2883 $order->{unitpricegsti} = Koha::Number::Price->new( $order->{unitprice} )->round;
2884 $order->{unitpricegste} = Koha::Number::Price->new(
2885 $order->{unitpricegsti} / ( 1 + $order->{gstrate} ) )->round;
2887 else {
2888 $order->{unitpricegste} = Koha::Number::Price->new( $order->{unitprice} )->round;
2889 $order->{unitpricegsti} = Koha::Number::Price->new(
2890 $order->{unitpricegste} * ( 1 + $order->{gstrate} ) )->round;
2892 $order->{gstvalue} = Koha::Number::Price->new(
2893 ( $order->{unitpricegsti} - $order->{unitpricegste} )
2894 * $order->{quantityreceived} )->round;
2896 $order->{totalgste} = $order->{unitpricegste} * $order->{quantity};
2897 $order->{totalgsti} = $order->{unitpricegsti} * $order->{quantity};
2900 return $order;
2903 =head3 GetOrderUsers
2905 $order_users_ids = &GetOrderUsers($ordernumber);
2907 Returns a list of all borrowernumbers that are in order users list
2909 =cut
2911 sub GetOrderUsers {
2912 my ($ordernumber) = @_;
2914 return unless $ordernumber;
2916 my $query = q|
2917 SELECT borrowernumber
2918 FROM aqorder_users
2919 WHERE ordernumber = ?
2921 my $dbh = C4::Context->dbh;
2922 my $sth = $dbh->prepare($query);
2923 $sth->execute($ordernumber);
2924 my $results = $sth->fetchall_arrayref( {} );
2926 my @borrowernumbers;
2927 foreach (@$results) {
2928 push @borrowernumbers, $_->{'borrowernumber'};
2931 return @borrowernumbers;
2934 =head3 ModOrderUsers
2936 my @order_users_ids = (1, 2, 3);
2937 &ModOrderUsers($ordernumber, @basketusers_ids);
2939 Delete all users from order users list, and add users in C<@order_users_ids>
2940 to this users list.
2942 =cut
2944 sub ModOrderUsers {
2945 my ( $ordernumber, @order_users_ids ) = @_;
2947 return unless $ordernumber;
2949 my $dbh = C4::Context->dbh;
2950 my $query = q|
2951 DELETE FROM aqorder_users
2952 WHERE ordernumber = ?
2954 my $sth = $dbh->prepare($query);
2955 $sth->execute($ordernumber);
2957 $query = q|
2958 INSERT INTO aqorder_users (ordernumber, borrowernumber)
2959 VALUES (?, ?)
2961 $sth = $dbh->prepare($query);
2962 foreach my $order_user_id (@order_users_ids) {
2963 $sth->execute( $ordernumber, $order_user_id );
2967 sub NotifyOrderUsers {
2968 my ($ordernumber) = @_;
2970 my @borrowernumbers = GetOrderUsers($ordernumber);
2971 return unless @borrowernumbers;
2973 my $order = GetOrder( $ordernumber );
2974 for my $borrowernumber (@borrowernumbers) {
2975 my $borrower = C4::Members::GetMember( borrowernumber => $borrowernumber );
2976 my $branch = C4::Branch::GetBranchDetail( $borrower->{branchcode} );
2977 my $biblio = C4::Biblio::GetBiblio( $order->{biblionumber} );
2978 my $letter = C4::Letters::GetPreparedLetter(
2979 module => 'acquisition',
2980 letter_code => 'ACQ_NOTIF_ON_RECEIV',
2981 branchcode => $branch->{branchcode},
2982 tables => {
2983 'branches' => $branch,
2984 'borrowers' => $borrower,
2985 'biblio' => $biblio,
2986 'aqorders' => $order,
2989 if ( $letter ) {
2990 C4::Letters::EnqueueLetter(
2992 letter => $letter,
2993 borrowernumber => $borrowernumber,
2994 LibraryName => C4::Context->preference("LibraryName"),
2995 message_transport_type => 'email',
2997 ) or warn "can't enqueue letter $letter";
3003 __END__
3005 =head1 AUTHOR
3007 Koha Development Team <http://koha-community.org/>
3009 =cut