Adds a cron script to be run periodically that populates
[koha.git] / misc / cronjobs / holds / build_holds_queue.pl
1 #!/usr/bin/perl 
2 #-----------------------------------
3 # Script Name: build_holds_queue.pl
4 # Description: builds a holds queue in the tmp_holdsqueue table
5 #-----------------------------------
6
7 use strict;
8 BEGIN {
9     # find Koha's Perl modules
10     # test carefully before changing this
11     use FindBin;
12     eval { require "$FindBin::Bin/../kohalib.pl" };
13 }
14
15 use C4::Context;
16 use C4::Search;
17 use C4::Items;
18 use C4::Branch;
19
20 # load the branches
21 my $branches = GetBranches();
22
23 # obtain the ranked list of weights for the case of static weighting
24 my $syspref = C4::Context->preference("StaticHoldsQueueWeight");
25 my @branch_loop;
26 @branch_loop = split(/,/, $syspref) if $syspref;
27
28 # TODO: Add Randomization Option
29
30 # If no syspref is set, use system-order to determine priority
31 unless ($syspref) {
32         for my $branch_hash (sort keys %$branches) {
33         push @branch_loop, {value => "$branch_hash" , branchname => $branches->{$branch_hash}->{'branchname'}, };
34         }
35 }
36
37 # if Randomization is enabled, randomize this array
38 @branch_loop = randarray(@branch_loop) if  C4::Context->preference("RandomizeHoldsQueueWeight");;
39
40 my ($biblionumber,$itemnumber,$barcode,$holdingbranch,$pickbranch,$notes,$cardnumber,$surname,$firstname,$phone,$title,$callno,$rdate,$borrno);
41
42 my $dbh   = C4::Context->dbh;
43
44 $dbh->do("DELETE FROM tmp_holdsqueue");  # clear the old table for new info
45
46 my $sth=$dbh->prepare("
47 SELECT biblionumber,itemnumber,reserves.branchcode,reservenotes,borrowers.borrowernumber,cardnumber,surname,firstname,phone,reservedate
48     FROM reserves,borrowers 
49 WHERE reserves.found IS NULL 
50     AND reserves.borrowernumber=borrowers.borrowernumber 
51     AND priority=1 
52     AND cancellationdate IS NULL 
53 GROUP BY biblionumber");
54
55 my $sth_load=$dbh->prepare("
56 INSERT INTO tmp_holdsqueue (biblionumber,itemnumber,barcode,surname,firstname,phone,borrowernumber,cardnumber,reservedate,title,itemcallnumber,holdingbranch,pickbranch,notes)
57     VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
58
59 $sth->execute();      # get the list of biblionumbers for unfilled holds
60
61 GETIT: 
62 while (my $data=$sth->fetchrow_hashref){
63     # get the basic hold info
64     $biblionumber = $data->{'biblionumber'};
65     $pickbranch = $data->{'branchcode'};
66     $notes = $data->{'reservenotes'};
67     $borrno = $data->{'borrowernumber'};
68     $cardnumber = $data->{'cardnumber'};
69     $surname = $data->{'surname'};
70     $firstname = $data->{'firstname'};
71     $phone = $data->{'phone'};
72     $rdate = $data->{'reservedate'};
73
74     my @items = GetItemsInfo($biblionumber,''); # get the items for this biblio
75     my @itemorder;   #  prepare a new array to hold re-ordered items
76         
77     # Make sure someone(else) doesn't already have this item waiting for them
78     my $found_sth = $dbh->prepare("
79         SELECT found FROM reserves WHERE itemnumber=? AND found = ? AND cancellationdate IS NULL");
80         
81     # The following lines take the retrieved items and run them through various
82     # tests to decide if they are to be used and then put them in the preferred
83     # 'pick' order.
84     foreach my $itm (@items) {
85
86         $found_sth->execute($itm->{itemnumber},"W");
87         my $found = $found_sth->fetchrow_hashref();
88         if ($found) {
89             $itm->{"found"} = $found->{"found"};
90         }
91         if ($itm->{"notforloan"}) {
92                         # item is on order
93             next if $itm->{"notforloan"}== -1;
94         }
95         if ( ( (!$itm->{"binding"}) || 
96                 # Item is at not at bindery, not checked out, and not lost
97                 ($itm->{"binding"}<1)) && (!$itm->{"found"}) && (!$itm->{"datedue"}) && ( (!$itm->{"itemlost"}) || 
98
99                 # Item is not lost and not notforloan
100                 ($itm->{"itemlost"}==0) ) && ( ($itm->{"notforloan"}==0) || 
101
102                 # Item is not notforloan
103                 (!$itm->{"notforloan"}) ) ) {
104
105             warn "patron requested pickup at $pickbranch for item in ".$itm->{'holdingbranch'};
106
107                         # This selects items for fulfilment, and weights them based on
108                         # a static list
109                         my $weight=0;
110                         # always prefer a direct match
111             if ($itm->{'holdingbranch'} eq $pickbranch) {
112                                 warn "Found match in pickuplibrary";
113                 $itemorder[$weight]=$itm;
114             } 
115                         else {
116                                 for my $branchcode (@branch_loop) {
117                                         $weight++;
118                                         if ($itm->{'homebranch'} eq $branchcode) {
119                                                 warn "Match found with weight $weight in ".$branchcode;
120                                 $itemorder[$weight]=$itm;
121                                         }
122                                 }
123             }
124         }
125     }
126     my $count = @itemorder;
127         warn "Empty array" if $count<1;
128     next GETIT if $count<1;  # if the re-ordered array is empty, skip to next
129
130     PREP: 
131     foreach my $itmlist (@itemorder) {
132         if ($itmlist) {
133             $barcode = $itmlist->{'barcode'};
134                         $itemnumber = $itmlist->{'itemnumber'};
135             $holdingbranch = $itmlist->{'holdingbranch'};
136             $title = $itmlist->{'title'};
137             $callno = $itmlist->{'itemcallnumber'};
138             last PREP;    # we only want the first def item in the array
139         }
140     }
141     $sth_load->execute($biblionumber,$itemnumber,$barcode,$surname,$firstname,$phone,$borrno,$cardnumber,$rdate,$title,$callno,$holdingbranch,$pickbranch,$notes);
142     $sth_load->finish;
143 }
144 $sth->finish;
145 $dbh->disconnect;
146
147 sub randarray {
148         my @array = @_;
149         my @rand = undef;
150         my $seed = $#array + 1;
151         my $randnum = int(rand($seed));
152         $rand[$randnum] = shift(@array);
153         while (1) {
154                 my $randnum = int(rand($seed));
155                 if ($rand[$randnum] eq undef) {
156                         $rand[$randnum] = shift(@array);
157                 }
158                 last if ($#array == -1);
159         }
160         return @rand;
161 }
162
163
164 print "finished\n";