Bug 16751: What is sitemaper?
[koha.git] / C4 / Acquisition.pm
blobc091f898a0b4c08ebd3031a5076f7949557a5b72
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;
38 use MARC::Field;
39 use MARC::Record;
41 use Time::localtime;
42 use HTML::Entities;
44 use vars qw(@ISA @EXPORT);
46 BEGIN {
47 require Exporter;
48 @ISA = qw(Exporter);
49 @EXPORT = qw(
50 &GetBasket &NewBasket &CloseBasket &ReopenBasket &DelBasket &ModBasket
51 &GetBasketAsCSV &GetBasketGroupAsCSV
52 &GetBasketsByBookseller &GetBasketsByBasketgroup
53 &GetBasketsInfosByBookseller
55 &GetBasketUsers &ModBasketUsers
56 &CanUserManageBasket
58 &ModBasketHeader
60 &ModBasketgroup &NewBasketgroup &DelBasketgroup &GetBasketgroup &CloseBasketgroup
61 &GetBasketgroups &ReOpenBasketgroup
63 &DelOrder &ModOrder &GetOrder &GetOrders &GetOrdersByBiblionumber
64 &GetLateOrders &GetOrderFromItemnumber
65 &SearchOrders &GetHistory &GetRecentAcqui
66 &ModReceiveOrder &CancelReceipt
67 &TransferOrder
68 &GetLastOrderNotReceivedFromSubscriptionid &GetLastOrderReceivedFromSubscriptionid
69 &ModItemOrder
71 &GetParcels
73 &GetInvoices
74 &GetInvoice
75 &GetInvoiceDetails
76 &AddInvoice
77 &ModInvoice
78 &CloseInvoice
79 &ReopenInvoice
80 &DelInvoice
81 &MergeInvoices
83 &GetItemnumbersFromOrder
85 &AddClaim
86 &GetBiblioCountByBasketno
88 &GetOrderUsers
89 &ModOrderUsers
90 &NotifyOrderUsers
92 &FillWithDefaultValues
100 sub GetOrderFromItemnumber {
101 my ($itemnumber) = @_;
102 my $dbh = C4::Context->dbh;
103 my $query = qq|
105 SELECT * from aqorders LEFT JOIN aqorders_items
106 ON ( aqorders.ordernumber = aqorders_items.ordernumber )
107 WHERE itemnumber = ? |;
109 my $sth = $dbh->prepare($query);
111 # $sth->trace(3);
113 $sth->execute($itemnumber);
115 my $order = $sth->fetchrow_hashref;
116 return ( $order );
120 # Returns the itemnumber(s) associated with the ordernumber given in parameter
121 sub GetItemnumbersFromOrder {
122 my ($ordernumber) = @_;
123 my $dbh = C4::Context->dbh;
124 my $query = "SELECT itemnumber FROM aqorders_items WHERE ordernumber=?";
125 my $sth = $dbh->prepare($query);
126 $sth->execute($ordernumber);
127 my @tab;
129 while (my $order = $sth->fetchrow_hashref) {
130 push @tab, $order->{'itemnumber'};
133 return @tab;
142 =head1 NAME
144 C4::Acquisition - Koha functions for dealing with orders and acquisitions
146 =head1 SYNOPSIS
148 use C4::Acquisition;
150 =head1 DESCRIPTION
152 The functions in this module deal with acquisitions, managing book
153 orders, basket and parcels.
155 =head1 FUNCTIONS
157 =head2 FUNCTIONS ABOUT BASKETS
159 =head3 GetBasket
161 $aqbasket = &GetBasket($basketnumber);
163 get all basket informations in aqbasket for a given basket
165 B<returns:> informations for a given basket returned as a hashref.
167 =cut
169 sub GetBasket {
170 my ($basketno) = @_;
171 my $dbh = C4::Context->dbh;
172 my $query = "
173 SELECT aqbasket.*,
174 concat( b.firstname,' ',b.surname) AS authorisedbyname
175 FROM aqbasket
176 LEFT JOIN borrowers b ON aqbasket.authorisedby=b.borrowernumber
177 WHERE basketno=?
179 my $sth=$dbh->prepare($query);
180 $sth->execute($basketno);
181 my $basket = $sth->fetchrow_hashref;
182 return ( $basket );
185 #------------------------------------------------------------#
187 =head3 NewBasket
189 $basket = &NewBasket( $booksellerid, $authorizedby, $basketname,
190 $basketnote, $basketbooksellernote, $basketcontractnumber, $deliveryplace, $billingplace, $is_standing );
192 Create a new basket in aqbasket table
194 =over
196 =item C<$booksellerid> is a foreign key in the aqbasket table
198 =item C<$authorizedby> is the username of who created the basket
200 =back
202 The other parameters are optional, see ModBasketHeader for more info on them.
204 =cut
206 sub NewBasket {
207 my ( $booksellerid, $authorisedby, $basketname, $basketnote,
208 $basketbooksellernote, $basketcontractnumber, $deliveryplace,
209 $billingplace, $is_standing ) = @_;
210 my $dbh = C4::Context->dbh;
211 my $query =
212 'INSERT INTO aqbasket (creationdate,booksellerid,authorisedby) '
213 . 'VALUES (now(),?,?)';
214 $dbh->do( $query, {}, $booksellerid, $authorisedby );
216 my $basket = $dbh->{mysql_insertid};
217 $basketname ||= q{}; # default to empty strings
218 $basketnote ||= q{};
219 $basketbooksellernote ||= q{};
220 ModBasketHeader( $basket, $basketname, $basketnote, $basketbooksellernote,
221 $basketcontractnumber, $booksellerid, $deliveryplace, $billingplace, $is_standing );
222 return $basket;
225 #------------------------------------------------------------#
227 =head3 CloseBasket
229 &CloseBasket($basketno);
231 close a basket (becomes unmodifiable, except for receives)
233 =cut
235 sub CloseBasket {
236 my ($basketno) = @_;
237 my $dbh = C4::Context->dbh;
238 $dbh->do('UPDATE aqbasket SET closedate=now() WHERE basketno=?', {}, $basketno );
240 $dbh->do( q{UPDATE aqorders SET orderstatus = 'ordered' WHERE basketno = ? AND orderstatus != 'complete'},
241 {}, $basketno);
242 return;
245 =head3 ReopenBasket
247 &ReopenBasket($basketno);
249 reopen a basket
251 =cut
253 sub ReopenBasket {
254 my ($basketno) = @_;
255 my $dbh = C4::Context->dbh;
256 $dbh->do( q{UPDATE aqbasket SET closedate=NULL WHERE basketno=?}, {}, $basketno );
258 $dbh->do( q{
259 UPDATE aqorders
260 SET orderstatus = 'new'
261 WHERE basketno = ?
262 AND orderstatus != 'complete'
263 }, {}, $basketno);
264 return;
267 #------------------------------------------------------------#
269 =head3 GetBasketAsCSV
271 &GetBasketAsCSV($basketno);
273 Export a basket as CSV
275 $cgi parameter is needed for column name translation
277 =cut
279 sub GetBasketAsCSV {
280 my ($basketno, $cgi) = @_;
281 my $basket = GetBasket($basketno);
282 my @orders = GetOrders($basketno);
283 my $contract = GetContract({
284 contractnumber => $basket->{'contractnumber'}
287 my $template = C4::Templates::gettemplate("acqui/csv/basket.tt", "intranet", $cgi);
289 my @rows;
290 foreach my $order (@orders) {
291 my $bd = GetBiblioData( $order->{'biblionumber'} );
292 my $row = {
293 contractname => $contract->{'contractname'},
294 ordernumber => $order->{'ordernumber'},
295 entrydate => $order->{'entrydate'},
296 isbn => $order->{'isbn'},
297 author => $bd->{'author'},
298 title => $bd->{'title'},
299 publicationyear => $bd->{'publicationyear'},
300 publishercode => $bd->{'publishercode'},
301 collectiontitle => $bd->{'collectiontitle'},
302 notes => $order->{'order_vendornote'},
303 quantity => $order->{'quantity'},
304 rrp => $order->{'rrp'},
305 deliveryplace => C4::Branch::GetBranchName( $basket->{'deliveryplace'} ),
306 billingplace => C4::Branch::GetBranchName( $basket->{'billingplace'} ),
308 foreach(qw(
309 contractname author title publishercode collectiontitle notes
310 deliveryplace billingplace
311 ) ) {
312 # Double the quotes to not be interpreted as a field end
313 $row->{$_} =~ s/"/""/g if $row->{$_};
315 push @rows, $row;
318 @rows = sort {
319 if(defined $a->{publishercode} and defined $b->{publishercode}) {
320 $a->{publishercode} cmp $b->{publishercode};
322 } @rows;
324 $template->param(rows => \@rows);
326 return $template->output;
330 =head3 GetBasketGroupAsCSV
332 &GetBasketGroupAsCSV($basketgroupid);
334 Export a basket group as CSV
336 $cgi parameter is needed for column name translation
338 =cut
340 sub GetBasketGroupAsCSV {
341 my ($basketgroupid, $cgi) = @_;
342 my $baskets = GetBasketsByBasketgroup($basketgroupid);
344 my $template = C4::Templates::gettemplate('acqui/csv/basketgroup.tt', 'intranet', $cgi);
346 my @rows;
347 for my $basket (@$baskets) {
348 my @orders = GetOrders( $basket->{basketno} );
349 my $contract = GetContract({
350 contractnumber => $basket->{contractnumber}
352 my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $basket->{booksellerid} });
353 my $basketgroup = GetBasketgroup( $$basket{basketgroupid} );
355 foreach my $order (@orders) {
356 my $bd = GetBiblioData( $order->{'biblionumber'} );
357 my $row = {
358 clientnumber => $bookseller->{accountnumber},
359 basketname => $basket->{basketname},
360 ordernumber => $order->{ordernumber},
361 author => $bd->{author},
362 title => $bd->{title},
363 publishercode => $bd->{publishercode},
364 publicationyear => $bd->{publicationyear},
365 collectiontitle => $bd->{collectiontitle},
366 isbn => $order->{isbn},
367 quantity => $order->{quantity},
368 rrp => $order->{rrp},
369 discount => $bookseller->{discount},
370 ecost => $order->{ecost},
371 notes => $order->{order_vendornote},
372 entrydate => $order->{entrydate},
373 booksellername => $bookseller->{name},
374 bookselleraddress => $bookseller->{address1},
375 booksellerpostal => $bookseller->{postal},
376 contractnumber => $contract->{contractnumber},
377 contractname => $contract->{contractname},
378 basketgroupdeliveryplace => C4::Branch::GetBranchName( $basketgroup->{deliveryplace} ),
379 basketgroupbillingplace => C4::Branch::GetBranchName( $basketgroup->{billingplace} ),
380 basketdeliveryplace => C4::Branch::GetBranchName( $basket->{deliveryplace} ),
381 basketbillingplace => C4::Branch::GetBranchName( $basket->{billingplace} ),
383 foreach(qw(
384 basketname author title publishercode collectiontitle notes
385 booksellername bookselleraddress booksellerpostal contractname
386 basketgroupdeliveryplace basketgroupbillingplace
387 basketdeliveryplace basketbillingplace
388 ) ) {
389 # Double the quotes to not be interpreted as a field end
390 $row->{$_} =~ s/"/""/g if $row->{$_};
392 push @rows, $row;
395 $template->param(rows => \@rows);
397 return $template->output;
401 =head3 CloseBasketgroup
403 &CloseBasketgroup($basketgroupno);
405 close a basketgroup
407 =cut
409 sub CloseBasketgroup {
410 my ($basketgroupno) = @_;
411 my $dbh = C4::Context->dbh;
412 my $sth = $dbh->prepare("
413 UPDATE aqbasketgroups
414 SET closed=1
415 WHERE id=?
417 $sth->execute($basketgroupno);
420 #------------------------------------------------------------#
422 =head3 ReOpenBaskergroup($basketgroupno)
424 &ReOpenBaskergroup($basketgroupno);
426 reopen a basketgroup
428 =cut
430 sub ReOpenBasketgroup {
431 my ($basketgroupno) = @_;
432 my $dbh = C4::Context->dbh;
433 my $sth = $dbh->prepare("
434 UPDATE aqbasketgroups
435 SET closed=0
436 WHERE id=?
438 $sth->execute($basketgroupno);
441 #------------------------------------------------------------#
444 =head3 DelBasket
446 &DelBasket($basketno);
448 Deletes the basket that has basketno field $basketno in the aqbasket table.
450 =over
452 =item C<$basketno> is the primary key of the basket in the aqbasket table.
454 =back
456 =cut
458 sub DelBasket {
459 my ( $basketno ) = @_;
460 my $query = "DELETE FROM aqbasket WHERE basketno=?";
461 my $dbh = C4::Context->dbh;
462 my $sth = $dbh->prepare($query);
463 $sth->execute($basketno);
464 return;
467 #------------------------------------------------------------#
469 =head3 ModBasket
471 &ModBasket($basketinfo);
473 Modifies a basket, using a hashref $basketinfo for the relevant information, only $basketinfo->{'basketno'} is required.
475 =over
477 =item C<$basketno> is the primary key of the basket in the aqbasket table.
479 =back
481 =cut
483 sub ModBasket {
484 my $basketinfo = shift;
485 my $query = "UPDATE aqbasket SET ";
486 my @params;
487 foreach my $key (keys %$basketinfo){
488 if ($key ne 'basketno'){
489 $query .= "$key=?, ";
490 push(@params, $basketinfo->{$key} || undef );
493 # get rid of the "," at the end of $query
494 if (substr($query, length($query)-2) eq ', '){
495 chop($query);
496 chop($query);
497 $query .= ' ';
499 $query .= "WHERE basketno=?";
500 push(@params, $basketinfo->{'basketno'});
501 my $dbh = C4::Context->dbh;
502 my $sth = $dbh->prepare($query);
503 $sth->execute(@params);
505 return;
508 #------------------------------------------------------------#
510 =head3 ModBasketHeader
512 &ModBasketHeader($basketno, $basketname, $note, $booksellernote, $contractnumber, $booksellerid);
514 Modifies a basket's header.
516 =over
518 =item C<$basketno> is the "basketno" field in the "aqbasket" table;
520 =item C<$basketname> is the "basketname" field in the "aqbasket" table;
522 =item C<$note> is the "note" field in the "aqbasket" table;
524 =item C<$booksellernote> is the "booksellernote" field in the "aqbasket" table;
526 =item C<$contractnumber> is the "contractnumber" (foreign) key in the "aqbasket" table.
528 =item C<$booksellerid> is the id (foreign) key in the "aqbooksellers" table for the vendor.
530 =item C<$deliveryplace> is the "deliveryplace" field in the aqbasket table.
532 =item C<$billingplace> is the "billingplace" field in the aqbasket table.
534 =item C<$is_standing> is the "is_standing" field in the aqbasket table.
536 =back
538 =cut
540 sub ModBasketHeader {
541 my ($basketno, $basketname, $note, $booksellernote, $contractnumber, $booksellerid, $deliveryplace, $billingplace, $is_standing) = @_;
542 my $query = qq{
543 UPDATE aqbasket
544 SET basketname=?, note=?, booksellernote=?, booksellerid=?, deliveryplace=?, billingplace=?, is_standing=?
545 WHERE basketno=?
548 my $dbh = C4::Context->dbh;
549 my $sth = $dbh->prepare($query);
550 $sth->execute($basketname, $note, $booksellernote, $booksellerid, $deliveryplace, $billingplace, $is_standing, $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 *, aqbasket.is_standing FROM aqorders LEFT JOIN aqbasket USING (basketno) 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->{is_standing} || $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->{is_standing} ? 1 : ( $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{
1690 AND (
1691 ( aqbasket.is_standing AND aqorders.orderstatus IN ( "new", "ordered", "partial" ) )
1692 OR (
1693 ( quantity > quantityreceived OR quantityreceived is NULL )
1696 if ( $ordered ) {
1697 $query .= q{ AND aqorders.orderstatus IN ( "ordered", "partial" )};
1699 $query .= q{
1705 my $userenv = C4::Context->userenv;
1706 if ( C4::Context->preference("IndependentBranches") ) {
1707 unless ( C4::Context->IsSuperLibrarian() ) {
1708 $query .= q{
1709 AND (
1710 borrowers.branchcode = ?
1711 OR borrowers.branchcode = ''
1714 push @args, $userenv->{branch};
1718 if ( $ordernumber ) {
1719 $query .= ' AND ( aqorders.ordernumber = ? OR aqorders_transfers.ordernumber_from = ? ) ';
1720 push @args, ( $ordernumber, $ordernumber );
1722 if ( $biblionumber ) {
1723 $query .= 'AND aqorders.biblionumber = ?';
1724 push @args, $biblionumber;
1726 if( $search ) {
1727 $query .= ' AND (biblio.title LIKE ? OR biblio.author LIKE ? OR biblioitems.isbn LIKE ?)';
1728 push @args, ("%$search%","%$search%","%$search%");
1730 if ( $ean ) {
1731 $query .= ' AND biblioitems.ean = ?';
1732 push @args, $ean;
1734 if ( $booksellerid ) {
1735 $query .= 'AND aqbasket.booksellerid = ?';
1736 push @args, $booksellerid;
1738 if( $basketno ) {
1739 $query .= 'AND aqbasket.basketno = ?';
1740 push @args, $basketno;
1742 if( $basketname ) {
1743 $query .= 'AND aqbasket.basketname LIKE ?';
1744 push @args, "%$basketname%";
1746 if( $basketgroupname ) {
1747 $query .= ' AND aqbasketgroups.name LIKE ?';
1748 push @args, "%$basketgroupname%";
1751 if ( $owner ) {
1752 $query .= ' AND aqbasket.authorisedby=? ';
1753 push @args, $userenv->{'number'};
1756 if ( $budget_id ) {
1757 $query .= ' AND aqorders.budget_id = ?';
1758 push @args, $budget_id;
1761 $query .= ' ORDER BY aqbasket.basketno';
1763 my $sth = $dbh->prepare($query);
1764 $sth->execute(@args);
1765 return $sth->fetchall_arrayref({});
1768 #------------------------------------------------------------#
1770 =head3 DelOrder
1772 &DelOrder($biblionumber, $ordernumber);
1774 Cancel the order with the given order and biblio numbers. It does not
1775 delete any entries in the aqorders table, it merely marks them as
1776 cancelled.
1778 =cut
1780 sub DelOrder {
1781 my ( $bibnum, $ordernumber, $delete_biblio, $reason ) = @_;
1783 my $error;
1784 my $dbh = C4::Context->dbh;
1785 my $query = "
1786 UPDATE aqorders
1787 SET datecancellationprinted=now(), orderstatus='cancelled'
1789 if($reason) {
1790 $query .= ", cancellationreason = ? ";
1792 $query .= "
1793 WHERE biblionumber=? AND ordernumber=?
1795 my $sth = $dbh->prepare($query);
1796 if($reason) {
1797 $sth->execute($reason, $bibnum, $ordernumber);
1798 } else {
1799 $sth->execute( $bibnum, $ordernumber );
1801 $sth->finish;
1803 my @itemnumbers = GetItemnumbersFromOrder( $ordernumber );
1804 foreach my $itemnumber (@itemnumbers){
1805 my $delcheck = C4::Items::DelItemCheck( $dbh, $bibnum, $itemnumber );
1807 if($delcheck != 1) {
1808 $error->{'delitem'} = 1;
1812 if($delete_biblio) {
1813 # We get the number of remaining items
1814 my $itemcount = C4::Items::GetItemsCount($bibnum);
1816 # If there are no items left,
1817 if ( $itemcount == 0 ) {
1818 # We delete the record
1819 my $delcheck = DelBiblio($bibnum);
1821 if($delcheck) {
1822 $error->{'delbiblio'} = 1;
1827 return $error;
1830 =head3 TransferOrder
1832 my $newordernumber = TransferOrder($ordernumber, $basketno);
1834 Transfer an order line to a basket.
1835 Mark $ordernumber as cancelled with an internal note 'Cancelled and transferred
1836 to BOOKSELLER on DATE' and create new order with internal note
1837 'Transferred from BOOKSELLER on DATE'.
1838 Move all attached items to the new order.
1839 Received orders cannot be transferred.
1840 Return the ordernumber of created order.
1842 =cut
1844 sub TransferOrder {
1845 my ($ordernumber, $basketno) = @_;
1847 return unless ($ordernumber and $basketno);
1849 my $order = GetOrder( $ordernumber );
1850 return if $order->{datereceived};
1851 my $basket = GetBasket($basketno);
1852 return unless $basket;
1854 my $dbh = C4::Context->dbh;
1855 my ($query, $sth, $rv);
1857 $query = q{
1858 UPDATE aqorders
1859 SET datecancellationprinted = CAST(NOW() AS date), orderstatus = ?
1860 WHERE ordernumber = ?
1862 $sth = $dbh->prepare($query);
1863 $rv = $sth->execute('cancelled', $ordernumber);
1865 delete $order->{'ordernumber'};
1866 delete $order->{parent_ordernumber};
1867 $order->{'basketno'} = $basketno;
1869 my $newordernumber = Koha::Acquisition::Order->new($order)->insert->{ordernumber};
1871 $query = q{
1872 UPDATE aqorders_items
1873 SET ordernumber = ?
1874 WHERE ordernumber = ?
1876 $sth = $dbh->prepare($query);
1877 $sth->execute($newordernumber, $ordernumber);
1879 $query = q{
1880 INSERT INTO aqorders_transfers (ordernumber_from, ordernumber_to)
1881 VALUES (?, ?)
1883 $sth = $dbh->prepare($query);
1884 $sth->execute($ordernumber, $newordernumber);
1886 return $newordernumber;
1889 =head2 FUNCTIONS ABOUT PARCELS
1891 =head3 GetParcels
1893 $results = &GetParcels($bookseller, $order, $code, $datefrom, $dateto);
1895 get a lists of parcels.
1897 * Input arg :
1899 =over
1901 =item $bookseller
1902 is the bookseller this function has to get parcels.
1904 =item $order
1905 To know on what criteria the results list has to be ordered.
1907 =item $code
1908 is the booksellerinvoicenumber.
1910 =item $datefrom & $dateto
1911 to know on what date this function has to filter its search.
1913 =back
1915 * return:
1916 a pointer on a hash list containing parcel informations as such :
1918 =over
1920 =item Creation date
1922 =item Last operation
1924 =item Number of biblio
1926 =item Number of items
1928 =back
1930 =cut
1932 sub GetParcels {
1933 my ($bookseller,$order, $code, $datefrom, $dateto) = @_;
1934 my $dbh = C4::Context->dbh;
1935 my @query_params = ();
1936 my $strsth ="
1937 SELECT aqinvoices.invoicenumber,
1938 datereceived,purchaseordernumber,
1939 count(DISTINCT biblionumber) AS biblio,
1940 sum(quantity) AS itemsexpected,
1941 sum(quantityreceived) AS itemsreceived
1942 FROM aqorders LEFT JOIN aqbasket ON aqbasket.basketno = aqorders.basketno
1943 LEFT JOIN aqinvoices ON aqorders.invoiceid = aqinvoices.invoiceid
1944 WHERE aqbasket.booksellerid = ? and datereceived IS NOT NULL
1946 push @query_params, $bookseller;
1948 if ( defined $code ) {
1949 $strsth .= ' and aqinvoices.invoicenumber like ? ';
1950 # add a % to the end of the code to allow stemming.
1951 push @query_params, "$code%";
1954 if ( defined $datefrom ) {
1955 $strsth .= ' and datereceived >= ? ';
1956 push @query_params, $datefrom;
1959 if ( defined $dateto ) {
1960 $strsth .= 'and datereceived <= ? ';
1961 push @query_params, $dateto;
1964 $strsth .= "group by aqinvoices.invoicenumber,datereceived ";
1966 # can't use a placeholder to place this column name.
1967 # but, we could probably be checking to make sure it is a column that will be fetched.
1968 $strsth .= "order by $order " if ($order);
1970 my $sth = $dbh->prepare($strsth);
1972 $sth->execute( @query_params );
1973 my $results = $sth->fetchall_arrayref({});
1974 return @{$results};
1977 #------------------------------------------------------------#
1979 =head3 GetLateOrders
1981 @results = &GetLateOrders;
1983 Searches for bookseller with late orders.
1985 return:
1986 the table of supplier with late issues. This table is full of hashref.
1988 =cut
1990 sub GetLateOrders {
1991 my $delay = shift;
1992 my $supplierid = shift;
1993 my $branch = shift;
1994 my $estimateddeliverydatefrom = shift;
1995 my $estimateddeliverydateto = shift;
1997 my $dbh = C4::Context->dbh;
1999 #BEWARE, order of parenthesis and LEFT JOIN is important for speed
2000 my $dbdriver = C4::Context->config("db_scheme") || "mysql";
2002 my @query_params = ();
2003 my $select = "
2004 SELECT aqbasket.basketno,
2005 aqorders.ordernumber,
2006 DATE(aqbasket.closedate) AS orderdate,
2007 aqbasket.basketname AS basketname,
2008 aqbasket.basketgroupid AS basketgroupid,
2009 aqbasketgroups.name AS basketgroupname,
2010 aqorders.rrp AS unitpricesupplier,
2011 aqorders.ecost AS unitpricelib,
2012 aqorders.claims_count AS claims_count,
2013 aqorders.claimed_date AS claimed_date,
2014 aqbudgets.budget_name AS budget,
2015 borrowers.branchcode AS branch,
2016 aqbooksellers.name AS supplier,
2017 aqbooksellers.id AS supplierid,
2018 biblio.author, biblio.title,
2019 biblioitems.publishercode AS publisher,
2020 biblioitems.publicationyear,
2021 ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) AS estimateddeliverydate,
2023 my $from = "
2024 FROM
2025 aqorders LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber
2026 LEFT JOIN biblioitems ON biblioitems.biblionumber = biblio.biblionumber
2027 LEFT JOIN aqbudgets ON aqorders.budget_id = aqbudgets.budget_id,
2028 aqbasket LEFT JOIN borrowers ON aqbasket.authorisedby = borrowers.borrowernumber
2029 LEFT JOIN aqbooksellers ON aqbasket.booksellerid = aqbooksellers.id
2030 LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid = aqbasketgroups.id
2031 WHERE aqorders.basketno = aqbasket.basketno
2032 AND ( datereceived = ''
2033 OR datereceived IS NULL
2034 OR aqorders.quantityreceived < aqorders.quantity
2036 AND aqbasket.closedate IS NOT NULL
2037 AND (aqorders.datecancellationprinted IS NULL OR aqorders.datecancellationprinted='0000-00-00')
2039 my $having = "";
2040 if ($dbdriver eq "mysql") {
2041 $select .= "
2042 aqorders.quantity - COALESCE(aqorders.quantityreceived,0) AS quantity,
2043 (aqorders.quantity - COALESCE(aqorders.quantityreceived,0)) * aqorders.rrp AS subtotal,
2044 DATEDIFF(CAST(now() AS date),closedate) AS latesince
2046 if ( defined $delay ) {
2047 $from .= " AND (closedate <= DATE_SUB(CAST(now() AS date),INTERVAL ? DAY)) " ;
2048 push @query_params, $delay;
2050 $having = "
2051 HAVING quantity <> 0
2052 AND unitpricesupplier <> 0
2053 AND unitpricelib <> 0
2055 } else {
2056 # FIXME: account for IFNULL as above
2057 $select .= "
2058 aqorders.quantity AS quantity,
2059 aqorders.quantity * aqorders.rrp AS subtotal,
2060 (CAST(now() AS date) - closedate) AS latesince
2062 if ( defined $delay ) {
2063 $from .= " AND (closedate <= (CAST(now() AS date) -(INTERVAL ? DAY)) ";
2064 push @query_params, $delay;
2067 if (defined $supplierid) {
2068 $from .= ' AND aqbasket.booksellerid = ? ';
2069 push @query_params, $supplierid;
2071 if (defined $branch) {
2072 $from .= ' AND borrowers.branchcode LIKE ? ';
2073 push @query_params, $branch;
2076 if ( defined $estimateddeliverydatefrom or defined $estimateddeliverydateto ) {
2077 $from .= ' AND aqbooksellers.deliverytime IS NOT NULL ';
2079 if ( defined $estimateddeliverydatefrom ) {
2080 $from .= ' AND ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) >= ?';
2081 push @query_params, $estimateddeliverydatefrom;
2083 if ( defined $estimateddeliverydateto ) {
2084 $from .= ' AND ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) <= ?';
2085 push @query_params, $estimateddeliverydateto;
2087 if ( defined $estimateddeliverydatefrom and not defined $estimateddeliverydateto ) {
2088 $from .= ' AND ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) <= CAST(now() AS date)';
2090 if (C4::Context->preference("IndependentBranches")
2091 && !C4::Context->IsSuperLibrarian() ) {
2092 $from .= ' AND borrowers.branchcode LIKE ? ';
2093 push @query_params, C4::Context->userenv->{branch};
2095 $from .= " AND orderstatus <> 'cancelled' ";
2096 my $query = "$select $from $having\nORDER BY latesince, basketno, borrowers.branchcode, supplier";
2097 $debug and print STDERR "GetLateOrders query: $query\nGetLateOrders args: " . join(" ",@query_params);
2098 my $sth = $dbh->prepare($query);
2099 $sth->execute(@query_params);
2100 my @results;
2101 while (my $data = $sth->fetchrow_hashref) {
2102 push @results, $data;
2104 return @results;
2107 #------------------------------------------------------------#
2109 =head3 GetHistory
2111 \@order_loop = GetHistory( %params );
2113 Retreives some acquisition history information
2115 params:
2116 title
2117 author
2118 name
2119 isbn
2121 from_placed_on
2122 to_placed_on
2123 basket - search both basket name and number
2124 booksellerinvoicenumber
2125 basketgroupname
2126 budget
2127 orderstatus (note that orderstatus '' will retrieve orders
2128 of any status except cancelled)
2129 biblionumber
2130 get_canceled_order (if set to a true value, cancelled orders will
2131 be included)
2133 returns:
2134 $order_loop is a list of hashrefs that each look like this:
2136 'author' => 'Twain, Mark',
2137 'basketno' => '1',
2138 'biblionumber' => '215',
2139 'count' => 1,
2140 'creationdate' => 'MM/DD/YYYY',
2141 'datereceived' => undef,
2142 'ecost' => '1.00',
2143 'id' => '1',
2144 'invoicenumber' => undef,
2145 'name' => '',
2146 'ordernumber' => '1',
2147 'quantity' => 1,
2148 'quantityreceived' => undef,
2149 'title' => 'The Adventures of Huckleberry Finn'
2152 =cut
2154 sub GetHistory {
2155 # don't run the query if there are no parameters (list would be too long for sure !)
2156 croak "No search params" unless @_;
2157 my %params = @_;
2158 my $title = $params{title};
2159 my $author = $params{author};
2160 my $isbn = $params{isbn};
2161 my $ean = $params{ean};
2162 my $name = $params{name};
2163 my $from_placed_on = $params{from_placed_on};
2164 my $to_placed_on = $params{to_placed_on};
2165 my $basket = $params{basket};
2166 my $booksellerinvoicenumber = $params{booksellerinvoicenumber};
2167 my $basketgroupname = $params{basketgroupname};
2168 my $budget = $params{budget};
2169 my $orderstatus = $params{orderstatus};
2170 my $biblionumber = $params{biblionumber};
2171 my $get_canceled_order = $params{get_canceled_order} || 0;
2172 my $ordernumber = $params{ordernumber};
2173 my $search_children_too = $params{search_children_too} || 0;
2174 my $created_by = $params{created_by} || [];
2176 my @order_loop;
2177 my $total_qty = 0;
2178 my $total_qtyreceived = 0;
2179 my $total_price = 0;
2181 my $dbh = C4::Context->dbh;
2182 my $query ="
2183 SELECT
2184 COALESCE(biblio.title, deletedbiblio.title) AS title,
2185 COALESCE(biblio.author, deletedbiblio.author) AS author,
2186 COALESCE(biblioitems.isbn, deletedbiblioitems.isbn) AS isbn,
2187 COALESCE(biblioitems.ean, deletedbiblioitems.ean) AS ean,
2188 aqorders.basketno,
2189 aqbasket.basketname,
2190 aqbasket.basketgroupid,
2191 aqbasket.authorisedby,
2192 concat( borrowers.firstname,' ',borrowers.surname) AS authorisedbyname,
2193 aqbasketgroups.name as groupname,
2194 aqbooksellers.name,
2195 aqbasket.creationdate,
2196 aqorders.datereceived,
2197 aqorders.quantity,
2198 aqorders.quantityreceived,
2199 aqorders.ecost,
2200 aqorders.ordernumber,
2201 aqorders.invoiceid,
2202 aqinvoices.invoicenumber,
2203 aqbooksellers.id as id,
2204 aqorders.biblionumber,
2205 aqorders.orderstatus,
2206 aqorders.parent_ordernumber,
2207 aqbudgets.budget_name
2209 $query .= ", aqbudgets.budget_id AS budget" if defined $budget;
2210 $query .= "
2211 FROM aqorders
2212 LEFT JOIN aqbasket ON aqorders.basketno=aqbasket.basketno
2213 LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid=aqbasketgroups.id
2214 LEFT JOIN aqbooksellers ON aqbasket.booksellerid=aqbooksellers.id
2215 LEFT JOIN biblioitems ON biblioitems.biblionumber=aqorders.biblionumber
2216 LEFT JOIN biblio ON biblio.biblionumber=aqorders.biblionumber
2217 LEFT JOIN aqbudgets ON aqorders.budget_id=aqbudgets.budget_id
2218 LEFT JOIN aqinvoices ON aqorders.invoiceid = aqinvoices.invoiceid
2219 LEFT JOIN deletedbiblio ON deletedbiblio.biblionumber=aqorders.biblionumber
2220 LEFT JOIN deletedbiblioitems ON deletedbiblioitems.biblionumber=aqorders.biblionumber
2221 LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber
2224 $query .= " WHERE 1 ";
2226 unless ($get_canceled_order or (defined $orderstatus and $orderstatus eq 'cancelled')) {
2227 $query .= " AND (datecancellationprinted is NULL or datecancellationprinted='0000-00-00') ";
2230 my @query_params = ();
2232 if ( $biblionumber ) {
2233 $query .= " AND biblio.biblionumber = ?";
2234 push @query_params, $biblionumber;
2237 if ( $title ) {
2238 $query .= " AND biblio.title LIKE ? ";
2239 $title =~ s/\s+/%/g;
2240 push @query_params, "%$title%";
2243 if ( $author ) {
2244 $query .= " AND biblio.author LIKE ? ";
2245 push @query_params, "%$author%";
2248 if ( $isbn ) {
2249 $query .= " AND biblioitems.isbn LIKE ? ";
2250 push @query_params, "%$isbn%";
2252 if ( $ean ) {
2253 $query .= " AND biblioitems.ean = ? ";
2254 push @query_params, "$ean";
2256 if ( $name ) {
2257 $query .= " AND aqbooksellers.name LIKE ? ";
2258 push @query_params, "%$name%";
2261 if ( $budget ) {
2262 $query .= " AND aqbudgets.budget_id = ? ";
2263 push @query_params, "$budget";
2266 if ( $from_placed_on ) {
2267 $query .= " AND creationdate >= ? ";
2268 push @query_params, $from_placed_on;
2271 if ( $to_placed_on ) {
2272 $query .= " AND creationdate <= ? ";
2273 push @query_params, $to_placed_on;
2276 if ( defined $orderstatus and $orderstatus ne '') {
2277 $query .= " AND aqorders.orderstatus = ? ";
2278 push @query_params, "$orderstatus";
2281 if ($basket) {
2282 if ($basket =~ m/^\d+$/) {
2283 $query .= " AND aqorders.basketno = ? ";
2284 push @query_params, $basket;
2285 } else {
2286 $query .= " AND aqbasket.basketname LIKE ? ";
2287 push @query_params, "%$basket%";
2291 if ($booksellerinvoicenumber) {
2292 $query .= " AND aqinvoices.invoicenumber LIKE ? ";
2293 push @query_params, "%$booksellerinvoicenumber%";
2296 if ($basketgroupname) {
2297 $query .= " AND aqbasketgroups.name LIKE ? ";
2298 push @query_params, "%$basketgroupname%";
2301 if ($ordernumber) {
2302 $query .= " AND (aqorders.ordernumber = ? ";
2303 push @query_params, $ordernumber;
2304 if ($search_children_too) {
2305 $query .= " OR aqorders.parent_ordernumber = ? ";
2306 push @query_params, $ordernumber;
2308 $query .= ") ";
2311 if ( @$created_by ) {
2312 $query .= ' AND aqbasket.authorisedby IN ( ' . join( ',', ('?') x @$created_by ) . ')';
2313 push @query_params, @$created_by;
2317 if ( C4::Context->preference("IndependentBranches") ) {
2318 unless ( C4::Context->IsSuperLibrarian() ) {
2319 $query .= " AND (borrowers.branchcode = ? OR borrowers.branchcode ='' ) ";
2320 push @query_params, C4::Context->userenv->{branch};
2323 $query .= " ORDER BY id";
2325 return $dbh->selectall_arrayref( $query, { Slice => {} }, @query_params );
2328 =head2 GetRecentAcqui
2330 $results = GetRecentAcqui($days);
2332 C<$results> is a ref to a table which containts hashref
2334 =cut
2336 sub GetRecentAcqui {
2337 my $limit = shift;
2338 my $dbh = C4::Context->dbh;
2339 my $query = "
2340 SELECT *
2341 FROM biblio
2342 ORDER BY timestamp DESC
2343 LIMIT 0,".$limit;
2345 my $sth = $dbh->prepare($query);
2346 $sth->execute;
2347 my $results = $sth->fetchall_arrayref({});
2348 return $results;
2351 #------------------------------------------------------------#
2353 =head3 AddClaim
2355 &AddClaim($ordernumber);
2357 Add a claim for an order
2359 =cut
2361 sub AddClaim {
2362 my ($ordernumber) = @_;
2363 my $dbh = C4::Context->dbh;
2364 my $query = "
2365 UPDATE aqorders SET
2366 claims_count = claims_count + 1,
2367 claimed_date = CURDATE()
2368 WHERE ordernumber = ?
2370 my $sth = $dbh->prepare($query);
2371 $sth->execute($ordernumber);
2374 =head3 GetInvoices
2376 my @invoices = GetInvoices(
2377 invoicenumber => $invoicenumber,
2378 supplierid => $supplierid,
2379 suppliername => $suppliername,
2380 shipmentdatefrom => $shipmentdatefrom, # ISO format
2381 shipmentdateto => $shipmentdateto, # ISO format
2382 billingdatefrom => $billingdatefrom, # ISO format
2383 billingdateto => $billingdateto, # ISO format
2384 isbneanissn => $isbn_or_ean_or_issn,
2385 title => $title,
2386 author => $author,
2387 publisher => $publisher,
2388 publicationyear => $publicationyear,
2389 branchcode => $branchcode,
2390 order_by => $order_by
2393 Return a list of invoices that match all given criteria.
2395 $order_by is "column_name (asc|desc)", where column_name is any of
2396 'invoicenumber', 'booksellerid', 'shipmentdate', 'billingdate', 'closedate',
2397 'shipmentcost', 'shipmentcost_budgetid'.
2399 asc is the default if omitted
2401 =cut
2403 sub GetInvoices {
2404 my %args = @_;
2406 my @columns = qw(invoicenumber booksellerid shipmentdate billingdate
2407 closedate shipmentcost shipmentcost_budgetid);
2409 my $dbh = C4::Context->dbh;
2410 my $query = qq{
2411 SELECT aqinvoices.*, aqbooksellers.name AS suppliername,
2412 COUNT(
2413 DISTINCT IF(
2414 aqorders.datereceived IS NOT NULL,
2415 aqorders.biblionumber,
2416 NULL
2418 ) AS receivedbiblios,
2419 COUNT(
2420 DISTINCT IF(
2421 aqorders.subscriptionid IS NOT NULL,
2422 aqorders.subscriptionid,
2423 NULL
2425 ) AS is_linked_to_subscriptions,
2426 SUM(aqorders.quantityreceived) AS receiveditems
2427 FROM aqinvoices
2428 LEFT JOIN aqbooksellers ON aqbooksellers.id = aqinvoices.booksellerid
2429 LEFT JOIN aqorders ON aqorders.invoiceid = aqinvoices.invoiceid
2430 LEFT JOIN aqbasket ON aqbasket.basketno=aqorders.basketno
2431 LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber
2432 LEFT JOIN biblio ON aqorders.biblionumber = biblio.biblionumber
2433 LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
2434 LEFT JOIN subscription ON biblio.biblionumber = subscription.biblionumber
2437 my @bind_args;
2438 my @bind_strs;
2439 if($args{supplierid}) {
2440 push @bind_strs, " aqinvoices.booksellerid = ? ";
2441 push @bind_args, $args{supplierid};
2443 if($args{invoicenumber}) {
2444 push @bind_strs, " aqinvoices.invoicenumber LIKE ? ";
2445 push @bind_args, "%$args{invoicenumber}%";
2447 if($args{suppliername}) {
2448 push @bind_strs, " aqbooksellers.name LIKE ? ";
2449 push @bind_args, "%$args{suppliername}%";
2451 if($args{shipmentdatefrom}) {
2452 push @bind_strs, " aqinvoices.shipmentdate >= ? ";
2453 push @bind_args, $args{shipmentdatefrom};
2455 if($args{shipmentdateto}) {
2456 push @bind_strs, " aqinvoices.shipmentdate <= ? ";
2457 push @bind_args, $args{shipmentdateto};
2459 if($args{billingdatefrom}) {
2460 push @bind_strs, " aqinvoices.billingdate >= ? ";
2461 push @bind_args, $args{billingdatefrom};
2463 if($args{billingdateto}) {
2464 push @bind_strs, " aqinvoices.billingdate <= ? ";
2465 push @bind_args, $args{billingdateto};
2467 if($args{isbneanissn}) {
2468 push @bind_strs, " (biblioitems.isbn LIKE CONCAT('%', ?, '%') OR biblioitems.ean LIKE CONCAT('%', ?, '%') OR biblioitems.issn LIKE CONCAT('%', ?, '%') ) ";
2469 push @bind_args, $args{isbneanissn}, $args{isbneanissn}, $args{isbneanissn};
2471 if($args{title}) {
2472 push @bind_strs, " biblio.title LIKE CONCAT('%', ?, '%') ";
2473 push @bind_args, $args{title};
2475 if($args{author}) {
2476 push @bind_strs, " biblio.author LIKE CONCAT('%', ?, '%') ";
2477 push @bind_args, $args{author};
2479 if($args{publisher}) {
2480 push @bind_strs, " biblioitems.publishercode LIKE CONCAT('%', ?, '%') ";
2481 push @bind_args, $args{publisher};
2483 if($args{publicationyear}) {
2484 push @bind_strs, " ((biblioitems.publicationyear LIKE CONCAT('%', ?, '%')) OR (biblio.copyrightdate LIKE CONCAT('%', ?, '%'))) ";
2485 push @bind_args, $args{publicationyear}, $args{publicationyear};
2487 if($args{branchcode}) {
2488 push @bind_strs, " borrowers.branchcode = ? ";
2489 push @bind_args, $args{branchcode};
2491 if($args{message_id}) {
2492 push @bind_strs, " aqinvoices.message_id = ? ";
2493 push @bind_args, $args{message_id};
2496 $query .= " WHERE " . join(" AND ", @bind_strs) if @bind_strs;
2497 $query .= " GROUP BY aqinvoices.invoiceid ";
2499 if($args{order_by}) {
2500 my ($column, $direction) = split / /, $args{order_by};
2501 if(grep /^$column$/, @columns) {
2502 $direction ||= 'ASC';
2503 $query .= " ORDER BY $column $direction";
2507 my $sth = $dbh->prepare($query);
2508 $sth->execute(@bind_args);
2510 my $results = $sth->fetchall_arrayref({});
2511 return @$results;
2514 =head3 GetInvoice
2516 my $invoice = GetInvoice($invoiceid);
2518 Get informations about invoice with given $invoiceid
2520 Return a hash filled with aqinvoices.* fields
2522 =cut
2524 sub GetInvoice {
2525 my ($invoiceid) = @_;
2526 my $invoice;
2528 return unless $invoiceid;
2530 my $dbh = C4::Context->dbh;
2531 my $query = qq{
2532 SELECT *
2533 FROM aqinvoices
2534 WHERE invoiceid = ?
2536 my $sth = $dbh->prepare($query);
2537 $sth->execute($invoiceid);
2539 $invoice = $sth->fetchrow_hashref;
2540 return $invoice;
2543 =head3 GetInvoiceDetails
2545 my $invoice = GetInvoiceDetails($invoiceid)
2547 Return informations about an invoice + the list of related order lines
2549 Orders informations are in $invoice->{orders} (array ref)
2551 =cut
2553 sub GetInvoiceDetails {
2554 my ($invoiceid) = @_;
2556 if ( !defined $invoiceid ) {
2557 carp 'GetInvoiceDetails called without an invoiceid';
2558 return;
2561 my $dbh = C4::Context->dbh;
2562 my $query = q{
2563 SELECT aqinvoices.*, aqbooksellers.name AS suppliername
2564 FROM aqinvoices
2565 LEFT JOIN aqbooksellers ON aqinvoices.booksellerid = aqbooksellers.id
2566 WHERE invoiceid = ?
2568 my $sth = $dbh->prepare($query);
2569 $sth->execute($invoiceid);
2571 my $invoice = $sth->fetchrow_hashref;
2573 $query = q{
2574 SELECT aqorders.*,
2575 biblio.*,
2576 biblio.copyrightdate,
2577 biblioitems.publishercode,
2578 biblioitems.publicationyear,
2579 aqbasket.basketname,
2580 aqbasketgroups.id AS basketgroupid,
2581 aqbasketgroups.name AS basketgroupname
2582 FROM aqorders
2583 LEFT JOIN aqbasket ON aqorders.basketno = aqbasket.basketno
2584 LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid = aqbasketgroups.id
2585 LEFT JOIN biblio ON aqorders.biblionumber = biblio.biblionumber
2586 LEFT JOIN biblioitems ON aqorders.biblionumber = biblioitems.biblionumber
2587 WHERE invoiceid = ?
2589 $sth = $dbh->prepare($query);
2590 $sth->execute($invoiceid);
2591 $invoice->{orders} = $sth->fetchall_arrayref({});
2592 $invoice->{orders} ||= []; # force an empty arrayref if fetchall_arrayref fails
2594 return $invoice;
2597 =head3 AddInvoice
2599 my $invoiceid = AddInvoice(
2600 invoicenumber => $invoicenumber,
2601 booksellerid => $booksellerid,
2602 shipmentdate => $shipmentdate,
2603 billingdate => $billingdate,
2604 closedate => $closedate,
2605 shipmentcost => $shipmentcost,
2606 shipmentcost_budgetid => $shipmentcost_budgetid
2609 Create a new invoice and return its id or undef if it fails.
2611 =cut
2613 sub AddInvoice {
2614 my %invoice = @_;
2616 return unless(%invoice and $invoice{invoicenumber});
2618 my @columns = qw(invoicenumber booksellerid shipmentdate billingdate
2619 closedate shipmentcost shipmentcost_budgetid message_id);
2621 my @set_strs;
2622 my @set_args;
2623 foreach my $key (keys %invoice) {
2624 if(0 < grep(/^$key$/, @columns)) {
2625 push @set_strs, "$key = ?";
2626 push @set_args, ($invoice{$key} || undef);
2630 my $rv;
2631 if(@set_args > 0) {
2632 my $dbh = C4::Context->dbh;
2633 my $query = "INSERT INTO aqinvoices SET ";
2634 $query .= join (",", @set_strs);
2635 my $sth = $dbh->prepare($query);
2636 $rv = $sth->execute(@set_args);
2637 if($rv) {
2638 $rv = $dbh->last_insert_id(undef, undef, 'aqinvoices', undef);
2641 return $rv;
2644 =head3 ModInvoice
2646 ModInvoice(
2647 invoiceid => $invoiceid, # Mandatory
2648 invoicenumber => $invoicenumber,
2649 booksellerid => $booksellerid,
2650 shipmentdate => $shipmentdate,
2651 billingdate => $billingdate,
2652 closedate => $closedate,
2653 shipmentcost => $shipmentcost,
2654 shipmentcost_budgetid => $shipmentcost_budgetid
2657 Modify an invoice, invoiceid is mandatory.
2659 Return undef if it fails.
2661 =cut
2663 sub ModInvoice {
2664 my %invoice = @_;
2666 return unless(%invoice and $invoice{invoiceid});
2668 my @columns = qw(invoicenumber booksellerid shipmentdate billingdate
2669 closedate shipmentcost shipmentcost_budgetid);
2671 my @set_strs;
2672 my @set_args;
2673 foreach my $key (keys %invoice) {
2674 if(0 < grep(/^$key$/, @columns)) {
2675 push @set_strs, "$key = ?";
2676 push @set_args, ($invoice{$key} || undef);
2680 my $dbh = C4::Context->dbh;
2681 my $query = "UPDATE aqinvoices SET ";
2682 $query .= join(",", @set_strs);
2683 $query .= " WHERE invoiceid = ?";
2685 my $sth = $dbh->prepare($query);
2686 $sth->execute(@set_args, $invoice{invoiceid});
2689 =head3 CloseInvoice
2691 CloseInvoice($invoiceid);
2693 Close an invoice.
2695 Equivalent to ModInvoice(invoiceid => $invoiceid, closedate => undef);
2697 =cut
2699 sub CloseInvoice {
2700 my ($invoiceid) = @_;
2702 return unless $invoiceid;
2704 my $dbh = C4::Context->dbh;
2705 my $query = qq{
2706 UPDATE aqinvoices
2707 SET closedate = CAST(NOW() AS DATE)
2708 WHERE invoiceid = ?
2710 my $sth = $dbh->prepare($query);
2711 $sth->execute($invoiceid);
2714 =head3 ReopenInvoice
2716 ReopenInvoice($invoiceid);
2718 Reopen an invoice
2720 Equivalent to ModInvoice(invoiceid => $invoiceid, closedate => output_pref({ dt=>dt_from_string, dateonly=>1, otputpref=>'iso' }))
2722 =cut
2724 sub ReopenInvoice {
2725 my ($invoiceid) = @_;
2727 return unless $invoiceid;
2729 my $dbh = C4::Context->dbh;
2730 my $query = qq{
2731 UPDATE aqinvoices
2732 SET closedate = NULL
2733 WHERE invoiceid = ?
2735 my $sth = $dbh->prepare($query);
2736 $sth->execute($invoiceid);
2739 =head3 DelInvoice
2741 DelInvoice($invoiceid);
2743 Delete an invoice if there are no items attached to it.
2745 =cut
2747 sub DelInvoice {
2748 my ($invoiceid) = @_;
2750 return unless $invoiceid;
2752 my $dbh = C4::Context->dbh;
2753 my $query = qq{
2754 SELECT COUNT(*)
2755 FROM aqorders
2756 WHERE invoiceid = ?
2758 my $sth = $dbh->prepare($query);
2759 $sth->execute($invoiceid);
2760 my $res = $sth->fetchrow_arrayref;
2761 if ( $res && $res->[0] == 0 ) {
2762 $query = qq{
2763 DELETE FROM aqinvoices
2764 WHERE invoiceid = ?
2766 my $sth = $dbh->prepare($query);
2767 return ( $sth->execute($invoiceid) > 0 );
2769 return;
2772 =head3 MergeInvoices
2774 MergeInvoices($invoiceid, \@sourceids);
2776 Merge the invoices identified by the IDs in \@sourceids into
2777 the invoice identified by $invoiceid.
2779 =cut
2781 sub MergeInvoices {
2782 my ($invoiceid, $sourceids) = @_;
2784 return unless $invoiceid;
2785 foreach my $sourceid (@$sourceids) {
2786 next if $sourceid == $invoiceid;
2787 my $source = GetInvoiceDetails($sourceid);
2788 foreach my $order (@{$source->{'orders'}}) {
2789 $order->{'invoiceid'} = $invoiceid;
2790 ModOrder($order);
2792 DelInvoice($source->{'invoiceid'});
2794 return;
2797 =head3 GetBiblioCountByBasketno
2799 $biblio_count = &GetBiblioCountByBasketno($basketno);
2801 Looks up the biblio's count that has basketno value $basketno
2803 Returns a quantity
2805 =cut
2807 sub GetBiblioCountByBasketno {
2808 my ($basketno) = @_;
2809 my $dbh = C4::Context->dbh;
2810 my $query = "
2811 SELECT COUNT( DISTINCT( biblionumber ) )
2812 FROM aqorders
2813 WHERE basketno = ?
2814 AND (datecancellationprinted IS NULL OR datecancellationprinted='0000-00-00')
2817 my $sth = $dbh->prepare($query);
2818 $sth->execute($basketno);
2819 return $sth->fetchrow;
2822 # This is *not* the good way to calcul prices
2823 # But it's how it works at the moment into Koha
2824 # This will be fixed later.
2825 # Note this subroutine should be moved to Koha::Acquisition::Order
2826 # Will do when a DBIC decision will be taken.
2827 sub populate_order_with_prices {
2828 my ($params) = @_;
2830 my $order = $params->{order};
2831 my $booksellerid = $params->{booksellerid};
2832 return unless $booksellerid;
2834 my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $booksellerid });
2836 my $receiving = $params->{receiving};
2837 my $ordering = $params->{ordering};
2838 my $discount = $order->{discount};
2839 $discount /= 100 if $discount > 1;
2841 $order->{rrp} = Koha::Number::Price->new( $order->{rrp} )->round;
2842 $order->{ecost} = Koha::Number::Price->new( $order->{ecost} )->round;
2843 if ($ordering) {
2844 if ( $bookseller->{listincgst} ) {
2845 $order->{rrpgsti} = $order->{rrp};
2846 $order->{rrpgste} = Koha::Number::Price->new(
2847 $order->{rrpgsti} / ( 1 + $order->{gstrate} ) )->round;
2848 $order->{ecostgsti} = $order->{ecost};
2849 $order->{ecostgste} = Koha::Number::Price->new(
2850 $order->{ecost} / ( 1 + $order->{gstrate} ) )->round;
2851 $order->{gstvalue} = Koha::Number::Price->new(
2852 ( $order->{ecostgsti} - $order->{ecostgste} ) *
2853 $order->{quantity} )->round;
2854 $order->{totalgste} = $order->{ecostgste} * $order->{quantity};
2855 $order->{totalgsti} = $order->{ecostgsti} * $order->{quantity};
2857 else {
2858 $order->{rrpgste} = $order->{rrp};
2859 $order->{rrpgsti} = Koha::Number::Price->new(
2860 $order->{rrp} * ( 1 + $order->{gstrate} ) )->round;
2861 $order->{ecostgste} = $order->{ecost};
2862 $order->{ecostgsti} = Koha::Number::Price->new(
2863 $order->{ecost} * ( 1 + $order->{gstrate} ) )->round;
2864 $order->{gstvalue} = Koha::Number::Price->new(
2865 ( $order->{ecostgsti} - $order->{ecostgste} ) *
2866 $order->{quantity} )->round;
2867 $order->{totalgste} = $order->{ecostgste} * $order->{quantity};
2868 $order->{totalgsti} = $order->{ecostgsti} * $order->{quantity};
2872 if ($receiving) {
2873 if ( $bookseller->{listincgst} ) {
2874 $order->{unitpricegsti} = Koha::Number::Price->new( $order->{unitprice} )->round;
2875 $order->{unitpricegste} = Koha::Number::Price->new(
2876 $order->{unitpricegsti} / ( 1 + $order->{gstrate} ) )->round;
2878 else {
2879 $order->{unitpricegste} = Koha::Number::Price->new( $order->{unitprice} )->round;
2880 $order->{unitpricegsti} = Koha::Number::Price->new(
2881 $order->{unitpricegste} * ( 1 + $order->{gstrate} ) )->round;
2883 $order->{gstvalue} = Koha::Number::Price->new(
2884 ( $order->{unitpricegsti} - $order->{unitpricegste} )
2885 * $order->{quantityreceived} )->round;
2887 $order->{totalgste} = $order->{unitpricegste} * $order->{quantity};
2888 $order->{totalgsti} = $order->{unitpricegsti} * $order->{quantity};
2891 return $order;
2894 =head3 GetOrderUsers
2896 $order_users_ids = &GetOrderUsers($ordernumber);
2898 Returns a list of all borrowernumbers that are in order users list
2900 =cut
2902 sub GetOrderUsers {
2903 my ($ordernumber) = @_;
2905 return unless $ordernumber;
2907 my $query = q|
2908 SELECT borrowernumber
2909 FROM aqorder_users
2910 WHERE ordernumber = ?
2912 my $dbh = C4::Context->dbh;
2913 my $sth = $dbh->prepare($query);
2914 $sth->execute($ordernumber);
2915 my $results = $sth->fetchall_arrayref( {} );
2917 my @borrowernumbers;
2918 foreach (@$results) {
2919 push @borrowernumbers, $_->{'borrowernumber'};
2922 return @borrowernumbers;
2925 =head3 ModOrderUsers
2927 my @order_users_ids = (1, 2, 3);
2928 &ModOrderUsers($ordernumber, @basketusers_ids);
2930 Delete all users from order users list, and add users in C<@order_users_ids>
2931 to this users list.
2933 =cut
2935 sub ModOrderUsers {
2936 my ( $ordernumber, @order_users_ids ) = @_;
2938 return unless $ordernumber;
2940 my $dbh = C4::Context->dbh;
2941 my $query = q|
2942 DELETE FROM aqorder_users
2943 WHERE ordernumber = ?
2945 my $sth = $dbh->prepare($query);
2946 $sth->execute($ordernumber);
2948 $query = q|
2949 INSERT INTO aqorder_users (ordernumber, borrowernumber)
2950 VALUES (?, ?)
2952 $sth = $dbh->prepare($query);
2953 foreach my $order_user_id (@order_users_ids) {
2954 $sth->execute( $ordernumber, $order_user_id );
2958 sub NotifyOrderUsers {
2959 my ($ordernumber) = @_;
2961 my @borrowernumbers = GetOrderUsers($ordernumber);
2962 return unless @borrowernumbers;
2964 my $order = GetOrder( $ordernumber );
2965 for my $borrowernumber (@borrowernumbers) {
2966 my $borrower = C4::Members::GetMember( borrowernumber => $borrowernumber );
2967 my $library = Koha::Libraries->find( $borrower->{branchcode} )->unblessed;
2968 my $biblio = C4::Biblio::GetBiblio( $order->{biblionumber} );
2969 my $letter = C4::Letters::GetPreparedLetter(
2970 module => 'acquisition',
2971 letter_code => 'ACQ_NOTIF_ON_RECEIV',
2972 branchcode => $library->{branchcode},
2973 tables => {
2974 'branches' => $library,
2975 'borrowers' => $borrower,
2976 'biblio' => $biblio,
2977 'aqorders' => $order,
2980 if ( $letter ) {
2981 C4::Letters::EnqueueLetter(
2983 letter => $letter,
2984 borrowernumber => $borrowernumber,
2985 LibraryName => C4::Context->preference("LibraryName"),
2986 message_transport_type => 'email',
2988 ) or warn "can't enqueue letter $letter";
2993 =head3 FillWithDefaultValues
2995 FillWithDefaultValues( $marc_record );
2997 This will update the record with default value defined in the ACQ framework.
2998 For all existing fields, if a default value exists and there are no subfield, it will be created.
2999 If the field does not exist, it will be created too.
3001 =cut
3003 sub FillWithDefaultValues {
3004 my ($record) = @_;
3005 my $tagslib = C4::Biblio::GetMarcStructure( 1, 'ACQ' );
3006 if ($tagslib) {
3007 my ($itemfield) =
3008 C4::Biblio::GetMarcFromKohaField( 'items.itemnumber', '' );
3009 for my $tag ( sort keys %$tagslib ) {
3010 next unless $tag;
3011 next if $tag == $itemfield;
3012 for my $subfield ( sort keys %{ $tagslib->{$tag} } ) {
3013 next if IsMarcStructureInternal($tagslib->{$tag}{$subfield});
3014 my $defaultvalue = $tagslib->{$tag}{$subfield}{defaultvalue};
3015 if ( defined $defaultvalue and $defaultvalue ne '' ) {
3016 my @fields = $record->field($tag);
3017 if (@fields) {
3018 for my $field (@fields) {
3019 unless ( defined $field->subfield($subfield) ) {
3020 $field->add_subfields(
3021 $subfield => $defaultvalue );
3025 else {
3026 $record->insert_fields_ordered(
3027 MARC::Field->new(
3028 $tag, '', '', $subfield => $defaultvalue
3039 __END__
3041 =head1 AUTHOR
3043 Koha Development Team <http://koha-community.org/>
3045 =cut