Added magic RCS string.
[koha.git] / C4 / Circulation / Borrower.pm
1 package C4::Circulation::Borrower; #assumes C4/Circulation/Borrower
2
3 #package to deal with Issues
4 #written 3/11/99 by chris@katipo.co.nz
5
6
7 # Copyright 2000-2002 Katipo Communications
8 #
9 # This file is part of Koha.
10 #
11 # Koha is free software; you can redistribute it and/or modify it under the
12 # terms of the GNU General Public License as published by the Free Software
13 # Foundation; either version 2 of the License, or (at your option) any later
14 # version.
15 #
16 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
17 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
19 #
20 # You should have received a copy of the GNU General Public License along with
21 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
22 # Suite 330, Boston, MA  02111-1307 USA
23
24 # FIXME - This module is never used. Obsolete?
25
26 use strict;
27 require Exporter;
28 use DBI;
29 use C4::Context;
30 use C4::Accounts;
31 use C4::InterfaceCDK;
32 use C4::Interface::FlagsCDK;
33 use C4::Circulation::Main;
34         # FIXME - C4::Circulation::Main and C4::Circulation::Borrower
35         # use each other, so functions get redefined.
36 use C4::Circulation::Issues;
37         # FIXME - C4::Circulation::Issues and C4::Circulation::Borrower
38         # use each other, so functions get redefined.
39 use C4::Circulation::Renewals;
40 use C4::Scan;
41 use C4::Search;
42 use C4::Stats;
43 use C4::Format;
44 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
45   
46 # set the version for version checking
47 $VERSION = 0.01;
48     
49 @ISA = qw(Exporter);
50 @EXPORT = qw(&findborrower &Borenq &findoneborrower &NewBorrowerNumber
51 &findguarantees);
52 %EXPORT_TAGS = ( );     # eg: TAG => [ qw!name1 name2! ],
53                   
54 # your exported package globals go here,
55 # as well as any optionally exported functions
56
57 @EXPORT_OK   = qw($Var1 %Hashit);
58
59
60 # non-exported package globals go here
61 use vars qw(@more $stuff);
62         
63 # initalize package globals, first exported ones
64
65 my $Var1   = '';
66 my %Hashit = ();
67                     
68 # then the others (which are still accessible as $Some::Module::stuff)
69 my $stuff  = '';
70 my @more   = ();
71         
72 # all file-scoped lexicals must be created before
73 # the functions below that use them.
74                 
75 # file-private lexicals go here
76 my $priv_var    = '';
77 my %secret_hash = ();
78                             
79 # here's a file-private function as a closure,
80 # callable as &$priv_func;  it cannot be prototyped.
81 my $priv_func = sub {
82   # stuff goes here.
83 };
84                                                     
85 # make all your functions, whether exported or not;
86
87
88 sub findborrower  {
89   my ($env,$dbh) = @_;
90   C4::InterfaceCDK::helptext('');       # FIXME - This looks useless
91   C4::InterfaceCDK::clearscreen();
92   my $bornum = "";
93   my $sth = "";
94   my $borcode = "";
95   my $borrower;
96   my $reason = "";
97   my $book;
98   while (($bornum eq '') && ($reason eq "")) {
99     #get borrowerbarcode from scanner
100     my $title = C4::InterfaceCDK::titlepanel($env,$env->{'sysarea'},"Borrower Entry");
101     if ($env->{'newborrower'} eq "") {
102       ($borcode,$reason,$book)=&C4::Circulation::Main::scanborrower($env); 
103     } else { 
104       $borcode = $env->{'newborrower'};
105       $reason = "";
106       $book = "";
107       $env->{'newborrower'}= "";
108     }  
109     #C4::Circulation::Main
110     if ($reason eq "") {
111       if ($borcode ne '') {
112         ($bornum,$borrower) = findoneborrower($env,$dbh,$borcode);
113         $env->{'IssuesAllowed'} = 1;
114       } elsif ($book ne "") {
115         my $query = "select * from issues,items where (barcode = '$book') 
116           and (items.itemnumber = issues.itemnumber) 
117           and (issues.returndate is null)";
118         my $iss_sth=$dbh->prepare($query);
119         $iss_sth->execute;
120         if (my $issdata  = $iss_sth->fetchrow_hashref) {
121            $bornum=$issdata->{'borrowernumber'};
122            $sth = $dbh->prepare("Select * from borrowers 
123              where borrowernumber =  '$bornum'");
124            $sth->execute;
125            $borrower=$sth->fetchrow_hashref;
126            $sth->finish;  
127          } else {
128            error_msg($env,"Item $book not found");
129          } 
130          $iss_sth->finish;
131       }
132     } 
133   } 
134   my ($issuesallowed,$owing);
135   if ($reason eq "") {
136     $env->{'bornum'} = $bornum;
137     $env->{'bcard'} = $borrower->{'cardnumber'};
138     my $borrowers=join(' ',($borrower->{'title'},$borrower->{'firstname'},$borrower->{'surname'}));
139     my $odues;
140     ($issuesallowed,$odues,$owing) = &checktraps($env,$dbh,$bornum,$borrower);
141 #    error_msg ($env,"bcard =  $env->{'bcard'}");
142   }
143   #debug_msg ($env,"2 =  $env->{'IssuesAllowed'}");
144   return ($bornum, $issuesallowed,$borrower,$reason,$owing);
145 };
146
147
148 sub findoneborrower {
149   #  output(1,1,$borcode);
150   my ($env,$dbh,$borcode)=@_;
151   my $bornum;
152   my $borrower;
153   my $ucborcode = uc $borcode;
154   my $lcborcode = lc $borcode;
155   my $sth=$dbh->prepare("Select * from borrowers where cardnumber=\"$ucborcode\"");
156   $sth->execute;
157   if ($borrower=$sth->fetchrow_hashref) {
158     $bornum=$borrower->{'borrowernumber'};
159     $sth->finish;
160   } else {
161     $sth->finish;
162     # my $borquery = "Select * from borrowers
163     # where surname ~* '$borcode' order by surname";
164               
165     my $borquery = "Select * from borrowers 
166       where lower(surname) like \"$lcborcode%\" order by surname,firstname";
167     my $sthb =$dbh->prepare($borquery);
168     $sthb->execute;
169     my $cntbor = 0;
170     my @borrows;
171     my @bornums;
172     while ($borrower= $sthb->fetchrow_hashref) {
173       my $line = $borrower->{'cardnumber'}.' '.$borrower->{'categorycode'}.' '.$borrower->{'surname'}.
174         ', '.$borrower->{'othernames'};
175       $borrows[$cntbor] = fmtstr($env,$line,"L50");
176       $bornums[$cntbor] =$borrower->{'borrowernumber'};
177       $cntbor++;
178     }
179     if ($cntbor == 1)  {
180       $bornum = $bornums[0];       
181       my $query = "select * from borrowers where borrowernumber = '$bornum'";      
182       $sth = $dbh->prepare($query);
183       $sth->execute;
184       $borrower =$sth->fetchrow_hashref;
185       $sth->finish;                                              
186     } elsif ($cntbor > 0) {
187       my ($cardnum) = C4::InterfaceCDK::selborrower($env,$dbh,\@borrows,\@bornums);
188       my $query = "select * from borrowers where cardnumber = '$cardnum'";   
189       $sth = $dbh->prepare($query);                          
190       $sth->execute;                          
191       $borrower =$sth->fetchrow_hashref;
192       $sth->finish;
193       $bornum=$borrower->{'borrowernumber'};
194       #C4::InterfaceCDK::clearscreen();
195       if ($bornum eq '') {
196         error_msg($env,"Borrower not found");
197       }
198     }  
199   }
200   return ($bornum,$borrower); 
201 }
202 sub checktraps {
203   my ($env,$dbh,$bornum,$borrower) = @_;
204   my $issuesallowed = "1";
205   #my @traps_set;
206   #check amountowing
207   my $traps_done; 
208   my $odues;
209   my $amount;
210   while ($traps_done ne "DONE") {
211     my @traps_set;
212     $amount=C4::Accounts::checkaccount($env,$bornum,$dbh);    #from C4::Accounts
213     if ($amount > 0) { push (@traps_set,"CHARGES");}  
214     if ($borrower->{'gonenoaddress'} == 1){ push (@traps_set,"GNA");}
215     #check if member has a card reported as lost
216     if ($borrower->{'lost'} ==1){push (@traps_set,"LOST");}
217     #check the notes field if notes exist display them
218     if ($borrower->{'borrowernotes'} ne ''){ push (@traps_set,"NOTES");}
219     #check if borrower has overdue items
220     #call overdue checker
221     my $odues = &C4::Circulation::Main::checkoverdues($env,$bornum,$dbh);
222     if ($odues > 0) {push (@traps_set,"ODUES");}  
223     #check if borrower has any items waiting
224     my ($nowaiting,$itemswaiting) = &C4::Circulation::Main::checkwaiting($env,$dbh,$bornum);
225     if ($nowaiting > 0) { push (@traps_set,"WAITING"); } 
226     # FIXME - This should be $traps_set[0], right?
227     if (@traps_set[0] ne "" ) {
228       ($issuesallowed,$traps_done,$amount,$odues) = 
229          process_traps($env,$dbh,$bornum,$borrower,
230          $amount,$odues,\@traps_set,$itemswaiting);
231     } else {
232       $traps_done = "DONE";
233     }   
234   }
235   return ($issuesallowed, $odues,$amount);
236 }
237
238 sub process_traps {
239   my ($env,$dbh,$bornum,$borrower,$amount,$odues,$traps_set,$waiting) = @_;
240   my $issuesallowed = 1;
241   my $x = 0;
242   my %traps;
243   while (@$traps_set[$x] ne "") {
244     $traps{@$traps_set[$x]} = 1; 
245     $x++;
246   }
247   my $traps_done;
248   my $trapact;
249   my $issues;
250   while ($trapact ne "NONE") {
251     $trapact = &trapscreen($env,$bornum,$borrower,$amount,$traps_set);
252     if ($trapact eq "CHARGES") {
253       C4::Accounts::reconcileaccount($env,$dbh,$bornum,$amount,$borrower,$odues);
254       ($odues,$issues,$amount)=borrdata2($env,$bornum);          
255       if ($amount <= 0) {
256         $traps{'CHARGES'} = 0;
257         my @newtraps;
258         $x =0;
259         while ($traps_set->[$x] ne "") {
260           if ($traps_set->[$x] ne "CHARGES") {
261             push @newtraps,$traps_set->[$x];
262           }
263           $x++;
264         }
265         $traps_set = \@newtraps;
266       }
267     } elsif ($trapact eq "WAITING") {
268       reserveslist($env,$borrower,$amount,$odues,$waiting);
269     } elsif ($trapact eq "ODUES") {
270       C4::Circulation::Renewals::bulkrenew($env,$dbh,$bornum,$amount,$borrower,$odues);
271       ($odues,$issues,$amount)=borrdata2($env,$bornum);
272       if ($odues == 0) {
273         $traps{'ODUES'} = 0;
274         my @newtraps;
275         $x =0;
276         while ($traps_set->[$x] ne "") {
277           if ($traps_set->[$x] ne "ODUES") {
278             push @newtraps,$traps_set->[$x];
279           }
280           $x++;
281         }
282         $traps_set = \@newtraps;
283       }
284     } elsif  ($trapact eq "NOTES") {
285       my $notes = trapsnotes($env,$bornum,$borrower,$amount);
286       if ($notes ne $borrower->{'borrowernotes'}) { 
287         my $query = "update borrowers set borrowernotes = '$notes' 
288            where borrowernumber = $bornum";
289         my $sth = $dbh->prepare($query);
290         $sth->execute();
291         $sth->finish();
292         $borrower->{'borrowernotes'} = $notes;
293       }
294       if ($notes eq "") {
295         $traps{'NOTES'} = 0;
296         my @newtraps;
297         $x =0;
298         while ($traps_set->[$x] ne "") {
299           if ($traps_set->[$x] ne "NOTES") {
300             push @newtraps,$traps_set->[$x];
301           }
302           $x++;
303         }                 
304         $traps_set = \@newtraps;                                                     
305       }
306     }
307     my $notr = @$traps_set;
308     if ($notr == 0) {
309       $trapact = "NONE";
310     }
311     $traps_done = "DONE";
312   }
313   if ($traps{'GNA'} eq 1 ) {
314     $issuesallowed=0;
315     $env->{'IssuesAllowed'} = 0;
316   }
317   if ($traps{'CHARGES'} eq 1) {
318     if ($amount > 5) {
319       $env->{'IssuesAllowed'} = 0;
320       $issuesallowed=0;
321     }
322   }
323   return ($issuesallowed,$traps_done,$amount,$odues);
324 } # end of process_traps
325
326 sub Borenq {
327   my ($env)=@_;
328   my $dbh = C4::Context->dbh;
329   #get borrower guff
330   my $bornum;
331   my $issuesallowed;
332   my $borrower;
333   my $reason;
334   $env->{'sysarea'} = "Enquiries";
335   while ($reason eq "") {
336     $env->{'sysarea'} = "Enquiries";
337     ($bornum,$issuesallowed,$borrower,$reason) = &findborrower($env,$dbh);
338     if ($reason eq "") {
339       my ($data,$reason)=&borrowerwindow($env,$borrower);
340       if ($reason eq 'Modify'){
341         modifyuser($env,$borrower);
342         $reason = "";
343       } elsif ($reason eq 'New'){
344         $reason = "";
345        }
346     }
347   }
348   return $reason;
349 }  
350
351 sub modifyuser {
352   my ($env,$borrower) = @_;
353   debug_msg($env,"Please use intranet");
354   #return;
355 }
356
357 sub reserveslist {
358   my ($env,$borrower,$amount,$odues,$waiting) = @_;
359   my $dbh = C4::Context->dbh;
360   my @items;
361   my $x=0;
362   my $query="Select * from reserves where
363   borrowernumber='$borrower->{'borrowernumber'}' and found='W' and
364   cancellationdate is null order by timestamp";
365   my $sth=$dbh->prepare($query);
366   $sth->execute;
367   while (my $data=$sth->fetchrow_hashref){
368     my $itemdata = itemnodata($env,$dbh,$data->{'itemnumber'});
369     if ($itemdata){
370       push @items,$itemdata;
371     }
372   }
373   $sth->finish;
374   reservesdisplay($env,$borrower,$amount,$odues,\@items);
375 }
376
377 =item NewBorrowerNumber
378
379   $num = &NewBorrowerNumber();
380
381 Allocates a new, unused borrower number, and returns it.
382
383 =cut
384 #'
385 # FIXME - This is identical to C4::Search::NewBorrowerNumber.
386 # Pick one (preferably this one) and stick with it.  
387
388 # FIXME - Race condition: this function just says what the next unused
389 # number is, but doesn't allocate it. Hence, two clients adding
390 # patrons at the same time could get the same new borrower number and
391 # clobber each other.
392 # A better approach might be to change the database to make
393 # borrowers.borrowernumber a unique key and auto_increment. Then, to
394 # allocate a new borrower number, use "insert" to create a new record
395 # (leaving the database daemon with the job of serializing requests),
396 # and use the newly-created record.
397
398 sub NewBorrowerNumber {
399   my $dbh = C4::Context->dbh;
400   my $sth=$dbh->prepare("Select max(borrowernumber) from borrowers");
401   $sth->execute;
402   my $data=$sth->fetchrow_hashref;
403   $sth->finish;
404   $data->{'max(borrowernumber)'}++;
405   return($data->{'max(borrowernumber)'});
406 }
407
408 sub findguarantees{
409   my ($bornum)=@_;
410   my $dbh = C4::Context->dbh;
411   my $query="select cardnumber,borrowernumber from borrowers where 
412   guarantor='$bornum'";
413   my $sth=$dbh->prepare($query);
414   $sth->execute;
415   my @dat;
416   my $i=0;
417   while (my $data=$sth->fetchrow_hashref){
418     $dat[$i]=$data;
419     $i++;
420   }
421   $sth->finish;
422   return($i,\@dat);
423 }
424 END { }       # module clean-up code here (global destructor)