File Coverage

File:C4/Acquisition.pm
Coverage:7.5%

linestmtbrancondsubtimecode
1package C4::Acquisition;
2
3# Copyright 2000-2002 Katipo Communications
4#
5# This file is part of Koha.
6#
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.
11#
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.
15#
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.
19
20
21
1
1
1
249
2
21
use strict;
22
1
1
1
5
1
27
use warnings;
23
1
1
1
4
1
53
use Carp;
24
1
1
1
5
1
58
use C4::Context;
25
1
1
1
5
2
78
use C4::Debug;
26
1
1
1
4
2
46
use C4::Dates qw(format_date format_date_in_iso);
27
1
1
1
4
2
32
use MARC::Record;
28
1
1
1
28
2
109
use C4::Suggestions;
29
1
1
1
4
2
517
use C4::Biblio;
30
1
1
1
4
1
66
use C4::Debug;
31
1
1
1
5
1
41
use C4::SQLHelper qw(InsertInTable);
32
33
1
1
1
155
4824
141
use Time::localtime;
34
1
1
1
12370
14553
180
use HTML::Entities;
35
36
1
1
1
43
33
219
use vars qw($VERSION @ISA @EXPORT);
37
38BEGIN {
39    # set the version for version checking
40
1
32
    $VERSION = 3.01;
41
1
33
    require Exporter;
42
1
43
    @ISA = qw(Exporter);
43
1
7281
    @EXPORT = qw(
44        &GetBasket &NewBasket &CloseBasket &DelBasket &ModBasket
45        &GetBasketAsCSV
46        &GetBasketsByBookseller &GetBasketsByBasketgroup
47        &GetBasketsInfosByBookseller
48
49        &ModBasketHeader
50
51        &ModBasketgroup &NewBasketgroup &DelBasketgroup &GetBasketgroup &CloseBasketgroup
52        &GetBasketgroups &ReOpenBasketgroup
53
54        &NewOrder &DelOrder &ModOrder &GetPendingOrders &GetOrder &GetOrders
55        &GetOrderNumber &GetLateOrders &GetOrderFromItemnumber
56        &SearchOrder &GetHistory &GetRecentAcqui
57        &ModReceiveOrder &ModOrderBiblioitemNumber
58        &GetCancelledOrders
59
60        &NewOrderItem &ModOrderItem
61
62        &GetParcels &GetParcel
63        &GetContracts &GetContract
64
65        &GetItemnumbersFromOrder
66
67        &AddClaim
68    );
69}
70
71
72
73
74
75sub GetOrderFromItemnumber {
76
0
    my ($itemnumber) = @_;
77
0
    my $dbh = C4::Context->dbh;
78
0
    my $query = qq|
79
80    SELECT * from aqorders LEFT JOIN aqorders_items
81    ON ( aqorders.ordernumber = aqorders_items.ordernumber )
82    WHERE itemnumber = ? |;
83
84
0
    my $sth = $dbh->prepare($query);
85
86# $sth->trace(3);
87
88
0
    $sth->execute($itemnumber);
89
90
0
    my $order = $sth->fetchrow_hashref;
91
0
    return ( $order );
92
93}
94
95# Returns the itemnumber(s) associated with the ordernumber given in parameter
96sub GetItemnumbersFromOrder {
97
0
    my ($ordernumber) = @_;
98
0
    my $dbh = C4::Context->dbh;
99
0
    my $query = "SELECT itemnumber FROM aqorders_items WHERE ordernumber=?";
100
0
    my $sth = $dbh->prepare($query);
101
0
    $sth->execute($ordernumber);
102
0
    my @tab;
103
104
0
    while (my $order = $sth->fetchrow_hashref) {
105
0
    push @tab, $order->{'itemnumber'};
106    }
107
108
0
    return @tab;
109
110}
111
112
113
114
115
116
117 - 142
=head1 NAME

C4::Acquisition - Koha functions for dealing with orders and acquisitions

=head1 SYNOPSIS

use C4::Acquisition;

=head1 DESCRIPTION

The functions in this module deal with acquisitions, managing book
orders, basket and parcels.

=head1 FUNCTIONS

=head2 FUNCTIONS ABOUT BASKETS

=head3 GetBasket

  $aqbasket = &GetBasket($basketnumber);

get all basket informations in aqbasket for a given basket

B<returns:> informations for a given basket returned as a hashref.

=cut
143
144sub GetBasket {
145
0
    my ($basketno) = @_;
146
0
    my $dbh = C4::Context->dbh;
147
0
    my $query = "
148        SELECT aqbasket.*,
149                concat( b.firstname,' ',b.surname) AS authorisedbyname,
150                b.branchcode AS branch
151        FROM aqbasket
152        LEFT JOIN borrowers b ON aqbasket.authorisedby=b.borrowernumber
153        WHERE basketno=?
154    ";
155
0
    my $sth=$dbh->prepare($query);
156
0
    $sth->execute($basketno);
157
0
    my $basket = $sth->fetchrow_hashref;
158
0
    return ( $basket );
159}
160
161#------------------------------------------------------------#
162
163 - 180
=head3 NewBasket

  $basket = &NewBasket( $booksellerid, $authorizedby, $basketname, 
      $basketnote, $basketbooksellernote, $basketcontractnumber );

Create a new basket in aqbasket table

=over

=item C<$booksellerid> is a foreign key in the aqbasket table

=item C<$authorizedby> is the username of who created the basket

=back

The other parameters are optional, see ModBasketHeader for more info on them.

=cut
181
182# FIXME : this function seems to be unused.
183
184sub NewBasket {
185
0
    my ( $booksellerid, $authorisedby, $basketname, $basketnote, $basketbooksellernote, $basketcontractnumber ) = @_;
186
0
    my $dbh = C4::Context->dbh;
187
0
    my $query = "
188        INSERT INTO aqbasket
189                (creationdate,booksellerid,authorisedby)
190        VALUES (now(),'$booksellerid','$authorisedby')
191    ";
192
0
    my $sth =
193    $dbh->do($query);
194#find & return basketno MYSQL dependant, but $dbh->last_insert_id always returns null :-(
195
0
    my $basket = $dbh->{'mysql_insertid'};
196
0
    ModBasketHeader($basket, $basketname || '', $basketnote || '', $basketbooksellernote || '', $basketcontractnumber || undef);
197
0
    return $basket;
198}
199
200#------------------------------------------------------------#
201
202 - 208
=head3 CloseBasket

  &CloseBasket($basketno);

close a basket (becomes unmodifiable,except for recieves)

=cut
209
210sub CloseBasket {
211
0
    my ($basketno) = @_;
212
0
    my $dbh = C4::Context->dbh;
213
0
    my $query = "
214        UPDATE aqbasket
215        SET closedate=now()
216        WHERE basketno=?
217    ";
218
0
    my $sth = $dbh->prepare($query);
219
0
    $sth->execute($basketno);
220}
221
222#------------------------------------------------------------#
223
224 - 230
=head3 GetBasketAsCSV

  &GetBasketAsCSV($basketno);

Export a basket as CSV

=cut
231
232sub GetBasketAsCSV {
233
0
    my ($basketno) = @_;
234
0
    my $basket = GetBasket($basketno);
235
0
    my @orders = GetOrders($basketno);
236
0
    my $contract = GetContract($basket->{'contractnumber'});
237
0
    my $csv = Text::CSV->new();
238
0
    my $output;
239
240    # TODO: Translate headers
241
0
    my @headers = qw(contractname ordernumber entrydate isbn author title publishercode collectiontitle notes quantity rrp);
242
243
0
    $csv->combine(@headers);
244
0
    $output = $csv->string() . "\n";
245
246
0
    my @rows;
247
0
    foreach my $order (@orders) {
248
0
        my @cols;
249        # newlines are not valid characters for Text::CSV combine()
250
0
        $order->{'notes'} =~ s/[\r\n]+//g;
251
0
        push(@cols,
252                $contract->{'contractname'},
253                $order->{'ordernumber'},
254                $order->{'entrydate'},
255                $order->{'isbn'},
256                $order->{'author'},
257                $order->{'title'},
258                $order->{'publishercode'},
259                $order->{'collectiontitle'},
260                $order->{'notes'},
261                $order->{'quantity'},
262                $order->{'rrp'},
263            );
264
0
        push (@rows, \@cols);
265    }
266
267
0
    foreach my $row (@rows) {
268
0
        $csv->combine(@$row);
269
0
        $output .= $csv->string() . "\n";
270
271    }
272
273
0
    return $output;
274
275}
276
277
278 - 284
=head3 CloseBasketgroup

  &CloseBasketgroup($basketgroupno);

close a basketgroup

=cut
285
286sub CloseBasketgroup {
287
0
    my ($basketgroupno) = @_;
288
0
    my $dbh = C4::Context->dbh;
289
0
    my $sth = $dbh->prepare("
290        UPDATE aqbasketgroups
291        SET closed=1
292        WHERE id=?
293    ");
294
0
    $sth->execute($basketgroupno);
295}
296
297#------------------------------------------------------------#
298
299 - 305
=head3 ReOpenBaskergroup($basketgroupno)

  &ReOpenBaskergroup($basketgroupno);

reopen a basketgroup

=cut
306
307sub ReOpenBasketgroup {
308
0
    my ($basketgroupno) = @_;
309
0
    my $dbh = C4::Context->dbh;
310
0
    my $sth = $dbh->prepare("
311        UPDATE aqbasketgroups
312        SET closed=0
313        WHERE id=?
314    ");
315
0
    $sth->execute($basketgroupno);
316}
317
318#------------------------------------------------------------#
319
320
321 - 333
=head3 DelBasket

  &DelBasket($basketno);

Deletes the basket that has basketno field $basketno in the aqbasket table.

=over

=item C<$basketno> is the primary key of the basket in the aqbasket table.

=back

=cut
334
335sub DelBasket {
336
0
    my ( $basketno ) = @_;
337
0
    my $query = "DELETE FROM aqbasket WHERE basketno=?";
338
0
    my $dbh = C4::Context->dbh;
339
0
    my $sth = $dbh->prepare($query);
340
0
    $sth->execute($basketno);
341
0
    $sth->finish;
342}
343
344#------------------------------------------------------------#
345
346 - 358
=head3 ModBasket

  &ModBasket($basketinfo);

Modifies a basket, using a hashref $basketinfo for the relevant information, only $basketinfo->{'basketno'} is required.

=over

=item C<$basketno> is the primary key of the basket in the aqbasket table.

=back

=cut
359
360sub ModBasket {
361
0
    my $basketinfo = shift;
362
0
    my $query = "UPDATE aqbasket SET ";
363
0
    my @params;
364
0
    foreach my $key (keys %$basketinfo){
365
0
        if ($key ne 'basketno'){
366
0
            $query .= "$key=?, ";
367
0
            push(@params, $basketinfo->{$key} || undef );
368        }
369    }
370# get rid of the "," at the end of $query
371
0
    if (substr($query, length($query)-2) eq ', '){
372
0
        chop($query);
373
0
        chop($query);
374
0
        $query .= ' ';
375    }
376
0
    $query .= "WHERE basketno=?";
377
0
    push(@params, $basketinfo->{'basketno'});
378
0
    my $dbh = C4::Context->dbh;
379
0
    my $sth = $dbh->prepare($query);
380
0
    $sth->execute(@params);
381
0
    $sth->finish;
382}
383
384#------------------------------------------------------------#
385
386 - 406
=head3 ModBasketHeader

  &ModBasketHeader($basketno, $basketname, $note, $booksellernote, $contractnumber);

Modifies a basket's header.

=over

=item C<$basketno> is the "basketno" field in the "aqbasket" table;

=item C<$basketname> is the "basketname" field in the "aqbasket" table;

=item C<$note> is the "note" field in the "aqbasket" table;

=item C<$booksellernote> is the "booksellernote" field in the "aqbasket" table;

=item C<$contractnumber> is the "contractnumber" (foreign) key in the "aqbasket" table.

=back

=cut
407
408sub ModBasketHeader {
409
0
    my ($basketno, $basketname, $note, $booksellernote, $contractnumber) = @_;
410
0
    my $query = "UPDATE aqbasket SET basketname=?, note=?, booksellernote=? WHERE basketno=?";
411
0
    my $dbh = C4::Context->dbh;
412
0
    my $sth = $dbh->prepare($query);
413
0
    $sth->execute($basketname,$note,$booksellernote,$basketno);
414
0
    if ( $contractnumber ) {
415
0
        my $query2 ="UPDATE aqbasket SET contractnumber=? WHERE basketno=?";
416
0
        my $sth2 = $dbh->prepare($query2);
417
0
        $sth2->execute($contractnumber,$basketno);
418
0
        $sth2->finish;
419    }
420
0
    $sth->finish;
421}
422
423#------------------------------------------------------------#
424
425 - 444
=head3 GetBasketsByBookseller

  @results = &GetBasketsByBookseller($booksellerid, $extra);

Returns a list of hashes of all the baskets that belong to bookseller 'booksellerid'.

=over

=item C<$booksellerid> is the 'id' field of the bookseller in the aqbooksellers table

=item C<$extra> is the extra sql parameters, can be

 $extra->{groupby}: group baskets by column
    ex. $extra->{groupby} = aqbasket.basketgroupid
 $extra->{orderby}: order baskets by column
 $extra->{limit}: limit number of results (can be helpful for pagination)

=back

=cut
445
446sub GetBasketsByBookseller {
447
0
    my ($booksellerid, $extra) = @_;
448
0
    my $query = "SELECT * FROM aqbasket WHERE booksellerid=?";
449
0
    if ($extra){
450
0
        if ($extra->{groupby}) {
451
0
            $query .= " GROUP by $extra->{groupby}";
452        }
453
0
        if ($extra->{orderby}){
454
0
            $query .= " ORDER by $extra->{orderby}";
455        }
456
0
        if ($extra->{limit}){
457
0
            $query .= " LIMIT $extra->{limit}";
458        }
459    }
460
0
    my $dbh = C4::Context->dbh;
461
0
    my $sth = $dbh->prepare($query);
462
0
    $sth->execute($booksellerid);
463
0
    my $results = $sth->fetchall_arrayref({});
464
0
    $sth->finish;
465
0
    return $results
466}
467
468 - 477
=head3 GetBasketsInfosByBookseller

    my $baskets = GetBasketsInfosByBookseller($supplierid);

Returns in a arrayref of hashref all about booksellers baskets, plus:
    total_biblios: Number of distinct biblios in basket
    total_items: Number of items in basket
    expected_items: Number of non-received items in basket

=cut
478
479sub GetBasketsInfosByBookseller {
480
0
    my ($supplierid) = @_;
481
482
0
    return unless $supplierid;
483
484
0
    my $dbh = C4::Context->dbh;
485
0
    my $query = qq{
486        SELECT aqbasket.*,
487          SUM(aqorders.quantity) AS total_items,
488          COUNT(DISTINCT aqorders.biblionumber) AS total_biblios,
489          SUM(IF(aqorders.datereceived IS NULL, aqorders.quantity, 0)) AS expected_items
490        FROM aqbasket
491          LEFT JOIN aqorders ON aqorders.basketno = aqbasket.basketno
492        WHERE booksellerid = ?
493        GROUP BY aqbasket.basketno
494    };
495
0
    my $sth = $dbh->prepare($query);
496
0
    $sth->execute($supplierid);
497
0
    return $sth->fetchall_arrayref({});
498}
499
500
501#------------------------------------------------------------#
502
503 - 509
=head3 GetBasketsByBasketgroup

  $baskets = &GetBasketsByBasketgroup($basketgroupid);

Returns a reference to all baskets that belong to basketgroup $basketgroupid.

=cut
510
511sub GetBasketsByBasketgroup {
512
0
    my $basketgroupid = shift;
513
0
    my $query = "SELECT * FROM aqbasket
514                LEFT JOIN aqcontract USING(contractnumber) WHERE basketgroupid=?";
515
0
    my $dbh = C4::Context->dbh;
516
0
    my $sth = $dbh->prepare($query);
517
0
    $sth->execute($basketgroupid);
518
0
    my $results = $sth->fetchall_arrayref({});
519
0
    $sth->finish;
520
0
    return $results
521}
522
523#------------------------------------------------------------#
524
525 - 543
=head3 NewBasketgroup

  $basketgroupid = NewBasketgroup(\%hashref);

Adds a basketgroup to the aqbasketgroups table, and add the initial baskets to it.

$hashref->{'booksellerid'} is the 'id' field of the bookseller in the aqbooksellers table,

$hashref->{'name'} is the 'name' field of the basketgroup in the aqbasketgroups table,

$hashref->{'basketlist'} is a list reference of the 'id's of the baskets that belong to this group,

$hashref->{'deliveryplace'} is the 'deliveryplace' field of the basketgroup in the aqbasketgroups table,

$hashref->{'deliverycomment'} is the 'deliverycomment' field of the basketgroup in the aqbasketgroups table,

$hashref->{'closed'} is the 'closed' field of the aqbasketgroups table, it is false if 0, true otherwise.

=cut
544
545sub NewBasketgroup {
546
0
    my $basketgroupinfo = shift;
547
0
    die "booksellerid is required to create a basketgroup" unless $basketgroupinfo->{'booksellerid'};
548
0
    my $query = "INSERT INTO aqbasketgroups (";
549
0
    my @params;
550
0
    foreach my $field ('name', 'deliveryplace', 'deliverycomment', 'closed') {
551
0
        if ( $basketgroupinfo->{$field} ) {
552
0
            $query .= "$field, ";
553
0
            push(@params, $basketgroupinfo->{$field});
554        }
555    }
556
0
    $query .= "booksellerid) VALUES (";
557
0
    foreach (@params) {
558
0
        $query .= "?, ";
559    }
560
0
    $query .= "?)";
561
0
    push(@params, $basketgroupinfo->{'booksellerid'});
562
0
    my $dbh = C4::Context->dbh;
563
0
    my $sth = $dbh->prepare($query);
564
0
    $sth->execute(@params);
565
0
    my $basketgroupid = $dbh->{'mysql_insertid'};
566
0
    if( $basketgroupinfo->{'basketlist'} ) {
567
0
0
        foreach my $basketno (@{$basketgroupinfo->{'basketlist'}}) {
568
0
            my $query2 = "UPDATE aqbasket SET basketgroupid=? WHERE basketno=?";
569
0
            my $sth2 = $dbh->prepare($query2);
570
0
            $sth2->execute($basketgroupid, $basketno);
571        }
572    }
573
0
    return $basketgroupid;
574}
575
576#------------------------------------------------------------#
577
578 - 598
=head3 ModBasketgroup

  ModBasketgroup(\%hashref);

Modifies a basketgroup in the aqbasketgroups table, and add the baskets to it.

$hashref->{'id'} is the 'id' field of the basketgroup in the aqbasketgroup table, this parameter is mandatory,

$hashref->{'name'} is the 'name' field of the basketgroup in the aqbasketgroups table,

$hashref->{'basketlist'} is a list reference of the 'id's of the baskets that belong to this group,

$hashref->{'billingplace'} is the 'billingplace' field of the basketgroup in the aqbasketgroups table,

$hashref->{'deliveryplace'} is the 'deliveryplace' field of the basketgroup in the aqbasketgroups table,

$hashref->{'deliverycomment'} is the 'deliverycomment' field of the basketgroup in the aqbasketgroups table,

$hashref->{'closed'} is the 'closed' field of the aqbasketgroups table, it is false if 0, true otherwise.

=cut
599
600sub ModBasketgroup {
601
0
    my $basketgroupinfo = shift;
602
0
    die "basketgroup id is required to edit a basketgroup" unless $basketgroupinfo->{'id'};
603
0
    my $dbh = C4::Context->dbh;
604
0
    my $query = "UPDATE aqbasketgroups SET ";
605
0
    my @params;
606
0
    foreach my $field (qw(name billingplace deliveryplace freedeliveryplace deliverycomment closed)) {
607
0
        if ( defined $basketgroupinfo->{$field} ) {
608
0
            $query .= "$field=?, ";
609
0
            push(@params, $basketgroupinfo->{$field});
610        }
611    }
612
0
    chop($query);
613
0
    chop($query);
614
0
    $query .= " WHERE id=?";
615
0
    push(@params, $basketgroupinfo->{'id'});
616
0
    my $sth = $dbh->prepare($query);
617
0
    $sth->execute(@params);
618
619
0
    $sth = $dbh->prepare('UPDATE aqbasket SET basketgroupid = NULL WHERE basketgroupid = ?');
620
0
    $sth->execute($basketgroupinfo->{'id'});
621
622
0
0
    if($basketgroupinfo->{'basketlist'} && @{$basketgroupinfo->{'basketlist'}}){
623
0
        $sth = $dbh->prepare("UPDATE aqbasket SET basketgroupid=? WHERE basketno=?");
624
0
0
        foreach my $basketno (@{$basketgroupinfo->{'basketlist'}}) {
625
0
            $sth->execute($basketgroupinfo->{'id'}, $basketno);
626
0
            $sth->finish;
627        }
628    }
629
0
    $sth->finish;
630}
631
632#------------------------------------------------------------#
633
634 - 646
=head3 DelBasketgroup

  DelBasketgroup($basketgroupid);

Deletes a basketgroup in the aqbasketgroups table, and removes the reference to it from the baskets,

=over

=item C<$basketgroupid> is the 'id' field of the basket in the aqbasketgroup table

=back

=cut
647
648sub DelBasketgroup {
649
0
    my $basketgroupid = shift;
650
0
    die "basketgroup id is required to edit a basketgroup" unless $basketgroupid;
651
0
    my $query = "DELETE FROM aqbasketgroups WHERE id=?";
652
0
    my $dbh = C4::Context->dbh;
653
0
    my $sth = $dbh->prepare($query);
654
0
    $sth->execute($basketgroupid);
655
0
    $sth->finish;
656}
657
658#------------------------------------------------------------#
659
660
661 - 669
=head2 FUNCTIONS ABOUT ORDERS

=head3 GetBasketgroup

  $basketgroup = &GetBasketgroup($basketgroupid);

Returns a reference to the hash containing all infermation about the basketgroup.

=cut
670
671sub GetBasketgroup {
672
0
    my $basketgroupid = shift;
673
0
    die "basketgroup id is required to edit a basketgroup" unless $basketgroupid;
674
0
    my $query = "SELECT * FROM aqbasketgroups WHERE id=?";
675
0
    my $dbh = C4::Context->dbh;
676
0
    my $sth = $dbh->prepare($query);
677
0
    $sth->execute($basketgroupid);
678
0
    my $result = $sth->fetchrow_hashref;
679
0
    $sth->finish;
680
0
    return $result
681}
682
683#------------------------------------------------------------#
684
685 - 691
=head3 GetBasketgroups

  $basketgroups = &GetBasketgroups($booksellerid);

Returns a reference to the array of all the basketgroups of bookseller $booksellerid.

=cut
692
693sub GetBasketgroups {
694
0
    my $booksellerid = shift;
695
0
    die "bookseller id is required to edit a basketgroup" unless $booksellerid;
696
0
    my $query = "SELECT * FROM aqbasketgroups WHERE booksellerid=? ORDER BY `id` DESC";
697
0
    my $dbh = C4::Context->dbh;
698
0
    my $sth = $dbh->prepare($query);
699
0
    $sth->execute($booksellerid);
700
0
    my $results = $sth->fetchall_arrayref({});
701
0
    $sth->finish;
702
0
    return $results
703}
704
705#------------------------------------------------------------#
706
707 - 709
=head2 FUNCTIONS ABOUT ORDERS

=cut
710
711#------------------------------------------------------------#
712
713 - 744
=head3 GetPendingOrders

  $orders = &GetPendingOrders($booksellerid, $grouped, $owner);

Finds pending orders from the bookseller with the given ID. Ignores
completed and cancelled orders.

C<$booksellerid> contains the bookseller identifier
C<$grouped> contains 0 or 1. 0 means returns the list, 1 means return the total
C<$owner> contains 0 or 1. 0 means any owner. 1 means only the list of orders entered by the user itself.

C<$orders> is a reference-to-array; each element is a
reference-to-hash with the following fields:
C<$grouped> is a boolean that, if set to 1 will group all order lines of the same basket
in a single result line

=over

=item C<authorizedby>

=item C<entrydate>

=item C<basketno>

=back

These give the value of the corresponding field in the aqorders table
of the Koha database.

Results are ordered from most to least recent.

=cut
745
746sub GetPendingOrders {
747
0
    my ($supplierid,$grouped,$owner,$basketno) = @_;
748
0
    my $dbh = C4::Context->dbh;
749
0
    my $strsth = "
750        SELECT ".($grouped?"count(*),":"")."aqbasket.basketno,
751                    surname,firstname,biblio.*,biblioitems.isbn,
752                    aqbasket.closedate, aqbasket.creationdate, aqbasket.basketname,
753                    aqorders.*
754        FROM aqorders
755        LEFT JOIN aqbasket ON aqbasket.basketno=aqorders.basketno
756        LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber
757        LEFT JOIN biblio ON biblio.biblionumber=aqorders.biblionumber
758        LEFT JOIN biblioitems ON biblioitems.biblionumber=biblio.biblionumber
759        WHERE booksellerid=?
760            AND (quantity > quantityreceived OR quantityreceived is NULL)
761            AND datecancellationprinted IS NULL";
762
0
    my @query_params = ( $supplierid );
763
0
    my $userenv = C4::Context->userenv;
764
0
    if ( C4::Context->preference("IndependantBranches") ) {
765
0
        if ( ($userenv) && ( $userenv->{flags} != 1 ) ) {
766
0
            $strsth .= " and (borrowers.branchcode = ?
767                        or borrowers.branchcode = '')";
768
0
            push @query_params, $userenv->{branch};
769        }
770    }
771
0
    if ($owner) {
772
0
        $strsth .= " AND aqbasket.authorisedby=? ";
773
0
        push @query_params, $userenv->{'number'};
774    }
775
0
    if ($basketno) {
776
0
        $strsth .= " AND aqbasket.basketno=? ";
777
0
        push @query_params, $basketno;
778    }
779
0
    $strsth .= " group by aqbasket.basketno" if $grouped;
780
0
    $strsth .= " order by aqbasket.basketno";
781
782
0
    my $sth = $dbh->prepare($strsth);
783
0
    $sth->execute( @query_params );
784
0
    my $results = $sth->fetchall_arrayref({});
785
0
    $sth->finish;
786
0
    return $results;
787}
788
789#------------------------------------------------------------#
790
791 - 804
=head3 GetOrders

  @orders = &GetOrders($basketnumber, $orderby);

Looks up the pending (non-cancelled) orders with the given basket
number. If C<$booksellerID> is non-empty, only orders from that seller
are returned.

return :
C<&basket> returns a two-element array. C<@orders> is an array of
references-to-hash, whose keys are the fields from the aqorders,
biblio, and biblioitems tables in the Koha database.

=cut
805
806sub GetOrders {
807
0
    my ( $basketno, $orderby ) = @_;
808
0
    my $dbh = C4::Context->dbh;
809
0
    my $query ="
810        SELECT biblio.*,biblioitems.*,
811                aqorders.*,
812                aqbudgets.*,
813                biblio.title
814        FROM aqorders
815            LEFT JOIN aqbudgets ON aqbudgets.budget_id = aqorders.budget_id
816            LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber
817            LEFT JOIN biblioitems ON biblioitems.biblionumber =biblio.biblionumber
818        WHERE basketno=?
819            AND (datecancellationprinted IS NULL OR datecancellationprinted='0000-00-00')
820    ";
821
822
0
    $orderby = "biblioitems.publishercode,biblio.title" unless $orderby;
823
0
    $query .= " ORDER BY $orderby";
824
0
    my $sth = $dbh->prepare($query);
825
0
    $sth->execute($basketno);
826
0
    my $results = $sth->fetchall_arrayref({});
827
0
    $sth->finish;
828
0
    return @$results;
829}
830
831#------------------------------------------------------------#
832
833 - 847
=head3 GetOrderNumber

  $ordernumber = &GetOrderNumber($biblioitemnumber, $biblionumber);

Looks up the ordernumber with the given biblionumber and biblioitemnumber.

Returns the number of this order.

=over

=item C<$ordernumber> is the order number.

=back

=cut
848
849sub GetOrderNumber {
850
0
    my ( $biblionumber,$biblioitemnumber ) = @_;
851
0
    my $dbh = C4::Context->dbh;
852
0
    my $query = "
853        SELECT ordernumber
854        FROM aqorders
855        WHERE biblionumber=?
856        AND biblioitemnumber=?
857    ";
858
0
    my $sth = $dbh->prepare($query);
859
0
    $sth->execute( $biblionumber, $biblioitemnumber );
860
861
0
    return $sth->fetchrow;
862}
863
864#------------------------------------------------------------#
865
866 - 875
=head3 GetOrder

  $order = &GetOrder($ordernumber);

Looks up an order by order number.

Returns a reference-to-hash describing the order. The keys of
C<$order> are fields from the biblio, biblioitems, aqorders tables of the Koha database.

=cut
876
877sub GetOrder {
878
0
    my ($ordernumber) = @_;
879
0
    my $dbh = C4::Context->dbh;
880
0
    my $query = "
881        SELECT biblioitems.*, biblio.*, aqorders.*
882        FROM aqorders
883        LEFT JOIN biblio on biblio.biblionumber=aqorders.biblionumber
884        LEFT JOIN biblioitems on biblioitems.biblionumber=aqorders.biblionumber
885        WHERE aqorders.ordernumber=?
886
887    ";
888
0
    my $sth= $dbh->prepare($query);
889
0
    $sth->execute($ordernumber);
890
0
    my $data = $sth->fetchrow_hashref;
891
0
    $sth->finish;
892
0
    return $data;
893}
894
895#------------------------------------------------------------#
896
897 - 925
=head3 NewOrder

  &NewOrder(\%hashref);

Adds a new order to the database. Any argument that isn't described
below is the new value of the field with the same name in the aqorders
table of the Koha database.

=over

=item $hashref->{'basketno'} is the basketno foreign key in aqorders, it is mandatory

=item $hashref->{'ordernumber'} is a "minimum order number."

=item $hashref->{'budgetdate'} is effectively ignored.
If it's undef (anything false) or the string 'now', the current day is used.
Else, the upcoming July 1st is used.

=item $hashref->{'subscription'} may be either "yes", or anything else for "no".

=item $hashref->{'uncertainprice'} may be 0 for "the price is known" or 1 for "the price is uncertain"

=item defaults entrydate to Now

The following keys are used: "biblionumber", "title", "basketno", "quantity", "notes", "biblioitemnumber", "rrp", "ecost", "gst", "unitprice", "subscription", "sort1", "sort2", "booksellerinvoicenumber", "listprice", "budgetdate", "purchaseordernumber", "branchcode", "booksellerinvoicenumber", "bookfundid".

=back

=cut
926
927sub NewOrder {
928
0
    my $orderinfo = shift;
929#### ------------------------------
930
0
    my $dbh = C4::Context->dbh;
931
0
    my @params;
932
933
934    # if these parameters are missing, we can't continue
935
0
    for my $key (qw/basketno quantity biblionumber budget_id/) {
936
0
        croak "Mandatory parameter $key missing" unless $orderinfo->{$key};
937    }
938
939
0
    if ( defined $orderinfo->{subscription} && $orderinfo->{'subscription'} eq 'yes' ) {
940
0
        $orderinfo->{'subscription'} = 1;
941    } else {
942
0
        $orderinfo->{'subscription'} = 0;
943    }
944
0
    $orderinfo->{'entrydate'} ||= C4::Dates->new()->output("iso");
945
0
    if (!$orderinfo->{quantityreceived}) {
946
0
        $orderinfo->{quantityreceived} = 0;
947    }
948
949
0
    my $ordernumber=InsertInTable("aqorders",$orderinfo);
950
0
    return ( $orderinfo->{'basketno'}, $ordernumber );
951}
952
953
954
955#------------------------------------------------------------#
956
957 - 961
=head3 NewOrderItem

  &NewOrderItem();

=cut
962
963sub NewOrderItem {
964
0
    my ($itemnumber, $ordernumber) = @_;
965
0
    my $dbh = C4::Context->dbh;
966
0
    my $query = qq|
967            INSERT INTO aqorders_items
968                (itemnumber, ordernumber)
969            VALUES (?,?) |;
970
971
0
    my $sth = $dbh->prepare($query);
972
0
    $sth->execute( $itemnumber, $ordernumber);
973}
974
975#------------------------------------------------------------#
976
977 - 986
=head3 ModOrder

  &ModOrder(\%hashref);

Modifies an existing order. Updates the order with order number
$hashref->{'ordernumber'} and biblionumber $hashref->{'biblionumber'}. All 
other keys of the hash update the fields with the same name in the aqorders 
table of the Koha database.

=cut
987
988sub ModOrder {
989
0
    my $orderinfo = shift;
990
991
0
    die "Ordernumber is required" if $orderinfo->{'ordernumber'} eq '' ;
992
0
    die "Biblionumber is required" if $orderinfo->{'biblionumber'} eq '';
993
994
0
    my $dbh = C4::Context->dbh;
995
0
    my @params;
996
997    # update uncertainprice to an integer, just in case (under FF, checked boxes have the value "ON" by default)
998
0
    $orderinfo->{uncertainprice}=1 if $orderinfo->{uncertainprice};
999
1000# delete($orderinfo->{'branchcode'});
1001    # the hash contains a lot of entries not in aqorders, so get the columns ...
1002
0
    my $sth = $dbh->prepare("SELECT * FROM aqorders LIMIT 1;");
1003
0
    $sth->execute;
1004
0
    my $colnames = $sth->{NAME};
1005
0
    my $query = "UPDATE aqorders SET ";
1006
1007
0
    foreach my $orderinfokey (grep(!/ordernumber/, keys %$orderinfo)){
1008        # ... and skip hash entries that are not in the aqorders table
1009        # FIXME : probably not the best way to do it (would be better to have a correct hash)
1010
0
        next unless grep(/^$orderinfokey$/, @$colnames);
1011
0
            $query .= "$orderinfokey=?, ";
1012
0
            push(@params, $orderinfo->{$orderinfokey});
1013    }
1014
1015
0
    $query .= "timestamp=NOW() WHERE ordernumber=?";
1016# push(@params, $specorderinfo{'ordernumber'});
1017
0
    push(@params, $orderinfo->{'ordernumber'} );
1018
0
    $sth = $dbh->prepare($query);
1019
0
    $sth->execute(@params);
1020
0
    $sth->finish;
1021}
1022
1023#------------------------------------------------------------#
1024
1025 - 1039
=head3 ModOrderItem

  &ModOrderItem(\%hashref);

Modifies the itemnumber in the aqorders_items table. The input hash needs three entities:

=over

=item - itemnumber: the old itemnumber
=item - ordernumber: the order this item is attached to
=item - newitemnumber: the new itemnumber we want to attach the line to

=back

=cut
1040
1041sub ModOrderItem {
1042
0
    my $orderiteminfo = shift;
1043
0
    if (! $orderiteminfo->{'ordernumber'} || ! $orderiteminfo->{'itemnumber'} || ! $orderiteminfo->{'newitemnumber'}){
1044
0
        die "Ordernumber, itemnumber and newitemnumber is required";
1045    }
1046
1047
0
    my $dbh = C4::Context->dbh;
1048
1049
0
    my $query = "UPDATE aqorders_items set itemnumber=? where itemnumber=? and ordernumber=?";
1050
0
    my @params = ($orderiteminfo->{'newitemnumber'}, $orderiteminfo->{'itemnumber'}, $orderiteminfo->{'ordernumber'});
1051
0
    my $sth = $dbh->prepare($query);
1052
0
    $sth->execute(@params);
1053
0
    return 0;
1054}
1055
1056#------------------------------------------------------------#
1057
1058
1059 - 1066
=head3 ModOrderBibliotemNumber

  &ModOrderBiblioitemNumber($biblioitemnumber,$ordernumber, $biblionumber);

Modifies the biblioitemnumber for an existing order.
Updates the order with order number C<$ordernum> and biblionumber C<$biblionumber>.

=cut
1067
1068#FIXME: is this used at all?
1069sub ModOrderBiblioitemNumber {
1070
0
    my ($biblioitemnumber,$ordernumber, $biblionumber) = @_;
1071
0
    my $dbh = C4::Context->dbh;
1072
0
    my $query = "
1073    UPDATE aqorders
1074    SET biblioitemnumber = ?
1075    WHERE ordernumber = ?
1076    AND biblionumber = ?";
1077
0
    my $sth = $dbh->prepare($query);
1078
0
    $sth->execute( $biblioitemnumber, $ordernumber, $biblionumber );
1079}
1080
1081 - 1087
=head3 GetCancelledOrders

  my @orders = GetCancelledOrders($basketno, $orderby);

Returns cancelled orders for a basket

=cut
1088
1089sub GetCancelledOrders {
1090
0
    my ( $basketno, $orderby ) = @_;
1091
1092
0
    return () unless $basketno;
1093
1094
0
    my $dbh = C4::Context->dbh;
1095
0
    my $query = "
1096        SELECT biblio.*, biblioitems.*, aqorders.*, aqbudgets.*
1097        FROM aqorders
1098          LEFT JOIN aqbudgets ON aqbudgets.budget_id = aqorders.budget_id
1099          LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber
1100          LEFT JOIN biblioitems ON biblioitems.biblionumber = biblio.biblionumber
1101        WHERE basketno = ?
1102          AND (datecancellationprinted IS NOT NULL
1103               AND datecancellationprinted <> '0000-00-00')
1104    ";
1105
1106
0
    $orderby = "aqorders.datecancellationprinted desc, aqorders.timestamp desc"
1107        unless $orderby;
1108
0
    $query .= " ORDER BY $orderby";
1109
0
    my $sth = $dbh->prepare($query);
1110
0
    $sth->execute($basketno);
1111
0
    my $results = $sth->fetchall_arrayref( {} );
1112
1113
0
    return @$results;
1114}
1115
1116
1117#------------------------------------------------------------#
1118
1119 - 1135
=head3 ModReceiveOrder

  &ModReceiveOrder($biblionumber, $ordernumber, $quantityreceived, $user,
    $unitprice, $booksellerinvoicenumber, $biblioitemnumber,
    $freight, $bookfund, $rrp);

Updates an order, to reflect the fact that it was received, at least
in part. All arguments not mentioned below update the fields with the
same name in the aqorders table of the Koha database.

If a partial order is received, splits the order into two.  The received
portion must have a booksellerinvoicenumber.

Updates the order with bibilionumber C<$biblionumber> and ordernumber
C<$ordernumber>.

=cut
1136
1137
1138sub ModReceiveOrder {
1139    my (
1140
0
        $biblionumber, $ordernumber, $quantrec, $user, $cost,
1141        $invoiceno, $freight, $rrp, $budget_id, $datereceived
1142    )
1143    = @_;
1144
0
    my $dbh = C4::Context->dbh;
1145
0
    $datereceived = C4::Dates->output('iso') unless $datereceived;
1146
0
    my $suggestionid = GetSuggestionFromBiblionumber( $dbh, $biblionumber );
1147
0
    if ($suggestionid) {
1148
0
        ModSuggestion( {suggestionid=>$suggestionid,
1149                        STATUS=>'AVAILABLE',
1150                        biblionumber=> $biblionumber}
1151                        );
1152    }
1153
1154
0
    my $sth=$dbh->prepare("
1155        SELECT * FROM aqorders
1156        WHERE biblionumber=? AND aqorders.ordernumber=?");
1157
1158
0
    $sth->execute($biblionumber,$ordernumber);
1159
0
    my $order = $sth->fetchrow_hashref();
1160
0
    $sth->finish();
1161
1162
0
    if ( $order->{quantity} > $quantrec ) {
1163
0
        $sth=$dbh->prepare("
1164            UPDATE aqorders
1165            SET quantityreceived=?
1166                , datereceived=?
1167                , booksellerinvoicenumber=?
1168                , unitprice=?
1169                , freight=?
1170                , rrp=?
1171                , quantity=?
1172            WHERE biblionumber=? AND ordernumber=?");
1173
1174
0
        $sth->execute($quantrec,$datereceived,$invoiceno,$cost,$freight,$rrp,$quantrec,$biblionumber,$ordernumber);
1175
0
        $sth->finish;
1176
1177        # create a new order for the remaining items, and set its bookfund.
1178
0
        foreach my $orderkey ( "linenumber", "allocation" ) {
1179
0
            delete($order->{'$orderkey'});
1180        }
1181
0
        $order->{'quantity'} -= $quantrec;
1182
0
        $order->{'quantityreceived'} = 0;
1183
0
        my $newOrder = NewOrder($order);
1184} else {
1185
0
        $sth=$dbh->prepare("update aqorders
1186                            set quantityreceived=?,datereceived=?,booksellerinvoicenumber=?,
1187                                unitprice=?,freight=?,rrp=?
1188                            where biblionumber=? and ordernumber=?");
1189
0
        $sth->execute($quantrec,$datereceived,$invoiceno,$cost,$freight,$rrp,$biblionumber,$ordernumber);
1190
0
        $sth->finish;
1191    }
1192
0
    return $datereceived;
1193}
1194#------------------------------------------------------------#
1195
1196 - 1228
=head3 SearchOrder

@results = &SearchOrder($search, $biblionumber, $complete);

Searches for orders.

C<$search> may take one of several forms: if it is an ISBN,
C<&ordersearch> returns orders with that ISBN. If C<$search> is an
order number, C<&ordersearch> returns orders with that order number
and biblionumber C<$biblionumber>. Otherwise, C<$search> is considered
to be a space-separated list of search terms; in this case, all of the
terms must appear in the title (matching the beginning of title
words).

If C<$complete> is C<yes>, the results will include only completed
orders. In any case, C<&ordersearch> ignores cancelled orders.

C<&ordersearch> returns an array.
C<@results> is an array of references-to-hash with the following keys:

=over 4

=item C<author>

=item C<seriestitle>

=item C<branchcode>

=item C<bookfundid>

=back

=cut
1229
1230sub SearchOrder {
1231#### -------- SearchOrder-------------------------------
1232
0
    my ($ordernumber, $search, $supplierid, $basket) = @_;
1233
1234
0
    my $dbh = C4::Context->dbh;
1235
0
    my @args = ();
1236
0
    my $query =
1237            "SELECT *
1238            FROM aqorders
1239            LEFT JOIN biblio ON aqorders.biblionumber=biblio.biblionumber
1240            LEFT JOIN biblioitems ON biblioitems.biblionumber=biblio.biblionumber
1241            LEFT JOIN aqbasket ON aqorders.basketno = aqbasket.basketno
1242                WHERE (datecancellationprinted is NULL)";
1243
1244
0
    if($ordernumber){
1245
0
        $query .= " AND (aqorders.ordernumber=?)";
1246
0
        push @args, $ordernumber;
1247    }
1248
0
    if($search){
1249
0
        $query .= " AND (biblio.title like ? OR biblio.author LIKE ? OR biblioitems.isbn like ?)";
1250
0
        push @args, ("%$search%","%$search%","%$search%");
1251    }
1252
0
    if($supplierid){
1253
0
        $query .= "AND aqbasket.booksellerid = ?";
1254
0
        push @args, $supplierid;
1255    }
1256
0
    if($basket){
1257
0
        $query .= "AND aqorders.basketno = ?";
1258
0
        push @args, $basket;
1259    }
1260
1261
0
    my $sth = $dbh->prepare($query);
1262
0
    $sth->execute(@args);
1263
0
    my $results = $sth->fetchall_arrayref({});
1264
0
    $sth->finish;
1265
0
    return $results;
1266}
1267
1268#------------------------------------------------------------#
1269
1270 - 1278
=head3 DelOrder

  &DelOrder($biblionumber, $ordernumber);

Cancel the order with the given order and biblio numbers. It does not
delete any entries in the aqorders table, it merely marks them as
cancelled.

=cut
1279
1280sub DelOrder {
1281
0
    my ( $bibnum, $ordernumber ) = @_;
1282
0
    my $dbh = C4::Context->dbh;
1283
0
    my $query = "
1284        UPDATE aqorders
1285        SET datecancellationprinted=now()
1286        WHERE biblionumber=? AND ordernumber=?
1287    ";
1288
0
    my $sth = $dbh->prepare($query);
1289
0
    $sth->execute( $bibnum, $ordernumber );
1290
0
    $sth->finish;
1291
0
    my @itemnumbers = GetItemnumbersFromOrder( $ordernumber );
1292
0
    foreach my $itemnumber (@itemnumbers){
1293
0
     C4::Items::DelItem( $dbh, $bibnum, $itemnumber );
1294    }
1295
1296}
1297
1298 - 1300
=head2 FUNCTIONS ABOUT PARCELS

=cut
1301
1302#------------------------------------------------------------#
1303
1304 - 1316
=head3 GetParcel

  @results = &GetParcel($booksellerid, $code, $date);

Looks up all of the received items from the supplier with the given
bookseller ID at the given date, for the given code (bookseller Invoice number). Ignores cancelled and completed orders.

C<@results> is an array of references-to-hash. The keys of each element are fields from
the aqorders, biblio, and biblioitems tables of the Koha database.

C<@results> is sorted alphabetically by book title.

=cut
1317
1318sub GetParcel {
1319    #gets all orders from a certain supplier, orders them alphabetically
1320
0
    my ( $supplierid, $code, $datereceived ) = @_;
1321
0
    my $dbh = C4::Context->dbh;
1322
0
    my @results = ();
1323
0
    $code .= '%'
1324    if $code; # add % if we search on a given code (otherwise, let him empty)
1325
0
    my $strsth ="
1326        SELECT authorisedby,
1327                creationdate,
1328                aqbasket.basketno,
1329                closedate,surname,
1330                firstname,
1331                aqorders.biblionumber,
1332                aqorders.ordernumber,
1333                aqorders.quantity,
1334                aqorders.quantityreceived,
1335                aqorders.unitprice,
1336                aqorders.listprice,
1337                aqorders.rrp,
1338                aqorders.ecost,
1339                biblio.title
1340        FROM aqorders
1341        LEFT JOIN aqbasket ON aqbasket.basketno=aqorders.basketno
1342        LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber
1343        LEFT JOIN biblio ON aqorders.biblionumber=biblio.biblionumber
1344        WHERE
1345            aqbasket.booksellerid = ?
1346            AND aqorders.booksellerinvoicenumber LIKE ?
1347            AND aqorders.datereceived = ? ";
1348
1349
0
    my @query_params = ( $supplierid, $code, $datereceived );
1350
0
    if ( C4::Context->preference("IndependantBranches") ) {
1351
0
        my $userenv = C4::Context->userenv;
1352
0
        if ( ($userenv) && ( $userenv->{flags} != 1 ) ) {
1353
0
            $strsth .= " and (borrowers.branchcode = ?
1354                        or borrowers.branchcode = '')";
1355
0
            push @query_params, $userenv->{branch};
1356        }
1357    }
1358
0
    $strsth .= " ORDER BY aqbasket.basketno";
1359    # ## parcelinformation : $strsth
1360
0
    my $sth = $dbh->prepare($strsth);
1361
0
    $sth->execute( @query_params );
1362
0
    while ( my $data = $sth->fetchrow_hashref ) {
1363
0
        push( @results, $data );
1364    }
1365    # ## countparcelbiblio: scalar(@results)
1366
0
    $sth->finish;
1367
1368
0
    return @results;
1369}
1370
1371#------------------------------------------------------------#
1372
1373 - 1412
=head3 GetParcels

  $results = &GetParcels($bookseller, $order, $code, $datefrom, $dateto);

get a lists of parcels.

* Input arg :

=over

=item $bookseller
is the bookseller this function has to get parcels.

=item $order
To know on what criteria the results list has to be ordered.

=item $code
is the booksellerinvoicenumber.

=item $datefrom & $dateto
to know on what date this function has to filter its search.

=back

* return:
a pointer on a hash list containing parcel informations as such :

=over

=item Creation date

=item Last operation

=item Number of biblio

=item Number of items

=back

=cut
1413
1414sub GetParcels {
1415
0
    my ($bookseller,$order, $code, $datefrom, $dateto) = @_;
1416
0
    my $dbh = C4::Context->dbh;
1417
0
    my @query_params = ();
1418
0
    my $strsth ="
1419        SELECT aqorders.booksellerinvoicenumber,
1420                datereceived,purchaseordernumber,
1421                count(DISTINCT biblionumber) AS biblio,
1422                sum(quantity) AS itemsexpected,
1423                sum(quantityreceived) AS itemsreceived
1424        FROM aqorders LEFT JOIN aqbasket ON aqbasket.basketno = aqorders.basketno
1425        WHERE aqbasket.booksellerid = ? and datereceived IS NOT NULL
1426    ";
1427
0
    push @query_params, $bookseller;
1428
1429
0
    if ( defined $code ) {
1430
0
        $strsth .= ' and aqorders.booksellerinvoicenumber like ? ';
1431        # add a % to the end of the code to allow stemming.
1432
0
        push @query_params, "$code%";
1433    }
1434
1435
0
    if ( defined $datefrom ) {
1436
0
        $strsth .= ' and datereceived >= ? ';
1437
0
        push @query_params, $datefrom;
1438    }
1439
1440
0
    if ( defined $dateto ) {
1441
0
        $strsth .= 'and datereceived <= ? ';
1442
0
        push @query_params, $dateto;
1443    }
1444
1445
0
    $strsth .= "group by aqorders.booksellerinvoicenumber,datereceived ";
1446
1447    # can't use a placeholder to place this column name.
1448    # but, we could probably be checking to make sure it is a column that will be fetched.
1449
0
    $strsth .= "order by $order " if ($order);
1450
1451
0
    my $sth = $dbh->prepare($strsth);
1452
1453
0
    $sth->execute( @query_params );
1454
0
    my $results = $sth->fetchall_arrayref({});
1455
0
    $sth->finish;
1456
0
    return @$results;
1457}
1458
1459#------------------------------------------------------------#
1460
1461 - 1470
=head3 GetLateOrders

  @results = &GetLateOrders;

Searches for bookseller with late orders.

return:
the table of supplier with late issues. This table is full of hashref.

=cut
1471
1472sub GetLateOrders {
1473
0
    my $delay = shift;
1474
0
    my $supplierid = shift;
1475
0
    my $branch = shift;
1476
1477
0
    my $dbh = C4::Context->dbh;
1478
1479    #BEWARE, order of parenthesis and LEFT JOIN is important for speed
1480
0
    my $dbdriver = C4::Context->config("db_scheme") || "mysql";
1481
1482
0
    my @query_params = ($delay); # delay is the first argument regardless
1483
0
    my $select = "
1484    SELECT aqbasket.basketno,
1485        aqorders.ordernumber,
1486        DATE(aqbasket.closedate) AS orderdate,
1487        aqorders.rrp AS unitpricesupplier,
1488        aqorders.ecost AS unitpricelib,
1489        aqorders.claims_count AS claims_count,
1490        aqorders.claimed_date AS claimed_date,
1491        aqbudgets.budget_name AS budget,
1492        borrowers.branchcode AS branch,
1493        aqbooksellers.name AS supplier,
1494        aqbooksellers.id AS supplierid,
1495        biblio.author, biblio.title,
1496        biblioitems.publishercode AS publisher,
1497        biblioitems.publicationyear,
1498    ";
1499
0
    my $from = "
1500    FROM
1501        aqorders LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber
1502        LEFT JOIN biblioitems ON biblioitems.biblionumber = biblio.biblionumber
1503        LEFT JOIN aqbudgets ON aqorders.budget_id = aqbudgets.budget_id,
1504        aqbasket LEFT JOIN borrowers ON aqbasket.authorisedby = borrowers.borrowernumber
1505        LEFT JOIN aqbooksellers ON aqbasket.booksellerid = aqbooksellers.id
1506        WHERE aqorders.basketno = aqbasket.basketno
1507        AND ( datereceived = ''
1508            OR datereceived IS NULL
1509            OR aqorders.quantityreceived < aqorders.quantity
1510        )
1511        AND (aqorders.datecancellationprinted IS NULL OR aqorders.datecancellationprinted='0000-00-00')
1512    ";
1513
0
    my $having = "";
1514
0
    if ($dbdriver eq "mysql") {
1515
0
        $select .= "
1516        aqorders.quantity - IFNULL(aqorders.quantityreceived,0) AS quantity,
1517        (aqorders.quantity - IFNULL(aqorders.quantityreceived,0)) * aqorders.rrp AS subtotal,
1518        DATEDIFF(CURDATE( ),closedate) AS latesince
1519        ";
1520
0
        $from .= " AND (closedate <= DATE_SUB(CURDATE( ),INTERVAL ? DAY)) ";
1521
0
        $having = "
1522        HAVING quantity <> 0
1523            AND unitpricesupplier <> 0
1524            AND unitpricelib <> 0
1525        ";
1526    } else {
1527        # FIXME: account for IFNULL as above
1528
0
        $select .= "
1529                aqorders.quantity AS quantity,
1530                aqorders.quantity * aqorders.rrp AS subtotal,
1531                (CURDATE - closedate) AS latesince
1532        ";
1533
0
        $from .= " AND (closedate <= (CURDATE -(INTERVAL ? DAY)) ";
1534    }
1535
0
    if (defined $supplierid) {
1536
0
        $from .= ' AND aqbasket.booksellerid = ? ';
1537
0
        push @query_params, $supplierid;
1538    }
1539
0
    if (defined $branch) {
1540
0
        $from .= ' AND borrowers.branchcode LIKE ? ';
1541
0
        push @query_params, $branch;
1542    }
1543
0
    if (C4::Context->preference("IndependantBranches")
1544            && C4::Context->userenv
1545            && C4::Context->userenv->{flags} != 1 ) {
1546
0
        $from .= ' AND borrowers.branchcode LIKE ? ';
1547
0
        push @query_params, C4::Context->userenv->{branch};
1548    }
1549
0
    my $query = "$select $from $having\nORDER BY latesince, basketno, borrowers.branchcode, supplier";
1550
0
    $debug and print STDERR "GetLateOrders query: $query\nGetLateOrders args: " . join(" ",@query_params);
1551
0
    my $sth = $dbh->prepare($query);
1552
0
    $sth->execute(@query_params);
1553
0
    my @results;
1554
0
    while (my $data = $sth->fetchrow_hashref) {
1555
0
        $data->{orderdate} = format_date($data->{orderdate});
1556
0
        $data->{claimed_date} = format_date($data->{claimed_date});
1557
0
        push @results, $data;
1558    }
1559
0
    return @results;
1560}
1561
1562#------------------------------------------------------------#
1563
1564 - 1601
=head3 GetHistory

  (\@order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( %params );

Retreives some acquisition history information

params:  
  title
  author
  name
  from_placed_on
  to_placed_on
  basket                  - search both basket name and number
  booksellerinvoicenumber 

returns:
    $order_loop is a list of hashrefs that each look like this:
            {
                'author'           => 'Twain, Mark',
                'basketno'         => '1',
                'biblionumber'     => '215',
                'count'            => 1,
                'creationdate'     => 'MM/DD/YYYY',
                'datereceived'     => undef,
                'ecost'            => '1.00',
                'id'               => '1',
                'invoicenumber'    => undef,
                'name'             => '',
                'ordernumber'      => '1',
                'quantity'         => 1,
                'quantityreceived' => undef,
                'title'            => 'The Adventures of Huckleberry Finn'
            }
    $total_qty is the sum of all of the quantities in $order_loop
    $total_price is the cost of each in $order_loop times the quantity
    $total_qtyreceived is the sum of all of the quantityreceived entries in $order_loop

=cut
1602
1603sub GetHistory {
1604# don't run the query if there are no parameters (list would be too long for sure !)
1605
0
    croak "No search params" unless @_;
1606
0
    my %params = @_;
1607
0
    my $title = $params{title};
1608
0
    my $author = $params{author};
1609
0
    my $isbn = $params{isbn};
1610
0
    my $name = $params{name};
1611
0
    my $from_placed_on = $params{from_placed_on};
1612
0
    my $to_placed_on = $params{to_placed_on};
1613
0
    my $basket = $params{basket};
1614
0
    my $booksellerinvoicenumber = $params{booksellerinvoicenumber};
1615
1616
0
    my @order_loop;
1617
0
    my $total_qty = 0;
1618
0
    my $total_qtyreceived = 0;
1619
0
    my $total_price = 0;
1620
1621
0
    my $dbh = C4::Context->dbh;
1622
0
    my $query ="
1623        SELECT
1624            biblio.title,
1625            biblio.author,
1626            biblioitems.isbn,
1627            aqorders.basketno,
1628    aqbasket.basketname,
1629    aqbasket.basketgroupid,
1630    aqbasketgroups.name as groupname,
1631            aqbooksellers.name,
1632    aqbasket.creationdate,
1633            aqorders.datereceived,
1634            aqorders.quantity,
1635            aqorders.quantityreceived,
1636            aqorders.ecost,
1637            aqorders.ordernumber,
1638            aqorders.booksellerinvoicenumber as invoicenumber,
1639            aqbooksellers.id as id,
1640            aqorders.biblionumber
1641        FROM aqorders
1642        LEFT JOIN aqbasket ON aqorders.basketno=aqbasket.basketno
1643    LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid=aqbasketgroups.id
1644        LEFT JOIN aqbooksellers ON aqbasket.booksellerid=aqbooksellers.id
1645        LEFT JOIN biblioitems ON biblioitems.biblionumber=aqorders.biblionumber
1646        LEFT JOIN biblio ON biblio.biblionumber=aqorders.biblionumber";
1647
1648
0
    $query .= " LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber"
1649    if ( C4::Context->preference("IndependantBranches") );
1650
1651
0
    $query .= " WHERE (datecancellationprinted is NULL or datecancellationprinted='0000-00-00') ";
1652
1653
0
    my @query_params = ();
1654
1655
0
    if ( $title ) {
1656
0
        $query .= " AND biblio.title LIKE ? ";
1657
0
        $title =~ s/\s+/%/g;
1658
0
        push @query_params, "%$title%";
1659    }
1660
1661
0
    if ( $author ) {
1662
0
        $query .= " AND biblio.author LIKE ? ";
1663
0
        push @query_params, "%$author%";
1664    }
1665
1666
0
    if ( $isbn ) {
1667
0
        $query .= " AND biblioitems.isbn LIKE ? ";
1668
0
        push @query_params, "%$isbn%";
1669    }
1670
1671
0
    if ( $name ) {
1672
0
        $query .= " AND aqbooksellers.name LIKE ? ";
1673
0
        push @query_params, "%$name%";
1674    }
1675
1676
0
    if ( $from_placed_on ) {
1677
0
        $query .= " AND creationdate >= ? ";
1678
0
        push @query_params, $from_placed_on;
1679    }
1680
1681
0
    if ( $to_placed_on ) {
1682
0
        $query .= " AND creationdate <= ? ";
1683
0
        push @query_params, $to_placed_on;
1684    }
1685
1686
0
    if ($basket) {
1687
0
        if ($basket =~ m/^\d+$/) {
1688
0
            $query .= " AND aqorders.basketno = ? ";
1689
0
            push @query_params, $basket;
1690        } else {
1691
0
            $query .= " AND aqbasket.basketname LIKE ? ";
1692
0
            push @query_params, "%$basket%";
1693        }
1694    }
1695
1696
0
    if ($booksellerinvoicenumber) {
1697
0
        $query .= " AND (aqorders.booksellerinvoicenumber LIKE ? OR aqbasket.booksellerinvoicenumber LIKE ?)";
1698
0
        push @query_params, "%$booksellerinvoicenumber%", "%$booksellerinvoicenumber%";
1699    }
1700
1701
0
    if ( C4::Context->preference("IndependantBranches") ) {
1702
0
        my $userenv = C4::Context->userenv;
1703
0
        if ( $userenv && ($userenv->{flags} || 0) != 1 ) {
1704
0
            $query .= " AND (borrowers.branchcode = ? OR borrowers.branchcode ='' ) ";
1705
0
            push @query_params, $userenv->{branch};
1706        }
1707    }
1708
0
    $query .= " ORDER BY id";
1709
0
    my $sth = $dbh->prepare($query);
1710
0
    $sth->execute( @query_params );
1711
0
    my $cnt = 1;
1712
0
    while ( my $line = $sth->fetchrow_hashref ) {
1713
0
        $line->{count} = $cnt++;
1714
0
        $line->{toggle} = 1 if $cnt % 2;
1715
0
        push @order_loop, $line;
1716
0
        $total_qty += $line->{'quantity'};
1717
0
        $total_qtyreceived += $line->{'quantityreceived'};
1718
0
        $total_price += $line->{'quantity'} * $line->{'ecost'};
1719    }
1720
0
    return \@order_loop, $total_qty, $total_price, $total_qtyreceived;
1721}
1722
1723 - 1729
=head2 GetRecentAcqui

  $results = GetRecentAcqui($days);

C<$results> is a ref to a table which containts hashref

=cut
1730
1731sub GetRecentAcqui {
1732
0
    my $limit = shift;
1733
0
    my $dbh = C4::Context->dbh;
1734
0
    my $query = "
1735        SELECT *
1736        FROM biblio
1737        ORDER BY timestamp DESC
1738        LIMIT 0,".$limit;
1739
1740
0
    my $sth = $dbh->prepare($query);
1741
0
    $sth->execute;
1742
0
    my $results = $sth->fetchall_arrayref({});
1743
0
    return $results;
1744}
1745
1746 - 1762
=head3 GetContracts

  $contractlist = &GetContracts($booksellerid, $activeonly);

Looks up the contracts that belong to a bookseller

Returns a list of contracts

=over

=item C<$booksellerid> is the "id" field in the "aqbooksellers" table.

=item C<$activeonly> if exists get only contracts that are still active.

=back

=cut
1763
1764sub GetContracts {
1765
0
    my ( $booksellerid, $activeonly ) = @_;
1766
0
    my $dbh = C4::Context->dbh;
1767
0
    my $query;
1768
0
    if (! $activeonly) {
1769
0
        $query = "
1770            SELECT *
1771            FROM aqcontract
1772            WHERE booksellerid=?
1773        ";
1774    } else {
1775
0
        $query = "SELECT *
1776            FROM aqcontract
1777            WHERE booksellerid=?
1778                AND contractenddate >= CURDATE( )";
1779    }
1780
0
    my $sth = $dbh->prepare($query);
1781
0
    $sth->execute( $booksellerid );
1782
0
    my @results;
1783
0
    while (my $data = $sth->fetchrow_hashref ) {
1784
0
        push(@results, $data);
1785    }
1786
0
    $sth->finish;
1787
0
    return @results;
1788}
1789
1790#------------------------------------------------------------#
1791
1792 - 1800
=head3 GetContract

  $contract = &GetContract($contractID);

Looks up the contract that has PRIMKEY (contractnumber) value $contractID

Returns a contract

=cut
1801
1802sub GetContract {
1803
0
    my ( $contractno ) = @_;
1804
0
    my $dbh = C4::Context->dbh;
1805
0
    my $query = "
1806        SELECT *
1807        FROM aqcontract
1808        WHERE contractnumber=?
1809        ";
1810
1811
0
    my $sth = $dbh->prepare($query);
1812
0
    $sth->execute( $contractno );
1813
0
    my $result = $sth->fetchrow_hashref;
1814
0
    return $result;
1815}
1816
1817 - 1827
=head3 AddClaim

=over 4

&AddClaim($ordernumber);

Add a claim for an order

=back

=cut
1828sub AddClaim {
1829
0
    my ($ordernumber) = @_;
1830
0
    my $dbh = C4::Context->dbh;
1831
0
    my $query = "
1832        UPDATE aqorders SET
1833            claims_count = claims_count + 1,
1834            claimed_date = CURDATE()
1835        WHERE ordernumber = ?
1836        ";
1837
0
    my $sth = $dbh->prepare($query);
1838
0
    $sth->execute($ordernumber);
1839
1840}
1841
18421;