adding three new variables for installation:
[koha.git] / C4 / Serials.pm
1 package C4::Serials;    #assumes C4/Serials.pm
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 with
17 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
18 # Suite 330, Boston, MA  02111-1307 USA
19
20
21 use strict;
22 use C4::Dates qw(format_date format_date_in_iso);
23 use Date::Calc qw(:all);
24 use POSIX qw(strftime);
25 use C4::Suggestions;
26 use C4::Koha;
27 use C4::Biblio;
28 use C4::Items;
29 use C4::Search;
30 use C4::Letters;
31 use C4::Log; # logaction
32
33 require Exporter;
34
35 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
36
37 $VERSION = 3.00;        # set version for version checking
38
39 =head1 NAME
40
41 C4::Serials - Give functions for serializing.
42
43 =head1 SYNOPSIS
44
45   use C4::Serials;
46
47 =head1 DESCRIPTION
48
49 Give all XYZ functions
50
51 =head1 FUNCTIONS
52
53 =cut
54
55 @ISA    = qw(Exporter);
56 @EXPORT = qw(
57     
58     &NewSubscription    &ModSubscription    &DelSubscription    &GetSubscriptions
59     &GetSubscription    &CountSubscriptionFromBiblionumber      &GetSubscriptionsFromBiblionumber
60     &GetFullSubscriptionsFromBiblionumber   &GetFullSubscription &ModSubscriptionHistory
61     &HasSubscriptionExpired &GetExpirationDate &abouttoexpire
62     
63     &GetNextSeq         &NewIssue           &ItemizeSerials    &GetSerials
64     &GetLatestSerials   &ModSerialStatus    &GetNextDate       &GetSerials2
65     &ReNewSubscription  &GetLateIssues      &GetLateOrMissingIssues
66     &GetSerialInformation                   &AddItem2Serial
67     &PrepareSerialsData
68     
69     &UpdateClaimdateIssues
70     &GetSuppliersWithLateIssues             &getsupplierbyserialid
71     &GetDistributedTo   &SetDistributedTo
72     &getroutinglist     &delroutingmember   &addroutingmember
73     &reorder_members
74     &check_routing &updateClaim &removeMissingIssue
75     
76     &old_newsubscription &old_modsubscription &old_getserials
77 );
78
79 =head2 GetSuppliersWithLateIssues
80
81 =over 4
82
83 %supplierlist = &GetSuppliersWithLateIssues
84
85 this function get all suppliers with late issues.
86
87 return :
88 the supplierlist into a hash. this hash containts id & name of the supplier
89
90 =back
91
92 =cut
93
94 sub GetSuppliersWithLateIssues {
95     my $dbh   = C4::Context->dbh;
96     my $query = qq|
97         SELECT DISTINCT id, name
98         FROM            subscription 
99         LEFT JOIN       serial ON serial.subscriptionid=subscription.subscriptionid
100         LEFT JOIN       aqbooksellers ON subscription.aqbooksellerid = aqbooksellers.id
101         WHERE           subscription.subscriptionid = serial.subscriptionid
102         AND             (planneddate < now() OR serial.STATUS = 3 OR serial.STATUS = 4)
103         ORDER BY name
104     |;
105     my $sth = $dbh->prepare($query);
106     $sth->execute;
107     my %supplierlist;
108     while ( my ( $id, $name ) = $sth->fetchrow ) {
109         $supplierlist{$id} = $name;
110     }
111     if ( C4::Context->preference("RoutingSerials") ) {
112         $supplierlist{''} = "All Suppliers";
113     }
114     return %supplierlist;
115 }
116
117 =head2 GetLateIssues
118
119 =over 4
120
121 @issuelist = &GetLateIssues($supplierid)
122
123 this function select late issues on database
124
125 return :
126 the issuelist into an table. Each line of this table containts a ref to a hash which it containts
127 name,title,planneddate,serialseq,serial.subscriptionid from tables : subscription, serial & biblio
128
129 =back
130
131 =cut
132
133 sub GetLateIssues {
134     my ($supplierid) = @_;
135     my $dbh = C4::Context->dbh;
136     my $sth;
137     if ($supplierid) {
138         my $query = qq|
139             SELECT     name,title,planneddate,serialseq,serial.subscriptionid
140             FROM       subscription
141             LEFT JOIN  serial ON subscription.subscriptionid = serial.subscriptionid
142             LEFT JOIN  biblio ON biblio.biblionumber = subscription.biblionumber
143             LEFT JOIN  aqbooksellers ON subscription.aqbooksellerid = aqbooksellers.id
144             WHERE      ((planneddate < now() AND serial.STATUS =1) OR serial.STATUS = 3)
145             AND        subscription.aqbooksellerid=$supplierid
146             ORDER BY   title
147         |;
148         $sth = $dbh->prepare($query);
149     }
150     else {
151         my $query = qq|
152             SELECT     name,title,planneddate,serialseq,serial.subscriptionid
153             FROM       subscription
154             LEFT JOIN  serial ON subscription.subscriptionid = serial.subscriptionid
155             LEFT JOIN  biblio ON biblio.biblionumber = subscription.biblionumber
156             LEFT JOIN  aqbooksellers ON subscription.aqbooksellerid = aqbooksellers.id
157             WHERE      ((planneddate < now() AND serial.STATUS =1) OR serial.STATUS = 3)
158             ORDER BY   title
159         |;
160         $sth = $dbh->prepare($query);
161     }
162     $sth->execute;
163     my @issuelist;
164     my $last_title;
165     my $odd   = 0;
166     my $count = 0;
167     while ( my $line = $sth->fetchrow_hashref ) {
168         $odd++ unless $line->{title} eq $last_title;
169         $line->{title} = "" if $line->{title} eq $last_title;
170         $last_title = $line->{title} if ( $line->{title} );
171         $line->{planneddate} = format_date( $line->{planneddate} );
172         $count++;
173         push @issuelist, $line;
174     }
175     return $count, @issuelist;
176 }
177
178 =head2 GetSubscriptionHistoryFromSubscriptionId
179
180 =over 4
181
182 $sth = GetSubscriptionHistoryFromSubscriptionId()
183 this function just prepare the SQL request.
184 After this function, don't forget to execute it by using $sth->execute($subscriptionid)
185 return :
186 $sth = $dbh->prepare($query).
187
188 =back
189
190 =cut
191
192 sub GetSubscriptionHistoryFromSubscriptionId() {
193     my $dbh   = C4::Context->dbh;
194     my $query = qq|
195         SELECT *
196         FROM   subscriptionhistory
197         WHERE  subscriptionid = ?
198     |;
199     return $dbh->prepare($query);
200 }
201
202 =head2 GetSerialStatusFromSerialId
203
204 =over 4
205
206 $sth = GetSerialStatusFromSerialId();
207 this function just prepare the SQL request.
208 After this function, don't forget to execute it by using $sth->execute($serialid)
209 return :
210 $sth = $dbh->prepare($query).
211
212 =back
213
214 =cut
215
216 sub GetSerialStatusFromSerialId() {
217     my $dbh   = C4::Context->dbh;
218     my $query = qq|
219         SELECT status
220         FROM   serial
221         WHERE  serialid = ?
222     |;
223     return $dbh->prepare($query);
224 }
225
226 =head2 GetSerialInformation
227
228 =over 4
229
230 $data = GetSerialInformation($serialid);
231 returns a hash containing :
232   items : items marcrecord (can be an array)
233   serial table field
234   subscription table field
235   + information about subscription expiration
236   
237 =back
238
239 =cut
240
241 sub GetSerialInformation {
242     my ($serialid) = @_;
243     my $dbh        = C4::Context->dbh;
244     my $query      = qq|
245         SELECT serial.*, serial.notes as sernotes, serial.status as serstatus,subscription.*,subscription.subscriptionid as subsid|;
246        if (C4::Context->preference('IndependantBranches') && 
247               C4::Context->userenv && 
248               C4::Context->userenv->{'flags'} != 1 && C4::Context->userenv->{'branch'}){
249                 $query.="
250       , ((subscription.branchcode <>\"".C4::Context->userenv->{'branch'}."\") and subscription.branchcode <>\"\" and subscription.branchcode IS NOT NULL) as cannotedit ";
251         }
252             $query .= qq|             
253         FROM   serial LEFT JOIN subscription ON subscription.subscriptionid=serial.subscriptionid
254         WHERE  serialid = ?
255     |;
256     my $rq = $dbh->prepare($query);
257     $rq->execute($serialid);
258     my $data = $rq->fetchrow_hashref;
259
260     if ( C4::Context->preference("serialsadditems") ) {
261         if ( $data->{'itemnumber'} ) {
262             my @itemnumbers = split /,/, $data->{'itemnumber'};
263             foreach my $itemnum (@itemnumbers) {
264
265                 #It is ASSUMED that GetMarcItem ALWAYS WORK...
266                 #Maybe GetMarcItem should return values on failure
267 #                 warn "itemnumber :$itemnum, bibnum :".$data->{'biblionumber'};
268                 my $itemprocessed =
269                   PrepareItemrecordDisplay( $data->{'biblionumber'}, $itemnum );
270                 $itemprocessed->{'itemnumber'}   = $itemnum;
271                 $itemprocessed->{'itemid'}       = $itemnum;
272                 $itemprocessed->{'serialid'}     = $serialid;
273                 $itemprocessed->{'biblionumber'} = $data->{'biblionumber'};
274                 push @{ $data->{'items'} }, $itemprocessed;
275             }
276         }
277         else {
278             my $itemprocessed =
279               PrepareItemrecordDisplay( $data->{'biblionumber'} );
280             $itemprocessed->{'itemid'}       = "N$serialid";
281             $itemprocessed->{'serialid'}     = $serialid;
282             $itemprocessed->{'biblionumber'} = $data->{'biblionumber'};
283             $itemprocessed->{'countitems'}   = 0;
284             push @{ $data->{'items'} }, $itemprocessed;
285         }
286     }
287     $data->{ "status" . $data->{'serstatus'} } = 1;
288     $data->{'subscriptionexpired'} =
289       HasSubscriptionExpired( $data->{'subscriptionid'} ) && $data->{'status'}==1;
290     $data->{'abouttoexpire'} =
291       abouttoexpire( $data->{'subscriptionid'} );
292     return $data;
293 }
294
295 =head2 AddItem2Serial
296
297 =over 4
298
299 $data = AddItem2Serial($serialid,$itemnumber);
300 Adds an itemnumber to Serial record
301 =back
302
303 =cut
304
305 sub AddItem2Serial {
306     my ( $serialid, $itemnumber ) = @_;
307     my $dbh   = C4::Context->dbh;
308     my $query = qq|
309         UPDATE serial SET itemnumber=IF(itemnumber IS NULL, $itemnumber, CONCAT(itemnumber,",",$itemnumber))
310         WHERE  serialid = ?
311     |;
312     my $rq = $dbh->prepare($query);
313     $rq->execute($serialid);
314     return $rq->rows;
315 }
316
317 =head2 UpdateClaimdateIssues
318
319 =over 4
320
321 UpdateClaimdateIssues($serialids,[$date]);
322
323 Update Claimdate for issues in @$serialids list with date $date 
324 (Take Today if none)
325 =back
326
327 =cut
328
329 sub UpdateClaimdateIssues {
330     my ( $serialids, $date ) = @_;
331     my $dbh   = C4::Context->dbh;
332     $date = strftime("%Y-%m-%d",localtime) unless ($date);
333     my $query = "
334         UPDATE serial SET claimdate=$date,status=7
335         WHERE  serialid in ".join (",",@$serialids);
336     ;
337     my $rq = $dbh->prepare($query);
338     $rq->execute;
339     return $rq->rows;
340 }
341
342 =head2 GetSubscription
343
344 =over 4
345
346 $subs = GetSubscription($subscriptionid)
347 this function get the subscription which has $subscriptionid as id.
348 return :
349 a hashref. This hash containts
350 subscription, subscriptionhistory, aqbudget.bookfundid, biblio.title
351
352 =back
353
354 =cut
355
356 sub GetSubscription {
357     my ($subscriptionid) = @_;
358     my $dbh              = C4::Context->dbh;
359     my $query            = qq(
360         SELECT  subscription.*,
361                 subscriptionhistory.*,
362                 aqbudget.bookfundid,
363                 aqbooksellers.name AS aqbooksellername,
364                 biblio.title AS bibliotitle,
365                 subscription.biblionumber as bibnum);
366        if (C4::Context->preference('IndependantBranches') && 
367               C4::Context->userenv && 
368               C4::Context->userenv->{'flags'} != 1 && C4::Context->userenv->{'branch'}){
369                 $query.="
370       , ((subscription.branchcode <>\"".C4::Context->userenv->{'branch'}."\") and subscription.branchcode <>\"\" and subscription.branchcode IS NOT NULL) as cannotedit ";
371         }
372             $query .= qq(             
373        FROM subscription
374        LEFT JOIN subscriptionhistory ON subscription.subscriptionid=subscriptionhistory.subscriptionid
375        LEFT JOIN aqbudget ON subscription.aqbudgetid=aqbudget.aqbudgetid
376        LEFT JOIN aqbooksellers ON subscription.aqbooksellerid=aqbooksellers.id
377        LEFT JOIN biblio ON biblio.biblionumber=subscription.biblionumber
378        WHERE subscription.subscriptionid = ?
379     );
380 #     if (C4::Context->preference('IndependantBranches') && 
381 #         C4::Context->userenv && 
382 #         C4::Context->userenv->{'flags'} != 1){
383 # #       warn "flags: ".C4::Context->userenv->{'flags'};
384 #       $query.=" AND subscription.branchcode IN ('".C4::Context->userenv->{'branch'}."',\"\")";
385 #     }
386 #        warn "query : $query";
387     my $sth = $dbh->prepare($query);
388 #       warn "subsid :$subscriptionid";
389     $sth->execute($subscriptionid);
390     my $subs = $sth->fetchrow_hashref;
391     return $subs;
392 }
393
394 =head2 GetFullSubscription
395
396 =over 4
397
398    \@res = GetFullSubscription($subscriptionid)
399    this function read on serial table.
400
401 =back
402
403 =cut
404
405 sub GetFullSubscription {
406     my ($subscriptionid) = @_;
407     my $dbh            = C4::Context->dbh;
408     my $query          = qq|
409   SELECT    serial.serialid,
410             serial.serialseq,
411             serial.planneddate, 
412             serial.publisheddate, 
413             serial.status, 
414             serial.notes as notes,
415             year(IF(serial.publisheddate="00-00-0000",serial.planneddate,serial.publisheddate)) as year,
416             aqbudget.bookfundid,aqbooksellers.name as aqbooksellername,
417             biblio.title as bibliotitle,
418             subscription.branchcode AS branchcode,
419             subscription.subscriptionid AS subscriptionid |;
420     if (C4::Context->preference('IndependantBranches') && 
421         C4::Context->userenv && 
422         C4::Context->userenv->{'flags'} != 1 && C4::Context->userenv->{'branch'}){
423       $query.="
424       , ((subscription.branchcode <>\"".C4::Context->userenv->{'branch'}."\") and subscription.branchcode <>\"\" and subscription.branchcode IS NOT NULL) as cannotedit ";
425     }
426     $query.=qq|
427   FROM      serial 
428   LEFT JOIN subscription ON 
429           (serial.subscriptionid=subscription.subscriptionid )
430   LEFT JOIN aqbudget ON subscription.aqbudgetid=aqbudget.aqbudgetid 
431   LEFT JOIN aqbooksellers on subscription.aqbooksellerid=aqbooksellers.id 
432   LEFT JOIN biblio on biblio.biblionumber=subscription.biblionumber 
433   WHERE     serial.subscriptionid = ? 
434   ORDER BY year DESC,
435           IF(serial.publisheddate="00-00-0000",serial.planneddate,serial.publisheddate) DESC,
436           serial.subscriptionid
437           |;
438 #     warn $query;   
439     my $sth = $dbh->prepare($query);
440     $sth->execute($subscriptionid);
441     my $subs = $sth->fetchall_arrayref({});
442     return $subs;
443 }
444
445
446 =head2 PrepareSerialsData
447
448 =over 4
449
450    \@res = PrepareSerialsData($serialinfomation)
451    where serialinformation is a hashref array
452
453 =back
454
455 =cut
456
457 sub PrepareSerialsData{
458     my ($lines)=@_;
459     my %tmpresults;
460     my $year;
461     my @res;
462     my $startdate;
463     my $aqbooksellername;
464     my $bibliotitle;
465     my @loopissues;
466     my $first;
467     my $previousnote = "";
468     
469     foreach  my $subs ( @$lines ) {
470         $subs->{'publisheddate'} =
471           ( $subs->{'publisheddate'}
472             ? format_date( $subs->{'publisheddate'} )
473             : "XXX" );
474         $subs->{'planneddate'} = format_date( $subs->{'planneddate'} );
475         $subs->{ "status" . $subs->{'status'} } = 1;
476
477 #         $subs->{'notes'} = $subs->{'notes'} eq $previousnote?"":$subs->{notes};
478         if ( $subs->{'year'} && $subs->{'year'} ne "" ) {
479             $year = $subs->{'year'};
480         }
481         else {
482             $year = "manage";
483         }
484         if ( $tmpresults{$year} ) {
485             push @{ $tmpresults{$year}->{'serials'} }, $subs;
486         }
487         else {
488             $tmpresults{$year} = {
489                 'year' => $year,
490
491                 #               'startdate'=>format_date($subs->{'startdate'}),
492                 'aqbooksellername' => $subs->{'aqbooksellername'},
493                 'bibliotitle'      => $subs->{'bibliotitle'},
494                 'serials'          => [$subs],
495                 'first'            => $first,
496 #                 'branchcode'       => $subs->{'branchcode'},
497 #                 'subscriptionid'   => $subs->{'subscriptionid'},
498             };
499         }
500
501         #         $previousnote=$subs->{notes};
502     }
503     foreach my $key ( sort { $b cmp $a } keys %tmpresults ) {
504         push @res, $tmpresults{$key};
505     }
506     $res[0]->{'first'}=1;  
507     return \@res;
508 }
509
510 =head2 GetSubscriptionsFromBiblionumber
511
512 \@res = GetSubscriptionsFromBiblionumber($biblionumber)
513 this function get the subscription list. it reads on subscription table.
514 return :
515 table of subscription which has the biblionumber given on input arg.
516 each line of this table is a hashref. All hashes containt
517 startdate, histstartdate,opacnote,missinglist,recievedlist,periodicity,status & enddate
518
519 =cut
520
521 sub GetSubscriptionsFromBiblionumber {
522     my ($biblionumber) = @_;
523     my $dbh            = C4::Context->dbh;
524     my $query          = qq(
525         SELECT subscription.*,
526                branches.branchname,
527                subscriptionhistory.*,
528                aqbudget.bookfundid,
529                aqbooksellers.name AS aqbooksellername,
530                biblio.title AS bibliotitle
531        FROM subscription
532        LEFT JOIN subscriptionhistory ON subscription.subscriptionid=subscriptionhistory.subscriptionid
533        LEFT JOIN aqbudget ON subscription.aqbudgetid=aqbudget.aqbudgetid
534        LEFT JOIN aqbooksellers ON subscription.aqbooksellerid=aqbooksellers.id
535        LEFT JOIN biblio ON biblio.biblionumber=subscription.biblionumber
536        LEFT JOIN branches ON branches.branchcode=subscription.branchcode
537        WHERE subscription.biblionumber = ?
538     );
539 #     if (C4::Context->preference('IndependantBranches') && 
540 #         C4::Context->userenv && 
541 #         C4::Context->userenv->{'flags'} != 1){
542 #        $query.=" AND subscription.branchcode IN ('".C4::Context->userenv->{'branch'}."',\"\")";
543 #     }
544     my $sth = $dbh->prepare($query);
545     $sth->execute($biblionumber);
546     my @res;
547     while ( my $subs = $sth->fetchrow_hashref ) {
548         $subs->{startdate}     = format_date( $subs->{startdate} );
549         $subs->{histstartdate} = format_date( $subs->{histstartdate} );
550         $subs->{opacnote}     =~ s/\n/\<br\/\>/g;
551         $subs->{missinglist}  =~ s/\n/\<br\/\>/g;
552         $subs->{recievedlist} =~ s/\n/\<br\/\>/g;
553         $subs->{ "periodicity" . $subs->{periodicity} } = 1;
554         $subs->{ "numberpattern" . $subs->{numberpattern} } = 1;
555         $subs->{ "status" . $subs->{'status'} } = 1;
556         $subs->{'cannotedit'}=(C4::Context->preference('IndependantBranches') && 
557                 C4::Context->userenv && 
558                 C4::Context->userenv->{flags} !=1  && 
559                 C4::Context->userenv->{branch} && $subs->{branchcode} &&
560                 (C4::Context->userenv->{branch} ne $subs->{branchcode}));
561         if ( $subs->{enddate} eq '0000-00-00' ) {
562             $subs->{enddate} = '';
563         }
564         else {
565             $subs->{enddate} = format_date( $subs->{enddate} );
566         }
567         $subs->{'abouttoexpire'}=abouttoexpire($subs->{'subscriptionid'});
568         $subs->{'subscriptionexpired'}=HasSubscriptionExpired($subs->{'subscriptionid'});
569         push @res, $subs;
570     }
571     return \@res;
572 }
573
574 =head2 GetFullSubscriptionsFromBiblionumber
575
576 =over 4
577
578    \@res = GetFullSubscriptionsFromBiblionumber($biblionumber)
579    this function read on serial table.
580
581 =back
582
583 =cut
584
585 sub GetFullSubscriptionsFromBiblionumber {
586     my ($biblionumber) = @_;
587     my $dbh            = C4::Context->dbh;
588     my $query          = qq|
589   SELECT    serial.serialid,
590             serial.serialseq,
591             serial.planneddate, 
592             serial.publisheddate, 
593             serial.status, 
594             serial.notes as notes,
595             year(IF(serial.publisheddate="00-00-0000",serial.planneddate,serial.publisheddate)) as year,
596             aqbudget.bookfundid,aqbooksellers.name as aqbooksellername,
597             biblio.title as bibliotitle,
598             subscription.branchcode AS branchcode,
599             subscription.subscriptionid AS subscriptionid|;
600      if (C4::Context->preference('IndependantBranches') && 
601         C4::Context->userenv && 
602         C4::Context->userenv->{'flags'} != 1 && C4::Context->userenv->{'branch'}){
603       $query.="
604       , ((subscription.branchcode <>\"".C4::Context->userenv->{'branch'}."\") and subscription.branchcode <>\"\" and subscription.branchcode IS NOT NULL) as cannotedit ";
605      }
606       
607      $query.=qq|      
608   FROM      serial 
609   LEFT JOIN subscription ON 
610           (serial.subscriptionid=subscription.subscriptionid)
611   LEFT JOIN aqbudget ON subscription.aqbudgetid=aqbudget.aqbudgetid 
612   LEFT JOIN aqbooksellers on subscription.aqbooksellerid=aqbooksellers.id 
613   LEFT JOIN biblio on biblio.biblionumber=subscription.biblionumber 
614   WHERE     subscription.biblionumber = ? 
615   ORDER BY year DESC,
616           IF(serial.publisheddate="00-00-0000",serial.planneddate,serial.publisheddate) DESC,
617           serial.subscriptionid
618           |;
619     my $sth = $dbh->prepare($query);
620     $sth->execute($biblionumber);
621     my $subs= $sth->fetchall_arrayref({});
622     return $subs;
623 }
624
625 =head2 GetSubscriptions
626
627 =over 4
628
629 @results = GetSubscriptions($title,$ISSN,$biblionumber);
630 this function get all subscriptions which has title like $title,ISSN like $ISSN and biblionumber like $biblionumber.
631 return:
632 a table of hashref. Each hash containt the subscription.
633
634 =back
635
636 =cut
637
638 sub GetSubscriptions {
639     my ( $title, $ISSN, $biblionumber ) = @_;
640     #return unless $title or $ISSN or $biblionumber;
641     my $dbh = C4::Context->dbh;
642     my $sth;
643     if ($biblionumber) {
644         my $query = qq(
645             SELECT subscription.*,biblio.title,biblioitems.issn,biblio.biblionumber
646             FROM   subscription
647             LEFT JOIN biblio ON biblio.biblionumber = subscription.biblionumber
648             LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
649             WHERE biblio.biblionumber=?
650         );
651         $query.=" ORDER BY title";
652 #         warn "query :$query";
653         $sth = $dbh->prepare($query);
654         $sth->execute($biblionumber);
655     }
656     else {
657         if ( $ISSN and $title ) {
658             my $query = qq|
659                 SELECT subscription.*,biblio.title,biblioitems.issn,biblio.biblionumber        
660                 FROM   subscription
661                 LEFT JOIN biblio ON biblio.biblionumber = subscription.biblionumber
662                 LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
663                 WHERE (biblioitems.issn = ? or|. join('and ',map{"biblio.title LIKE \"%$_%\""}split (" ",$title))." )";
664             $query.=" ORDER BY title";
665             $sth = $dbh->prepare($query);
666             $sth->execute( $ISSN );
667         }
668         else {
669             if ($ISSN) {
670                 my $query = qq(
671                     SELECT subscription.*,biblio.title,biblioitems.issn,biblio.biblionumber
672                     FROM   subscription
673                     LEFT JOIN biblio ON biblio.biblionumber = subscription.biblionumber
674                     LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
675                     WHERE biblioitems.issn LIKE ?
676                 );
677                 $query.=" ORDER BY title";
678 #         warn "query :$query";
679                 $sth = $dbh->prepare($query);
680                 $sth->execute( "%" . $ISSN . "%" );
681             }
682             else {
683                 my $query = qq(
684                     SELECT subscription.*,biblio.title,biblioitems.issn,biblio.biblionumber
685                     FROM   subscription
686                     LEFT JOIN biblio ON biblio.biblionumber = subscription.biblionumber
687                     LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
688                     WHERE 1
689                     ).($title?" and ":""). join('and ',map{"biblio.title LIKE \"%$_%\""} split (" ",$title) );
690                 
691                 $query.=" ORDER BY title";
692 #                 warn $query;       
693                 $sth = $dbh->prepare($query);
694                 $sth->execute;
695             }
696         }
697     }
698     my @results;
699     my $previoustitle = "";
700     my $odd           = 1;
701     while ( my $line = $sth->fetchrow_hashref ) {
702         if ( $previoustitle eq $line->{title} ) {
703             $line->{title}  = "";
704             $line->{issn}   = "";
705             $line->{toggle} = 1 if $odd == 1;
706         }
707         else {
708             $previoustitle = $line->{title};
709             $odd           = -$odd;
710             $line->{toggle} = 1 if $odd == 1;
711         }
712         $line->{'cannotedit'}=(C4::Context->preference('IndependantBranches') && 
713                 C4::Context->userenv && 
714                 C4::Context->userenv->{flags} !=1  && 
715                 C4::Context->userenv->{branch} && $line->{branchcode} &&
716                 (C4::Context->userenv->{branch} ne $line->{branchcode}));
717         push @results, $line;
718     }
719     return @results;
720 }
721
722 =head2 GetSerials
723
724 =over 4
725
726 ($totalissues,@serials) = GetSerials($subscriptionid);
727 this function get every serial not arrived for a given subscription
728 as well as the number of issues registered in the database (all types)
729 this number is used to see if a subscription can be deleted (=it must have only 1 issue)
730
731 =back
732
733 =cut
734
735 sub GetSerials {
736     my ($subscriptionid,$count) = @_;
737     my $dbh = C4::Context->dbh;
738
739     # status = 2 is "arrived"
740     my $counter = 0;
741     $count=5 unless ($count);
742     my @serials;
743     my $query =
744       "SELECT serialid,serialseq, status, publisheddate, planneddate,notes, routingnotes
745                         FROM   serial
746                         WHERE  subscriptionid = ? AND status NOT IN (2,4,5) 
747                         ORDER BY IF(publisheddate<>'0000-00-00',publisheddate,planneddate) DESC";
748     my $sth = $dbh->prepare($query);
749     $sth->execute($subscriptionid);
750     while ( my $line = $sth->fetchrow_hashref ) {
751         $line->{ "status" . $line->{status} } =
752           1;    # fills a "statusX" value, used for template status select list
753         $line->{"publisheddate"} = format_date( $line->{"publisheddate"} );
754         $line->{"planneddate"}   = format_date( $line->{"planneddate"} );
755         push @serials, $line;
756     }
757     # OK, now add the last 5 issues arrives/missing
758     $query =
759       "SELECT   serialid,serialseq, status, planneddate, publisheddate,notes, routingnotes
760        FROM     serial
761        WHERE    subscriptionid = ?
762        AND      (status in (2,4,5))
763        ORDER BY IF(publisheddate<>'0000-00-00',publisheddate,planneddate) DESC
764       ";
765     $sth = $dbh->prepare($query);
766     $sth->execute($subscriptionid);
767     while ( ( my $line = $sth->fetchrow_hashref ) && $counter < $count ) {
768         $counter++;
769         $line->{ "status" . $line->{status} } =
770           1;    # fills a "statusX" value, used for template status select list
771         $line->{"planneddate"}   = format_date( $line->{"planneddate"} );
772         $line->{"publisheddate"} = format_date( $line->{"publisheddate"} );
773         push @serials, $line;
774     }
775
776     $query = "SELECT count(*) FROM serial WHERE subscriptionid=?";
777     $sth = $dbh->prepare($query);
778     $sth->execute($subscriptionid);
779     my ($totalissues) = $sth->fetchrow;
780     return ( $totalissues, @serials );
781 }
782
783 =head2 GetSerials2
784
785 =over 4
786
787 ($totalissues,@serials) = GetSerials2($subscriptionid,$status);
788 this function get every serial waited for a given subscription
789 as well as the number of issues registered in the database (all types)
790 this number is used to see if a subscription can be deleted (=it must have only 1 issue)
791
792 =back
793
794 =cut
795 sub GetSerials2 {
796     my ($subscription,$status) = @_;
797     my $dbh = C4::Context->dbh;
798     my $query = qq|
799                  SELECT   serialid,serialseq, status, planneddate, publisheddate,notes, routingnotes
800                  FROM     serial 
801                  WHERE    subscriptionid=$subscription AND status IN ($status)
802                  ORDER BY publisheddate,serialid DESC
803                     |;
804 #     warn $query;
805     my $sth=$dbh->prepare($query);
806     $sth->execute;
807     my @serials;
808     while(my $line = $sth->fetchrow_hashref) {
809         $line->{"status".$line->{status}} = 1; # fills a "statusX" value, used for template status select list
810         $line->{"planneddate"} = format_date($line->{"planneddate"});
811         $line->{"publisheddate"} = format_date($line->{"publisheddate"});
812         push @serials,$line;
813     }
814     my ($totalissues) = scalar(@serials);
815     return ($totalissues,@serials);
816 }
817
818 =head2 GetLatestSerials
819
820 =over 4
821
822 \@serials = GetLatestSerials($subscriptionid,$limit)
823 get the $limit's latest serials arrived or missing for a given subscription
824 return :
825 a ref to a table which it containts all of the latest serials stored into a hash.
826
827 =back
828
829 =cut
830
831 sub GetLatestSerials {
832     my ( $subscriptionid, $limit ) = @_;
833     my $dbh = C4::Context->dbh;
834
835     # status = 2 is "arrived"
836     my $strsth = "SELECT   serialid,serialseq, status, planneddate, notes
837                         FROM     serial
838                         WHERE    subscriptionid = ?
839                         AND      (status =2 or status=4)
840                         ORDER BY planneddate DESC LIMIT 0,$limit
841                 ";
842     my $sth = $dbh->prepare($strsth);
843     $sth->execute($subscriptionid);
844     my @serials;
845     while ( my $line = $sth->fetchrow_hashref ) {
846         $line->{ "status" . $line->{status} } =
847           1;    # fills a "statusX" value, used for template status select list
848         $line->{"planneddate"} = format_date( $line->{"planneddate"} );
849         push @serials, $line;
850     }
851
852     #     my $query = qq|
853     #         SELECT count(*)
854     #         FROM   serial
855     #         WHERE  subscriptionid=?
856     #     |;
857     #     $sth=$dbh->prepare($query);
858     #     $sth->execute($subscriptionid);
859     #     my ($totalissues) = $sth->fetchrow;
860     return \@serials;
861 }
862
863 =head2 GetDistributedTo
864
865 =over 4
866
867 $distributedto=GetDistributedTo($subscriptionid)
868 This function select the old previous value of distributedto in the database.
869
870 =back
871
872 =cut
873
874 sub GetDistributedTo {
875     my $dbh = C4::Context->dbh;
876     my $distributedto;
877     my $subscriptionid = @_;
878     my $query = "SELECT distributedto FROM subscription WHERE subscriptionid=?";
879     my $sth   = $dbh->prepare($query);
880     $sth->execute($subscriptionid);
881     return ($distributedto) = $sth->fetchrow;
882 }
883
884 =head2 GetNextSeq
885
886 =over 4
887
888 GetNextSeq($val)
889 $val is a hashref containing all the attributes of the table 'subscription'
890 This function get the next issue for the subscription given on input arg
891 return:
892 all the input params updated.
893
894 =back
895
896 =cut
897
898 # sub GetNextSeq {
899 #     my ($val) =@_;
900 #     my ($calculated,$newlastvalue1,$newlastvalue2,$newlastvalue3,$newinnerloop1,$newinnerloop2,$newinnerloop3);
901 #     $calculated = $val->{numberingmethod};
902 # # calculate the (expected) value of the next issue recieved.
903 #     $newlastvalue1 = $val->{lastvalue1};
904 # # check if we have to increase the new value.
905 #     $newinnerloop1 = $val->{innerloop1}+1;
906 #     $newinnerloop1=0 if ($newinnerloop1 >= $val->{every1});
907 #     $newlastvalue1 += $val->{add1} if ($newinnerloop1<1); # <1 to be true when 0 or empty.
908 #     $newlastvalue1=$val->{setto1} if ($newlastvalue1>$val->{whenmorethan1}); # reset counter if needed.
909 #     $calculated =~ s/\{X\}/$newlastvalue1/g;
910 #
911 #     $newlastvalue2 = $val->{lastvalue2};
912 # # check if we have to increase the new value.
913 #     $newinnerloop2 = $val->{innerloop2}+1;
914 #     $newinnerloop2=0 if ($newinnerloop2 >= $val->{every2});
915 #     $newlastvalue2 += $val->{add2} if ($newinnerloop2<1); # <1 to be true when 0 or empty.
916 #     $newlastvalue2=$val->{setto2} if ($newlastvalue2>$val->{whenmorethan2}); # reset counter if needed.
917 #     $calculated =~ s/\{Y\}/$newlastvalue2/g;
918 #
919 #     $newlastvalue3 = $val->{lastvalue3};
920 # # check if we have to increase the new value.
921 #     $newinnerloop3 = $val->{innerloop3}+1;
922 #     $newinnerloop3=0 if ($newinnerloop3 >= $val->{every3});
923 #     $newlastvalue3 += $val->{add3} if ($newinnerloop3<1); # <1 to be true when 0 or empty.
924 #     $newlastvalue3=$val->{setto3} if ($newlastvalue3>$val->{whenmorethan3}); # reset counter if needed.
925 #     $calculated =~ s/\{Z\}/$newlastvalue3/g;
926 #     return ($calculated,$newlastvalue1,$newlastvalue2,$newlastvalue3,$newinnerloop1,$newinnerloop2,$newinnerloop3);
927 # }
928
929 sub GetNextSeq {
930     my ($val) = @_;
931     my (
932         $calculated,    $newlastvalue1, $newlastvalue2, $newlastvalue3,
933         $newinnerloop1, $newinnerloop2, $newinnerloop3
934     );
935     my $pattern = $val->{numberpattern};
936     my @seasons = ( 'nothing', 'Winter', 'Spring', 'Summer', 'Autumn' );
937     my @southern_seasons = ( '', 'Summer', 'Autumn', 'Winter', 'Spring' );
938     $calculated    = $val->{numberingmethod};
939     $newlastvalue1 = $val->{lastvalue1};
940     $newlastvalue2 = $val->{lastvalue2};
941     $newlastvalue3 = $val->{lastvalue3};
942   $newlastvalue1 = $val->{lastvalue1};
943   # check if we have to increase the new value.
944   $newinnerloop1 = $val->{innerloop1} + 1;
945   $newinnerloop1=0 if ($newinnerloop1 >= $val->{every1});
946   $newlastvalue1 += $val->{add1} if ($newinnerloop1<1); # <1 to be true when 0 or empty.
947   $newlastvalue1=$val->{setto1} if ($newlastvalue1>$val->{whenmorethan1}); # reset counter if needed.
948   $calculated =~ s/\{X\}/$newlastvalue1/g;
949   
950   $newlastvalue2 = $val->{lastvalue2};
951   # check if we have to increase the new value.
952   $newinnerloop2 = $val->{innerloop2} + 1;
953   $newinnerloop2=0 if ($newinnerloop2 >= $val->{every2});
954   $newlastvalue2 += $val->{add2} if ($newinnerloop2<1); # <1 to be true when 0 or empty.
955   $newlastvalue2=$val->{setto2} if ($newlastvalue2>$val->{whenmorethan2}); # reset counter if needed.
956   if ( $pattern == 6 ) {
957     if ( $val->{hemisphere} == 2 ) {
958        my $newlastvalue2seq = $southern_seasons[$newlastvalue2];
959        $calculated =~ s/\{Y\}/$newlastvalue2seq/g;
960     }
961     else {
962        my $newlastvalue2seq = $seasons[$newlastvalue2];
963        $calculated =~ s/\{Y\}/$newlastvalue2seq/g;
964     }
965   }
966   else {
967     $calculated =~ s/\{Y\}/$newlastvalue2/g;
968   }
969   
970   
971   $newlastvalue3 = $val->{lastvalue3};
972   # check if we have to increase the new value.
973   $newinnerloop3 = $val->{innerloop3} + 1;
974   $newinnerloop3=0 if ($newinnerloop3 >= $val->{every3});
975   $newlastvalue3 += $val->{add3} if ($newinnerloop3<1); # <1 to be true when 0 or empty.
976   $newlastvalue3=$val->{setto3} if ($newlastvalue3>$val->{whenmorethan3}); # reset counter if needed.
977   $calculated =~ s/\{Z\}/$newlastvalue3/g;
978     
979   return ( $calculated, $newlastvalue1, $newlastvalue2, $newlastvalue3 ,
980            $newinnerloop1, $newinnerloop2, $newinnerloop3);
981 }
982
983 =head2 GetSeq
984
985 =over 4
986
987 $calculated = GetSeq($val)
988 $val is a hashref containing all the attributes of the table 'subscription'
989 this function transforms {X},{Y},{Z} to 150,0,0 for example.
990 return:
991 the sequence in integer format
992
993 =back
994
995 =cut
996
997 sub GetSeq {
998     my ($val)      = @_;
999     my $pattern = $val->{numberpattern};
1000     my @seasons = ( 'nothing', 'Winter', 'Spring', 'Summer', 'Autumn' );
1001     my @southern_seasons = ( '', 'Summer', 'Autumn', 'Winter', 'Spring' );
1002     my $calculated = $val->{numberingmethod};
1003     my $x          = $val->{'lastvalue1'};
1004     $calculated =~ s/\{X\}/$x/g;
1005     my $newlastvalue2 = $val->{'lastvalue2'};
1006     if ( $pattern == 6 ) {
1007         if ( $val->{hemisphere} == 2 ) {
1008             my $newlastvalue2seq = $southern_seasons[$newlastvalue2];
1009             $calculated =~ s/\{Y\}/$newlastvalue2seq/g;
1010         }
1011         else {
1012             my $newlastvalue2seq = $seasons[$newlastvalue2];
1013             $calculated =~ s/\{Y\}/$newlastvalue2seq/g;
1014         }
1015     }
1016     else {
1017         $calculated =~ s/\{Y\}/$newlastvalue2/g;
1018     }
1019     my $z = $val->{'lastvalue3'};
1020     $calculated =~ s/\{Z\}/$z/g;
1021     return $calculated;
1022 }
1023
1024 =head2 GetExpirationDate
1025
1026 $sensddate = GetExpirationDate($subscriptionid)
1027
1028 this function return the expiration date for a subscription given on input args.
1029
1030 return
1031 the enddate
1032
1033 =cut
1034
1035 sub GetExpirationDate {
1036     my ($subscriptionid) = @_;
1037     my $dbh              = C4::Context->dbh;
1038     my $subscription     = GetSubscription($subscriptionid);
1039     my $enddate          = $subscription->{startdate};
1040
1041 # we don't do the same test if the subscription is based on X numbers or on X weeks/months
1042     if (($subscription->{periodicity} % 16) >0){
1043       if ( $subscription->{numberlength} ) {
1044           #calculate the date of the last issue.
1045           my $length = $subscription->{numberlength};
1046           for ( my $i = 1 ; $i <= $length ; $i++ ) {
1047               $enddate = GetNextDate( $enddate, $subscription );
1048           }
1049       }
1050       elsif ( $subscription->{monthlength} ){
1051           my @date=split (/-/,$subscription->{startdate});
1052           my @enddate = Add_Delta_YM($date[0],$date[1],$date[2],0,$subscription->{monthlength});
1053           $enddate=sprintf("%04d-%02d-%02d",$enddate[0],$enddate[1],$enddate[2]);
1054       } elsif ( $subscription->{weeklength} ){
1055           my @date=split (/-/,$subscription->{startdate});
1056           my @enddate = Add_Delta_Days($date[0],$date[1],$date[2],$subscription->{weeklength}*7);
1057           $enddate=sprintf("%04d-%02d-%02d",$enddate[0],$enddate[1],$enddate[2]);
1058       }
1059       return $enddate;
1060     } else {
1061       return 0;  
1062     }  
1063 }
1064
1065 =head2 CountSubscriptionFromBiblionumber
1066
1067 =over 4
1068
1069 $subscriptionsnumber = CountSubscriptionFromBiblionumber($biblionumber)
1070 this count the number of subscription for a biblionumber given.
1071 return :
1072 the number of subscriptions with biblionumber given on input arg.
1073
1074 =back
1075
1076 =cut
1077
1078 sub CountSubscriptionFromBiblionumber {
1079     my ($biblionumber) = @_;
1080     my $dbh = C4::Context->dbh;
1081     my $query = "SELECT count(*) FROM subscription WHERE biblionumber=?";
1082     my $sth   = $dbh->prepare($query);
1083     $sth->execute($biblionumber);
1084     my $subscriptionsnumber = $sth->fetchrow;
1085     return $subscriptionsnumber;
1086 }
1087
1088 =head2 ModSubscriptionHistory
1089
1090 =over 4
1091
1092 ModSubscriptionHistory($subscriptionid,$histstartdate,$enddate,$recievedlist,$missinglist,$opacnote,$librariannote);
1093
1094 this function modify the history of a subscription. Put your new values on input arg.
1095
1096 =back
1097
1098 =cut
1099
1100 sub ModSubscriptionHistory {
1101     my (
1102         $subscriptionid, $histstartdate, $enddate, $recievedlist,
1103         $missinglist,    $opacnote,      $librariannote
1104     ) = @_;
1105     my $dbh   = C4::Context->dbh;
1106     my $query = "UPDATE subscriptionhistory 
1107                     SET histstartdate=?,enddate=?,recievedlist=?,missinglist=?,opacnote=?,librariannote=?
1108                     WHERE subscriptionid=?
1109                 ";
1110     my $sth = $dbh->prepare($query);
1111     $recievedlist =~ s/^,//g;
1112     $missinglist  =~ s/^,//g;
1113     $opacnote     =~ s/^,//g;
1114     $sth->execute(
1115         $histstartdate, $enddate,       $recievedlist, $missinglist,
1116         $opacnote,      $librariannote, $subscriptionid
1117     );
1118     return $sth->rows;
1119 }
1120
1121 =head2 ModSerialStatus
1122
1123 =over 4
1124
1125 ModSerialStatus($serialid,$serialseq, $planneddate,$publisheddate,$status,$notes)
1126
1127 This function modify the serial status. Serial status is a number.(eg 2 is "arrived")
1128 Note : if we change from "waited" to something else,then we will have to create a new "waited" entry
1129
1130 =back
1131
1132 =cut
1133
1134 sub ModSerialStatus {
1135     my ( $serialid, $serialseq,  $planneddate,$publisheddate, $status, $notes )
1136       = @_;
1137
1138     #It is a usual serial
1139     # 1st, get previous status :
1140     my $dbh   = C4::Context->dbh;
1141     my $query = "SELECT subscriptionid,status FROM serial WHERE  serialid=?";
1142     my $sth   = $dbh->prepare($query);
1143     $sth->execute($serialid);
1144     my ( $subscriptionid, $oldstatus ) = $sth->fetchrow;
1145
1146     # change status & update subscriptionhistory
1147     my $val;
1148     if ( $status eq 6 ) {
1149         DelIssue( {'serialid'=>$serialid, 'subscriptionid'=>$subscriptionid,'serialseq'=>$serialseq} );
1150     }
1151     else {
1152         my $query =
1153 "UPDATE serial SET serialseq=?,publisheddate=?,planneddate=?,status=?,notes=? WHERE  serialid = ?";
1154         $sth = $dbh->prepare($query);
1155         $sth->execute( $serialseq, $publisheddate, $planneddate, $status,
1156             $notes, $serialid );
1157         $query = "SELECT * FROM   subscription WHERE  subscriptionid = ?";
1158         $sth = $dbh->prepare($query);
1159         $sth->execute($subscriptionid);
1160         my $val = $sth->fetchrow_hashref;
1161         unless ( $val->{manualhistory} ) {
1162             $query =
1163 "SELECT missinglist,recievedlist FROM subscriptionhistory WHERE  subscriptionid=?";
1164             $sth = $dbh->prepare($query);
1165             $sth->execute($subscriptionid);
1166             my ( $missinglist, $recievedlist ) = $sth->fetchrow;
1167             if ( $status eq 2 ) {
1168
1169 #             warn "receivedlist : $recievedlist serialseq :$serialseq, ".index("$recievedlist","$serialseq");
1170                 $recievedlist .= ",$serialseq"
1171                   unless ( index( "$recievedlist", "$serialseq" ) >= 0 );
1172             }
1173
1174 #         warn "missinglist : $missinglist serialseq :$serialseq, ".index("$missinglist","$serialseq");
1175             $missinglist .= ",$serialseq"
1176               if ( $status eq 4
1177                 and not index( "$missinglist", "$serialseq" ) >= 0 );
1178             $missinglist .= ",not issued $serialseq"
1179               if ( $status eq 5
1180                 and index( "$missinglist", "$serialseq" ) >= 0 );
1181             $query =
1182 "UPDATE subscriptionhistory SET recievedlist=?, missinglist=? WHERE  subscriptionid=?";
1183             $sth = $dbh->prepare($query);
1184             $sth->execute( $recievedlist, $missinglist, $subscriptionid );
1185         }
1186     }
1187
1188     # create new waited entry if needed (ie : was a "waited" and has changed)
1189     if ( $oldstatus eq 1 && $status ne 1 ) {
1190         my $query = "SELECT * FROM   subscription WHERE  subscriptionid = ?";
1191         $sth = $dbh->prepare($query);
1192         $sth->execute($subscriptionid);
1193         my $val = $sth->fetchrow_hashref;
1194
1195         # next issue number
1196 #     warn "Next Seq";    
1197         my (
1198             $newserialseq,  $newlastvalue1, $newlastvalue2, $newlastvalue3,
1199             $newinnerloop1, $newinnerloop2, $newinnerloop3
1200         ) = GetNextSeq($val);
1201 #     warn "Next Seq End";    
1202
1203         # next date (calculated from actual date & frequency parameters)
1204 #         warn "publisheddate :$publisheddate ";
1205         my $nextpublisheddate = GetNextDate( $publisheddate, $val );
1206         NewIssue( $newserialseq, $subscriptionid, $val->{'biblionumber'},
1207             1, $nextpublisheddate, $nextpublisheddate );
1208         $query =
1209 "UPDATE subscription SET lastvalue1=?, lastvalue2=?, lastvalue3=?, innerloop1=?, innerloop2=?, innerloop3=?
1210                     WHERE  subscriptionid = ?";
1211         $sth = $dbh->prepare($query);
1212         $sth->execute(
1213             $newlastvalue1, $newlastvalue2, $newlastvalue3, $newinnerloop1,
1214             $newinnerloop2, $newinnerloop3, $subscriptionid
1215         );
1216
1217 # check if an alert must be sent... (= a letter is defined & status became "arrived"
1218         if ( $val->{letter} && $status eq 2 && $oldstatus ne 2 ) {
1219             SendAlerts( 'issue', $val->{subscriptionid}, $val->{letter} );
1220         }
1221     }
1222 }
1223
1224 =head2 ModSubscription
1225
1226 =over 4
1227
1228 this function modify a subscription. Put all new values on input args.
1229
1230 =back
1231
1232 =cut
1233
1234 sub ModSubscription {
1235     my (
1236         $auser,           $branchcode,   $aqbooksellerid, $cost,
1237         $aqbudgetid,      $startdate,    $periodicity,    $firstacquidate,
1238         $dow,             $irregularity, $numberpattern,  $numberlength,
1239         $weeklength,      $monthlength,  $add1,           $every1,
1240         $whenmorethan1,   $setto1,       $lastvalue1,     $innerloop1,
1241         $add2,            $every2,       $whenmorethan2,  $setto2,
1242         $lastvalue2,      $innerloop2,   $add3,           $every3,
1243         $whenmorethan3,   $setto3,       $lastvalue3,     $innerloop3,
1244         $numberingmethod, $status,       $biblionumber,   $callnumber,
1245         $notes,           $letter,       $hemisphere,     $manualhistory,
1246         $internalnotes,
1247         $subscriptionid
1248     ) = @_;
1249 #     warn $irregularity;
1250     my $dbh   = C4::Context->dbh;
1251     my $query = "UPDATE subscription
1252                     SET librarian=?, branchcode=?,aqbooksellerid=?,cost=?,aqbudgetid=?,startdate=?,
1253                         periodicity=?,firstacquidate=?,dow=?,irregularity=?, numberpattern=?, numberlength=?,weeklength=?,monthlength=?,
1254                         add1=?,every1=?,whenmorethan1=?,setto1=?,lastvalue1=?,innerloop1=?,
1255                         add2=?,every2=?,whenmorethan2=?,setto2=?,lastvalue2=?,innerloop2=?,
1256                         add3=?,every3=?,whenmorethan3=?,setto3=?,lastvalue3=?,innerloop3=?,
1257                         numberingmethod=?, status=?, biblionumber=?, callnumber=?, notes=?, letter=?, hemisphere=?,manualhistory=?,internalnotes=?
1258                     WHERE subscriptionid = ?";
1259 #     warn "query :".$query;
1260     my $sth = $dbh->prepare($query);
1261     $sth->execute(
1262         $auser,           $branchcode,   $aqbooksellerid, $cost,
1263         $aqbudgetid,      $startdate,    $periodicity,    $firstacquidate,
1264         $dow,             "$irregularity", $numberpattern,  $numberlength,
1265         $weeklength,      $monthlength,  $add1,           $every1,
1266         $whenmorethan1,   $setto1,       $lastvalue1,     $innerloop1,
1267         $add2,            $every2,       $whenmorethan2,  $setto2,
1268         $lastvalue2,      $innerloop2,   $add3,           $every3,
1269         $whenmorethan3,   $setto3,       $lastvalue3,     $innerloop3,
1270         $numberingmethod, $status,       $biblionumber,   $callnumber,
1271         $notes,           $letter,       $hemisphere,     ($manualhistory?$manualhistory:0),
1272         $internalnotes,
1273         $subscriptionid
1274     );
1275     my $rows=$sth->rows;
1276     $sth->finish;
1277     
1278     &logaction(C4::Context->userenv->{'number'},"SERIAL","MODIFY",$subscriptionid,"") 
1279         if C4::Context->preference("SubscriptionLog");
1280     return $rows;
1281 }
1282
1283 =head2 NewSubscription
1284
1285 =over 4
1286
1287 $subscriptionid = &NewSubscription($auser,branchcode,$aqbooksellerid,$cost,$aqbudgetid,$biblionumber,
1288     $startdate,$periodicity,$dow,$numberlength,$weeklength,$monthlength,
1289     $add1,$every1,$whenmorethan1,$setto1,$lastvalue1,$innerloop1,
1290     $add2,$every2,$whenmorethan2,$setto2,$lastvalue2,$innerloop2,
1291     $add3,$every3,$whenmorethan3,$setto3,$lastvalue3,$innerloop3,
1292     $numberingmethod, $status, $notes)
1293
1294 Create a new subscription with value given on input args.
1295
1296 return :
1297 the id of this new subscription
1298
1299 =back
1300
1301 =cut
1302
1303 sub NewSubscription {
1304     my (
1305         $auser,         $branchcode,   $aqbooksellerid,  $cost,
1306         $aqbudgetid,    $biblionumber, $startdate,       $periodicity,
1307         $dow,           $numberlength, $weeklength,      $monthlength,
1308         $add1,          $every1,       $whenmorethan1,   $setto1,
1309         $lastvalue1,    $innerloop1,   $add2,            $every2,
1310         $whenmorethan2, $setto2,       $lastvalue2,      $innerloop2,
1311         $add3,          $every3,       $whenmorethan3,   $setto3,
1312         $lastvalue3,    $innerloop3,   $numberingmethod, $status,
1313         $notes,         $letter,       $firstacquidate,  $irregularity,
1314         $numberpattern, $callnumber,   $hemisphere,      $manualhistory,
1315         $internalnotes
1316     ) = @_;
1317     my $dbh = C4::Context->dbh;
1318
1319     #save subscription (insert into database)
1320     my $query = qq|
1321         INSERT INTO subscription
1322             (librarian,branchcode,aqbooksellerid,cost,aqbudgetid,biblionumber,
1323             startdate,periodicity,dow,numberlength,weeklength,monthlength,
1324             add1,every1,whenmorethan1,setto1,lastvalue1,innerloop1,
1325             add2,every2,whenmorethan2,setto2,lastvalue2,innerloop2,
1326             add3,every3,whenmorethan3,setto3,lastvalue3,innerloop3,
1327             numberingmethod, status, notes, letter,firstacquidate,irregularity,
1328             numberpattern, callnumber, hemisphere,manualhistory,internalnotes)
1329         VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
1330         |;
1331     my $sth = $dbh->prepare($query);
1332     $sth->execute(
1333         $auser,                         $branchcode,
1334         $aqbooksellerid,                $cost,
1335         $aqbudgetid,                    $biblionumber,
1336         format_date_in_iso($startdate), $periodicity,
1337         $dow,                           $numberlength,
1338         $weeklength,                    $monthlength,
1339         $add1,                          $every1,
1340         $whenmorethan1,                 $setto1,
1341         $lastvalue1,                    $innerloop1,
1342         $add2,                          $every2,
1343         $whenmorethan2,                 $setto2,
1344         $lastvalue2,                    $innerloop2,
1345         $add3,                          $every3,
1346         $whenmorethan3,                 $setto3,
1347         $lastvalue3,                    $innerloop3,
1348         $numberingmethod,               "$status",
1349         $notes,                         $letter,
1350         format_date_in_iso($firstacquidate),                $irregularity,
1351         $numberpattern,                 $callnumber,
1352         $hemisphere,                    $manualhistory,
1353         $internalnotes
1354     );
1355
1356     #then create the 1st waited number
1357     my $subscriptionid = $dbh->{'mysql_insertid'};
1358     $query             = qq(
1359         INSERT INTO subscriptionhistory
1360             (biblionumber, subscriptionid, histstartdate, enddate, missinglist, recievedlist, opacnote, librariannote)
1361         VALUES (?,?,?,?,?,?,?,?)
1362         );
1363     $sth = $dbh->prepare($query);
1364     $sth->execute( $biblionumber, $subscriptionid,
1365         format_date_in_iso($startdate),
1366         0, "", "", "", "$notes" );
1367
1368    # reread subscription to get a hash (for calculation of the 1st issue number)
1369     $query = qq(
1370         SELECT *
1371         FROM   subscription
1372         WHERE  subscriptionid = ?
1373     );
1374     $sth = $dbh->prepare($query);
1375     $sth->execute($subscriptionid);
1376     my $val = $sth->fetchrow_hashref;
1377
1378     # calculate issue number
1379     my $serialseq = GetSeq($val);
1380     $query     = qq|
1381         INSERT INTO serial
1382             (serialseq,subscriptionid,biblionumber,status, planneddate, publisheddate)
1383         VALUES (?,?,?,?,?,?)
1384     |;
1385     $sth = $dbh->prepare($query);
1386     $sth->execute(
1387         "$serialseq", $subscriptionid, $biblionumber, 1,
1388         format_date_in_iso($startdate),
1389         format_date_in_iso($startdate)
1390     );
1391     
1392     &logaction(C4::Context->userenv->{'number'},"SERIAL","ADD",$subscriptionid,"") 
1393         if C4::Context->preference("SubscriptionLog");
1394     
1395     return $subscriptionid;
1396 }
1397
1398 =head2 ReNewSubscription
1399
1400 =over 4
1401
1402 ReNewSubscription($subscriptionid,$user,$startdate,$numberlength,$weeklength,$monthlength,$note)
1403
1404 this function renew a subscription with values given on input args.
1405
1406 =back
1407
1408 =cut
1409
1410 sub ReNewSubscription {
1411     my ( $subscriptionid, $user, $startdate, $numberlength, $weeklength,
1412         $monthlength, $note )
1413       = @_;
1414     my $dbh          = C4::Context->dbh;
1415     my $subscription = GetSubscription($subscriptionid);
1416      my $query        = qq|
1417          SELECT *
1418          FROM   biblio 
1419          LEFT JOIN biblioitems ON biblio.biblionumber=biblioitems.biblionumber
1420          WHERE    biblio.biblionumber=?
1421      |;
1422      my $sth = $dbh->prepare($query);
1423      $sth->execute( $subscription->{biblionumber} );
1424      my $biblio = $sth->fetchrow_hashref;
1425      NewSuggestion(
1426          $user,             $subscription->{bibliotitle},
1427          $biblio->{author}, $biblio->{publishercode},
1428          $biblio->{note},   '',
1429          '',                '',
1430          '',                '',
1431          $subscription->{biblionumber}
1432      );
1433
1434     # renew subscription
1435     $query = qq|
1436         UPDATE subscription
1437         SET    startdate=?,numberlength=?,weeklength=?,monthlength=?
1438         WHERE  subscriptionid=?
1439     |;
1440     $sth = $dbh->prepare($query);
1441     $sth->execute( format_date_in_iso($startdate),
1442         $numberlength, $weeklength, $monthlength, $subscriptionid );
1443         
1444     &logaction(C4::Context->userenv->{'number'},"SERIAL","RENEW",$subscriptionid,"") 
1445         if C4::Context->preference("SubscriptionLog");
1446 }
1447
1448 =head2 NewIssue
1449
1450 =over 4
1451
1452 NewIssue($serialseq,$subscriptionid,$biblionumber,$status, $planneddate, $publisheddate,  $notes)
1453
1454 Create a new issue stored on the database.
1455 Note : we have to update the recievedlist and missinglist on subscriptionhistory for this subscription.
1456
1457 =back
1458
1459 =cut
1460
1461 sub NewIssue {
1462     my ( $serialseq, $subscriptionid, $biblionumber, $status, 
1463         $planneddate, $publisheddate, $notes )
1464       = @_;
1465     ### FIXME biblionumber CAN be provided by subscriptionid. So Do we STILL NEED IT ?
1466     
1467     my $dbh   = C4::Context->dbh;
1468     my $query = qq|
1469         INSERT INTO serial
1470             (serialseq,subscriptionid,biblionumber,status,publisheddate,planneddate,notes)
1471         VALUES (?,?,?,?,?,?,?)
1472     |;
1473     my $sth = $dbh->prepare($query);
1474     $sth->execute( $serialseq, $subscriptionid, $biblionumber, $status,
1475         $publisheddate, $planneddate,$notes );
1476     my $serialid=$dbh->{'mysql_insertid'};
1477     $query = qq|
1478         SELECT missinglist,recievedlist
1479         FROM   subscriptionhistory
1480         WHERE  subscriptionid=?
1481     |;
1482     $sth = $dbh->prepare($query);
1483     $sth->execute($subscriptionid);
1484     my ( $missinglist, $recievedlist ) = $sth->fetchrow;
1485
1486     if ( $status eq 2 ) {
1487       ### TODO Add a feature that improves recognition and description.
1488       ### As such count (serialseq) i.e. : N18,2(N19),N20
1489       ### Would use substr and index But be careful to previous presence of ()
1490         $recievedlist .= ",$serialseq" unless (index($recievedlist,$serialseq)>0);
1491     }
1492     if ( $status eq 4 ) {
1493         $missinglist .= ",$serialseq" unless (index($missinglist,$serialseq)>0);
1494     }
1495     $query = qq|
1496         UPDATE subscriptionhistory
1497         SET    recievedlist=?, missinglist=?
1498         WHERE  subscriptionid=?
1499     |;
1500     $sth = $dbh->prepare($query);
1501     $sth->execute( $recievedlist, $missinglist, $subscriptionid );
1502     return $serialid;
1503 }
1504
1505 =head2 ItemizeSerials
1506
1507 =over 4
1508
1509 ItemizeSerials($serialid, $info);
1510 $info is a hashref containing  barcode branch, itemcallnumber, status, location
1511 $serialid the serialid
1512 return :
1513 1 if the itemize is a succes.
1514 0 and @error else. @error containts the list of errors found.
1515
1516 =back
1517
1518 =cut
1519
1520 sub ItemizeSerials {
1521     my ( $serialid, $info ) = @_;
1522     my $now = POSIX::strftime( "%Y-%m-%d",localtime );
1523
1524     my $dbh   = C4::Context->dbh;
1525     my $query = qq|
1526         SELECT *
1527         FROM   serial
1528         WHERE  serialid=?
1529     |;
1530     my $sth = $dbh->prepare($query);
1531     $sth->execute($serialid);
1532     my $data = $sth->fetchrow_hashref;
1533     if ( C4::Context->preference("RoutingSerials") ) {
1534
1535         # check for existing biblioitem relating to serial issue
1536         my ( $count, @results ) =
1537           GetBiblioItemByBiblioNumber( $data->{'biblionumber'} );
1538         my $bibitemno = 0;
1539         for ( my $i = 0 ; $i < $count ; $i++ ) {
1540             if (  $results[$i]->{'volumeddesc'} eq $data->{'serialseq'} . ' ('
1541                 . $data->{'planneddate'}
1542                 . ')' )
1543             {
1544                 $bibitemno = $results[$i]->{'biblioitemnumber'};
1545                 last;
1546             }
1547         }
1548         if ( $bibitemno == 0 ) {
1549
1550     # warn "need to add new biblioitem so copy last one and make minor changes";
1551             my $sth =
1552               $dbh->prepare(
1553 "SELECT * FROM biblioitems WHERE biblionumber = ? ORDER BY biblioitemnumber DESC"
1554               );
1555             $sth->execute( $data->{'biblionumber'} );
1556             my $biblioitem = $sth->fetchrow_hashref;
1557             $biblioitem->{'volumedate'} =
1558               format_date_in_iso( $data->{planneddate} );
1559             $biblioitem->{'volumeddesc'} =
1560               $data->{serialseq} . ' ('
1561               . format_date( $data->{'planneddate'} ) . ')';
1562             $biblioitem->{'dewey'} = $info->{itemcallnumber};
1563
1564             #FIXME  HDL : I don't understand why you need to call newbiblioitem, as the biblioitem should already be somewhere.
1565             # so I comment it, we can speak of it when you want
1566             # newbiblioitems has been removed from Biblio.pm, as it has a deprecated API now
1567 #             if ( $info->{barcode} )
1568 #             {    # only make biblioitem if we are going to make item also
1569 #                 $bibitemno = newbiblioitem($biblioitem);
1570 #             }
1571         }
1572     }
1573
1574     my $fwk = GetFrameworkCode( $data->{'biblionumber'} );
1575     if ( $info->{barcode} ) {
1576         my @errors;
1577         my $exists = itemdata( $info->{'barcode'} );
1578         push @errors, "barcode_not_unique" if ($exists);
1579         unless ($exists) {
1580             my $marcrecord = MARC::Record->new();
1581             my ( $tag, $subfield ) =
1582               GetMarcFromKohaField( "items.barcode", $fwk );
1583             my $newField =
1584               MARC::Field->new( "$tag", '', '',
1585                 "$subfield" => $info->{barcode} );
1586             $marcrecord->insert_fields_ordered($newField);
1587             if ( $info->{branch} ) {
1588                 my ( $tag, $subfield ) =
1589                   GetMarcFromKohaField( "items.homebranch",
1590                     $fwk );
1591
1592                 #warn "items.homebranch : $tag , $subfield";
1593                 if ( $marcrecord->field($tag) ) {
1594                     $marcrecord->field($tag)
1595                       ->add_subfields( "$subfield" => $info->{branch} );
1596                 }
1597                 else {
1598                     my $newField =
1599                       MARC::Field->new( "$tag", '', '',
1600                         "$subfield" => $info->{branch} );
1601                     $marcrecord->insert_fields_ordered($newField);
1602                 }
1603                 ( $tag, $subfield ) =
1604                   GetMarcFromKohaField( "items.holdingbranch",
1605                     $fwk );
1606
1607                 #warn "items.holdingbranch : $tag , $subfield";
1608                 if ( $marcrecord->field($tag) ) {
1609                     $marcrecord->field($tag)
1610                       ->add_subfields( "$subfield" => $info->{branch} );
1611                 }
1612                 else {
1613                     my $newField =
1614                       MARC::Field->new( "$tag", '', '',
1615                         "$subfield" => $info->{branch} );
1616                     $marcrecord->insert_fields_ordered($newField);
1617                 }
1618             }
1619             if ( $info->{itemcallnumber} ) {
1620                 my ( $tag, $subfield ) =
1621                   GetMarcFromKohaField( "items.itemcallnumber",
1622                     $fwk );
1623
1624                 #warn "items.itemcallnumber : $tag , $subfield";
1625                 if ( $marcrecord->field($tag) ) {
1626                     $marcrecord->field($tag)
1627                       ->add_subfields( "$subfield" => $info->{itemcallnumber} );
1628                 }
1629                 else {
1630                     my $newField =
1631                       MARC::Field->new( "$tag", '', '',
1632                         "$subfield" => $info->{itemcallnumber} );
1633                     $marcrecord->insert_fields_ordered($newField);
1634                 }
1635             }
1636             if ( $info->{notes} ) {
1637                 my ( $tag, $subfield ) =
1638                   GetMarcFromKohaField( "items.itemnotes", $fwk );
1639
1640                 # warn "items.itemnotes : $tag , $subfield";
1641                 if ( $marcrecord->field($tag) ) {
1642                     $marcrecord->field($tag)
1643                       ->add_subfields( "$subfield" => $info->{notes} );
1644                 }
1645                 else {
1646                     my $newField =
1647                       MARC::Field->new( "$tag", '', '',
1648                         "$subfield" => $info->{notes} );
1649                     $marcrecord->insert_fields_ordered($newField);
1650                 }
1651             }
1652             if ( $info->{location} ) {
1653                 my ( $tag, $subfield ) =
1654                   GetMarcFromKohaField( "items.location", $fwk );
1655
1656                 # warn "items.location : $tag , $subfield";
1657                 if ( $marcrecord->field($tag) ) {
1658                     $marcrecord->field($tag)
1659                       ->add_subfields( "$subfield" => $info->{location} );
1660                 }
1661                 else {
1662                     my $newField =
1663                       MARC::Field->new( "$tag", '', '',
1664                         "$subfield" => $info->{location} );
1665                     $marcrecord->insert_fields_ordered($newField);
1666                 }
1667             }
1668             if ( $info->{status} ) {
1669                 my ( $tag, $subfield ) =
1670                   GetMarcFromKohaField( "items.notforloan",
1671                     $fwk );
1672
1673                 # warn "items.notforloan : $tag , $subfield";
1674                 if ( $marcrecord->field($tag) ) {
1675                     $marcrecord->field($tag)
1676                       ->add_subfields( "$subfield" => $info->{status} );
1677                 }
1678                 else {
1679                     my $newField =
1680                       MARC::Field->new( "$tag", '', '',
1681                         "$subfield" => $info->{status} );
1682                     $marcrecord->insert_fields_ordered($newField);
1683                 }
1684             }
1685             if ( C4::Context->preference("RoutingSerials") ) {
1686                 my ( $tag, $subfield ) =
1687                   GetMarcFromKohaField( "items.dateaccessioned",
1688                     $fwk );
1689                 if ( $marcrecord->field($tag) ) {
1690                     $marcrecord->field($tag)
1691                       ->add_subfields( "$subfield" => $now );
1692                 }
1693                 else {
1694                     my $newField =
1695                       MARC::Field->new( "$tag", '', '', "$subfield" => $now );
1696                     $marcrecord->insert_fields_ordered($newField);
1697                 }
1698             }
1699             AddItemFromMarc( $marcrecord, $data->{'biblionumber'} );
1700             return 1;
1701         }
1702         return ( 0, @errors );
1703     }
1704 }
1705
1706 =head2 HasSubscriptionExpired
1707
1708 =over 4
1709
1710 1 or 0 = HasSubscriptionExpired($subscriptionid)
1711
1712 the subscription has expired when the next issue to arrive is out of subscription limit.
1713
1714 return :
1715 1 if true, 0 if false.
1716
1717 =back
1718
1719 =cut
1720
1721 sub HasSubscriptionExpired {
1722     my ($subscriptionid) = @_;
1723     my $dbh              = C4::Context->dbh;
1724     my $subscription     = GetSubscription($subscriptionid);
1725     if (($subscription->{periodicity} % 16)>0){
1726       my $expirationdate   = GetExpirationDate($subscriptionid);
1727       my $query = qq|
1728             SELECT max(planneddate)
1729             FROM   serial
1730             WHERE  subscriptionid=?
1731       |;
1732       my $sth = $dbh->prepare($query);
1733       $sth->execute($subscriptionid);
1734       my ($res) = $sth->fetchrow  ;
1735       my @res=split (/-/,$res);
1736 # warn "date expiration :$expirationdate";
1737       my @endofsubscriptiondate=split(/-/,$expirationdate);
1738       return 1 if ( (@endofsubscriptiondate && Delta_Days($res[0],$res[1],$res[2],
1739                   $endofsubscriptiondate[0],$endofsubscriptiondate[1],$endofsubscriptiondate[2]) <= 0)
1740                   || (!$res));
1741       return 0;
1742     } else {
1743       if ($subscription->{'numberlength'}){
1744         my $countreceived=countissuesfrom($subscriptionid,$subscription->{'startdate'});
1745         return 1 if ($countreceived >$subscription->{'numberlentgh'});
1746               return 0;
1747       } else {
1748               return 0;
1749       }
1750     }
1751     return 0;
1752 }
1753
1754 =head2 SetDistributedto
1755
1756 =over 4
1757
1758 SetDistributedto($distributedto,$subscriptionid);
1759 This function update the value of distributedto for a subscription given on input arg.
1760
1761 =back
1762
1763 =cut
1764
1765 sub SetDistributedto {
1766     my ( $distributedto, $subscriptionid ) = @_;
1767     my $dbh   = C4::Context->dbh;
1768     my $query = qq|
1769         UPDATE subscription
1770         SET    distributedto=?
1771         WHERE  subscriptionid=?
1772     |;
1773     my $sth = $dbh->prepare($query);
1774     $sth->execute( $distributedto, $subscriptionid );
1775 }
1776
1777 =head2 DelSubscription
1778
1779 =over 4
1780
1781 DelSubscription($subscriptionid)
1782 this function delete the subscription which has $subscriptionid as id.
1783
1784 =back
1785
1786 =cut
1787
1788 sub DelSubscription {
1789     my ($subscriptionid) = @_;
1790     my $dbh = C4::Context->dbh;
1791     $subscriptionid = $dbh->quote($subscriptionid);
1792     $dbh->do("DELETE FROM subscription WHERE subscriptionid=$subscriptionid");
1793     $dbh->do(
1794         "DELETE FROM subscriptionhistory WHERE subscriptionid=$subscriptionid");
1795     $dbh->do("DELETE FROM serial WHERE subscriptionid=$subscriptionid");
1796     
1797     &logaction(C4::Context->userenv->{'number'},"SERIAL","DELETE",$subscriptionid,"") 
1798         if C4::Context->preference("SubscriptionLog");
1799 }
1800
1801 =head2 DelIssue
1802
1803 =over 4
1804
1805 DelIssue($serialseq,$subscriptionid)
1806 this function delete an issue which has $serialseq and $subscriptionid given on input arg.
1807
1808 =back
1809
1810 =cut
1811
1812 sub DelIssue {
1813     my ( $dataissue) = @_;
1814     my $dbh   = C4::Context->dbh;
1815     ### TODO Add itemdeletion. Would need to get itemnumbers. Should be in a pref ?
1816     
1817     my $query = qq|
1818         DELETE FROM serial
1819         WHERE       serialid= ?
1820         AND         subscriptionid= ?
1821     |;
1822     my $mainsth = $dbh->prepare($query);
1823     $mainsth->execute( $dataissue->{'serialid'}, $dataissue->{'subscriptionid'});
1824
1825     #Delete element from subscription history
1826     $query = "SELECT * FROM   subscription WHERE  subscriptionid = ?";
1827     my $sth   = $dbh->prepare($query);
1828     $sth->execute($dataissue->{'subscriptionid'});
1829     my $val = $sth->fetchrow_hashref;
1830     unless ( $val->{manualhistory} ) {
1831         my $query = qq|
1832           SELECT * FROM subscriptionhistory
1833           WHERE       subscriptionid= ?
1834       |;
1835         my $sth = $dbh->prepare($query);
1836         $sth->execute($dataissue->{'subscriptionid'});
1837         my $data = $sth->fetchrow_hashref;
1838         my $serialseq= $dataissue->{'serialseq'};
1839         $data->{'missinglist'}  =~ s/\b$serialseq\b//;
1840         $data->{'recievedlist'} =~ s/\b$serialseq\b//;
1841         my $strsth = "UPDATE subscriptionhistory SET "
1842           . join( ",",
1843             map { join( "=", $_, $dbh->quote( $data->{$_} ) ) } keys %$data )
1844           . " WHERE subscriptionid=?";
1845         $sth = $dbh->prepare($strsth);
1846         $sth->execute($dataissue->{'subscriptionid'});
1847     }
1848     
1849     return $mainsth->rows;
1850 }
1851
1852 =head2 GetLateOrMissingIssues
1853
1854 =over 4
1855
1856 ($count,@issuelist) = &GetLateMissingIssues($supplierid,$serialid)
1857
1858 this function select missing issues on database - where serial.status = 4 or serial.status=3 or planneddate<now
1859
1860 return :
1861 a count of the number of missing issues
1862 the issuelist into a table. Each line of this table containts a ref to a hash which it containts
1863 name,title,planneddate,serialseq,serial.subscriptionid from tables : subscription, serial & biblio
1864
1865 =back
1866
1867 =cut
1868
1869 sub GetLateOrMissingIssues {
1870     my ( $supplierid, $serialid,$order ) = @_;
1871     my $dbh = C4::Context->dbh;
1872     my $sth;
1873     my $byserial = '';
1874     if ($serialid) {
1875         $byserial = "and serialid = " . $serialid;
1876     }
1877     if ($order){
1878       $order.=", title";
1879     } else {
1880       $order="title";
1881     }
1882     if ($supplierid) {
1883         $sth = $dbh->prepare(
1884 "SELECT
1885    serialid,
1886    aqbooksellerid,
1887    name,
1888    biblio.title,
1889    planneddate,
1890    serialseq,
1891    serial.status,
1892    serial.subscriptionid,
1893    claimdate
1894 FROM      serial 
1895 LEFT JOIN subscription  ON serial.subscriptionid=subscription.subscriptionid 
1896 LEFT JOIN biblio        ON subscription.biblionumber=biblio.biblionumber
1897 LEFT JOIN aqbooksellers ON subscription.aqbooksellerid = aqbooksellers.id
1898 WHERE subscription.subscriptionid = serial.subscriptionid 
1899 AND (serial.STATUS = 4 OR ((planneddate < now() AND serial.STATUS =1) OR serial.STATUS = 3))
1900 AND subscription.aqbooksellerid=$supplierid
1901 $byserial
1902 ORDER BY $order"
1903         );
1904     }
1905     else {
1906         $sth = $dbh->prepare(
1907 "SELECT 
1908    serialid,
1909    aqbooksellerid,
1910    name,
1911    biblio.title,
1912    planneddate,
1913    serialseq,
1914    serial.status,
1915    serial.subscriptionid,
1916    claimdate
1917 FROM serial 
1918 LEFT JOIN subscription 
1919 ON serial.subscriptionid=subscription.subscriptionid 
1920 LEFT JOIN biblio 
1921 ON subscription.biblionumber=biblio.biblionumber
1922 LEFT JOIN aqbooksellers 
1923 ON subscription.aqbooksellerid = aqbooksellers.id
1924 WHERE 
1925    subscription.subscriptionid = serial.subscriptionid 
1926 AND (serial.STATUS = 4 OR ((planneddate < now() AND serial.STATUS =1) OR serial.STATUS = 3))
1927 $byserial
1928 ORDER BY $order"
1929         );
1930     }
1931     $sth->execute;
1932     my @issuelist;
1933     my $last_title;
1934     my $odd   = 0;
1935     my $count = 0;
1936     while ( my $line = $sth->fetchrow_hashref ) {
1937         $odd++ unless $line->{title} eq $last_title;
1938         $last_title = $line->{title} if ( $line->{title} );
1939         $line->{planneddate} = format_date( $line->{planneddate} );
1940         $line->{claimdate}   = format_date( $line->{claimdate} );
1941         $line->{"status".$line->{status}}   = 1;
1942         $line->{'odd'} = 1 if $odd % 2;
1943         $count++;
1944         push @issuelist, $line;
1945     }
1946     return $count, @issuelist;
1947 }
1948
1949 =head2 removeMissingIssue
1950
1951 =over 4
1952
1953 removeMissingIssue($subscriptionid)
1954
1955 this function removes an issue from being part of the missing string in 
1956 subscriptionlist.missinglist column
1957
1958 called when a missing issue is found from the serials-recieve.pl file
1959
1960 =back
1961
1962 =cut
1963
1964 sub removeMissingIssue {
1965     my ( $sequence, $subscriptionid ) = @_;
1966     my $dbh = C4::Context->dbh;
1967     my $sth =
1968       $dbh->prepare(
1969         "SELECT * FROM subscriptionhistory WHERE subscriptionid = ?");
1970     $sth->execute($subscriptionid);
1971     my $data              = $sth->fetchrow_hashref;
1972     my $missinglist       = $data->{'missinglist'};
1973     my $missinglistbefore = $missinglist;
1974
1975     # warn $missinglist." before";
1976     $missinglist =~ s/($sequence)//;
1977
1978     # warn $missinglist." after";
1979     if ( $missinglist ne $missinglistbefore ) {
1980         $missinglist =~ s/\|\s\|/\|/g;
1981         $missinglist =~ s/^\| //g;
1982         $missinglist =~ s/\|$//g;
1983         my $sth2 = $dbh->prepare(
1984             "UPDATE subscriptionhistory
1985                                        SET missinglist = ?
1986                                        WHERE subscriptionid = ?"
1987         );
1988         $sth2->execute( $missinglist, $subscriptionid );
1989     }
1990 }
1991
1992 =head2 updateClaim
1993
1994 =over 4
1995
1996 &updateClaim($serialid)
1997
1998 this function updates the time when a claim is issued for late/missing items
1999
2000 called from claims.pl file
2001
2002 =back
2003
2004 =cut
2005
2006 sub updateClaim {
2007     my ($serialid) = @_;
2008     my $dbh        = C4::Context->dbh;
2009     my $sth        = $dbh->prepare(
2010         "UPDATE serial SET claimdate = now()
2011                                    WHERE serialid = ?
2012                                    "
2013     );
2014     $sth->execute($serialid);
2015 }
2016
2017 =head2 getsupplierbyserialid
2018
2019 =over 4
2020
2021 ($result) = &getsupplierbyserialid($serialid)
2022
2023 this function is used to find the supplier id given a serial id
2024
2025 return :
2026 hashref containing serialid, subscriptionid, and aqbooksellerid
2027
2028 =back
2029
2030 =cut
2031
2032 sub getsupplierbyserialid {
2033     my ($serialid) = @_;
2034     my $dbh        = C4::Context->dbh;
2035     my $sth        = $dbh->prepare(
2036         "SELECT serialid, serial.subscriptionid, aqbooksellerid
2037          FROM serial 
2038          LEFT JOIN subscription ON serial.subscriptionid = subscription.subscriptionid
2039          WHERE serialid = ?
2040                                    "
2041     );
2042     $sth->execute($serialid);
2043     my $line   = $sth->fetchrow_hashref;
2044     my $result = $line->{'aqbooksellerid'};
2045     return $result;
2046 }
2047
2048 =head2 check_routing
2049
2050 =over 4
2051
2052 ($result) = &check_routing($subscriptionid)
2053
2054 this function checks to see if a serial has a routing list and returns the count of routingid
2055 used to show either an 'add' or 'edit' link
2056 =back
2057
2058 =cut
2059
2060 sub check_routing {
2061     my ($subscriptionid) = @_;
2062     my $dbh              = C4::Context->dbh;
2063     my $sth              = $dbh->prepare(
2064 "SELECT count(routingid) routingids FROM subscription LEFT JOIN subscriptionroutinglist 
2065                               ON subscription.subscriptionid = subscriptionroutinglist.subscriptionid
2066                               WHERE subscription.subscriptionid = ? ORDER BY ranking ASC
2067                               "
2068     );
2069     $sth->execute($subscriptionid);
2070     my $line   = $sth->fetchrow_hashref;
2071     my $result = $line->{'routingids'};
2072     return $result;
2073 }
2074
2075 =head2 addroutingmember
2076
2077 =over 4
2078
2079 &addroutingmember($borrowernumber,$subscriptionid)
2080
2081 this function takes a borrowernumber and subscriptionid and add the member to the
2082 routing list for that serial subscription and gives them a rank on the list
2083 of either 1 or highest current rank + 1
2084
2085 =back
2086
2087 =cut
2088
2089 sub addroutingmember {
2090     my ( $borrowernumber, $subscriptionid ) = @_;
2091     my $rank;
2092     my $dbh = C4::Context->dbh;
2093     my $sth =
2094       $dbh->prepare(
2095 "SELECT max(ranking) rank FROM subscriptionroutinglist WHERE subscriptionid = ?"
2096       );
2097     $sth->execute($subscriptionid);
2098     while ( my $line = $sth->fetchrow_hashref ) {
2099         if ( $line->{'rank'} > 0 ) {
2100             $rank = $line->{'rank'} + 1;
2101         }
2102         else {
2103             $rank = 1;
2104         }
2105     }
2106     $sth =
2107       $dbh->prepare(
2108 "INSERT INTO subscriptionroutinglist (subscriptionid,borrowernumber,ranking) VALUES (?,?,?)"
2109       );
2110     $sth->execute( $subscriptionid, $borrowernumber, $rank );
2111 }
2112
2113 =head2 reorder_members
2114
2115 =over 4
2116
2117 &reorder_members($subscriptionid,$routingid,$rank)
2118
2119 this function is used to reorder the routing list
2120
2121 it takes the routingid of the member one wants to re-rank and the rank it is to move to
2122 - it gets all members on list puts their routingid's into an array
2123 - removes the one in the array that is $routingid
2124 - then reinjects $routingid at point indicated by $rank
2125 - then update the database with the routingids in the new order
2126
2127 =back
2128
2129 =cut
2130
2131 sub reorder_members {
2132     my ( $subscriptionid, $routingid, $rank ) = @_;
2133     my $dbh = C4::Context->dbh;
2134     my $sth =
2135       $dbh->prepare(
2136 "SELECT * FROM subscriptionroutinglist WHERE subscriptionid = ? ORDER BY ranking ASC"
2137       );
2138     $sth->execute($subscriptionid);
2139     my @result;
2140     while ( my $line = $sth->fetchrow_hashref ) {
2141         push( @result, $line->{'routingid'} );
2142     }
2143
2144     # To find the matching index
2145     my $i;
2146     my $key = -1;    # to allow for 0 being a valid response
2147     for ( $i = 0 ; $i < @result ; $i++ ) {
2148         if ( $routingid == $result[$i] ) {
2149             $key = $i;    # save the index
2150             last;
2151         }
2152     }
2153
2154     # if index exists in array then move it to new position
2155     if ( $key > -1 && $rank > 0 ) {
2156         my $new_rank = $rank -
2157           1;    # $new_rank is what you want the new index to be in the array
2158         my $moving_item = splice( @result, $key, 1 );
2159         splice( @result, $new_rank, 0, $moving_item );
2160     }
2161     for ( my $j = 0 ; $j < @result ; $j++ ) {
2162         my $sth =
2163           $dbh->prepare( "UPDATE subscriptionroutinglist SET ranking = '"
2164               . ( $j + 1 )
2165               . "' WHERE routingid = '"
2166               . $result[$j]
2167               . "'" );
2168         $sth->execute;
2169     }
2170 }
2171
2172 =head2 delroutingmember
2173
2174 =over 4
2175
2176 &delroutingmember($routingid,$subscriptionid)
2177
2178 this function either deletes one member from routing list if $routingid exists otherwise
2179 deletes all members from the routing list
2180
2181 =back
2182
2183 =cut
2184
2185 sub delroutingmember {
2186
2187 # if $routingid exists then deletes that row otherwise deletes all with $subscriptionid
2188     my ( $routingid, $subscriptionid ) = @_;
2189     my $dbh = C4::Context->dbh;
2190     if ($routingid) {
2191         my $sth =
2192           $dbh->prepare(
2193             "DELETE FROM subscriptionroutinglist WHERE routingid = ?");
2194         $sth->execute($routingid);
2195         reorder_members( $subscriptionid, $routingid );
2196     }
2197     else {
2198         my $sth =
2199           $dbh->prepare(
2200             "DELETE FROM subscriptionroutinglist WHERE subscriptionid = ?");
2201         $sth->execute($subscriptionid);
2202     }
2203 }
2204
2205 =head2 getroutinglist
2206
2207 =over 4
2208
2209 ($count,@routinglist) = &getroutinglist($subscriptionid)
2210
2211 this gets the info from the subscriptionroutinglist for $subscriptionid
2212
2213 return :
2214 a count of the number of members on routinglist
2215 the routinglist into a table. Each line of this table containts a ref to a hash which containts
2216 routingid - a unique id, borrowernumber, ranking, and biblionumber of subscription
2217
2218 =back
2219
2220 =cut
2221
2222 sub getroutinglist {
2223     my ($subscriptionid) = @_;
2224     my $dbh              = C4::Context->dbh;
2225     my $sth              = $dbh->prepare(
2226         "SELECT routingid, borrowernumber,
2227                               ranking, biblionumber 
2228          FROM subscription 
2229          LEFT JOIN subscriptionroutinglist ON subscription.subscriptionid = subscriptionroutinglist.subscriptionid
2230          WHERE subscription.subscriptionid = ? ORDER BY ranking ASC
2231                               "
2232     );
2233     $sth->execute($subscriptionid);
2234     my @routinglist;
2235     my $count = 0;
2236     while ( my $line = $sth->fetchrow_hashref ) {
2237         $count++;
2238         push( @routinglist, $line );
2239     }
2240     return ( $count, @routinglist );
2241 }
2242
2243 =head2 countissuesfrom
2244
2245 =over 4
2246
2247 $result = &countissuesfrom($subscriptionid,$startdate)
2248
2249
2250 =back
2251
2252 =cut
2253
2254 sub countissuesfrom {
2255     my ($subscriptionid,$startdate) = @_;
2256     my $dbh              = C4::Context->dbh;
2257     my $query = qq|
2258             SELECT count(*)
2259             FROM   serial
2260             WHERE  subscriptionid=?
2261             AND serial.publisheddate>?
2262         |;
2263     my $sth=$dbh->prepare($query);
2264     $sth->execute($subscriptionid, $startdate);
2265     my ($countreceived)=$sth->fetchrow;
2266     return $countreceived;  
2267 }
2268
2269 =head2 abouttoexpire
2270
2271 =over 4
2272
2273 $result = &abouttoexpire($subscriptionid)
2274
2275 this function alerts you to the penultimate issue for a serial subscription
2276
2277 returns 1 - if this is the penultimate issue
2278 returns 0 - if not
2279
2280 =back
2281
2282 =cut
2283
2284 sub abouttoexpire {
2285     my ($subscriptionid) = @_;
2286     my $dbh              = C4::Context->dbh;
2287     my $subscription     = GetSubscription($subscriptionid);
2288     my $per = $subscription->{'periodicity'};
2289     if ($per % 16>0){
2290       my $expirationdate   = GetExpirationDate($subscriptionid);
2291       my $sth =
2292         $dbh->prepare(
2293           "select max(planneddate) from serial where subscriptionid=?");
2294       $sth->execute($subscriptionid);
2295       my ($res) = $sth->fetchrow ;
2296 #        warn "date expiration : ".$expirationdate." date courante ".$res;
2297       my @res=split /-/,$res;
2298       @res=Date::Calc::Today if ($res[0]*$res[1]==0);
2299       my @endofsubscriptiondate=split/-/,$expirationdate;
2300       my $x;
2301       if ( $per == 1 ) {$x=7;}
2302       if ( $per == 2 ) {$x=7; }
2303       if ( $per == 3 ) {$x=14;}
2304       if ( $per == 4 ) { $x = 21; }
2305       if ( $per == 5 ) { $x = 31; }
2306       if ( $per == 6 ) { $x = 62; }
2307       if ( $per == 7 || $per == 8 ) { $x = 93; }
2308       if ( $per == 9 )  { $x = 190; }
2309       if ( $per == 10 ) { $x = 365; }
2310       if ( $per == 11 ) { $x = 730; }
2311       my @datebeforeend=Add_Delta_Days(  $endofsubscriptiondate[0],$endofsubscriptiondate[1],$endofsubscriptiondate[2],
2312                     - (3 * $x)) if (@endofsubscriptiondate && $endofsubscriptiondate[0]*$endofsubscriptiondate[1]*$endofsubscriptiondate[2]);
2313               # warn "DATE BEFORE END: $datebeforeend";
2314       return 1 if ( @res && 
2315                     (@datebeforeend && 
2316                         Delta_Days($res[0],$res[1],$res[2],
2317                         $datebeforeend[0],$datebeforeend[1],$datebeforeend[2]) <= 0) && 
2318                     (@endofsubscriptiondate && 
2319                         Delta_Days($res[0],$res[1],$res[2],
2320                         $endofsubscriptiondate[0],$endofsubscriptiondate[1],$endofsubscriptiondate[2]) >= 0) );
2321     return 0;
2322    } elsif ($subscription->{numberlength}>0) {
2323     return (countissuesfrom($subscriptionid,$subscription->{'startdate'}) >=$subscription->{numberlength}-1);
2324    } else {return 0}
2325 }
2326
2327 =head2 old_newsubscription
2328
2329 =over 4
2330
2331 ($subscriptionid) = &old_newsubscription($auser,$aqbooksellerid,$cost,$aqbudgetid,$biblionumber,
2332                         $startdate,$periodicity,$firstacquidate,$dow,$irregularity,$numberpattern,$numberlength,$weeklength,$monthlength,
2333                         $add1,$every1,$whenmorethan1,$setto1,$lastvalue1,
2334                         $add2,$every2,$whenmorethan2,$setto2,$lastvalue2,
2335                         $add3,$every3,$whenmorethan3,$setto3,$lastvalue3,
2336                         $numberingmethod, $status, $callnumber, $notes, $hemisphere)
2337
2338 this function is similar to the NewSubscription subroutine but has a few different
2339 values passed in 
2340 $firstacquidate - date of first serial issue to arrive
2341 $irregularity - the issues not expected separated by a '|'
2342 - eg. monthly issue but not expecting issue for june and july would have $irregularity of '6|7'
2343 $numberpattern - the number for an array of labels to reconstruct the javascript correctly in the 
2344    subscription-add.tmpl file
2345 $callnumber - display the callnumber of the serial
2346 $hemisphere - either 2 = southern hemisphere or 1 = northern hemisphere - used for quarterly serials
2347
2348 return :
2349 the $subscriptionid number of the new subscription
2350
2351 =back
2352
2353 =cut
2354
2355 sub old_newsubscription {
2356     my (
2357         $auser,         $aqbooksellerid,  $cost,          $aqbudgetid,
2358         $biblionumber,  $startdate,       $periodicity,   $firstacquidate,
2359         $dow,           $irregularity,    $numberpattern, $numberlength,
2360         $weeklength,    $monthlength,     $add1,          $every1,
2361         $whenmorethan1, $setto1,          $lastvalue1,    $add2,
2362         $every2,        $whenmorethan2,   $setto2,        $lastvalue2,
2363         $add3,          $every3,          $whenmorethan3, $setto3,
2364         $lastvalue3,    $numberingmethod, $status,        $callnumber,
2365         $notes,         $hemisphere
2366     ) = @_;
2367     my $dbh = C4::Context->dbh;
2368
2369     #save subscription
2370     my $sth = $dbh->prepare(
2371 "insert into subscription (librarian,aqbooksellerid,cost,aqbudgetid,biblionumber,
2372                                                         startdate,periodicity,firstacquidate,dow,irregularity,numberpattern,numberlength,weeklength,monthlength,
2373                                                                 add1,every1,whenmorethan1,setto1,lastvalue1,
2374                                                                 add2,every2,whenmorethan2,setto2,lastvalue2,
2375                                                                 add3,every3,whenmorethan3,setto3,lastvalue3,
2376                                                                 numberingmethod, status, callnumber, notes, hemisphere) values
2377                                                           (?,?,?,?,?,?,?,?,?,?,?,
2378                                                                                            ?,?,?,?,?,?,?,?,?,?,?,
2379                                                                                            ?,?,?,?,?,?,?,?,?,?,?,?)"
2380     );
2381     $sth->execute(
2382         $auser,         $aqbooksellerid,
2383         $cost,          $aqbudgetid,
2384         $biblionumber,  format_date_in_iso($startdate),
2385         $periodicity,   format_date_in_iso($firstacquidate),
2386         $dow,           $irregularity,
2387         $numberpattern, $numberlength,
2388         $weeklength,    $monthlength,
2389         $add1,          $every1,
2390         $whenmorethan1, $setto1,
2391         $lastvalue1,    $add2,
2392         $every2,        $whenmorethan2,
2393         $setto2,        $lastvalue2,
2394         $add3,          $every3,
2395         $whenmorethan3, $setto3,
2396         $lastvalue3,    $numberingmethod,
2397         $status,        $callnumber,
2398         $notes,         $hemisphere
2399     );
2400
2401     #then create the 1st waited number
2402     my $subscriptionid = $dbh->{'mysql_insertid'};
2403     my $enddate        = GetExpirationDate($subscriptionid);
2404
2405     $sth =
2406       $dbh->prepare(
2407 "insert into subscriptionhistory (biblionumber, subscriptionid, histstartdate, enddate, missinglist, recievedlist, opacnote, librariannote) values (?,?,?,?,?,?,?,?)"
2408       );
2409     $sth->execute(
2410         $biblionumber, $subscriptionid,
2411         format_date_in_iso($startdate),
2412         format_date_in_iso($enddate),
2413         "", "", "", $notes
2414     );
2415
2416    # reread subscription to get a hash (for calculation of the 1st issue number)
2417     $sth =
2418       $dbh->prepare("select * from subscription where subscriptionid = ? ");
2419     $sth->execute($subscriptionid);
2420     my $val = $sth->fetchrow_hashref;
2421
2422     # calculate issue number
2423     my $serialseq = GetSeq($val);
2424     $sth =
2425       $dbh->prepare(
2426 "insert into serial (serialseq,subscriptionid,biblionumber,status, planneddate) values (?,?,?,?,?)"
2427       );
2428     $sth->execute( $serialseq, $subscriptionid, $val->{'biblionumber'},
2429         1, format_date_in_iso($startdate) );
2430     return $subscriptionid;
2431 }
2432
2433 =head2 old_modsubscription
2434
2435 =over 4
2436
2437 ($subscriptionid) = &old_modsubscription($auser,$aqbooksellerid,$cost,$aqbudgetid,$biblionumber,
2438                         $startdate,$periodicity,$firstacquidate,$dow,$irregularity,$numberpattern,$numberlength,$weeklength,$monthlength,
2439                         $add1,$every1,$whenmorethan1,$setto1,$lastvalue1,
2440                         $add2,$every2,$whenmorethan2,$setto2,$lastvalue2,
2441                         $add3,$every3,$whenmorethan3,$setto3,$lastvalue3,
2442                         $numberingmethod, $status, $callnumber, $notes, $hemisphere, $subscriptionid)
2443
2444 this function is similar to the ModSubscription subroutine but has a few different
2445 values passed in 
2446 $firstacquidate - date of first serial issue to arrive
2447 $irregularity - the issues not expected separated by a '|'
2448 - eg. monthly issue but not expecting issue for june and july would have $irregularity of '6|7'
2449 $numberpattern - the number for an array of labels to reconstruct the javascript correctly in the 
2450    subscription-add.tmpl file
2451 $callnumber - display the callnumber of the serial
2452 $hemisphere - either 2 = southern hemisphere or 1 = northern hemisphere - used for quarterly serials
2453
2454 =back
2455
2456 =cut
2457
2458 sub old_modsubscription {
2459     my (
2460         $auser,        $aqbooksellerid, $cost,           $aqbudgetid,
2461         $startdate,    $periodicity,    $firstacquidate, $dow,
2462         $irregularity, $numberpattern,  $numberlength,   $weeklength,
2463         $monthlength,  $add1,           $every1,         $whenmorethan1,
2464         $setto1,       $lastvalue1,     $innerloop1,     $add2,
2465         $every2,       $whenmorethan2,  $setto2,         $lastvalue2,
2466         $innerloop2,   $add3,           $every3,         $whenmorethan3,
2467         $setto3,       $lastvalue3,     $innerloop3,     $numberingmethod,
2468         $status,       $biblionumber,   $callnumber,     $notes,
2469         $hemisphere,   $subscriptionid
2470     ) = @_;
2471     my $dbh = C4::Context->dbh;
2472     my $sth = $dbh->prepare(
2473 "update subscription set librarian=?, aqbooksellerid=?,cost=?,aqbudgetid=?,startdate=?,
2474                                                    periodicity=?,firstacquidate=?,dow=?,irregularity=?,numberpattern=?,numberlength=?,weeklength=?,monthlength=?,
2475                                                   add1=?,every1=?,whenmorethan1=?,setto1=?,lastvalue1=?,innerloop1=?,
2476                                                   add2=?,every2=?,whenmorethan2=?,setto2=?,lastvalue2=?,innerloop2=?,
2477                                                   add3=?,every3=?,whenmorethan3=?,setto3=?,lastvalue3=?,innerloop3=?,
2478                                                   numberingmethod=?, status=?, biblionumber=?, callnumber=?, notes=?, hemisphere=? where subscriptionid = ?"
2479     );
2480     $sth->execute(
2481         $auser,        $aqbooksellerid, $cost,           $aqbudgetid,
2482         $startdate,    $periodicity,    $firstacquidate, $dow,
2483         $irregularity, $numberpattern,  $numberlength,   $weeklength,
2484         $monthlength,  $add1,           $every1,         $whenmorethan1,
2485         $setto1,       $lastvalue1,     $innerloop1,     $add2,
2486         $every2,       $whenmorethan2,  $setto2,         $lastvalue2,
2487         $innerloop2,   $add3,           $every3,         $whenmorethan3,
2488         $setto3,       $lastvalue3,     $innerloop3,     $numberingmethod,
2489         $status,       $biblionumber,   $callnumber,     $notes,
2490         $hemisphere,   $subscriptionid
2491     );
2492     $sth->finish;
2493
2494     $sth =
2495       $dbh->prepare("select * from subscription where subscriptionid = ? ");
2496     $sth->execute($subscriptionid);
2497     my $val = $sth->fetchrow_hashref;
2498
2499     # calculate issue number
2500     my $serialseq = Get_Seq($val);
2501     $sth =
2502       $dbh->prepare("UPDATE serial SET serialseq = ? WHERE subscriptionid = ?");
2503     $sth->execute( $serialseq, $subscriptionid );
2504
2505     my $enddate = subscriptionexpirationdate($subscriptionid);
2506     $sth = $dbh->prepare("update subscriptionhistory set enddate=?");
2507     $sth->execute( format_date_in_iso($enddate) );
2508 }
2509
2510 =head2 old_getserials
2511
2512 =over 4
2513
2514 ($totalissues,@serials) = &old_getserials($subscriptionid)
2515
2516 this function get a hashref of serials and the total count of them
2517
2518 return :
2519 $totalissues - number of serial lines
2520 the serials into a table. Each line of this table containts a ref to a hash which it containts
2521 serialid, serialseq, status,planneddate,notes,routingnotes  from tables : serial where status is not 2, 4, or 5
2522
2523 =back
2524
2525 =cut
2526
2527 sub old_getserials {
2528     my ($subscriptionid) = @_;
2529     my $dbh = C4::Context->dbh;
2530
2531     # status = 2 is "arrived"
2532     my $sth =
2533       $dbh->prepare(
2534 "select serialid,serialseq, status, planneddate,notes,routingnotes from serial where subscriptionid = ? and status <>2 and status <>4 and status <>5"
2535       );
2536     $sth->execute($subscriptionid);
2537     my @serials;
2538     my $num = 1;
2539     while ( my $line = $sth->fetchrow_hashref ) {
2540         $line->{ "status" . $line->{status} } =
2541           1;    # fills a "statusX" value, used for template status select list
2542         $line->{"planneddate"} = format_date( $line->{"planneddate"} );
2543         $line->{"num"}         = $num;
2544         $num++;
2545         push @serials, $line;
2546     }
2547     $sth = $dbh->prepare("select count(*) from serial where subscriptionid=?");
2548     $sth->execute($subscriptionid);
2549     my ($totalissues) = $sth->fetchrow;
2550     return ( $totalissues, @serials );
2551 }
2552
2553 =head2 GetNextDate
2554
2555 ($resultdate) = &GetNextDate($planneddate,$subscription)
2556
2557 this function is an extension of GetNextDate which allows for checking for irregularity
2558
2559 it takes the planneddate and will return the next issue's date and will skip dates if there
2560 exists an irregularity
2561 - eg if periodicity is monthly and $planneddate is 2007-02-10 but if March and April is to be 
2562 skipped then the returned date will be 2007-05-10
2563
2564 return :
2565 $resultdate - then next date in the sequence
2566
2567 Return 0 if periodicity==0
2568
2569 =cut
2570 sub in_array { # used in next sub down
2571   my ($val,@elements) = @_;
2572   foreach my $elem(@elements) {
2573     if($val == $elem) {
2574             return 1;
2575     }
2576   }
2577   return 0;
2578 }
2579
2580 sub GetNextDate(@) {
2581     my ( $planneddate, $subscription ) = @_;
2582     my @irreg = split( /\,/, $subscription->{irregularity} );
2583
2584     #date supposed to be in ISO.
2585     
2586     my ( $year, $month, $day ) = split(/-/, $planneddate);
2587     $month=1 unless ($month);
2588     $day=1 unless ($day);
2589     my @resultdate;
2590
2591     #       warn "DOW $dayofweek";
2592     if ( $subscription->{periodicity} % 16 == 0 ) {
2593       return 0;
2594     }  
2595     if ( $subscription->{periodicity} == 1 ) {
2596         my $dayofweek = eval{Day_of_Week( $year,$month, $day )};
2597         if ($@){warn "year month day : $year $month $day $subscription->{subscriptionid} : $@";}
2598         else {    
2599           for ( my $i = 0 ; $i < @irreg ; $i++ ) {
2600               $dayofweek = 0 if ( $dayofweek == 7 ); 
2601               if ( in_array( ($dayofweek + 1), @irreg ) ) {
2602                   ($year,$month,$day) = Add_Delta_Days($year,$month, $day , 1 );
2603                   $dayofweek++;
2604               }
2605           }
2606           @resultdate = Add_Delta_Days($year,$month, $day , 1 );
2607         }    
2608     }
2609     if ( $subscription->{periodicity} == 2 ) {
2610         my ($wkno,$year) = eval {Week_of_Year( $year,$month, $day )};
2611         if ($@){warn "year month day : $year $month $day $subscription->{subscriptionid} : $@";}
2612         else {    
2613           for ( my $i = 0 ; $i < @irreg ; $i++ ) {
2614               if ( $irreg[$i] == (($wkno!=51)?($wkno +1) % 52 :52)) {
2615                   ($year,$month,$day) = Add_Delta_Days($year,$month, $day , 7 );
2616                   $wkno=(($wkno!=51)?($wkno +1) % 52 :52);
2617               }
2618           }
2619           @resultdate = Add_Delta_Days( $year,$month, $day, 7);
2620         }        
2621     }
2622     if ( $subscription->{periodicity} == 3 ) {        
2623         my ($wkno,$year) = eval {Week_of_Year( $year,$month, $day )};
2624         if ($@){warn "year month day : $year $month $day $subscription->{subscriptionid} : $@";}
2625         else {    
2626           for ( my $i = 0 ; $i < @irreg ; $i++ ) {
2627               if ( $irreg[$i] == (($wkno!=50)?($wkno +2) % 52 :52)) {
2628               ### BUGFIX was previously +1 ^
2629                   ($year,$month,$day) = Add_Delta_Days($year,$month, $day , 14 );
2630                   $wkno=(($wkno!=50)?($wkno +2) % 52 :52);
2631               }
2632           }
2633           @resultdate = Add_Delta_Days($year,$month, $day , 14 );
2634         }        
2635     }
2636     if ( $subscription->{periodicity} == 4 ) {
2637         my ($wkno,$year) = eval {Week_of_Year( $year,$month, $day )};
2638         if ($@){warn "annĂ©e mois jour : $year $month $day $subscription->{subscriptionid} : $@";}
2639         else {    
2640           for ( my $i = 0 ; $i < @irreg ; $i++ ) {
2641               if ( $irreg[$i] == (($wkno!=49)?($wkno +3) % 52 :52)) {
2642                   ($year,$month,$day) = Add_Delta_Days($year,$month, $day , 21 );
2643                   $wkno=(($wkno!=49)?($wkno +3) % 52 :52);
2644               }
2645           }
2646           @resultdate = Add_Delta_Days($year,$month, $day , 21 );
2647         }        
2648     }
2649     my $tmpmonth=$month;
2650     if ($year && $month && $day){
2651     if ( $subscription->{periodicity} == 5 ) {
2652           for ( my $i = 0 ; $i < @irreg ; $i++ ) {
2653               if ( $irreg[$i] == (($tmpmonth!=11)?($tmpmonth +1) % 12 :12)) {
2654                   ($year,$month,$day) = Add_Delta_YMD($year,$month, $day ,0,1,0 );
2655                   $tmpmonth=(($tmpmonth!=11)?($tmpmonth +1) % 12 :12);
2656               }
2657           }        
2658           @resultdate = Add_Delta_YMD($year,$month, $day ,0,1,0 );
2659     }
2660     if ( $subscription->{periodicity} == 6 ) {
2661           for ( my $i = 0 ; $i < @irreg ; $i++ ) {
2662               if ( $irreg[$i] == (($tmpmonth!=10)?($tmpmonth +2) % 12 :12)) {
2663                   ($year,$month,$day) = Add_Delta_YMD($year,$month, $day ,0,2,0 );
2664                   $tmpmonth=(($tmpmonth!=10)?($tmpmonth + 2) % 12 :12);
2665               }
2666           }
2667           @resultdate = Add_Delta_YMD($year,$month, $day, 0, 2,0 );
2668     }
2669     if ( $subscription->{periodicity} == 7 ) {
2670         for ( my $i = 0 ; $i < @irreg ; $i++ ) {
2671             if ( $irreg[$i] == (($tmpmonth!=9)?($tmpmonth +3) % 12 :12)) {
2672                 ($year,$month,$day) = Add_Delta_YMD($year,$month, $day, 0, 3,0 );
2673                 $tmpmonth=(($tmpmonth!=9)?($tmpmonth + 3) % 12 :12);
2674             }
2675         }
2676         @resultdate = Add_Delta_YMD($year,$month, $day, 0, 3, 0);
2677     }
2678     if ( $subscription->{periodicity} == 8 ) {
2679         for ( my $i = 0 ; $i < @irreg ; $i++ ) {
2680             if ( $irreg[$i] == (($tmpmonth!=9)?($tmpmonth +3) % 12 :12)) {
2681                 ($year,$month,$day) = Add_Delta_YMD($year,$month, $day, 0, 3,0 );
2682                 $tmpmonth=(($tmpmonth!=9)?($tmpmonth + 3) % 12 :12);
2683             }
2684         }
2685         @resultdate = Add_Delta_YMD($year,$month, $day, 0, 3, 0);
2686     }
2687     if ( $subscription->{periodicity} == 9 ) {
2688         for ( my $i = 0 ; $i < @irreg ; $i++ ) {
2689             if ( $irreg[$i] == (($tmpmonth!=9)?($tmpmonth +3) % 12 :12)) {
2690             ### BUFIX Seems to need more Than One ?
2691                 ($year,$month,$day) = Add_Delta_YM($year,$month, $day, 0, 6 );
2692                 $tmpmonth=(($tmpmonth!=6)?($tmpmonth + 6) % 12 :12);
2693             }
2694         }
2695         @resultdate = Add_Delta_YM($year,$month, $day, 0, 6);
2696     }
2697     if ( $subscription->{periodicity} == 10 ) {
2698         @resultdate = Add_Delta_YM($year,$month, $day, 1, 0 );
2699     }
2700     if ( $subscription->{periodicity} == 11 ) {
2701         @resultdate = Add_Delta_YM($year,$month, $day, 2, 0 );
2702     }
2703     }  
2704     my $resultdate=sprintf("%04d-%02d-%02d",$resultdate[0],$resultdate[1],$resultdate[2]);
2705       
2706 #     warn "dateNEXTSEQ : ".$resultdate;
2707     return "$resultdate";
2708 }
2709
2710 =head2 itemdata
2711
2712   $item = &itemdata($barcode);
2713
2714 Looks up the item with the given barcode, and returns a
2715 reference-to-hash containing information about that item. The keys of
2716 the hash are the fields from the C<items> and C<biblioitems> tables in
2717 the Koha database.
2718
2719 =cut
2720
2721 #'
2722 sub itemdata {
2723     my ($barcode) = @_;
2724     my $dbh       = C4::Context->dbh;
2725     my $sth       = $dbh->prepare(
2726         "Select * from items LEFT JOIN biblioitems ON items.biblioitemnumber=biblioitems.biblioitemnumber 
2727         WHERE barcode=?"
2728     );
2729     $sth->execute($barcode);
2730     my $data = $sth->fetchrow_hashref;
2731     $sth->finish;
2732     return ($data);
2733 }
2734
2735 END { }    # module clean-up code here (global destructor)
2736
2737 1;
2738
2739 =back
2740
2741 =head1 AUTHOR
2742
2743 Koha Developement team <info@koha.org>
2744
2745 =cut