Bug 9803 - question mark in cataloging not clearly a link
[koha.git] / C4 / Acquisition.pm
blob597345651526bee43d4f317c273f4c770d71e412
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 strict;
22 use warnings;
23 use Carp;
24 use C4::Context;
25 use C4::Debug;
26 use C4::Dates qw(format_date format_date_in_iso);
27 use MARC::Record;
28 use C4::Suggestions;
29 use C4::Biblio;
30 use C4::Debug;
31 use C4::SQLHelper qw(InsertInTable);
32 use C4::Bookseller qw(GetBookSellerFromId);
33 use C4::Templates qw(gettemplate);
35 use Time::localtime;
36 use HTML::Entities;
38 use vars qw($VERSION @ISA @EXPORT);
40 BEGIN {
41 # set the version for version checking
42 $VERSION = 3.07.00.049;
43 require Exporter;
44 @ISA = qw(Exporter);
45 @EXPORT = qw(
46 &GetBasket &NewBasket &CloseBasket &DelBasket &ModBasket
47 &GetBasketAsCSV &GetBasketGroupAsCSV
48 &GetBasketsByBookseller &GetBasketsByBasketgroup
49 &GetBasketsInfosByBookseller
51 &ModBasketHeader
53 &ModBasketgroup &NewBasketgroup &DelBasketgroup &GetBasketgroup &CloseBasketgroup
54 &GetBasketgroups &ReOpenBasketgroup
56 &NewOrder &DelOrder &ModOrder &GetPendingOrders &GetOrder &GetOrders
57 &GetOrderNumber &GetLateOrders &GetOrderFromItemnumber
58 &SearchOrder &GetHistory &GetRecentAcqui
59 &ModReceiveOrder &CancelReceipt &ModOrderBiblioitemNumber
60 &GetCancelledOrders
61 &GetLastOrderNotReceivedFromSubscriptionid &GetLastOrderReceivedFromSubscriptionid
62 &NewOrderItem &ModOrderItem &ModItemOrder
64 &GetParcels &GetParcel
65 &GetContracts &GetContract
67 &GetInvoices
68 &GetInvoice
69 &GetInvoiceDetails
70 &AddInvoice
71 &ModInvoice
72 &CloseInvoice
73 &ReopenInvoice
75 &GetItemnumbersFromOrder
77 &AddClaim
85 sub GetOrderFromItemnumber {
86 my ($itemnumber) = @_;
87 my $dbh = C4::Context->dbh;
88 my $query = qq|
90 SELECT * from aqorders LEFT JOIN aqorders_items
91 ON ( aqorders.ordernumber = aqorders_items.ordernumber )
92 WHERE itemnumber = ? |;
94 my $sth = $dbh->prepare($query);
96 # $sth->trace(3);
98 $sth->execute($itemnumber);
100 my $order = $sth->fetchrow_hashref;
101 return ( $order );
105 # Returns the itemnumber(s) associated with the ordernumber given in parameter
106 sub GetItemnumbersFromOrder {
107 my ($ordernumber) = @_;
108 my $dbh = C4::Context->dbh;
109 my $query = "SELECT itemnumber FROM aqorders_items WHERE ordernumber=?";
110 my $sth = $dbh->prepare($query);
111 $sth->execute($ordernumber);
112 my @tab;
114 while (my $order = $sth->fetchrow_hashref) {
115 push @tab, $order->{'itemnumber'};
118 return @tab;
127 =head1 NAME
129 C4::Acquisition - Koha functions for dealing with orders and acquisitions
131 =head1 SYNOPSIS
133 use C4::Acquisition;
135 =head1 DESCRIPTION
137 The functions in this module deal with acquisitions, managing book
138 orders, basket and parcels.
140 =head1 FUNCTIONS
142 =head2 FUNCTIONS ABOUT BASKETS
144 =head3 GetBasket
146 $aqbasket = &GetBasket($basketnumber);
148 get all basket informations in aqbasket for a given basket
150 B<returns:> informations for a given basket returned as a hashref.
152 =cut
154 sub GetBasket {
155 my ($basketno) = @_;
156 my $dbh = C4::Context->dbh;
157 my $query = "
158 SELECT aqbasket.*,
159 concat( b.firstname,' ',b.surname) AS authorisedbyname,
160 b.branchcode AS branch
161 FROM aqbasket
162 LEFT JOIN borrowers b ON aqbasket.authorisedby=b.borrowernumber
163 WHERE basketno=?
165 my $sth=$dbh->prepare($query);
166 $sth->execute($basketno);
167 my $basket = $sth->fetchrow_hashref;
168 return ( $basket );
171 #------------------------------------------------------------#
173 =head3 NewBasket
175 $basket = &NewBasket( $booksellerid, $authorizedby, $basketname,
176 $basketnote, $basketbooksellernote, $basketcontractnumber, $deliveryplace, $billingplace );
178 Create a new basket in aqbasket table
180 =over
182 =item C<$booksellerid> is a foreign key in the aqbasket table
184 =item C<$authorizedby> is the username of who created the basket
186 =back
188 The other parameters are optional, see ModBasketHeader for more info on them.
190 =cut
192 sub NewBasket {
193 my ( $booksellerid, $authorisedby, $basketname, $basketnote,
194 $basketbooksellernote, $basketcontractnumber, $deliveryplace,
195 $billingplace ) = @_;
196 my $dbh = C4::Context->dbh;
197 my $query =
198 'INSERT INTO aqbasket (creationdate,booksellerid,authorisedby) '
199 . 'VALUES (now(),?,?)';
200 $dbh->do( $query, {}, $booksellerid, $authorisedby );
202 my $basket = $dbh->{mysql_insertid};
203 $basketname ||= q{}; # default to empty strings
204 $basketnote ||= q{};
205 $basketbooksellernote ||= q{};
206 ModBasketHeader( $basket, $basketname, $basketnote, $basketbooksellernote,
207 $basketcontractnumber, $booksellerid, $deliveryplace, $billingplace );
208 return $basket;
211 #------------------------------------------------------------#
213 =head3 CloseBasket
215 &CloseBasket($basketno);
217 close a basket (becomes unmodifiable,except for recieves)
219 =cut
221 sub CloseBasket {
222 my ($basketno) = @_;
223 my $dbh = C4::Context->dbh;
224 my $query = "
225 UPDATE aqbasket
226 SET closedate=now()
227 WHERE basketno=?
229 my $sth = $dbh->prepare($query);
230 $sth->execute($basketno);
233 #------------------------------------------------------------#
235 =head3 GetBasketAsCSV
237 &GetBasketAsCSV($basketno);
239 Export a basket as CSV
241 $cgi parameter is needed for column name translation
243 =cut
245 sub GetBasketAsCSV {
246 my ($basketno, $cgi) = @_;
247 my $basket = GetBasket($basketno);
248 my @orders = GetOrders($basketno);
249 my $contract = GetContract($basket->{'contractnumber'});
251 my $template = C4::Templates::gettemplate("acqui/csv/basket.tmpl", "intranet", $cgi);
253 my @rows;
254 foreach my $order (@orders) {
255 my $bd = GetBiblioData( $order->{'biblionumber'} );
256 my $row = {
257 contractname => $contract->{'contractname'},
258 ordernumber => $order->{'ordernumber'},
259 entrydate => $order->{'entrydate'},
260 isbn => $order->{'isbn'},
261 author => $bd->{'author'},
262 title => $bd->{'title'},
263 publicationyear => $bd->{'publicationyear'},
264 publishercode => $bd->{'publishercode'},
265 collectiontitle => $bd->{'collectiontitle'},
266 notes => $order->{'notes'},
267 quantity => $order->{'quantity'},
268 rrp => $order->{'rrp'},
269 deliveryplace => C4::Branch::GetBranchName( $basket->{'deliveryplace'} ),
270 billingplace => C4::Branch::GetBranchName( $basket->{'billingplace'} ),
272 foreach(qw(
273 contractname author title publishercode collectiontitle notes
274 deliveryplace billingplace
275 ) ) {
276 # Double the quotes to not be interpreted as a field end
277 $row->{$_} =~ s/"/""/g if $row->{$_};
279 push @rows, $row;
282 @rows = sort {
283 if(defined $a->{publishercode} and defined $b->{publishercode}) {
284 $a->{publishercode} cmp $b->{publishercode};
286 } @rows;
288 $template->param(rows => \@rows);
290 return $template->output;
294 =head3 GetBasketGroupAsCSV
296 =over 4
298 &GetBasketGroupAsCSV($basketgroupid);
300 Export a basket group as CSV
302 $cgi parameter is needed for column name translation
304 =back
306 =cut
308 sub GetBasketGroupAsCSV {
309 my ($basketgroupid, $cgi) = @_;
310 my $baskets = GetBasketsByBasketgroup($basketgroupid);
312 my $template = C4::Templates::gettemplate('acqui/csv/basketgroup.tmpl', 'intranet', $cgi);
314 my @rows;
315 for my $basket (@$baskets) {
316 my @orders = GetOrders( $$basket{basketno} );
317 my $contract = GetContract( $$basket{contractnumber} );
318 my $bookseller = GetBookSellerFromId( $$basket{booksellerid} );
319 my $basketgroup = GetBasketgroup( $$basket{basketgroupid} );
321 foreach my $order (@orders) {
322 my $bd = GetBiblioData( $order->{'biblionumber'} );
323 my $row = {
324 clientnumber => $bookseller->{accountnumber},
325 basketname => $basket->{basketname},
326 ordernumber => $order->{ordernumber},
327 author => $bd->{author},
328 title => $bd->{title},
329 publishercode => $bd->{publishercode},
330 publicationyear => $bd->{publicationyear},
331 collectiontitle => $bd->{collectiontitle},
332 isbn => $order->{isbn},
333 quantity => $order->{quantity},
334 rrp => $order->{rrp},
335 discount => $bookseller->{discount},
336 ecost => $order->{ecost},
337 notes => $order->{notes},
338 entrydate => $order->{entrydate},
339 booksellername => $bookseller->{name},
340 bookselleraddress => $bookseller->{address1},
341 booksellerpostal => $bookseller->{postal},
342 contractnumber => $contract->{contractnumber},
343 contractname => $contract->{contractname},
344 basketgroupdeliveryplace => C4::Branch::GetBranchName( $basketgroup->{deliveryplace} ),
345 basketgroupbillingplace => C4::Branch::GetBranchName( $basketgroup->{billingplace} ),
346 basketdeliveryplace => C4::Branch::GetBranchName( $basket->{deliveryplace} ),
347 basketbillingplace => C4::Branch::GetBranchName( $basket->{billingplace} ),
349 foreach(qw(
350 basketname author title publishercode collectiontitle notes
351 booksellername bookselleraddress booksellerpostal contractname
352 basketgroupdeliveryplace basketgroupbillingplace
353 basketdeliveryplace basketbillingplace
354 ) ) {
355 # Double the quotes to not be interpreted as a field end
356 $row->{$_} =~ s/"/""/g if $row->{$_};
358 push @rows, $row;
361 $template->param(rows => \@rows);
363 return $template->output;
367 =head3 CloseBasketgroup
369 &CloseBasketgroup($basketgroupno);
371 close a basketgroup
373 =cut
375 sub CloseBasketgroup {
376 my ($basketgroupno) = @_;
377 my $dbh = C4::Context->dbh;
378 my $sth = $dbh->prepare("
379 UPDATE aqbasketgroups
380 SET closed=1
381 WHERE id=?
383 $sth->execute($basketgroupno);
386 #------------------------------------------------------------#
388 =head3 ReOpenBaskergroup($basketgroupno)
390 &ReOpenBaskergroup($basketgroupno);
392 reopen a basketgroup
394 =cut
396 sub ReOpenBasketgroup {
397 my ($basketgroupno) = @_;
398 my $dbh = C4::Context->dbh;
399 my $sth = $dbh->prepare("
400 UPDATE aqbasketgroups
401 SET closed=0
402 WHERE id=?
404 $sth->execute($basketgroupno);
407 #------------------------------------------------------------#
410 =head3 DelBasket
412 &DelBasket($basketno);
414 Deletes the basket that has basketno field $basketno in the aqbasket table.
416 =over
418 =item C<$basketno> is the primary key of the basket in the aqbasket table.
420 =back
422 =cut
424 sub DelBasket {
425 my ( $basketno ) = @_;
426 my $query = "DELETE FROM aqbasket WHERE basketno=?";
427 my $dbh = C4::Context->dbh;
428 my $sth = $dbh->prepare($query);
429 $sth->execute($basketno);
430 $sth->finish;
433 #------------------------------------------------------------#
435 =head3 ModBasket
437 &ModBasket($basketinfo);
439 Modifies a basket, using a hashref $basketinfo for the relevant information, only $basketinfo->{'basketno'} is required.
441 =over
443 =item C<$basketno> is the primary key of the basket in the aqbasket table.
445 =back
447 =cut
449 sub ModBasket {
450 my $basketinfo = shift;
451 my $query = "UPDATE aqbasket SET ";
452 my @params;
453 foreach my $key (keys %$basketinfo){
454 if ($key ne 'basketno'){
455 $query .= "$key=?, ";
456 push(@params, $basketinfo->{$key} || undef );
459 # get rid of the "," at the end of $query
460 if (substr($query, length($query)-2) eq ', '){
461 chop($query);
462 chop($query);
463 $query .= ' ';
465 $query .= "WHERE basketno=?";
466 push(@params, $basketinfo->{'basketno'});
467 my $dbh = C4::Context->dbh;
468 my $sth = $dbh->prepare($query);
469 $sth->execute(@params);
470 $sth->finish;
473 #------------------------------------------------------------#
475 =head3 ModBasketHeader
477 &ModBasketHeader($basketno, $basketname, $note, $booksellernote, $contractnumber, $booksellerid);
479 Modifies a basket's header.
481 =over
483 =item C<$basketno> is the "basketno" field in the "aqbasket" table;
485 =item C<$basketname> is the "basketname" field in the "aqbasket" table;
487 =item C<$note> is the "note" field in the "aqbasket" table;
489 =item C<$booksellernote> is the "booksellernote" field in the "aqbasket" table;
491 =item C<$contractnumber> is the "contractnumber" (foreign) key in the "aqbasket" table.
493 =item C<$booksellerid> is the id (foreign) key in the "aqbooksellers" table for the vendor.
495 =item C<$deliveryplace> is the "deliveryplace" field in the aqbasket table.
497 =item C<$billingplace> is the "billingplace" field in the aqbasket table.
499 =back
501 =cut
503 sub ModBasketHeader {
504 my ($basketno, $basketname, $note, $booksellernote, $contractnumber, $booksellerid, $deliveryplace, $billingplace) = @_;
505 my $query = qq{
506 UPDATE aqbasket
507 SET basketname=?, note=?, booksellernote=?, booksellerid=?, deliveryplace=?, billingplace=?
508 WHERE basketno=?
511 my $dbh = C4::Context->dbh;
512 my $sth = $dbh->prepare($query);
513 $sth->execute($basketname, $note, $booksellernote, $booksellerid, $deliveryplace, $billingplace, $basketno);
515 if ( $contractnumber ) {
516 my $query2 ="UPDATE aqbasket SET contractnumber=? WHERE basketno=?";
517 my $sth2 = $dbh->prepare($query2);
518 $sth2->execute($contractnumber,$basketno);
519 $sth2->finish;
521 $sth->finish;
524 #------------------------------------------------------------#
526 =head3 GetBasketsByBookseller
528 @results = &GetBasketsByBookseller($booksellerid, $extra);
530 Returns a list of hashes of all the baskets that belong to bookseller 'booksellerid'.
532 =over
534 =item C<$booksellerid> is the 'id' field of the bookseller in the aqbooksellers table
536 =item C<$extra> is the extra sql parameters, can be
538 $extra->{groupby}: group baskets by column
539 ex. $extra->{groupby} = aqbasket.basketgroupid
540 $extra->{orderby}: order baskets by column
541 $extra->{limit}: limit number of results (can be helpful for pagination)
543 =back
545 =cut
547 sub GetBasketsByBookseller {
548 my ($booksellerid, $extra) = @_;
549 my $query = "SELECT * FROM aqbasket WHERE booksellerid=?";
550 if ($extra){
551 if ($extra->{groupby}) {
552 $query .= " GROUP by $extra->{groupby}";
554 if ($extra->{orderby}){
555 $query .= " ORDER by $extra->{orderby}";
557 if ($extra->{limit}){
558 $query .= " LIMIT $extra->{limit}";
561 my $dbh = C4::Context->dbh;
562 my $sth = $dbh->prepare($query);
563 $sth->execute($booksellerid);
564 my $results = $sth->fetchall_arrayref({});
565 $sth->finish;
566 return $results
569 =head3 GetBasketsInfosByBookseller
571 my $baskets = GetBasketsInfosByBookseller($supplierid);
573 Returns in a arrayref of hashref all about booksellers baskets, plus:
574 total_biblios: Number of distinct biblios in basket
575 total_items: Number of items in basket
576 expected_items: Number of non-received items in basket
578 =cut
580 sub GetBasketsInfosByBookseller {
581 my ($supplierid) = @_;
583 return unless $supplierid;
585 my $dbh = C4::Context->dbh;
586 my $query = qq{
587 SELECT aqbasket.*,
588 SUM(aqorders.quantity) AS total_items,
589 COUNT(DISTINCT aqorders.biblionumber) AS total_biblios,
590 SUM(
591 IF(aqorders.datereceived IS NULL
592 AND aqorders.datecancellationprinted IS NULL
593 , aqorders.quantity
594 , 0)
595 ) AS expected_items
596 FROM aqbasket
597 LEFT JOIN aqorders ON aqorders.basketno = aqbasket.basketno
598 WHERE booksellerid = ?
599 GROUP BY aqbasket.basketno
601 my $sth = $dbh->prepare($query);
602 $sth->execute($supplierid);
603 return $sth->fetchall_arrayref({});
607 #------------------------------------------------------------#
609 =head3 GetBasketsByBasketgroup
611 $baskets = &GetBasketsByBasketgroup($basketgroupid);
613 Returns a reference to all baskets that belong to basketgroup $basketgroupid.
615 =cut
617 sub GetBasketsByBasketgroup {
618 my $basketgroupid = shift;
619 my $query = qq{
620 SELECT *, aqbasket.booksellerid as booksellerid
621 FROM aqbasket
622 LEFT JOIN aqcontract USING(contractnumber) WHERE basketgroupid=?
624 my $dbh = C4::Context->dbh;
625 my $sth = $dbh->prepare($query);
626 $sth->execute($basketgroupid);
627 my $results = $sth->fetchall_arrayref({});
628 $sth->finish;
629 return $results
632 #------------------------------------------------------------#
634 =head3 NewBasketgroup
636 $basketgroupid = NewBasketgroup(\%hashref);
638 Adds a basketgroup to the aqbasketgroups table, and add the initial baskets to it.
640 $hashref->{'booksellerid'} is the 'id' field of the bookseller in the aqbooksellers table,
642 $hashref->{'name'} is the 'name' field of the basketgroup in the aqbasketgroups table,
644 $hashref->{'basketlist'} is a list reference of the 'id's of the baskets that belong to this group,
646 $hashref->{'deliveryplace'} is the 'deliveryplace' field of the basketgroup in the aqbasketgroups table,
648 $hashref->{'deliverycomment'} is the 'deliverycomment' field of the basketgroup in the aqbasketgroups table,
650 $hashref->{'closed'} is the 'closed' field of the aqbasketgroups table, it is false if 0, true otherwise.
652 =cut
654 sub NewBasketgroup {
655 my $basketgroupinfo = shift;
656 die "booksellerid is required to create a basketgroup" unless $basketgroupinfo->{'booksellerid'};
657 my $query = "INSERT INTO aqbasketgroups (";
658 my @params;
659 foreach my $field ('name', 'deliveryplace', 'deliverycomment', 'closed') {
660 if ( $basketgroupinfo->{$field} ) {
661 $query .= "$field, ";
662 push(@params, $basketgroupinfo->{$field});
665 $query .= "booksellerid) VALUES (";
666 foreach (@params) {
667 $query .= "?, ";
669 $query .= "?)";
670 push(@params, $basketgroupinfo->{'booksellerid'});
671 my $dbh = C4::Context->dbh;
672 my $sth = $dbh->prepare($query);
673 $sth->execute(@params);
674 my $basketgroupid = $dbh->{'mysql_insertid'};
675 if( $basketgroupinfo->{'basketlist'} ) {
676 foreach my $basketno (@{$basketgroupinfo->{'basketlist'}}) {
677 my $query2 = "UPDATE aqbasket SET basketgroupid=? WHERE basketno=?";
678 my $sth2 = $dbh->prepare($query2);
679 $sth2->execute($basketgroupid, $basketno);
682 return $basketgroupid;
685 #------------------------------------------------------------#
687 =head3 ModBasketgroup
689 ModBasketgroup(\%hashref);
691 Modifies a basketgroup in the aqbasketgroups table, and add the baskets to it.
693 $hashref->{'id'} is the 'id' field of the basketgroup in the aqbasketgroup table, this parameter is mandatory,
695 $hashref->{'name'} is the 'name' field of the basketgroup in the aqbasketgroups table,
697 $hashref->{'basketlist'} is a list reference of the 'id's of the baskets that belong to this group,
699 $hashref->{'billingplace'} is the 'billingplace' field of the basketgroup in the aqbasketgroups table,
701 $hashref->{'deliveryplace'} is the 'deliveryplace' field of the basketgroup in the aqbasketgroups table,
703 $hashref->{'deliverycomment'} is the 'deliverycomment' field of the basketgroup in the aqbasketgroups table,
705 $hashref->{'closed'} is the 'closed' field of the aqbasketgroups table, it is false if 0, true otherwise.
707 =cut
709 sub ModBasketgroup {
710 my $basketgroupinfo = shift;
711 die "basketgroup id is required to edit a basketgroup" unless $basketgroupinfo->{'id'};
712 my $dbh = C4::Context->dbh;
713 my $query = "UPDATE aqbasketgroups SET ";
714 my @params;
715 foreach my $field (qw(name billingplace deliveryplace freedeliveryplace deliverycomment closed)) {
716 if ( defined $basketgroupinfo->{$field} ) {
717 $query .= "$field=?, ";
718 push(@params, $basketgroupinfo->{$field});
721 chop($query);
722 chop($query);
723 $query .= " WHERE id=?";
724 push(@params, $basketgroupinfo->{'id'});
725 my $sth = $dbh->prepare($query);
726 $sth->execute(@params);
728 $sth = $dbh->prepare('UPDATE aqbasket SET basketgroupid = NULL WHERE basketgroupid = ?');
729 $sth->execute($basketgroupinfo->{'id'});
731 if($basketgroupinfo->{'basketlist'} && @{$basketgroupinfo->{'basketlist'}}){
732 $sth = $dbh->prepare("UPDATE aqbasket SET basketgroupid=? WHERE basketno=?");
733 foreach my $basketno (@{$basketgroupinfo->{'basketlist'}}) {
734 $sth->execute($basketgroupinfo->{'id'}, $basketno);
735 $sth->finish;
738 $sth->finish;
741 #------------------------------------------------------------#
743 =head3 DelBasketgroup
745 DelBasketgroup($basketgroupid);
747 Deletes a basketgroup in the aqbasketgroups table, and removes the reference to it from the baskets,
749 =over
751 =item C<$basketgroupid> is the 'id' field of the basket in the aqbasketgroup table
753 =back
755 =cut
757 sub DelBasketgroup {
758 my $basketgroupid = shift;
759 die "basketgroup id is required to edit a basketgroup" unless $basketgroupid;
760 my $query = "DELETE FROM aqbasketgroups WHERE id=?";
761 my $dbh = C4::Context->dbh;
762 my $sth = $dbh->prepare($query);
763 $sth->execute($basketgroupid);
764 $sth->finish;
767 #------------------------------------------------------------#
770 =head2 FUNCTIONS ABOUT ORDERS
772 =head3 GetBasketgroup
774 $basketgroup = &GetBasketgroup($basketgroupid);
776 Returns a reference to the hash containing all infermation about the basketgroup.
778 =cut
780 sub GetBasketgroup {
781 my $basketgroupid = shift;
782 die "basketgroup id is required to edit a basketgroup" unless $basketgroupid;
783 my $query = "SELECT * FROM aqbasketgroups WHERE id=?";
784 my $dbh = C4::Context->dbh;
785 my $sth = $dbh->prepare($query);
786 $sth->execute($basketgroupid);
787 my $result = $sth->fetchrow_hashref;
788 $sth->finish;
789 return $result
792 #------------------------------------------------------------#
794 =head3 GetBasketgroups
796 $basketgroups = &GetBasketgroups($booksellerid);
798 Returns a reference to the array of all the basketgroups of bookseller $booksellerid.
800 =cut
802 sub GetBasketgroups {
803 my $booksellerid = shift;
804 die 'bookseller id is required to edit a basketgroup' unless $booksellerid;
805 my $query = 'SELECT * FROM aqbasketgroups WHERE booksellerid=? ORDER BY id DESC';
806 my $dbh = C4::Context->dbh;
807 my $sth = $dbh->prepare($query);
808 $sth->execute($booksellerid);
809 return $sth->fetchall_arrayref({});
812 #------------------------------------------------------------#
814 =head2 FUNCTIONS ABOUT ORDERS
816 =cut
818 #------------------------------------------------------------#
820 =head3 GetPendingOrders
822 $orders = &GetPendingOrders($supplierid,$grouped,$owner,$basketno,$ordernumber,$search,$ean);
824 Finds pending orders from the bookseller with the given ID. Ignores
825 completed and cancelled orders.
827 C<$booksellerid> contains the bookseller identifier
828 C<$owner> contains 0 or 1. 0 means any owner. 1 means only the list of orders entered by the user itself.
829 C<$grouped> is a boolean that, if set to 1 will group all order lines of the same basket
830 in a single result line
831 C<$orders> is a reference-to-array; each element is a reference-to-hash.
833 Used also by the filter in parcel.pl
834 I have added:
836 C<$ordernumber>
837 C<$search>
838 C<$ean>
840 These give the value of the corresponding field in the aqorders table
841 of the Koha database.
843 Results are ordered from most to least recent.
845 =cut
847 sub GetPendingOrders {
848 my ($supplierid,$grouped,$owner,$basketno,$ordernumber,$search,$ean) = @_;
849 my $dbh = C4::Context->dbh;
850 my $strsth = "
851 SELECT ".($grouped?"count(*),":"")."aqbasket.basketno,
852 surname,firstname,biblio.*,biblioitems.isbn,
853 aqbasket.closedate, aqbasket.creationdate, aqbasket.basketname,
854 aqorders.*
855 FROM aqorders
856 LEFT JOIN aqbasket ON aqbasket.basketno=aqorders.basketno
857 LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber
858 LEFT JOIN biblio ON biblio.biblionumber=aqorders.biblionumber
859 LEFT JOIN biblioitems ON biblioitems.biblionumber=biblio.biblionumber
860 WHERE (quantity > quantityreceived OR quantityreceived is NULL)
861 AND datecancellationprinted IS NULL";
862 my @query_params;
863 my $userenv = C4::Context->userenv;
864 if ( C4::Context->preference("IndependantBranches") ) {
865 if ( ($userenv) && ( $userenv->{flags} != 1 ) ) {
866 $strsth .= " AND (borrowers.branchcode = ?
867 or borrowers.branchcode = '')";
868 push @query_params, $userenv->{branch};
871 if ($supplierid) {
872 $strsth .= " AND aqbasket.booksellerid = ?";
873 push @query_params, $supplierid;
875 if($ordernumber){
876 $strsth .= " AND (aqorders.ordernumber=?)";
877 push @query_params, $ordernumber;
879 if($search){
880 $strsth .= " AND (biblio.title like ? OR biblio.author LIKE ? OR biblioitems.isbn like ?)";
881 push @query_params, ("%$search%","%$search%","%$search%");
883 if ($ean) {
884 $strsth .= " AND biblioitems.ean = ?";
885 push @query_params, $ean;
887 if ($basketno) {
888 $strsth .= " AND aqbasket.basketno=? ";
889 push @query_params, $basketno;
891 if ($owner) {
892 $strsth .= " AND aqbasket.authorisedby=? ";
893 push @query_params, $userenv->{'number'};
895 $strsth .= " group by aqbasket.basketno" if $grouped;
896 $strsth .= " order by aqbasket.basketno";
897 my $sth = $dbh->prepare($strsth);
898 $sth->execute( @query_params );
899 my $results = $sth->fetchall_arrayref({});
900 $sth->finish;
901 return $results;
904 #------------------------------------------------------------#
906 =head3 GetOrders
908 @orders = &GetOrders($basketnumber, $orderby);
910 Looks up the pending (non-cancelled) orders with the given basket
911 number. If C<$booksellerID> is non-empty, only orders from that seller
912 are returned.
914 return :
915 C<&basket> returns a two-element array. C<@orders> is an array of
916 references-to-hash, whose keys are the fields from the aqorders,
917 biblio, and biblioitems tables in the Koha database.
919 =cut
921 sub GetOrders {
922 my ( $basketno, $orderby ) = @_;
923 my $dbh = C4::Context->dbh;
924 my $query ="
925 SELECT biblio.*,biblioitems.*,
926 aqorders.*,
927 aqbudgets.*,
928 biblio.title
929 FROM aqorders
930 LEFT JOIN aqbudgets ON aqbudgets.budget_id = aqorders.budget_id
931 LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber
932 LEFT JOIN biblioitems ON biblioitems.biblionumber =biblio.biblionumber
933 WHERE basketno=?
934 AND (datecancellationprinted IS NULL OR datecancellationprinted='0000-00-00')
937 $orderby = "biblioitems.publishercode,biblio.title" unless $orderby;
938 $query .= " ORDER BY $orderby";
939 my $sth = $dbh->prepare($query);
940 $sth->execute($basketno);
941 my $results = $sth->fetchall_arrayref({});
942 $sth->finish;
943 return @$results;
946 #------------------------------------------------------------#
948 =head3 GetOrderNumber
950 $ordernumber = &GetOrderNumber($biblioitemnumber, $biblionumber);
952 Looks up the ordernumber with the given biblionumber and biblioitemnumber.
954 Returns the number of this order.
956 =over
958 =item C<$ordernumber> is the order number.
960 =back
962 =cut
964 sub GetOrderNumber {
965 my ( $biblionumber,$biblioitemnumber ) = @_;
966 my $dbh = C4::Context->dbh;
967 my $query = "
968 SELECT ordernumber
969 FROM aqorders
970 WHERE biblionumber=?
971 AND biblioitemnumber=?
973 my $sth = $dbh->prepare($query);
974 $sth->execute( $biblionumber, $biblioitemnumber );
976 return $sth->fetchrow;
979 #------------------------------------------------------------#
981 =head3 GetOrder
983 $order = &GetOrder($ordernumber);
985 Looks up an order by order number.
987 Returns a reference-to-hash describing the order. The keys of
988 C<$order> are fields from the biblio, biblioitems, aqorders tables of the Koha database.
990 =cut
992 sub GetOrder {
993 my ($ordernumber) = @_;
994 my $dbh = C4::Context->dbh;
995 my $query = "
996 SELECT biblioitems.*, biblio.*, aqorders.*
997 FROM aqorders
998 LEFT JOIN biblio on biblio.biblionumber=aqorders.biblionumber
999 LEFT JOIN biblioitems on biblioitems.biblionumber=aqorders.biblionumber
1000 WHERE aqorders.ordernumber=?
1003 my $sth= $dbh->prepare($query);
1004 $sth->execute($ordernumber);
1005 my $data = $sth->fetchrow_hashref;
1006 $sth->finish;
1007 return $data;
1010 =head3 GetLastOrderNotReceivedFromSubscriptionid
1012 $order = &GetLastOrderNotReceivedFromSubscriptionid($subscriptionid);
1014 Returns a reference-to-hash describing the last order not received for a subscription.
1016 =cut
1018 sub GetLastOrderNotReceivedFromSubscriptionid {
1019 my ( $subscriptionid ) = @_;
1020 my $dbh = C4::Context->dbh;
1021 my $query = qq|
1022 SELECT * FROM aqorders
1023 LEFT JOIN subscription
1024 ON ( aqorders.subscriptionid = subscription.subscriptionid )
1025 WHERE aqorders.subscriptionid = ?
1026 AND aqorders.datereceived IS NULL
1027 LIMIT 1
1029 my $sth = $dbh->prepare( $query );
1030 $sth->execute( $subscriptionid );
1031 my $order = $sth->fetchrow_hashref;
1032 return $order;
1035 =head3 GetLastOrderReceivedFromSubscriptionid
1037 $order = &GetLastOrderReceivedFromSubscriptionid($subscriptionid);
1039 Returns a reference-to-hash describing the last order received for a subscription.
1041 =cut
1043 sub GetLastOrderReceivedFromSubscriptionid {
1044 my ( $subscriptionid ) = @_;
1045 my $dbh = C4::Context->dbh;
1046 my $query = qq|
1047 SELECT * FROM aqorders
1048 LEFT JOIN subscription
1049 ON ( aqorders.subscriptionid = subscription.subscriptionid )
1050 WHERE aqorders.subscriptionid = ?
1051 AND aqorders.datereceived =
1053 SELECT MAX( aqorders.datereceived )
1054 FROM aqorders
1055 LEFT JOIN subscription
1056 ON ( aqorders.subscriptionid = subscription.subscriptionid )
1057 WHERE aqorders.subscriptionid = ?
1058 AND aqorders.datereceived IS NOT NULL
1060 ORDER BY ordernumber DESC
1061 LIMIT 1
1063 my $sth = $dbh->prepare( $query );
1064 $sth->execute( $subscriptionid, $subscriptionid );
1065 my $order = $sth->fetchrow_hashref;
1066 return $order;
1071 #------------------------------------------------------------#
1073 =head3 NewOrder
1075 &NewOrder(\%hashref);
1077 Adds a new order to the database. Any argument that isn't described
1078 below is the new value of the field with the same name in the aqorders
1079 table of the Koha database.
1081 =over
1083 =item $hashref->{'basketno'} is the basketno foreign key in aqorders, it is mandatory
1085 =item $hashref->{'ordernumber'} is a "minimum order number."
1087 =item $hashref->{'budgetdate'} is effectively ignored.
1088 If it's undef (anything false) or the string 'now', the current day is used.
1089 Else, the upcoming July 1st is used.
1091 =item $hashref->{'subscription'} may be either "yes", or anything else for "no".
1093 =item $hashref->{'uncertainprice'} may be 0 for "the price is known" or 1 for "the price is uncertain"
1095 =item defaults entrydate to Now
1097 The following keys are used: "biblionumber", "title", "basketno", "quantity", "notes", "biblioitemnumber", "rrp", "ecost", "gstrate", "unitprice", "subscription", "sort1", "sort2", "booksellerinvoicenumber", "listprice", "budgetdate", "purchaseordernumber", "branchcode", "booksellerinvoicenumber", "budget_id".
1099 =back
1101 =cut
1103 sub NewOrder {
1104 my $orderinfo = shift;
1105 #### ------------------------------
1106 my $dbh = C4::Context->dbh;
1107 my @params;
1110 # if these parameters are missing, we can't continue
1111 for my $key (qw/basketno quantity biblionumber budget_id/) {
1112 croak "Mandatory parameter $key missing" unless $orderinfo->{$key};
1115 if ( defined $orderinfo->{subscription} && $orderinfo->{'subscription'} eq 'yes' ) {
1116 $orderinfo->{'subscription'} = 1;
1117 } else {
1118 $orderinfo->{'subscription'} = 0;
1120 $orderinfo->{'entrydate'} ||= C4::Dates->new()->output("iso");
1121 if (!$orderinfo->{quantityreceived}) {
1122 $orderinfo->{quantityreceived} = 0;
1125 my $ordernumber=InsertInTable("aqorders",$orderinfo);
1126 if (not $orderinfo->{parent_ordernumber}) {
1127 my $sth = $dbh->prepare("
1128 UPDATE aqorders
1129 SET parent_ordernumber = ordernumber
1130 WHERE ordernumber = ?
1132 $sth->execute($ordernumber);
1134 return ( $orderinfo->{'basketno'}, $ordernumber );
1139 #------------------------------------------------------------#
1141 =head3 NewOrderItem
1143 &NewOrderItem();
1145 =cut
1147 sub NewOrderItem {
1148 my ($itemnumber, $ordernumber) = @_;
1149 my $dbh = C4::Context->dbh;
1150 my $query = qq|
1151 INSERT INTO aqorders_items
1152 (itemnumber, ordernumber)
1153 VALUES (?,?) |;
1155 my $sth = $dbh->prepare($query);
1156 $sth->execute( $itemnumber, $ordernumber);
1159 #------------------------------------------------------------#
1161 =head3 ModOrder
1163 &ModOrder(\%hashref);
1165 Modifies an existing order. Updates the order with order number
1166 $hashref->{'ordernumber'} and biblionumber $hashref->{'biblionumber'}. All
1167 other keys of the hash update the fields with the same name in the aqorders
1168 table of the Koha database.
1170 =cut
1172 sub ModOrder {
1173 my $orderinfo = shift;
1175 die "Ordernumber is required" if $orderinfo->{'ordernumber'} eq '' ;
1176 die "Biblionumber is required" if $orderinfo->{'biblionumber'} eq '';
1178 my $dbh = C4::Context->dbh;
1179 my @params;
1181 # update uncertainprice to an integer, just in case (under FF, checked boxes have the value "ON" by default)
1182 $orderinfo->{uncertainprice}=1 if $orderinfo->{uncertainprice};
1184 # delete($orderinfo->{'branchcode'});
1185 # the hash contains a lot of entries not in aqorders, so get the columns ...
1186 my $sth = $dbh->prepare("SELECT * FROM aqorders LIMIT 1;");
1187 $sth->execute;
1188 my $colnames = $sth->{NAME};
1189 my $query = "UPDATE aqorders SET ";
1191 foreach my $orderinfokey (grep(!/ordernumber/, keys %$orderinfo)){
1192 # ... and skip hash entries that are not in the aqorders table
1193 # FIXME : probably not the best way to do it (would be better to have a correct hash)
1194 next unless grep(/^$orderinfokey$/, @$colnames);
1195 $query .= "$orderinfokey=?, ";
1196 push(@params, $orderinfo->{$orderinfokey});
1199 $query .= "timestamp=NOW() WHERE ordernumber=?";
1200 # push(@params, $specorderinfo{'ordernumber'});
1201 push(@params, $orderinfo->{'ordernumber'} );
1202 $sth = $dbh->prepare($query);
1203 $sth->execute(@params);
1204 $sth->finish;
1207 #------------------------------------------------------------#
1209 =head3 ModOrderItem
1211 &ModOrderItem(\%hashref);
1213 Modifies the itemnumber in the aqorders_items table. The input hash needs three entities:
1215 =over
1217 =item - itemnumber: the old itemnumber
1218 =item - ordernumber: the order this item is attached to
1219 =item - newitemnumber: the new itemnumber we want to attach the line to
1221 =back
1223 =cut
1225 sub ModOrderItem {
1226 my $orderiteminfo = shift;
1227 if (! $orderiteminfo->{'ordernumber'} || ! $orderiteminfo->{'itemnumber'} || ! $orderiteminfo->{'newitemnumber'}){
1228 die "Ordernumber, itemnumber and newitemnumber is required";
1231 my $dbh = C4::Context->dbh;
1233 my $query = "UPDATE aqorders_items set itemnumber=? where itemnumber=? and ordernumber=?";
1234 my @params = ($orderiteminfo->{'newitemnumber'}, $orderiteminfo->{'itemnumber'}, $orderiteminfo->{'ordernumber'});
1235 my $sth = $dbh->prepare($query);
1236 $sth->execute(@params);
1237 return 0;
1240 =head3 ModItemOrder
1242 ModItemOrder($itemnumber, $ordernumber);
1244 Modifies the ordernumber of an item in aqorders_items.
1246 =cut
1248 sub ModItemOrder {
1249 my ($itemnumber, $ordernumber) = @_;
1251 return unless ($itemnumber and $ordernumber);
1253 my $dbh = C4::Context->dbh;
1254 my $query = qq{
1255 UPDATE aqorders_items
1256 SET ordernumber = ?
1257 WHERE itemnumber = ?
1259 my $sth = $dbh->prepare($query);
1260 return $sth->execute($ordernumber, $itemnumber);
1263 #------------------------------------------------------------#
1266 =head3 ModOrderBibliotemNumber
1268 &ModOrderBiblioitemNumber($biblioitemnumber,$ordernumber, $biblionumber);
1270 Modifies the biblioitemnumber for an existing order.
1271 Updates the order with order number C<$ordernum> and biblionumber C<$biblionumber>.
1273 =cut
1275 #FIXME: is this used at all?
1276 sub ModOrderBiblioitemNumber {
1277 my ($biblioitemnumber,$ordernumber, $biblionumber) = @_;
1278 my $dbh = C4::Context->dbh;
1279 my $query = "
1280 UPDATE aqorders
1281 SET biblioitemnumber = ?
1282 WHERE ordernumber = ?
1283 AND biblionumber = ?";
1284 my $sth = $dbh->prepare($query);
1285 $sth->execute( $biblioitemnumber, $ordernumber, $biblionumber );
1288 =head3 GetCancelledOrders
1290 my @orders = GetCancelledOrders($basketno, $orderby);
1292 Returns cancelled orders for a basket
1294 =cut
1296 sub GetCancelledOrders {
1297 my ( $basketno, $orderby ) = @_;
1299 return () unless $basketno;
1301 my $dbh = C4::Context->dbh;
1302 my $query = "
1303 SELECT biblio.*, biblioitems.*, aqorders.*, aqbudgets.*
1304 FROM aqorders
1305 LEFT JOIN aqbudgets ON aqbudgets.budget_id = aqorders.budget_id
1306 LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber
1307 LEFT JOIN biblioitems ON biblioitems.biblionumber = biblio.biblionumber
1308 WHERE basketno = ?
1309 AND (datecancellationprinted IS NOT NULL
1310 AND datecancellationprinted <> '0000-00-00')
1313 $orderby = "aqorders.datecancellationprinted desc, aqorders.timestamp desc"
1314 unless $orderby;
1315 $query .= " ORDER BY $orderby";
1316 my $sth = $dbh->prepare($query);
1317 $sth->execute($basketno);
1318 my $results = $sth->fetchall_arrayref( {} );
1320 return @$results;
1324 #------------------------------------------------------------#
1326 =head3 ModReceiveOrder
1328 &ModReceiveOrder($biblionumber, $ordernumber, $quantityreceived, $user,
1329 $unitprice, $invoiceid, $biblioitemnumber,
1330 $bookfund, $rrp, \@received_itemnumbers);
1332 Updates an order, to reflect the fact that it was received, at least
1333 in part. All arguments not mentioned below update the fields with the
1334 same name in the aqorders table of the Koha database.
1336 If a partial order is received, splits the order into two.
1338 Updates the order with bibilionumber C<$biblionumber> and ordernumber
1339 C<$ordernumber>.
1341 =cut
1344 sub ModReceiveOrder {
1345 my (
1346 $biblionumber, $ordernumber, $quantrec, $user, $cost, $ecost,
1347 $invoiceid, $rrp, $budget_id, $datereceived, $received_items
1349 = @_;
1351 my $dbh = C4::Context->dbh;
1352 $datereceived = C4::Dates->output('iso') unless $datereceived;
1353 my $suggestionid = GetSuggestionFromBiblionumber( $biblionumber );
1354 if ($suggestionid) {
1355 ModSuggestion( {suggestionid=>$suggestionid,
1356 STATUS=>'AVAILABLE',
1357 biblionumber=> $biblionumber}
1361 my $sth=$dbh->prepare("
1362 SELECT * FROM aqorders
1363 WHERE biblionumber=? AND aqorders.ordernumber=?");
1365 $sth->execute($biblionumber,$ordernumber);
1366 my $order = $sth->fetchrow_hashref();
1367 $sth->finish();
1369 my $new_ordernumber = $ordernumber;
1370 if ( $order->{quantity} > $quantrec ) {
1371 # Split order line in two parts: the first is the original order line
1372 # without received items (the quantity is decreased),
1373 # the second part is a new order line with quantity=quantityrec
1374 # (entirely received)
1375 $sth=$dbh->prepare("
1376 UPDATE aqorders
1377 SET quantity = ?
1378 WHERE ordernumber = ?
1381 $sth->execute($order->{quantity} - $quantrec, $ordernumber);
1383 $sth->finish;
1385 delete $order->{'ordernumber'};
1386 $order->{'quantity'} = $quantrec;
1387 $order->{'quantityreceived'} = $quantrec;
1388 $order->{'datereceived'} = $datereceived;
1389 $order->{'invoiceid'} = $invoiceid;
1390 $order->{'unitprice'} = $cost;
1391 $order->{'rrp'} = $rrp;
1392 $order->{ecost} = $ecost;
1393 $order->{'orderstatus'} = 3; # totally received
1394 $new_ordernumber = NewOrder($order);
1396 if ($received_items) {
1397 foreach my $itemnumber (@$received_items) {
1398 ModItemOrder($itemnumber, $new_ordernumber);
1401 } else {
1402 $sth=$dbh->prepare("update aqorders
1403 set quantityreceived=?,datereceived=?,invoiceid=?,
1404 unitprice=?,rrp=?,ecost=?
1405 where biblionumber=? and ordernumber=?");
1406 $sth->execute($quantrec,$datereceived,$invoiceid,$cost,$rrp,$ecost,$biblionumber,$ordernumber);
1407 $sth->finish;
1409 return ($datereceived, $new_ordernumber);
1412 =head3 CancelReceipt
1414 my $parent_ordernumber = CancelReceipt($ordernumber);
1416 Cancel an order line receipt and update the parent order line, as if no
1417 receipt was made.
1418 If items are created at receipt (AcqCreateItem = receiving) then delete
1419 these items.
1421 =cut
1423 sub CancelReceipt {
1424 my $ordernumber = shift;
1426 return unless $ordernumber;
1428 my $dbh = C4::Context->dbh;
1429 my $query = qq{
1430 SELECT datereceived, parent_ordernumber, quantity
1431 FROM aqorders
1432 WHERE ordernumber = ?
1434 my $sth = $dbh->prepare($query);
1435 $sth->execute($ordernumber);
1436 my $order = $sth->fetchrow_hashref;
1437 unless($order) {
1438 warn "CancelReceipt: order $ordernumber does not exist";
1439 return;
1441 unless($order->{'datereceived'}) {
1442 warn "CancelReceipt: order $ordernumber is not received";
1443 return;
1446 my $parent_ordernumber = $order->{'parent_ordernumber'};
1448 if($parent_ordernumber == $ordernumber || not $parent_ordernumber) {
1449 # The order line has no parent, just mark it as not received
1450 $query = qq{
1451 UPDATE aqorders
1452 SET quantityreceived = ?,
1453 datereceived = ?,
1454 invoiceid = ?
1455 WHERE ordernumber = ?
1457 $sth = $dbh->prepare($query);
1458 $sth->execute(0, undef, undef, $ordernumber);
1459 } else {
1460 # The order line has a parent, increase parent quantity and delete
1461 # the order line.
1462 $query = qq{
1463 SELECT quantity, datereceived
1464 FROM aqorders
1465 WHERE ordernumber = ?
1467 $sth = $dbh->prepare($query);
1468 $sth->execute($parent_ordernumber);
1469 my $parent_order = $sth->fetchrow_hashref;
1470 unless($parent_order) {
1471 warn "Parent order $parent_ordernumber does not exist.";
1472 return;
1474 if($parent_order->{'datereceived'}) {
1475 warn "CancelReceipt: parent order is received.".
1476 " Can't cancel receipt.";
1477 return;
1479 $query = qq{
1480 UPDATE aqorders
1481 SET quantity = ?
1482 WHERE ordernumber = ?
1484 $sth = $dbh->prepare($query);
1485 my $rv = $sth->execute(
1486 $order->{'quantity'} + $parent_order->{'quantity'},
1487 $parent_ordernumber
1489 unless($rv) {
1490 warn "Cannot update parent order line, so do not cancel".
1491 " receipt";
1492 return;
1494 if(C4::Context->preference('AcqCreateItem') eq 'receiving') {
1495 # Remove items that were created at receipt
1496 $query = qq{
1497 DELETE FROM items, aqorders_items
1498 USING items, aqorders_items
1499 WHERE items.itemnumber = ? AND aqorders_items.itemnumber = ?
1501 $sth = $dbh->prepare($query);
1502 my @itemnumbers = GetItemnumbersFromOrder($ordernumber);
1503 foreach my $itemnumber (@itemnumbers) {
1504 $sth->execute($itemnumber, $itemnumber);
1506 } else {
1507 # Update items
1508 my @itemnumbers = GetItemnumbersFromOrder($ordernumber);
1509 foreach my $itemnumber (@itemnumbers) {
1510 ModItemOrder($itemnumber, $parent_ordernumber);
1513 # Delete order line
1514 $query = qq{
1515 DELETE FROM aqorders
1516 WHERE ordernumber = ?
1518 $sth = $dbh->prepare($query);
1519 $sth->execute($ordernumber);
1523 return $parent_ordernumber;
1526 #------------------------------------------------------------#
1528 =head3 SearchOrder
1530 @results = &SearchOrder($search, $biblionumber, $complete);
1532 Searches for orders.
1534 C<$search> may take one of several forms: if it is an ISBN,
1535 C<&ordersearch> returns orders with that ISBN. If C<$search> is an
1536 order number, C<&ordersearch> returns orders with that order number
1537 and biblionumber C<$biblionumber>. Otherwise, C<$search> is considered
1538 to be a space-separated list of search terms; in this case, all of the
1539 terms must appear in the title (matching the beginning of title
1540 words).
1542 If C<$complete> is C<yes>, the results will include only completed
1543 orders. In any case, C<&ordersearch> ignores cancelled orders.
1545 C<&ordersearch> returns an array.
1546 C<@results> is an array of references-to-hash with the following keys:
1548 =over 4
1550 =item C<author>
1552 =item C<seriestitle>
1554 =item C<branchcode>
1556 =item C<budget_id>
1558 =back
1560 =cut
1562 sub SearchOrder {
1563 #### -------- SearchOrder-------------------------------
1564 my ( $ordernumber, $search, $ean, $supplierid, $basket ) = @_;
1566 my $dbh = C4::Context->dbh;
1567 my @args = ();
1568 my $query =
1569 "SELECT *
1570 FROM aqorders
1571 LEFT JOIN biblio ON aqorders.biblionumber=biblio.biblionumber
1572 LEFT JOIN biblioitems ON biblioitems.biblionumber=biblio.biblionumber
1573 LEFT JOIN aqbasket ON aqorders.basketno = aqbasket.basketno
1574 WHERE (datecancellationprinted is NULL)";
1576 if($ordernumber){
1577 $query .= " AND (aqorders.ordernumber=?)";
1578 push @args, $ordernumber;
1580 if($search){
1581 $query .= " AND (biblio.title like ? OR biblio.author LIKE ? OR biblioitems.isbn like ?)";
1582 push @args, ("%$search%","%$search%","%$search%");
1584 if ($ean) {
1585 $query .= " AND biblioitems.ean = ?";
1586 push @args, $ean;
1588 if ($supplierid) {
1589 $query .= "AND aqbasket.booksellerid = ?";
1590 push @args, $supplierid;
1592 if($basket){
1593 $query .= "AND aqorders.basketno = ?";
1594 push @args, $basket;
1597 my $sth = $dbh->prepare($query);
1598 $sth->execute(@args);
1599 my $results = $sth->fetchall_arrayref({});
1600 $sth->finish;
1601 return $results;
1604 #------------------------------------------------------------#
1606 =head3 DelOrder
1608 &DelOrder($biblionumber, $ordernumber);
1610 Cancel the order with the given order and biblio numbers. It does not
1611 delete any entries in the aqorders table, it merely marks them as
1612 cancelled.
1614 =cut
1616 sub DelOrder {
1617 my ( $bibnum, $ordernumber ) = @_;
1618 my $dbh = C4::Context->dbh;
1619 my $query = "
1620 UPDATE aqorders
1621 SET datecancellationprinted=now()
1622 WHERE biblionumber=? AND ordernumber=?
1624 my $sth = $dbh->prepare($query);
1625 $sth->execute( $bibnum, $ordernumber );
1626 $sth->finish;
1627 my @itemnumbers = GetItemnumbersFromOrder( $ordernumber );
1628 foreach my $itemnumber (@itemnumbers){
1629 C4::Items::DelItem( $dbh, $bibnum, $itemnumber );
1634 =head2 FUNCTIONS ABOUT PARCELS
1636 =cut
1638 #------------------------------------------------------------#
1640 =head3 GetParcel
1642 @results = &GetParcel($booksellerid, $code, $date);
1644 Looks up all of the received items from the supplier with the given
1645 bookseller ID at the given date, for the given code (bookseller Invoice number). Ignores cancelled and completed orders.
1647 C<@results> is an array of references-to-hash. The keys of each element are fields from
1648 the aqorders, biblio, and biblioitems tables of the Koha database.
1650 C<@results> is sorted alphabetically by book title.
1652 =cut
1654 sub GetParcel {
1655 #gets all orders from a certain supplier, orders them alphabetically
1656 my ( $supplierid, $code, $datereceived ) = @_;
1657 my $dbh = C4::Context->dbh;
1658 my @results = ();
1659 $code .= '%'
1660 if $code; # add % if we search on a given code (otherwise, let him empty)
1661 my $strsth ="
1662 SELECT authorisedby,
1663 creationdate,
1664 aqbasket.basketno,
1665 closedate,surname,
1666 firstname,
1667 aqorders.biblionumber,
1668 aqorders.ordernumber,
1669 aqorders.parent_ordernumber,
1670 aqorders.quantity,
1671 aqorders.quantityreceived,
1672 aqorders.unitprice,
1673 aqorders.listprice,
1674 aqorders.rrp,
1675 aqorders.ecost,
1676 aqorders.gstrate,
1677 biblio.title
1678 FROM aqorders
1679 LEFT JOIN aqbasket ON aqbasket.basketno=aqorders.basketno
1680 LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber
1681 LEFT JOIN biblio ON aqorders.biblionumber=biblio.biblionumber
1682 LEFT JOIN aqinvoices ON aqorders.invoiceid = aqinvoices.invoiceid
1683 WHERE
1684 aqbasket.booksellerid = ?
1685 AND aqinvoices.invoicenumber LIKE ?
1686 AND aqorders.datereceived = ? ";
1688 my @query_params = ( $supplierid, $code, $datereceived );
1689 if ( C4::Context->preference("IndependantBranches") ) {
1690 my $userenv = C4::Context->userenv;
1691 if ( ($userenv) && ( $userenv->{flags} != 1 ) ) {
1692 $strsth .= " and (borrowers.branchcode = ?
1693 or borrowers.branchcode = '')";
1694 push @query_params, $userenv->{branch};
1697 $strsth .= " ORDER BY aqbasket.basketno";
1698 # ## parcelinformation : $strsth
1699 my $sth = $dbh->prepare($strsth);
1700 $sth->execute( @query_params );
1701 while ( my $data = $sth->fetchrow_hashref ) {
1702 push( @results, $data );
1704 # ## countparcelbiblio: scalar(@results)
1705 $sth->finish;
1707 return @results;
1710 #------------------------------------------------------------#
1712 =head3 GetParcels
1714 $results = &GetParcels($bookseller, $order, $code, $datefrom, $dateto);
1716 get a lists of parcels.
1718 * Input arg :
1720 =over
1722 =item $bookseller
1723 is the bookseller this function has to get parcels.
1725 =item $order
1726 To know on what criteria the results list has to be ordered.
1728 =item $code
1729 is the booksellerinvoicenumber.
1731 =item $datefrom & $dateto
1732 to know on what date this function has to filter its search.
1734 =back
1736 * return:
1737 a pointer on a hash list containing parcel informations as such :
1739 =over
1741 =item Creation date
1743 =item Last operation
1745 =item Number of biblio
1747 =item Number of items
1749 =back
1751 =cut
1753 sub GetParcels {
1754 my ($bookseller,$order, $code, $datefrom, $dateto) = @_;
1755 my $dbh = C4::Context->dbh;
1756 my @query_params = ();
1757 my $strsth ="
1758 SELECT aqinvoices.invoicenumber,
1759 datereceived,purchaseordernumber,
1760 count(DISTINCT biblionumber) AS biblio,
1761 sum(quantity) AS itemsexpected,
1762 sum(quantityreceived) AS itemsreceived
1763 FROM aqorders LEFT JOIN aqbasket ON aqbasket.basketno = aqorders.basketno
1764 LEFT JOIN aqinvoices ON aqorders.invoiceid = aqinvoices.invoiceid
1765 WHERE aqbasket.booksellerid = ? and datereceived IS NOT NULL
1767 push @query_params, $bookseller;
1769 if ( defined $code ) {
1770 $strsth .= ' and aqinvoices.invoicenumber like ? ';
1771 # add a % to the end of the code to allow stemming.
1772 push @query_params, "$code%";
1775 if ( defined $datefrom ) {
1776 $strsth .= ' and datereceived >= ? ';
1777 push @query_params, $datefrom;
1780 if ( defined $dateto ) {
1781 $strsth .= 'and datereceived <= ? ';
1782 push @query_params, $dateto;
1785 $strsth .= "group by aqinvoices.invoicenumber,datereceived ";
1787 # can't use a placeholder to place this column name.
1788 # but, we could probably be checking to make sure it is a column that will be fetched.
1789 $strsth .= "order by $order " if ($order);
1791 my $sth = $dbh->prepare($strsth);
1793 $sth->execute( @query_params );
1794 my $results = $sth->fetchall_arrayref({});
1795 $sth->finish;
1796 return @$results;
1799 #------------------------------------------------------------#
1801 =head3 GetLateOrders
1803 @results = &GetLateOrders;
1805 Searches for bookseller with late orders.
1807 return:
1808 the table of supplier with late issues. This table is full of hashref.
1810 =cut
1812 sub GetLateOrders {
1813 my $delay = shift;
1814 my $supplierid = shift;
1815 my $branch = shift;
1816 my $estimateddeliverydatefrom = shift;
1817 my $estimateddeliverydateto = shift;
1819 my $dbh = C4::Context->dbh;
1821 #BEWARE, order of parenthesis and LEFT JOIN is important for speed
1822 my $dbdriver = C4::Context->config("db_scheme") || "mysql";
1824 my @query_params = ();
1825 my $select = "
1826 SELECT aqbasket.basketno,
1827 aqorders.ordernumber,
1828 DATE(aqbasket.closedate) AS orderdate,
1829 aqorders.rrp AS unitpricesupplier,
1830 aqorders.ecost AS unitpricelib,
1831 aqorders.claims_count AS claims_count,
1832 aqorders.claimed_date AS claimed_date,
1833 aqbudgets.budget_name AS budget,
1834 borrowers.branchcode AS branch,
1835 aqbooksellers.name AS supplier,
1836 aqbooksellers.id AS supplierid,
1837 biblio.author, biblio.title,
1838 biblioitems.publishercode AS publisher,
1839 biblioitems.publicationyear,
1840 ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) AS estimateddeliverydate,
1842 my $from = "
1843 FROM
1844 aqorders LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber
1845 LEFT JOIN biblioitems ON biblioitems.biblionumber = biblio.biblionumber
1846 LEFT JOIN aqbudgets ON aqorders.budget_id = aqbudgets.budget_id,
1847 aqbasket LEFT JOIN borrowers ON aqbasket.authorisedby = borrowers.borrowernumber
1848 LEFT JOIN aqbooksellers ON aqbasket.booksellerid = aqbooksellers.id
1849 WHERE aqorders.basketno = aqbasket.basketno
1850 AND ( datereceived = ''
1851 OR datereceived IS NULL
1852 OR aqorders.quantityreceived < aqorders.quantity
1854 AND aqbasket.closedate IS NOT NULL
1855 AND (aqorders.datecancellationprinted IS NULL OR aqorders.datecancellationprinted='0000-00-00')
1857 my $having = "";
1858 if ($dbdriver eq "mysql") {
1859 $select .= "
1860 aqorders.quantity - COALESCE(aqorders.quantityreceived,0) AS quantity,
1861 (aqorders.quantity - COALESCE(aqorders.quantityreceived,0)) * aqorders.rrp AS subtotal,
1862 DATEDIFF(CAST(now() AS date),closedate) AS latesince
1864 if ( defined $delay ) {
1865 $from .= " AND (closedate <= DATE_SUB(CAST(now() AS date),INTERVAL ? DAY)) " ;
1866 push @query_params, $delay;
1868 $having = "
1869 HAVING quantity <> 0
1870 AND unitpricesupplier <> 0
1871 AND unitpricelib <> 0
1873 } else {
1874 # FIXME: account for IFNULL as above
1875 $select .= "
1876 aqorders.quantity AS quantity,
1877 aqorders.quantity * aqorders.rrp AS subtotal,
1878 (CAST(now() AS date) - closedate) AS latesince
1880 if ( defined $delay ) {
1881 $from .= " AND (closedate <= (CAST(now() AS date) -(INTERVAL ? DAY)) ";
1882 push @query_params, $delay;
1885 if (defined $supplierid) {
1886 $from .= ' AND aqbasket.booksellerid = ? ';
1887 push @query_params, $supplierid;
1889 if (defined $branch) {
1890 $from .= ' AND borrowers.branchcode LIKE ? ';
1891 push @query_params, $branch;
1894 if ( defined $estimateddeliverydatefrom or defined $estimateddeliverydateto ) {
1895 $from .= ' AND aqbooksellers.deliverytime IS NOT NULL ';
1897 if ( defined $estimateddeliverydatefrom ) {
1898 $from .= ' AND ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) >= ?';
1899 push @query_params, $estimateddeliverydatefrom;
1901 if ( defined $estimateddeliverydateto ) {
1902 $from .= ' AND ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) <= ?';
1903 push @query_params, $estimateddeliverydateto;
1905 if ( defined $estimateddeliverydatefrom and not defined $estimateddeliverydateto ) {
1906 $from .= ' AND ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) <= CAST(now() AS date)';
1908 if (C4::Context->preference("IndependantBranches")
1909 && C4::Context->userenv
1910 && C4::Context->userenv->{flags} != 1 ) {
1911 $from .= ' AND borrowers.branchcode LIKE ? ';
1912 push @query_params, C4::Context->userenv->{branch};
1914 my $query = "$select $from $having\nORDER BY latesince, basketno, borrowers.branchcode, supplier";
1915 $debug and print STDERR "GetLateOrders query: $query\nGetLateOrders args: " . join(" ",@query_params);
1916 my $sth = $dbh->prepare($query);
1917 $sth->execute(@query_params);
1918 my @results;
1919 while (my $data = $sth->fetchrow_hashref) {
1920 $data->{orderdate} = format_date($data->{orderdate});
1921 $data->{claimed_date} = format_date($data->{claimed_date});
1922 push @results, $data;
1924 return @results;
1927 #------------------------------------------------------------#
1929 =head3 GetHistory
1931 (\@order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( %params );
1933 Retreives some acquisition history information
1935 params:
1936 title
1937 author
1938 name
1939 from_placed_on
1940 to_placed_on
1941 basket - search both basket name and number
1942 booksellerinvoicenumber
1944 returns:
1945 $order_loop is a list of hashrefs that each look like this:
1947 'author' => 'Twain, Mark',
1948 'basketno' => '1',
1949 'biblionumber' => '215',
1950 'count' => 1,
1951 'creationdate' => 'MM/DD/YYYY',
1952 'datereceived' => undef,
1953 'ecost' => '1.00',
1954 'id' => '1',
1955 'invoicenumber' => undef,
1956 'name' => '',
1957 'ordernumber' => '1',
1958 'quantity' => 1,
1959 'quantityreceived' => undef,
1960 'title' => 'The Adventures of Huckleberry Finn'
1962 $total_qty is the sum of all of the quantities in $order_loop
1963 $total_price is the cost of each in $order_loop times the quantity
1964 $total_qtyreceived is the sum of all of the quantityreceived entries in $order_loop
1966 =cut
1968 sub GetHistory {
1969 # don't run the query if there are no parameters (list would be too long for sure !)
1970 croak "No search params" unless @_;
1971 my %params = @_;
1972 my $title = $params{title};
1973 my $author = $params{author};
1974 my $isbn = $params{isbn};
1975 my $ean = $params{ean};
1976 my $name = $params{name};
1977 my $from_placed_on = $params{from_placed_on};
1978 my $to_placed_on = $params{to_placed_on};
1979 my $basket = $params{basket};
1980 my $booksellerinvoicenumber = $params{booksellerinvoicenumber};
1981 my $basketgroupname = $params{basketgroupname};
1982 my @order_loop;
1983 my $total_qty = 0;
1984 my $total_qtyreceived = 0;
1985 my $total_price = 0;
1987 my $dbh = C4::Context->dbh;
1988 my $query ="
1989 SELECT
1990 biblio.title,
1991 biblio.author,
1992 biblioitems.isbn,
1993 biblioitems.ean,
1994 aqorders.basketno,
1995 aqbasket.basketname,
1996 aqbasket.basketgroupid,
1997 aqbasketgroups.name as groupname,
1998 aqbooksellers.name,
1999 aqbasket.creationdate,
2000 aqorders.datereceived,
2001 aqorders.quantity,
2002 aqorders.quantityreceived,
2003 aqorders.ecost,
2004 aqorders.ordernumber,
2005 aqinvoices.invoicenumber,
2006 aqbooksellers.id as id,
2007 aqorders.biblionumber
2008 FROM aqorders
2009 LEFT JOIN aqbasket ON aqorders.basketno=aqbasket.basketno
2010 LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid=aqbasketgroups.id
2011 LEFT JOIN aqbooksellers ON aqbasket.booksellerid=aqbooksellers.id
2012 LEFT JOIN biblioitems ON biblioitems.biblionumber=aqorders.biblionumber
2013 LEFT JOIN biblio ON biblio.biblionumber=aqorders.biblionumber
2014 LEFT JOIN aqinvoices ON aqorders.invoiceid = aqinvoices.invoiceid";
2016 $query .= " LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber"
2017 if ( C4::Context->preference("IndependantBranches") );
2019 $query .= " WHERE (datecancellationprinted is NULL or datecancellationprinted='0000-00-00') ";
2021 my @query_params = ();
2023 if ( $title ) {
2024 $query .= " AND biblio.title LIKE ? ";
2025 $title =~ s/\s+/%/g;
2026 push @query_params, "%$title%";
2029 if ( $author ) {
2030 $query .= " AND biblio.author LIKE ? ";
2031 push @query_params, "%$author%";
2034 if ( $isbn ) {
2035 $query .= " AND biblioitems.isbn LIKE ? ";
2036 push @query_params, "%$isbn%";
2038 if ( defined $ean and $ean ) {
2039 $query .= " AND biblioitems.ean = ? ";
2040 push @query_params, "$ean";
2042 if ( $name ) {
2043 $query .= " AND aqbooksellers.name LIKE ? ";
2044 push @query_params, "%$name%";
2047 if ( $from_placed_on ) {
2048 $query .= " AND creationdate >= ? ";
2049 push @query_params, $from_placed_on;
2052 if ( $to_placed_on ) {
2053 $query .= " AND creationdate <= ? ";
2054 push @query_params, $to_placed_on;
2057 if ($basket) {
2058 if ($basket =~ m/^\d+$/) {
2059 $query .= " AND aqorders.basketno = ? ";
2060 push @query_params, $basket;
2061 } else {
2062 $query .= " AND aqbasket.basketname LIKE ? ";
2063 push @query_params, "%$basket%";
2067 if ($booksellerinvoicenumber) {
2068 $query .= " AND aqinvoices.invoicenumber LIKE ? ";
2069 push @query_params, "%$booksellerinvoicenumber%";
2072 if ($basketgroupname) {
2073 $query .= " AND aqbasketgroups.name LIKE ? ";
2074 push @query_params, "%$basketgroupname%";
2077 if ( C4::Context->preference("IndependantBranches") ) {
2078 my $userenv = C4::Context->userenv;
2079 if ( $userenv && ($userenv->{flags} || 0) != 1 ) {
2080 $query .= " AND (borrowers.branchcode = ? OR borrowers.branchcode ='' ) ";
2081 push @query_params, $userenv->{branch};
2084 $query .= " ORDER BY id";
2085 my $sth = $dbh->prepare($query);
2086 $sth->execute( @query_params );
2087 my $cnt = 1;
2088 while ( my $line = $sth->fetchrow_hashref ) {
2089 $line->{count} = $cnt++;
2090 $line->{toggle} = 1 if $cnt % 2;
2091 push @order_loop, $line;
2092 $total_qty += $line->{'quantity'};
2093 $total_qtyreceived += $line->{'quantityreceived'};
2094 $total_price += $line->{'quantity'} * $line->{'ecost'};
2096 return \@order_loop, $total_qty, $total_price, $total_qtyreceived;
2099 =head2 GetRecentAcqui
2101 $results = GetRecentAcqui($days);
2103 C<$results> is a ref to a table which containts hashref
2105 =cut
2107 sub GetRecentAcqui {
2108 my $limit = shift;
2109 my $dbh = C4::Context->dbh;
2110 my $query = "
2111 SELECT *
2112 FROM biblio
2113 ORDER BY timestamp DESC
2114 LIMIT 0,".$limit;
2116 my $sth = $dbh->prepare($query);
2117 $sth->execute;
2118 my $results = $sth->fetchall_arrayref({});
2119 return $results;
2122 =head3 GetContracts
2124 $contractlist = &GetContracts($booksellerid, $activeonly);
2126 Looks up the contracts that belong to a bookseller
2128 Returns a list of contracts
2130 =over
2132 =item C<$booksellerid> is the "id" field in the "aqbooksellers" table.
2134 =item C<$activeonly> if exists get only contracts that are still active.
2136 =back
2138 =cut
2140 sub GetContracts {
2141 my ( $booksellerid, $activeonly ) = @_;
2142 my $dbh = C4::Context->dbh;
2143 my $query;
2144 if (! $activeonly) {
2145 $query = "
2146 SELECT *
2147 FROM aqcontract
2148 WHERE booksellerid=?
2150 } else {
2151 $query = "SELECT *
2152 FROM aqcontract
2153 WHERE booksellerid=?
2154 AND contractenddate >= CURDATE( )";
2156 my $sth = $dbh->prepare($query);
2157 $sth->execute( $booksellerid );
2158 my @results;
2159 while (my $data = $sth->fetchrow_hashref ) {
2160 push(@results, $data);
2162 $sth->finish;
2163 return @results;
2166 #------------------------------------------------------------#
2168 =head3 GetContract
2170 $contract = &GetContract($contractID);
2172 Looks up the contract that has PRIMKEY (contractnumber) value $contractID
2174 Returns a contract
2176 =cut
2178 sub GetContract {
2179 my ( $contractno ) = @_;
2180 my $dbh = C4::Context->dbh;
2181 my $query = "
2182 SELECT *
2183 FROM aqcontract
2184 WHERE contractnumber=?
2187 my $sth = $dbh->prepare($query);
2188 $sth->execute( $contractno );
2189 my $result = $sth->fetchrow_hashref;
2190 return $result;
2193 =head3 AddClaim
2195 =over 4
2197 &AddClaim($ordernumber);
2199 Add a claim for an order
2201 =back
2203 =cut
2204 sub AddClaim {
2205 my ($ordernumber) = @_;
2206 my $dbh = C4::Context->dbh;
2207 my $query = "
2208 UPDATE aqorders SET
2209 claims_count = claims_count + 1,
2210 claimed_date = CURDATE()
2211 WHERE ordernumber = ?
2213 my $sth = $dbh->prepare($query);
2214 $sth->execute($ordernumber);
2217 =head3 GetInvoices
2219 my @invoices = GetInvoices(
2220 invoicenumber => $invoicenumber,
2221 suppliername => $suppliername,
2222 shipmentdatefrom => $shipmentdatefrom, # ISO format
2223 shipmentdateto => $shipmentdateto, # ISO format
2224 billingdatefrom => $billingdatefrom, # ISO format
2225 billingdateto => $billingdateto, # ISO format
2226 isbneanissn => $isbn_or_ean_or_issn,
2227 title => $title,
2228 author => $author,
2229 publisher => $publisher,
2230 publicationyear => $publicationyear,
2231 branchcode => $branchcode,
2232 order_by => $order_by
2235 Return a list of invoices that match all given criteria.
2237 $order_by is "column_name (asc|desc)", where column_name is any of
2238 'invoicenumber', 'booksellerid', 'shipmentdate', 'billingdate', 'closedate',
2239 'shipmentcost', 'shipmentcost_budgetid'.
2241 asc is the default if omitted
2243 =cut
2245 sub GetInvoices {
2246 my %args = @_;
2248 my @columns = qw(invoicenumber booksellerid shipmentdate billingdate
2249 closedate shipmentcost shipmentcost_budgetid);
2251 my $dbh = C4::Context->dbh;
2252 my $query = qq{
2253 SELECT aqinvoices.*, aqbooksellers.name AS suppliername,
2254 COUNT(
2255 DISTINCT IF(
2256 aqorders.datereceived IS NOT NULL,
2257 aqorders.biblionumber,
2258 NULL
2260 ) AS receivedbiblios,
2261 SUM(aqorders.quantityreceived) AS receiveditems
2262 FROM aqinvoices
2263 LEFT JOIN aqbooksellers ON aqbooksellers.id = aqinvoices.booksellerid
2264 LEFT JOIN aqorders ON aqorders.invoiceid = aqinvoices.invoiceid
2265 LEFT JOIN biblio ON aqorders.biblionumber = biblio.biblionumber
2266 LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
2267 LEFT JOIN subscription ON biblio.biblionumber = subscription.biblionumber
2270 my @bind_args;
2271 my @bind_strs;
2272 if($args{supplierid}) {
2273 push @bind_strs, " aqinvoices.booksellerid = ? ";
2274 push @bind_args, $args{supplierid};
2276 if($args{invoicenumber}) {
2277 push @bind_strs, " aqinvoices.invoicenumber LIKE ? ";
2278 push @bind_args, "%$args{invoicenumber}%";
2280 if($args{suppliername}) {
2281 push @bind_strs, " aqbooksellers.name LIKE ? ";
2282 push @bind_args, "%$args{suppliername}%";
2284 if($args{shipmentdatefrom}) {
2285 push @bind_strs, " aqinvoices.shipementdate >= ? ";
2286 push @bind_args, $args{shipmentdatefrom};
2288 if($args{shipmentdateto}) {
2289 push @bind_strs, " aqinvoices.shipementdate <= ? ";
2290 push @bind_args, $args{shipmentdateto};
2292 if($args{billingdatefrom}) {
2293 push @bind_strs, " aqinvoices.billingdate >= ? ";
2294 push @bind_args, $args{billingdatefrom};
2296 if($args{billingdateto}) {
2297 push @bind_strs, " aqinvoices.billingdate <= ? ";
2298 push @bind_args, $args{billingdateto};
2300 if($args{isbneanissn}) {
2301 push @bind_strs, " (biblioitems.isbn LIKE ? OR biblioitems.ean LIKE ? OR biblioitems.issn LIKE ? ) ";
2302 push @bind_args, $args{isbneanissn}, $args{isbneanissn}, $args{isbneanissn};
2304 if($args{title}) {
2305 push @bind_strs, " biblio.title LIKE ? ";
2306 push @bind_args, $args{title};
2308 if($args{author}) {
2309 push @bind_strs, " biblio.author LIKE ? ";
2310 push @bind_args, $args{author};
2312 if($args{publisher}) {
2313 push @bind_strs, " biblioitems.publishercode LIKE ? ";
2314 push @bind_args, $args{publisher};
2316 if($args{publicationyear}) {
2317 push @bind_strs, " biblioitems.publicationyear = ? ";
2318 push @bind_args, $args{publicationyear};
2320 if($args{branchcode}) {
2321 push @bind_strs, " aqorders.branchcode = ? ";
2322 push @bind_args, $args{branchcode};
2325 $query .= " WHERE " . join(" AND ", @bind_strs) if @bind_strs;
2326 $query .= " GROUP BY aqinvoices.invoiceid ";
2328 if($args{order_by}) {
2329 my ($column, $direction) = split / /, $args{order_by};
2330 if(grep /^$column$/, @columns) {
2331 $direction ||= 'ASC';
2332 $query .= " ORDER BY $column $direction";
2336 my $sth = $dbh->prepare($query);
2337 $sth->execute(@bind_args);
2339 my $results = $sth->fetchall_arrayref({});
2340 return @$results;
2343 =head3 GetInvoice
2345 my $invoice = GetInvoice($invoiceid);
2347 Get informations about invoice with given $invoiceid
2349 Return a hash filled with aqinvoices.* fields
2351 =cut
2353 sub GetInvoice {
2354 my ($invoiceid) = @_;
2355 my $invoice;
2357 return unless $invoiceid;
2359 my $dbh = C4::Context->dbh;
2360 my $query = qq{
2361 SELECT *
2362 FROM aqinvoices
2363 WHERE invoiceid = ?
2365 my $sth = $dbh->prepare($query);
2366 $sth->execute($invoiceid);
2368 $invoice = $sth->fetchrow_hashref;
2369 return $invoice;
2372 =head3 GetInvoiceDetails
2374 my $invoice = GetInvoiceDetails($invoiceid)
2376 Return informations about an invoice + the list of related order lines
2378 Orders informations are in $invoice->{orders} (array ref)
2380 =cut
2382 sub GetInvoiceDetails {
2383 my ($invoiceid) = @_;
2385 if ( !defined $invoiceid ) {
2386 carp 'GetInvoiceDetails called without an invoiceid';
2387 return;
2390 my $dbh = C4::Context->dbh;
2391 my $query = qq{
2392 SELECT aqinvoices.*, aqbooksellers.name AS suppliername
2393 FROM aqinvoices
2394 LEFT JOIN aqbooksellers ON aqinvoices.booksellerid = aqbooksellers.id
2395 WHERE invoiceid = ?
2397 my $sth = $dbh->prepare($query);
2398 $sth->execute($invoiceid);
2400 my $invoice = $sth->fetchrow_hashref;
2402 $query = qq{
2403 SELECT aqorders.*, biblio.*
2404 FROM aqorders
2405 LEFT JOIN biblio ON aqorders.biblionumber = biblio.biblionumber
2406 WHERE invoiceid = ?
2408 $sth = $dbh->prepare($query);
2409 $sth->execute($invoiceid);
2410 $invoice->{orders} = $sth->fetchall_arrayref({});
2411 $invoice->{orders} ||= []; # force an empty arrayref if fetchall_arrayref fails
2413 return $invoice;
2416 =head3 AddInvoice
2418 my $invoiceid = AddInvoice(
2419 invoicenumber => $invoicenumber,
2420 booksellerid => $booksellerid,
2421 shipmentdate => $shipmentdate,
2422 billingdate => $billingdate,
2423 closedate => $closedate,
2424 shipmentcost => $shipmentcost,
2425 shipmentcost_budgetid => $shipmentcost_budgetid
2428 Create a new invoice and return its id or undef if it fails.
2430 =cut
2432 sub AddInvoice {
2433 my %invoice = @_;
2435 return unless(%invoice and $invoice{invoicenumber});
2437 my @columns = qw(invoicenumber booksellerid shipmentdate billingdate
2438 closedate shipmentcost shipmentcost_budgetid);
2440 my @set_strs;
2441 my @set_args;
2442 foreach my $key (keys %invoice) {
2443 if(0 < grep(/^$key$/, @columns)) {
2444 push @set_strs, "$key = ?";
2445 push @set_args, ($invoice{$key} || undef);
2449 my $rv;
2450 if(@set_args > 0) {
2451 my $dbh = C4::Context->dbh;
2452 my $query = "INSERT INTO aqinvoices SET ";
2453 $query .= join (",", @set_strs);
2454 my $sth = $dbh->prepare($query);
2455 $rv = $sth->execute(@set_args);
2456 if($rv) {
2457 $rv = $dbh->last_insert_id(undef, undef, 'aqinvoices', undef);
2460 return $rv;
2463 =head3 ModInvoice
2465 ModInvoice(
2466 invoiceid => $invoiceid, # Mandatory
2467 invoicenumber => $invoicenumber,
2468 booksellerid => $booksellerid,
2469 shipmentdate => $shipmentdate,
2470 billingdate => $billingdate,
2471 closedate => $closedate,
2472 shipmentcost => $shipmentcost,
2473 shipmentcost_budgetid => $shipmentcost_budgetid
2476 Modify an invoice, invoiceid is mandatory.
2478 Return undef if it fails.
2480 =cut
2482 sub ModInvoice {
2483 my %invoice = @_;
2485 return unless(%invoice and $invoice{invoiceid});
2487 my @columns = qw(invoicenumber booksellerid shipmentdate billingdate
2488 closedate shipmentcost shipmentcost_budgetid);
2490 my @set_strs;
2491 my @set_args;
2492 foreach my $key (keys %invoice) {
2493 if(0 < grep(/^$key$/, @columns)) {
2494 push @set_strs, "$key = ?";
2495 push @set_args, ($invoice{$key} || undef);
2499 my $dbh = C4::Context->dbh;
2500 my $query = "UPDATE aqinvoices SET ";
2501 $query .= join(",", @set_strs);
2502 $query .= " WHERE invoiceid = ?";
2504 my $sth = $dbh->prepare($query);
2505 $sth->execute(@set_args, $invoice{invoiceid});
2508 =head3 CloseInvoice
2510 CloseInvoice($invoiceid);
2512 Close an invoice.
2514 Equivalent to ModInvoice(invoiceid => $invoiceid, closedate => undef);
2516 =cut
2518 sub CloseInvoice {
2519 my ($invoiceid) = @_;
2521 return unless $invoiceid;
2523 my $dbh = C4::Context->dbh;
2524 my $query = qq{
2525 UPDATE aqinvoices
2526 SET closedate = CAST(NOW() AS DATE)
2527 WHERE invoiceid = ?
2529 my $sth = $dbh->prepare($query);
2530 $sth->execute($invoiceid);
2533 =head3 ReopenInvoice
2535 ReopenInvoice($invoiceid);
2537 Reopen an invoice
2539 Equivalent to ModInvoice(invoiceid => $invoiceid, closedate => C4::Dates->new()->output('iso'))
2541 =cut
2543 sub ReopenInvoice {
2544 my ($invoiceid) = @_;
2546 return unless $invoiceid;
2548 my $dbh = C4::Context->dbh;
2549 my $query = qq{
2550 UPDATE aqinvoices
2551 SET closedate = NULL
2552 WHERE invoiceid = ?
2554 my $sth = $dbh->prepare($query);
2555 $sth->execute($invoiceid);
2559 __END__
2561 =head1 AUTHOR
2563 Koha Development Team <http://koha-community.org/>
2565 =cut