3 # Copyright 2000-2002 Katipo Communications
4 # Parts Copyright 2010 Biblibre
6 # This file is part of Koha.
8 # Koha is free software; you can redistribute it and/or modify it
9 # under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 3 of the License, or
11 # (at your option) any later version.
13 # Koha is distributed in the hope that it will be useful, but
14 # WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with Koha; if not, see <http://www.gnu.org/licenses>.
23 use C4
::Auth
qw(haspermission);
26 use Date
::Calc
qw(:all);
27 use POSIX
qw(strftime);
29 use C4
::Log
; # logaction
31 use C4
::Serials
::Frequency
;
32 use C4
::Serials
::Numberpattern
;
33 use Koha
::AdditionalField
;
36 use vars
qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
44 MISSING_NEVER_RECIEVED => 41,
45 MISSING_SOLD_OUT => 42,
46 MISSING_DAMAGED => 43,
54 use constant MISSING_STATUSES => (
55 MISSING, MISSING_NEVER_RECIEVED,
56 MISSING_SOLD_OUT, MISSING_DAMAGED,
61 $VERSION = 3.07.00.049; # set version for version checking
65 &NewSubscription &ModSubscription &DelSubscription
66 &GetSubscription &CountSubscriptionFromBiblionumber &GetSubscriptionsFromBiblionumber
68 &GetFullSubscriptionsFromBiblionumber &GetFullSubscription &ModSubscriptionHistory
69 &HasSubscriptionStrictlyExpired &HasSubscriptionExpired &GetExpirationDate &abouttoexpire
70 &GetSubscriptionHistoryFromSubscriptionId
72 &GetNextSeq &GetSeq &NewIssue &GetSerials
73 &GetLatestSerials &ModSerialStatus &GetNextDate &GetSerials2
74 &ReNewSubscription &GetLateOrMissingIssues
75 &GetSerialInformation &AddItem2Serial
76 &PrepareSerialsData &GetNextExpected &ModNextExpected
78 &UpdateClaimdateIssues
79 &GetSuppliersWithLateIssues &getsupplierbyserialid
80 &GetDistributedTo &SetDistributedTo
81 &getroutinglist &delroutingmember &addroutingmember
83 &check_routing &updateClaim
86 &GetSubscriptionsFromBorrower
87 &subscriptionCurrentlyOnOrder
94 C4::Serials - Serials Module Functions
102 Functions for handling subscriptions, claims routing etc.
107 =head2 GetSuppliersWithLateIssues
109 $supplierlist = GetSuppliersWithLateIssues()
111 this function get all suppliers with late issues.
114 an array_ref of suppliers each entry is a hash_ref containing id and name
115 the array is in name order
119 sub GetSuppliersWithLateIssues
{
120 my $dbh = C4
::Context
->dbh;
121 my $statuses = join(',', ( LATE
, MISSING_STATUSES
, CLAIMED
) );
123 SELECT DISTINCT id
, name
125 LEFT JOIN serial ON serial
.subscriptionid
=subscription
.subscriptionid
126 LEFT JOIN aqbooksellers ON subscription
.aqbooksellerid
= aqbooksellers
.id
129 (planneddate
< now
() AND serial
.status
=1)
130 OR serial
.STATUS IN
( $statuses )
132 AND subscription
.closed
= 0
134 return $dbh->selectall_arrayref($query, { Slice
=> {} });
137 =head2 GetSubscriptionHistoryFromSubscriptionId
139 $history = GetSubscriptionHistoryFromSubscriptionId($subscriptionid);
141 This function returns the subscription history as a hashref
145 sub GetSubscriptionHistoryFromSubscriptionId
{
146 my ($subscriptionid) = @_;
148 return unless $subscriptionid;
150 my $dbh = C4
::Context
->dbh;
153 FROM subscriptionhistory
154 WHERE subscriptionid
= ?
156 my $sth = $dbh->prepare($query);
157 $sth->execute($subscriptionid);
158 my $results = $sth->fetchrow_hashref;
164 =head2 GetSerialStatusFromSerialId
166 $sth = GetSerialStatusFromSerialId();
167 this function returns a statement handle
168 After this function, don't forget to execute it by using $sth->execute($serialid)
170 $sth = $dbh->prepare($query).
174 sub GetSerialStatusFromSerialId
{
175 my $dbh = C4
::Context
->dbh;
181 return $dbh->prepare($query);
184 =head2 GetSerialInformation
187 $data = GetSerialInformation($serialid);
188 returns a hash_ref containing :
189 items : items marcrecord (can be an array)
191 subscription table field
192 + information about subscription expiration
196 sub GetSerialInformation
{
198 my $dbh = C4
::Context
->dbh;
200 SELECT serial
.*, serial
.notes as sernotes
, serial
.status as serstatus
,subscription
.*,subscription
.subscriptionid as subsid
201 FROM serial LEFT JOIN subscription ON subscription
.subscriptionid
=serial
.subscriptionid
204 my $rq = $dbh->prepare($query);
205 $rq->execute($serialid);
206 my $data = $rq->fetchrow_hashref;
208 # create item information if we have serialsadditems for this subscription
209 if ( $data->{'serialsadditems'} ) {
210 my $queryitem = $dbh->prepare("SELECT itemnumber from serialitems where serialid=?");
211 $queryitem->execute($serialid);
212 my $itemnumbers = $queryitem->fetchall_arrayref( [0] );
214 if ( scalar(@
$itemnumbers) > 0 ) {
215 foreach my $itemnum (@
$itemnumbers) {
217 #It is ASSUMED that GetMarcItem ALWAYS WORK...
218 #Maybe GetMarcItem should return values on failure
219 $debug and warn "itemnumber :$itemnum->[0], bibnum :" . $data->{'biblionumber'};
220 my $itemprocessed = C4
::Items
::PrepareItemrecordDisplay
( $data->{'biblionumber'}, $itemnum->[0], $data );
221 $itemprocessed->{'itemnumber'} = $itemnum->[0];
222 $itemprocessed->{'itemid'} = $itemnum->[0];
223 $itemprocessed->{'serialid'} = $serialid;
224 $itemprocessed->{'biblionumber'} = $data->{'biblionumber'};
225 push @
{ $data->{'items'} }, $itemprocessed;
228 my $itemprocessed = C4
::Items
::PrepareItemrecordDisplay
( $data->{'biblionumber'}, '', $data );
229 $itemprocessed->{'itemid'} = "N$serialid";
230 $itemprocessed->{'serialid'} = $serialid;
231 $itemprocessed->{'biblionumber'} = $data->{'biblionumber'};
232 $itemprocessed->{'countitems'} = 0;
233 push @
{ $data->{'items'} }, $itemprocessed;
236 $data->{ "status" . $data->{'serstatus'} } = 1;
237 $data->{'subscriptionexpired'} = HasSubscriptionExpired
( $data->{'subscriptionid'} ) && $data->{'status'} == 1;
238 $data->{'abouttoexpire'} = abouttoexpire
( $data->{'subscriptionid'} );
239 $data->{cannotedit
} = not can_edit_subscription
( $data );
243 =head2 AddItem2Serial
245 $rows = AddItem2Serial($serialid,$itemnumber);
246 Adds an itemnumber to Serial record
247 returns the number of rows affected
252 my ( $serialid, $itemnumber ) = @_;
254 return unless ($serialid and $itemnumber);
256 my $dbh = C4
::Context
->dbh;
257 my $rq = $dbh->prepare("INSERT INTO `serialitems` SET serialid=? , itemnumber=?");
258 $rq->execute( $serialid, $itemnumber );
262 =head2 UpdateClaimdateIssues
264 UpdateClaimdateIssues($serialids,[$date]);
266 Update Claimdate for issues in @$serialids list with date $date
271 sub UpdateClaimdateIssues
{
272 my ( $serialids, $date ) = @_;
274 return unless ($serialids);
276 my $dbh = C4
::Context
->dbh;
277 $date = strftime
( "%Y-%m-%d", localtime ) unless ($date);
282 claims_count = claims_count + 1
283 WHERE serialid in (" . join( ",", map { '?' } @
$serialids ) . ")
285 my $rq = $dbh->prepare($query);
286 $rq->execute($date, CLAIMED
, @
$serialids);
290 =head2 GetSubscription
292 $subs = GetSubscription($subscriptionid)
293 this function returns the subscription which has $subscriptionid as id.
295 a hashref. This hash containts
296 subscription, subscriptionhistory, aqbooksellers.name, biblio.title
300 sub GetSubscription
{
301 my ($subscriptionid) = @_;
302 my $dbh = C4
::Context
->dbh;
304 SELECT subscription
.*,
305 subscriptionhistory
.*,
306 aqbooksellers
.name AS aqbooksellername
,
307 biblio
.title AS bibliotitle
,
308 subscription
.biblionumber as bibnum
310 LEFT JOIN subscriptionhistory ON subscription
.subscriptionid
=subscriptionhistory
.subscriptionid
311 LEFT JOIN aqbooksellers ON subscription
.aqbooksellerid
=aqbooksellers
.id
312 LEFT JOIN biblio ON biblio
.biblionumber
=subscription
.biblionumber
313 WHERE subscription
.subscriptionid
= ?
316 $debug and warn "query : $query\nsubsid :$subscriptionid";
317 my $sth = $dbh->prepare($query);
318 $sth->execute($subscriptionid);
319 my $subscription = $sth->fetchrow_hashref;
321 $subscription->{cannotedit
} = not can_edit_subscription
( $subscription );
323 # Add additional fields to the subscription into a new key "additional_fields"
324 my $additional_field_values = Koha
::AdditionalField
->fetch_all_values({
325 tablename
=> 'subscription',
326 record_id
=> $subscriptionid,
328 $subscription->{additional_fields
} = $additional_field_values->{$subscriptionid};
330 return $subscription;
333 =head2 GetFullSubscription
335 $array_ref = GetFullSubscription($subscriptionid)
336 this function reads the serial table.
340 sub GetFullSubscription
{
341 my ($subscriptionid) = @_;
343 return unless ($subscriptionid);
345 my $dbh = C4
::Context
->dbh;
347 SELECT serial
.serialid
,
350 serial
.publisheddate
,
351 serial
.publisheddatetext
,
353 serial
.notes as notes
,
354 year
(IF
(serial
.publisheddate
="00-00-0000",serial
.planneddate
,serial
.publisheddate
)) as year
,
355 aqbooksellers
.name as aqbooksellername
,
356 biblio
.title as bibliotitle
,
357 subscription
.branchcode AS branchcode
,
358 subscription
.subscriptionid AS subscriptionid
360 LEFT JOIN subscription ON
361 (serial
.subscriptionid
=subscription
.subscriptionid
)
362 LEFT JOIN aqbooksellers on subscription
.aqbooksellerid
=aqbooksellers
.id
363 LEFT JOIN biblio on biblio
.biblionumber
=subscription
.biblionumber
364 WHERE serial
.subscriptionid
= ?
366 IF
(serial
.publisheddate
="00-00-0000",serial
.planneddate
,serial
.publisheddate
) DESC
,
367 serial
.subscriptionid
369 $debug and warn "GetFullSubscription query: $query";
370 my $sth = $dbh->prepare($query);
371 $sth->execute($subscriptionid);
372 my $subscriptions = $sth->fetchall_arrayref( {} );
373 for my $subscription ( @
$subscriptions ) {
374 $subscription->{cannotedit
} = not can_edit_subscription
( $subscription );
376 return $subscriptions;
379 =head2 PrepareSerialsData
381 $array_ref = PrepareSerialsData($serialinfomation)
382 where serialinformation is a hashref array
386 sub PrepareSerialsData
{
389 return unless ($lines);
395 my $aqbooksellername;
399 my $previousnote = "";
401 foreach my $subs (@
{$lines}) {
402 for my $datefield ( qw(publisheddate planneddate) ) {
403 # handle 0000-00-00 dates
404 if (defined $subs->{$datefield} and $subs->{$datefield} =~ m/^00/) {
405 $subs->{$datefield} = undef;
408 $subs->{ "status" . $subs->{'status'} } = 1;
409 if ( grep { $_ == $subs->{status
} } ( EXPECTED
, LATE
, MISSING_STATUSES
, CLAIMED
) ) {
410 $subs->{"checked"} = 1;
413 if ( $subs->{'year'} && $subs->{'year'} ne "" ) {
414 $year = $subs->{'year'};
418 if ( $tmpresults{$year} ) {
419 push @
{ $tmpresults{$year}->{'serials'} }, $subs;
421 $tmpresults{$year} = {
423 'aqbooksellername' => $subs->{'aqbooksellername'},
424 'bibliotitle' => $subs->{'bibliotitle'},
425 'serials' => [$subs],
430 foreach my $key ( sort { $b cmp $a } keys %tmpresults ) {
431 push @res, $tmpresults{$key};
436 =head2 GetSubscriptionsFromBiblionumber
438 $array_ref = GetSubscriptionsFromBiblionumber($biblionumber)
439 this function get the subscription list. it reads the subscription table.
441 reference to an array of subscriptions which have the biblionumber given on input arg.
442 each element of this array is a hashref containing
443 startdate, histstartdate,opacnote,missinglist,recievedlist,periodicity,status & enddate
447 sub GetSubscriptionsFromBiblionumber
{
448 my ($biblionumber) = @_;
450 return unless ($biblionumber);
452 my $dbh = C4
::Context
->dbh;
454 SELECT subscription
.*,
456 subscriptionhistory
.*,
457 aqbooksellers
.name AS aqbooksellername
,
458 biblio
.title AS bibliotitle
460 LEFT JOIN subscriptionhistory ON subscription
.subscriptionid
=subscriptionhistory
.subscriptionid
461 LEFT JOIN aqbooksellers ON subscription
.aqbooksellerid
=aqbooksellers
.id
462 LEFT JOIN biblio ON biblio
.biblionumber
=subscription
.biblionumber
463 LEFT JOIN branches ON branches
.branchcode
=subscription
.branchcode
464 WHERE subscription
.biblionumber
= ?
466 my $sth = $dbh->prepare($query);
467 $sth->execute($biblionumber);
469 while ( my $subs = $sth->fetchrow_hashref ) {
470 $subs->{startdate
} = output_pref
( { dt
=> dt_from_string
( $subs->{startdate
} ), dateonly
=> 1 } );
471 $subs->{histstartdate
} = output_pref
( { dt
=> dt_from_string
( $subs->{histstartdate
} ), dateonly
=> 1 } );
472 $subs->{histenddate
} = output_pref
( { dt
=> dt_from_string
( $subs->{histenddate
} ), dateonly
=> 1 } );
473 $subs->{opacnote
} =~ s/\n/\<br\/\
>/g
;
474 $subs->{missinglist
} =~ s/\n/\<br\/\
>/g
;
475 $subs->{recievedlist
} =~ s/\n/\<br\/\
>/g
;
476 $subs->{ "periodicity" . $subs->{periodicity
} } = 1;
477 $subs->{ "numberpattern" . $subs->{numberpattern
} } = 1;
478 $subs->{ "status" . $subs->{'status'} } = 1;
480 if ( $subs->{enddate
} eq '0000-00-00' ) {
481 $subs->{enddate
} = '';
483 $subs->{enddate
} = output_pref
( { dt
=> dt_from_string
( $subs->{enddate
}), dateonly
=> 1 } );
485 $subs->{'abouttoexpire'} = abouttoexpire
( $subs->{'subscriptionid'} );
486 $subs->{'subscriptionexpired'} = HasSubscriptionExpired
( $subs->{'subscriptionid'} );
487 $subs->{cannotedit
} = not can_edit_subscription
( $subs );
493 =head2 GetFullSubscriptionsFromBiblionumber
495 $array_ref = GetFullSubscriptionsFromBiblionumber($biblionumber)
496 this function reads the serial table.
500 sub GetFullSubscriptionsFromBiblionumber
{
501 my ($biblionumber) = @_;
502 my $dbh = C4
::Context
->dbh;
504 SELECT serial
.serialid
,
507 serial
.publisheddate
,
508 serial
.publisheddatetext
,
510 serial
.notes as notes
,
511 year
(IF
(serial
.publisheddate
="00-00-0000",serial
.planneddate
,serial
.publisheddate
)) as year
,
512 biblio
.title as bibliotitle
,
513 subscription
.branchcode AS branchcode
,
514 subscription
.subscriptionid AS subscriptionid
516 LEFT JOIN subscription ON
517 (serial
.subscriptionid
=subscription
.subscriptionid
)
518 LEFT JOIN aqbooksellers on subscription
.aqbooksellerid
=aqbooksellers
.id
519 LEFT JOIN biblio on biblio
.biblionumber
=subscription
.biblionumber
520 WHERE subscription
.biblionumber
= ?
522 IF
(serial
.publisheddate
="00-00-0000",serial
.planneddate
,serial
.publisheddate
) DESC
,
523 serial
.subscriptionid
525 my $sth = $dbh->prepare($query);
526 $sth->execute($biblionumber);
527 my $subscriptions = $sth->fetchall_arrayref( {} );
528 for my $subscription ( @
$subscriptions ) {
529 $subscription->{cannotedit
} = not can_edit_subscription
( $subscription );
531 return $subscriptions;
534 =head2 SearchSubscriptions
536 @results = SearchSubscriptions($args);
538 This function returns a list of hashrefs, one for each subscription
539 that meets the conditions specified by the $args hashref.
541 The valid search fields are:
555 The expiration_date search field is special; it specifies the maximum
556 subscription expiration date.
560 sub SearchSubscriptions
{
563 my $additional_fields = $args->{additional_fields
} // [];
564 my $matching_record_ids_for_additional_fields = [];
565 if ( @
$additional_fields ) {
566 $matching_record_ids_for_additional_fields = Koha
::AdditionalField
->get_matching_record_ids({
567 fields
=> $additional_fields,
568 tablename
=> 'subscription',
571 return () unless @
$matching_record_ids_for_additional_fields;
576 subscription
.notes AS publicnotes
,
577 subscriptionhistory
.*,
579 biblio
.notes AS biblionotes
,
585 LEFT JOIN subscriptionhistory USING
(subscriptionid
)
586 LEFT JOIN biblio ON biblio
.biblionumber
= subscription
.biblionumber
587 LEFT JOIN biblioitems ON biblioitems
.biblionumber
= subscription
.biblionumber
588 LEFT JOIN aqbooksellers ON subscription
.aqbooksellerid
= aqbooksellers
.id
590 $query .= q
| WHERE
1|;
593 if( $args->{biblionumber
} ) {
594 push @where_strs, "biblio.biblionumber = ?";
595 push @where_args, $args->{biblionumber
};
598 if( $args->{title
} ){
599 my @words = split / /, $args->{title
};
601 foreach my $word (@words) {
602 push @strs, "biblio.title LIKE ?";
603 push @args, "%$word%";
606 push @where_strs, '(' . join (' AND ', @strs) . ')';
607 push @where_args, @args;
611 push @where_strs, "biblioitems.issn LIKE ?";
612 push @where_args, "%$args->{issn}%";
615 push @where_strs, "biblioitems.ean LIKE ?";
616 push @where_args, "%$args->{ean}%";
618 if ( $args->{callnumber
} ) {
619 push @where_strs, "subscription.callnumber LIKE ?";
620 push @where_args, "%$args->{callnumber}%";
622 if( $args->{publisher
} ){
623 push @where_strs, "biblioitems.publishercode LIKE ?";
624 push @where_args, "%$args->{publisher}%";
626 if( $args->{bookseller
} ){
627 push @where_strs, "aqbooksellers.name LIKE ?";
628 push @where_args, "%$args->{bookseller}%";
630 if( $args->{branch
} ){
631 push @where_strs, "subscription.branchcode = ?";
632 push @where_args, "$args->{branch}";
634 if ( $args->{location
} ) {
635 push @where_strs, "subscription.location = ?";
636 push @where_args, "$args->{location}";
638 if ( $args->{expiration_date
} ) {
639 push @where_strs, "subscription.enddate <= ?";
640 push @where_args, "$args->{expiration_date}";
642 if( defined $args->{closed
} ){
643 push @where_strs, "subscription.closed = ?";
644 push @where_args, "$args->{closed}";
648 $query .= ' AND ' . join(' AND ', @where_strs);
650 if ( @
$additional_fields ) {
651 $query .= ' AND subscriptionid IN ('
652 . join( ', ', @
$matching_record_ids_for_additional_fields )
656 $query .= " ORDER BY " . $args->{orderby
} if $args->{orderby
};
658 my $dbh = C4
::Context
->dbh;
659 my $sth = $dbh->prepare($query);
660 $sth->execute(@where_args);
661 my $results = $sth->fetchall_arrayref( {} );
663 for my $subscription ( @
$results ) {
664 $subscription->{cannotedit
} = not can_edit_subscription
( $subscription );
665 $subscription->{cannotdisplay
} = not can_show_subscription
( $subscription );
667 my $additional_field_values = Koha
::AdditionalField
->fetch_all_values({
668 record_id
=> $subscription->{subscriptionid
},
669 tablename
=> 'subscription'
671 $subscription->{additional_fields
} = $additional_field_values->{$subscription->{subscriptionid
}};
680 ($totalissues,@serials) = GetSerials($subscriptionid);
681 this function gets every serial not arrived for a given subscription
682 as well as the number of issues registered in the database (all types)
683 this number is used to see if a subscription can be deleted (=it must have only 1 issue)
685 FIXME: We should return \@serials.
690 my ( $subscriptionid, $count ) = @_;
692 return unless $subscriptionid;
694 my $dbh = C4
::Context
->dbh;
696 # status = 2 is "arrived"
698 $count = 5 unless ($count);
700 my $statuses = join( ',', ( ARRIVED
, MISSING_STATUSES
, NOT_ISSUED
) );
701 my $query = "SELECT serialid,serialseq, status, publisheddate,
702 publisheddatetext, planneddate,notes, routingnotes
704 WHERE subscriptionid = ? AND status NOT IN ( $statuses )
705 ORDER BY IF(publisheddate<>'0000-00-00',publisheddate,planneddate) DESC";
706 my $sth = $dbh->prepare($query);
707 $sth->execute($subscriptionid);
709 while ( my $line = $sth->fetchrow_hashref ) {
710 $line->{ "status" . $line->{status
} } = 1; # fills a "statusX" value, used for template status select list
711 for my $datefield ( qw( planneddate publisheddate) ) {
712 if ($line->{$datefield} && $line->{$datefield}!~m/^00/) {
713 $line->{$datefield} = output_pref
( { dt
=> dt_from_string
( $line->{$datefield} ), dateonly
=> 1 } );
715 $line->{$datefield} = q{};
718 push @serials, $line;
721 # OK, now add the last 5 issues arrives/missing
722 $query = "SELECT serialid,serialseq, status, planneddate, publisheddate,
723 publisheddatetext, notes, routingnotes
725 WHERE subscriptionid = ?
726 AND status IN ( $statuses )
727 ORDER BY IF(publisheddate<>'0000-00-00',publisheddate,planneddate) DESC
729 $sth = $dbh->prepare($query);
730 $sth->execute($subscriptionid);
731 while ( ( my $line = $sth->fetchrow_hashref ) && $counter < $count ) {
733 $line->{ "status" . $line->{status
} } = 1; # fills a "statusX" value, used for template status select list
734 for my $datefield ( qw( planneddate publisheddate) ) {
735 if ($line->{$datefield} && $line->{$datefield}!~m/^00/) {
736 $line->{$datefield} = output_pref
( { dt
=> dt_from_string
( $line->{$datefield} ), dateonly
=> 1 } );
738 $line->{$datefield} = q{};
742 push @serials, $line;
745 $query = "SELECT count(*) FROM serial WHERE subscriptionid=?";
746 $sth = $dbh->prepare($query);
747 $sth->execute($subscriptionid);
748 my ($totalissues) = $sth->fetchrow;
749 return ( $totalissues, @serials );
754 @serials = GetSerials2($subscriptionid,$statuses);
755 this function returns every serial waited for a given subscription
756 as well as the number of issues registered in the database (all types)
757 this number is used to see if a subscription can be deleted (=it must have only 1 issue)
759 $statuses is an arrayref of statuses and is mandatory.
764 my ( $subscription, $statuses ) = @_;
766 return unless ($subscription and @
$statuses);
768 my $statuses_string = join ',', @
$statuses;
770 my $dbh = C4
::Context
->dbh;
772 SELECT serialid
,serialseq
, status
, planneddate
, publisheddate
,
773 publisheddatetext
, notes
, routingnotes
775 WHERE subscriptionid
=$subscription AND status IN
($statuses_string)
776 ORDER BY publisheddate
,serialid DESC
778 $debug and warn "GetSerials2 query: $query";
779 my $sth = $dbh->prepare($query);
783 while ( my $line = $sth->fetchrow_hashref ) {
784 $line->{ "status" . $line->{status
} } = 1; # fills a "statusX" value, used for template status select list
785 # Format dates for display
786 for my $datefield ( qw( planneddate publisheddate ) ) {
787 if (!defined($line->{$datefield}) || $line->{$datefield} =~m/^00/) {
788 $line->{$datefield} = q{};
791 $line->{$datefield} = output_pref
( { dt
=> dt_from_string
( $line->{$datefield} ), dateonly
=> 1 } );
794 push @serials, $line;
799 =head2 GetLatestSerials
801 \@serials = GetLatestSerials($subscriptionid,$limit)
802 get the $limit's latest serials arrived or missing for a given subscription
804 a ref to an array which contains all of the latest serials stored into a hash.
808 sub GetLatestSerials
{
809 my ( $subscriptionid, $limit ) = @_;
811 return unless ($subscriptionid and $limit);
813 my $dbh = C4
::Context
->dbh;
815 my $statuses = join( ',', ( ARRIVED
, MISSING_STATUSES
) );
816 my $strsth = "SELECT serialid,serialseq, status, planneddate, publisheddate, notes
818 WHERE subscriptionid = ?
819 AND status IN ($statuses)
820 ORDER BY publisheddate DESC LIMIT 0,$limit
822 my $sth = $dbh->prepare($strsth);
823 $sth->execute($subscriptionid);
825 while ( my $line = $sth->fetchrow_hashref ) {
826 $line->{ "status" . $line->{status
} } = 1; # fills a "statusX" value, used for template status select list
827 $line->{planneddate
} = output_pref
( { dt
=> dt_from_string
( $line->{planneddate
} ), dateonly
=> 1 } );
828 $line->{publisheddate
} = output_pref
( { dt
=> dt_from_string
( $line->{publisheddate
} ), dateonly
=> 1 } );
829 push @serials, $line;
835 =head2 GetDistributedTo
837 $distributedto=GetDistributedTo($subscriptionid)
838 This function returns the field distributedto for the subscription matching subscriptionid
842 sub GetDistributedTo
{
843 my $dbh = C4
::Context
->dbh;
845 my ($subscriptionid) = @_;
847 return unless ($subscriptionid);
849 my $query = "SELECT distributedto FROM subscription WHERE subscriptionid=?";
850 my $sth = $dbh->prepare($query);
851 $sth->execute($subscriptionid);
852 return ($distributedto) = $sth->fetchrow;
858 $nextseq, $newlastvalue1, $newlastvalue2, $newlastvalue3,
859 $newinnerloop1, $newinnerloop2, $newinnerloop3
860 ) = GetNextSeq( $subscription, $pattern, $planneddate );
862 $subscription is a hashref containing all the attributes of the table
864 $pattern is a hashref containing all the attributes of the table
865 'subscription_numberpatterns'.
866 $planneddate is a date string in iso format.
867 This function get the next issue for the subscription given on input arg
872 my ($subscription, $pattern, $planneddate) = @_;
874 return unless ($subscription and $pattern);
876 my ( $newlastvalue1, $newlastvalue2, $newlastvalue3,
877 $newinnerloop1, $newinnerloop2, $newinnerloop3 );
880 if ($subscription->{'skip_serialseq'}) {
881 my @irreg = split /;/, $subscription->{'irregularity'};
883 my $irregularities = {};
884 $irregularities->{$_} = 1 foreach(@irreg);
885 my $issueno = GetFictiveIssueNumber
($subscription, $planneddate) + 1;
886 while($irregularities->{$issueno}) {
893 my $numberingmethod = $pattern->{numberingmethod
};
895 if ($numberingmethod) {
896 $calculated = $numberingmethod;
897 my $locale = $subscription->{locale
};
898 $newlastvalue1 = $subscription->{lastvalue1
} || 0;
899 $newlastvalue2 = $subscription->{lastvalue2
} || 0;
900 $newlastvalue3 = $subscription->{lastvalue3
} || 0;
901 $newinnerloop1 = $subscription->{innerloop1
} || 0;
902 $newinnerloop2 = $subscription->{innerloop2
} || 0;
903 $newinnerloop3 = $subscription->{innerloop3
} || 0;
906 $calc{$_} = 1 if ($numberingmethod =~ /\{$_\}/);
909 for(my $i = 0; $i < $count; $i++) {
911 # check if we have to increase the new value.
913 if ($newinnerloop1 >= $pattern->{every1
}) {
915 $newlastvalue1 += $pattern->{add1
};
917 # reset counter if needed.
918 $newlastvalue1 = $pattern->{setto1
} if ($newlastvalue1 > $pattern->{whenmorethan1
});
921 # check if we have to increase the new value.
923 if ($newinnerloop2 >= $pattern->{every2
}) {
925 $newlastvalue2 += $pattern->{add2
};
927 # reset counter if needed.
928 $newlastvalue2 = $pattern->{setto2
} if ($newlastvalue2 > $pattern->{whenmorethan2
});
931 # check if we have to increase the new value.
933 if ($newinnerloop3 >= $pattern->{every3
}) {
935 $newlastvalue3 += $pattern->{add3
};
937 # reset counter if needed.
938 $newlastvalue3 = $pattern->{setto3
} if ($newlastvalue3 > $pattern->{whenmorethan3
});
942 my $newlastvalue1string = _numeration
( $newlastvalue1, $pattern->{numbering1
}, $locale );
943 $calculated =~ s/\{X\}/$newlastvalue1string/g;
946 my $newlastvalue2string = _numeration
( $newlastvalue2, $pattern->{numbering2
}, $locale );
947 $calculated =~ s/\{Y\}/$newlastvalue2string/g;
950 my $newlastvalue3string = _numeration
( $newlastvalue3, $pattern->{numbering3
}, $locale );
951 $calculated =~ s/\{Z\}/$newlastvalue3string/g;
956 $newlastvalue1, $newlastvalue2, $newlastvalue3,
957 $newinnerloop1, $newinnerloop2, $newinnerloop3);
962 $calculated = GetSeq($subscription, $pattern)
963 $subscription is a hashref containing all the attributes of the table 'subscription'
964 $pattern is a hashref containing all the attributes of the table 'subscription_numberpatterns'
965 this function transforms {X},{Y},{Z} to 150,0,0 for example.
967 the sequence in string format
972 my ($subscription, $pattern) = @_;
974 return unless ($subscription and $pattern);
976 my $locale = $subscription->{locale
};
978 my $calculated = $pattern->{numberingmethod
};
980 my $newlastvalue1 = $subscription->{'lastvalue1'} || 0;
981 $newlastvalue1 = _numeration
($newlastvalue1, $pattern->{numbering1
}, $locale) if ($pattern->{numbering1
}); # reset counter if needed.
982 $calculated =~ s/\{X\}/$newlastvalue1/g;
984 my $newlastvalue2 = $subscription->{'lastvalue2'} || 0;
985 $newlastvalue2 = _numeration
($newlastvalue2, $pattern->{numbering2
}, $locale) if ($pattern->{numbering2
}); # reset counter if needed.
986 $calculated =~ s/\{Y\}/$newlastvalue2/g;
988 my $newlastvalue3 = $subscription->{'lastvalue3'} || 0;
989 $newlastvalue3 = _numeration
($newlastvalue3, $pattern->{numbering3
}, $locale) if ($pattern->{numbering3
}); # reset counter if needed.
990 $calculated =~ s/\{Z\}/$newlastvalue3/g;
994 =head2 GetExpirationDate
996 $enddate = GetExpirationDate($subscriptionid, [$startdate])
998 this function return the next expiration date for a subscription given on input args.
1001 the enddate or undef
1005 sub GetExpirationDate
{
1006 my ( $subscriptionid, $startdate ) = @_;
1008 return unless ($subscriptionid);
1010 my $dbh = C4
::Context
->dbh;
1011 my $subscription = GetSubscription
($subscriptionid);
1014 # we don't do the same test if the subscription is based on X numbers or on X weeks/months
1015 $enddate = $startdate || $subscription->{startdate
};
1016 my @date = split( /-/, $enddate );
1018 return if ( scalar(@date) != 3 || not check_date
(@date) );
1020 my $frequency = C4
::Serials
::Frequency
::GetSubscriptionFrequency
($subscription->{periodicity
});
1021 if ( $frequency and $frequency->{unit
} ) {
1024 if ( my $length = $subscription->{numberlength
} ) {
1026 #calculate the date of the last issue.
1027 for ( my $i = 1 ; $i <= $length ; $i++ ) {
1028 $enddate = GetNextDate
( $subscription, $enddate );
1030 } elsif ( $subscription->{monthlength
} ) {
1031 if ( $$subscription{startdate
} ) {
1032 my @enddate = Add_Delta_YM
( $date[0], $date[1], $date[2], 0, $subscription->{monthlength
} );
1033 $enddate = sprintf( "%04d-%02d-%02d", $enddate[0], $enddate[1], $enddate[2] );
1035 } elsif ( $subscription->{weeklength
} ) {
1036 if ( $$subscription{startdate
} ) {
1037 my @date = split( /-/, $subscription->{startdate
} );
1038 my @enddate = Add_Delta_Days
( $date[0], $date[1], $date[2], $subscription->{weeklength
} * 7 );
1039 $enddate = sprintf( "%04d-%02d-%02d", $enddate[0], $enddate[1], $enddate[2] );
1042 $enddate = $subscription->{enddate
};
1046 return $subscription->{enddate
};
1050 =head2 CountSubscriptionFromBiblionumber
1052 $subscriptionsnumber = CountSubscriptionFromBiblionumber($biblionumber)
1053 this returns a count of the subscriptions for a given biblionumber
1055 the number of subscriptions
1059 sub CountSubscriptionFromBiblionumber
{
1060 my ($biblionumber) = @_;
1062 return unless ($biblionumber);
1064 my $dbh = C4
::Context
->dbh;
1065 my $query = "SELECT count(*) FROM subscription WHERE biblionumber=?";
1066 my $sth = $dbh->prepare($query);
1067 $sth->execute($biblionumber);
1068 my $subscriptionsnumber = $sth->fetchrow;
1069 return $subscriptionsnumber;
1072 =head2 ModSubscriptionHistory
1074 ModSubscriptionHistory($subscriptionid,$histstartdate,$enddate,$recievedlist,$missinglist,$opacnote,$librariannote);
1076 this function modifies the history of a subscription. Put your new values on input arg.
1077 returns the number of rows affected
1081 sub ModSubscriptionHistory
{
1082 my ( $subscriptionid, $histstartdate, $enddate, $receivedlist, $missinglist, $opacnote, $librariannote ) = @_;
1084 return unless ($subscriptionid);
1086 my $dbh = C4
::Context
->dbh;
1087 my $query = "UPDATE subscriptionhistory
1088 SET histstartdate=?,histenddate=?,recievedlist=?,missinglist=?,opacnote=?,librariannote=?
1089 WHERE subscriptionid=?
1091 my $sth = $dbh->prepare($query);
1092 $receivedlist =~ s/^; // if $receivedlist;
1093 $missinglist =~ s/^; // if $missinglist;
1094 $opacnote =~ s/^; // if $opacnote;
1095 $sth->execute( $histstartdate, $enddate, $receivedlist, $missinglist, $opacnote, $librariannote, $subscriptionid );
1099 =head2 ModSerialStatus
1101 ModSerialStatus($serialid, $serialseq, $planneddate, $publisheddate,
1102 $publisheddatetext, $status, $notes);
1104 This function modify the serial status. Serial status is a number.(eg 2 is "arrived")
1105 Note : if we change from "waited" to something else,then we will have to create a new "waited" entry
1109 sub ModSerialStatus
{
1110 my ($serialid, $serialseq, $planneddate, $publisheddate, $publisheddatetext,
1111 $status, $notes) = @_;
1113 return unless ($serialid);
1115 #It is a usual serial
1116 # 1st, get previous status :
1117 my $dbh = C4
::Context
->dbh;
1118 my $query = "SELECT serial.subscriptionid,serial.status,subscription.periodicity
1119 FROM serial, subscription
1120 WHERE serial.subscriptionid=subscription.subscriptionid
1122 my $sth = $dbh->prepare($query);
1123 $sth->execute($serialid);
1124 my ( $subscriptionid, $oldstatus, $periodicity ) = $sth->fetchrow;
1125 my $frequency = GetSubscriptionFrequency
($periodicity);
1127 # change status & update subscriptionhistory
1129 if ( $status == DELETED
) {
1130 DelIssue
( { 'serialid' => $serialid, 'subscriptionid' => $subscriptionid, 'serialseq' => $serialseq } );
1135 SET serialseq = ?, publisheddate = ?, publisheddatetext = ?,
1136 planneddate = ?, status = ?, notes = ?
1139 $sth = $dbh->prepare($query);
1140 $sth->execute( $serialseq, $publisheddate, $publisheddatetext,
1141 $planneddate, $status, $notes, $serialid );
1142 $query = "SELECT * FROM subscription WHERE subscriptionid = ?";
1143 $sth = $dbh->prepare($query);
1144 $sth->execute($subscriptionid);
1145 my $val = $sth->fetchrow_hashref;
1146 unless ( $val->{manualhistory
} ) {
1147 $query = "SELECT missinglist,recievedlist FROM subscriptionhistory WHERE subscriptionid=?";
1148 $sth = $dbh->prepare($query);
1149 $sth->execute($subscriptionid);
1150 my ( $missinglist, $recievedlist ) = $sth->fetchrow;
1152 if ( $status == ARRIVED
|| ($oldstatus == ARRIVED
&& $status != ARRIVED
) ) {
1153 $recievedlist .= "; $serialseq"
1154 if ($recievedlist !~ /(^|;)\s*$serialseq(?=;|$)/);
1157 # in case serial has been previously marked as missing
1158 if (grep /$status/, (EXPECTED
, ARRIVED
, LATE
, CLAIMED
)) {
1159 $missinglist=~ s/(^|;)\s*$serialseq(?=;|$)//g;
1162 $missinglist .= "; $serialseq"
1163 if ( ( grep { $_ == $status } ( MISSING_STATUSES
) ) && ( $missinglist !~/(^|;)\s*$serialseq(?=;|$)/ ) );
1164 $missinglist .= "; not issued $serialseq"
1165 if ( $status == NOT_ISSUED
&& $missinglist !~ /(^|;)\s*$serialseq(?=;|$)/ );
1167 $query = "UPDATE subscriptionhistory SET recievedlist=?, missinglist=? WHERE subscriptionid=?";
1168 $sth = $dbh->prepare($query);
1169 $recievedlist =~ s/^; //;
1170 $missinglist =~ s/^; //;
1171 $sth->execute( $recievedlist, $missinglist, $subscriptionid );
1175 # create new waited entry if needed (ie : was a "waited" and has changed)
1176 if ( $oldstatus == EXPECTED
&& $status != EXPECTED
) {
1177 my $subscription = GetSubscription
($subscriptionid);
1178 my $pattern = C4
::Serials
::Numberpattern
::GetSubscriptionNumberpattern
($subscription->{numberpattern
});
1182 $newserialseq, $newlastvalue1, $newlastvalue2, $newlastvalue3,
1183 $newinnerloop1, $newinnerloop2, $newinnerloop3
1185 = GetNextSeq
( $subscription, $pattern, $publisheddate );
1187 # next date (calculated from actual date & frequency parameters)
1188 my $nextpublisheddate = GetNextDate
($subscription, $publisheddate, 1);
1189 my $nextpubdate = $nextpublisheddate;
1190 NewIssue
( $newserialseq, $subscriptionid, $subscription->{'biblionumber'}, 1, $nextpubdate, $nextpubdate );
1191 $query = "UPDATE subscription SET lastvalue1=?, lastvalue2=?, lastvalue3=?, innerloop1=?, innerloop2=?, innerloop3=?
1192 WHERE subscriptionid = ?";
1193 $sth = $dbh->prepare($query);
1194 $sth->execute( $newlastvalue1, $newlastvalue2, $newlastvalue3, $newinnerloop1, $newinnerloop2, $newinnerloop3, $subscriptionid );
1196 # check if an alert must be sent... (= a letter is defined & status became "arrived"
1197 if ( $subscription->{letter
} && $status == ARRIVED
&& $oldstatus != ARRIVED
) {
1198 require C4
::Letters
;
1199 C4
::Letters
::SendAlerts
( 'issue', $serialid, $subscription->{letter
} );
1206 =head2 GetNextExpected
1208 $nextexpected = GetNextExpected($subscriptionid)
1210 Get the planneddate for the current expected issue of the subscription.
1216 planneddate => ISO date
1221 sub GetNextExpected
{
1222 my ($subscriptionid) = @_;
1224 my $dbh = C4
::Context
->dbh;
1228 WHERE subscriptionid
= ?
1232 my $sth = $dbh->prepare($query);
1234 # Each subscription has only one 'expected' issue.
1235 $sth->execute( $subscriptionid, EXPECTED
);
1236 my $nextissue = $sth->fetchrow_hashref;
1237 if ( !$nextissue ) {
1241 WHERE subscriptionid
= ?
1242 ORDER BY publisheddate DESC
1245 $sth = $dbh->prepare($query);
1246 $sth->execute($subscriptionid);
1247 $nextissue = $sth->fetchrow_hashref;
1249 foreach(qw
/planneddate publisheddate/) {
1250 if ( !defined $nextissue->{$_} ) {
1251 # or should this default to 1st Jan ???
1252 $nextissue->{$_} = strftime
( '%Y-%m-%d', localtime );
1254 $nextissue->{$_} = ($nextissue->{$_} ne '0000-00-00')
1262 =head2 ModNextExpected
1264 ModNextExpected($subscriptionid,$date)
1266 Update the planneddate for the current expected issue of the subscription.
1267 This will modify all future prediction results.
1269 C<$date> is an ISO date.
1275 sub ModNextExpected
{
1276 my ( $subscriptionid, $date ) = @_;
1277 my $dbh = C4
::Context
->dbh;
1279 #FIXME: Would expect to only set planneddate, but we set both on new issue creation, so updating it here
1280 my $sth = $dbh->prepare('UPDATE serial SET planneddate=?,publisheddate=? WHERE subscriptionid=? AND status=?');
1282 # Each subscription has only one 'expected' issue.
1283 $sth->execute( $date, $date, $subscriptionid, EXPECTED
);
1288 =head2 GetSubscriptionIrregularities
1292 =item @irreg = &GetSubscriptionIrregularities($subscriptionid);
1293 get the list of irregularities for a subscription
1299 sub GetSubscriptionIrregularities
{
1300 my $subscriptionid = shift;
1302 return unless $subscriptionid;
1304 my $dbh = C4
::Context
->dbh;
1308 WHERE subscriptionid
= ?
1310 my $sth = $dbh->prepare($query);
1311 $sth->execute($subscriptionid);
1313 my ($result) = $sth->fetchrow_array;
1314 my @irreg = split /;/, $result;
1319 =head2 ModSubscription
1321 this function modifies a subscription. Put all new values on input args.
1322 returns the number of rows affected
1326 sub ModSubscription
{
1328 $auser, $branchcode, $aqbooksellerid, $cost, $aqbudgetid, $startdate,
1329 $periodicity, $firstacquidate, $irregularity, $numberpattern, $locale,
1330 $numberlength, $weeklength, $monthlength, $lastvalue1, $innerloop1,
1331 $lastvalue2, $innerloop2, $lastvalue3, $innerloop3, $status,
1332 $biblionumber, $callnumber, $notes, $letter, $manualhistory,
1333 $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount,
1334 $graceperiod, $location, $enddate, $subscriptionid, $skip_serialseq
1337 my $dbh = C4
::Context
->dbh;
1338 my $query = "UPDATE subscription
1339 SET librarian=?, branchcode=?, aqbooksellerid=?, cost=?, aqbudgetid=?,
1340 startdate=?, periodicity=?, firstacquidate=?, irregularity=?,
1341 numberpattern=?, locale=?, numberlength=?, weeklength=?, monthlength=?,
1342 lastvalue1=?, innerloop1=?, lastvalue2=?, innerloop2=?,
1343 lastvalue3=?, innerloop3=?, status=?, biblionumber=?,
1344 callnumber=?, notes=?, letter=?, manualhistory=?,
1345 internalnotes=?, serialsadditems=?, staffdisplaycount=?,
1346 opacdisplaycount=?, graceperiod=?, location = ?, enddate=?,
1348 WHERE subscriptionid = ?";
1350 my $sth = $dbh->prepare($query);
1352 $auser, $branchcode, $aqbooksellerid, $cost,
1353 $aqbudgetid, $startdate, $periodicity, $firstacquidate,
1354 $irregularity, $numberpattern, $locale, $numberlength,
1355 $weeklength, $monthlength, $lastvalue1, $innerloop1,
1356 $lastvalue2, $innerloop2, $lastvalue3, $innerloop3,
1357 $status, $biblionumber, $callnumber, $notes,
1358 $letter, ($manualhistory ?
$manualhistory : 0),
1359 $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount,
1360 $graceperiod, $location, $enddate, $skip_serialseq,
1363 my $rows = $sth->rows;
1365 logaction
( "SERIAL", "MODIFY", $subscriptionid, "" ) if C4
::Context
->preference("SubscriptionLog");
1369 =head2 NewSubscription
1371 $subscriptionid = &NewSubscription($auser,branchcode,$aqbooksellerid,$cost,$aqbudgetid,$biblionumber,
1372 $startdate,$periodicity,$numberlength,$weeklength,$monthlength,
1373 $lastvalue1,$innerloop1,$lastvalue2,$innerloop2,$lastvalue3,$innerloop3,
1374 $status, $notes, $letter, $firstacquidate, $irregularity, $numberpattern,
1375 $locale, $callnumber, $manualhistory, $internalnotes, $serialsadditems,
1376 $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate, $skip_serialseq);
1378 Create a new subscription with value given on input args.
1381 the id of this new subscription
1385 sub NewSubscription
{
1387 $auser, $branchcode, $aqbooksellerid, $cost, $aqbudgetid, $biblionumber,
1388 $startdate, $periodicity, $numberlength, $weeklength, $monthlength,
1389 $lastvalue1, $innerloop1, $lastvalue2, $innerloop2, $lastvalue3,
1390 $innerloop3, $status, $notes, $letter, $firstacquidate, $irregularity,
1391 $numberpattern, $locale, $callnumber, $manualhistory, $internalnotes,
1392 $serialsadditems, $staffdisplaycount, $opacdisplaycount, $graceperiod,
1393 $location, $enddate, $skip_serialseq
1395 my $dbh = C4
::Context
->dbh;
1397 #save subscription (insert into database)
1399 INSERT INTO subscription
1400 (librarian
, branchcode
, aqbooksellerid
, cost
, aqbudgetid
,
1401 biblionumber
, startdate
, periodicity
, numberlength
, weeklength
,
1402 monthlength
, lastvalue1
, innerloop1
, lastvalue2
, innerloop2
,
1403 lastvalue3
, innerloop3
, status
, notes
, letter
, firstacquidate
,
1404 irregularity
, numberpattern
, locale
, callnumber
,
1405 manualhistory
, internalnotes
, serialsadditems
, staffdisplaycount
,
1406 opacdisplaycount
, graceperiod
, location
, enddate
, skip_serialseq
)
1407 VALUES
(?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
,?
)
1409 my $sth = $dbh->prepare($query);
1411 $auser, $branchcode, $aqbooksellerid, $cost, $aqbudgetid, $biblionumber,
1412 $startdate, $periodicity, $numberlength, $weeklength,
1413 $monthlength, $lastvalue1, $innerloop1, $lastvalue2, $innerloop2,
1414 $lastvalue3, $innerloop3, $status, $notes, $letter,
1415 $firstacquidate, $irregularity, $numberpattern, $locale, $callnumber,
1416 $manualhistory, $internalnotes, $serialsadditems, $staffdisplaycount,
1417 $opacdisplaycount, $graceperiod, $location, $enddate, $skip_serialseq
1420 my $subscriptionid = $dbh->{'mysql_insertid'};
1422 $enddate = GetExpirationDate
( $subscriptionid, $startdate );
1426 WHERE subscriptionid
=?
1428 $sth = $dbh->prepare($query);
1429 $sth->execute( $enddate, $subscriptionid );
1432 # then create the 1st expected number
1434 INSERT INTO subscriptionhistory
1435 (biblionumber
, subscriptionid
, histstartdate
)
1438 $sth = $dbh->prepare($query);
1439 $sth->execute( $biblionumber, $subscriptionid, $startdate);
1441 # reread subscription to get a hash (for calculation of the 1st issue number)
1442 my $subscription = GetSubscription
($subscriptionid);
1443 my $pattern = C4
::Serials
::Numberpattern
::GetSubscriptionNumberpattern
($subscription->{numberpattern
});
1445 # calculate issue number
1446 my $serialseq = GetSeq
($subscription, $pattern) || q{};
1449 (serialseq
,subscriptionid
,biblionumber
,status
, planneddate
, publisheddate
)
1450 VALUES
(?
,?
,?
,?
,?
,?
)
1452 $sth = $dbh->prepare($query);
1453 $sth->execute( $serialseq, $subscriptionid, $biblionumber, EXPECTED
, $firstacquidate, $firstacquidate );
1455 logaction
( "SERIAL", "ADD", $subscriptionid, "" ) if C4
::Context
->preference("SubscriptionLog");
1457 #set serial flag on biblio if not already set.
1458 my $bib = GetBiblio
($biblionumber);
1459 if ( $bib and !$bib->{'serial'} ) {
1460 my $record = GetMarcBiblio
($biblionumber);
1461 my ( $tag, $subf ) = GetMarcFromKohaField
( 'biblio.serial', $bib->{'frameworkcode'} );
1463 eval { $record->field($tag)->update( $subf => 1 ); };
1465 ModBiblio
( $record, $biblionumber, $bib->{'frameworkcode'} );
1467 return $subscriptionid;
1470 =head2 ReNewSubscription
1472 ReNewSubscription($subscriptionid,$user,$startdate,$numberlength,$weeklength,$monthlength,$note)
1474 this function renew a subscription with values given on input args.
1478 sub ReNewSubscription
{
1479 my ( $subscriptionid, $user, $startdate, $numberlength, $weeklength, $monthlength, $note ) = @_;
1480 my $dbh = C4
::Context
->dbh;
1481 my $subscription = GetSubscription
($subscriptionid);
1485 LEFT JOIN biblioitems ON biblio
.biblionumber
=biblioitems
.biblionumber
1486 WHERE biblio
.biblionumber
=?
1488 my $sth = $dbh->prepare($query);
1489 $sth->execute( $subscription->{biblionumber
} );
1490 my $biblio = $sth->fetchrow_hashref;
1492 if ( C4
::Context
->preference("RenewSerialAddsSuggestion") ) {
1493 require C4
::Suggestions
;
1494 C4
::Suggestions
::NewSuggestion
(
1495 { 'suggestedby' => $user,
1496 'title' => $subscription->{bibliotitle
},
1497 'author' => $biblio->{author
},
1498 'publishercode' => $biblio->{publishercode
},
1499 'note' => $biblio->{note
},
1500 'biblionumber' => $subscription->{biblionumber
}
1505 # renew subscription
1508 SET startdate
=?
,numberlength
=?
,weeklength
=?
,monthlength
=?
,reneweddate
=NOW
()
1509 WHERE subscriptionid
=?
1511 $sth = $dbh->prepare($query);
1512 $sth->execute( $startdate, $numberlength, $weeklength, $monthlength, $subscriptionid );
1513 my $enddate = GetExpirationDate
($subscriptionid);
1514 $debug && warn "enddate :$enddate";
1518 WHERE subscriptionid
=?
1520 $sth = $dbh->prepare($query);
1521 $sth->execute( $enddate, $subscriptionid );
1523 UPDATE subscriptionhistory
1525 WHERE subscriptionid
=?
1527 $sth = $dbh->prepare($query);
1528 $sth->execute( $enddate, $subscriptionid );
1530 logaction
( "SERIAL", "RENEW", $subscriptionid, "" ) if C4
::Context
->preference("SubscriptionLog");
1536 NewIssue($serialseq,$subscriptionid,$biblionumber,$status, $planneddate, $publisheddate, $notes)
1538 Create a new issue stored on the database.
1539 Note : we have to update the recievedlist and missinglist on subscriptionhistory for this subscription.
1540 returns the serial id
1545 my ( $serialseq, $subscriptionid, $biblionumber, $status, $planneddate,
1546 $publisheddate, $publisheddatetext, $notes ) = @_;
1547 ### FIXME biblionumber CAN be provided by subscriptionid. So Do we STILL NEED IT ?
1549 return unless ($subscriptionid);
1551 my $dbh = C4
::Context
->dbh;
1553 INSERT INTO serial
(serialseq
, subscriptionid
, biblionumber
, status
,
1554 publisheddate
, publisheddatetext
, planneddate
, notes
)
1555 VALUES
(?
,?
,?
,?
,?
,?
,?
,?
)
1557 my $sth = $dbh->prepare($query);
1558 $sth->execute( $serialseq, $subscriptionid, $biblionumber, $status,
1559 $publisheddate, $publisheddatetext, $planneddate, $notes );
1560 my $serialid = $dbh->{'mysql_insertid'};
1562 SELECT missinglist
,recievedlist
1563 FROM subscriptionhistory
1564 WHERE subscriptionid
=?
1566 $sth = $dbh->prepare($query);
1567 $sth->execute($subscriptionid);
1568 my ( $missinglist, $recievedlist ) = $sth->fetchrow;
1570 if ( $status == ARRIVED
) {
1571 ### TODO Add a feature that improves recognition and description.
1572 ### As such count (serialseq) i.e. : N18,2(N19),N20
1573 ### Would use substr and index But be careful to previous presence of ()
1574 $recievedlist .= "; $serialseq" unless (index($recievedlist,$serialseq)>0);
1576 if ( grep {/^$status$/} ( MISSING_STATUSES
) ) {
1577 $missinglist .= "; $serialseq" unless (index($missinglist,$serialseq)>0);
1580 UPDATE subscriptionhistory
1581 SET recievedlist
=?
, missinglist
=?
1582 WHERE subscriptionid
=?
1584 $sth = $dbh->prepare($query);
1585 $recievedlist =~ s/^; //;
1586 $missinglist =~ s/^; //;
1587 $sth->execute( $recievedlist, $missinglist, $subscriptionid );
1591 =head2 HasSubscriptionStrictlyExpired
1593 1 or 0 = HasSubscriptionStrictlyExpired($subscriptionid)
1595 the subscription has stricly expired when today > the end subscription date
1598 1 if true, 0 if false, -1 if the expiration date is not set.
1602 sub HasSubscriptionStrictlyExpired
{
1604 # Getting end of subscription date
1605 my ($subscriptionid) = @_;
1607 return unless ($subscriptionid);
1609 my $dbh = C4
::Context
->dbh;
1610 my $subscription = GetSubscription
($subscriptionid);
1611 my $expirationdate = $subscription->{enddate
} || GetExpirationDate
($subscriptionid);
1613 # If the expiration date is set
1614 if ( $expirationdate != 0 ) {
1615 my ( $endyear, $endmonth, $endday ) = split( '-', $expirationdate );
1617 # Getting today's date
1618 my ( $nowyear, $nowmonth, $nowday ) = Today
();
1620 # if today's date > expiration date, then the subscription has stricly expired
1621 if ( Delta_Days
( $nowyear, $nowmonth, $nowday, $endyear, $endmonth, $endday ) < 0 ) {
1628 # There are some cases where the expiration date is not set
1629 # As we can't determine if the subscription has expired on a date-basis,
1635 =head2 HasSubscriptionExpired
1637 $has_expired = HasSubscriptionExpired($subscriptionid)
1639 the subscription has expired when the next issue to arrive is out of subscription limit.
1642 0 if the subscription has not expired
1643 1 if the subscription has expired
1644 2 if has subscription does not have a valid expiration date set
1648 sub HasSubscriptionExpired
{
1649 my ($subscriptionid) = @_;
1651 return unless ($subscriptionid);
1653 my $dbh = C4
::Context
->dbh;
1654 my $subscription = GetSubscription
($subscriptionid);
1655 my $frequency = C4
::Serials
::Frequency
::GetSubscriptionFrequency
($subscription->{periodicity
});
1656 if ( $frequency and $frequency->{unit
} ) {
1657 my $expirationdate = $subscription->{enddate
} || GetExpirationDate
($subscriptionid);
1658 if (!defined $expirationdate) {
1659 $expirationdate = q{};
1662 SELECT max
(planneddate
)
1664 WHERE subscriptionid
=?
1666 my $sth = $dbh->prepare($query);
1667 $sth->execute($subscriptionid);
1668 my ($res) = $sth->fetchrow;
1669 if (!$res || $res=~m/^0000/) {
1672 my @res = split( /-/, $res );
1673 my @endofsubscriptiondate = split( /-/, $expirationdate );
1674 return 2 if ( scalar(@res) != 3 || scalar(@endofsubscriptiondate) != 3 || not check_date
(@res) || not check_date
(@endofsubscriptiondate) );
1676 if ( ( @endofsubscriptiondate && Delta_Days
( $res[0], $res[1], $res[2], $endofsubscriptiondate[0], $endofsubscriptiondate[1], $endofsubscriptiondate[2] ) <= 0 )
1681 if ( $subscription->{'numberlength'} ) {
1682 my $countreceived = countissuesfrom
( $subscriptionid, $subscription->{'startdate'} );
1683 return 1 if ( $countreceived > $subscription->{'numberlength'} );
1689 return 0; # Notice that you'll never get here.
1692 =head2 SetDistributedto
1694 SetDistributedto($distributedto,$subscriptionid);
1695 This function update the value of distributedto for a subscription given on input arg.
1699 sub SetDistributedto
{
1700 my ( $distributedto, $subscriptionid ) = @_;
1701 my $dbh = C4
::Context
->dbh;
1705 WHERE subscriptionid
=?
1707 my $sth = $dbh->prepare($query);
1708 $sth->execute( $distributedto, $subscriptionid );
1712 =head2 DelSubscription
1714 DelSubscription($subscriptionid)
1715 this function deletes subscription which has $subscriptionid as id.
1719 sub DelSubscription
{
1720 my ($subscriptionid) = @_;
1721 my $dbh = C4
::Context
->dbh;
1722 $dbh->do("DELETE FROM subscription WHERE subscriptionid=?", undef, $subscriptionid);
1723 $dbh->do("DELETE FROM subscriptionhistory WHERE subscriptionid=?", undef, $subscriptionid);
1724 $dbh->do("DELETE FROM serial WHERE subscriptionid=?", undef, $subscriptionid);
1726 my $afs = Koha
::AdditionalField
->all({tablename
=> 'subscription'});
1727 foreach my $af (@
$afs) {
1728 $af->delete_values({record_id
=> $subscriptionid});
1731 logaction
( "SERIAL", "DELETE", $subscriptionid, "" ) if C4
::Context
->preference("SubscriptionLog");
1736 DelIssue($serialseq,$subscriptionid)
1737 this function deletes an issue which has $serialseq and $subscriptionid given on input arg.
1739 returns the number of rows affected
1744 my ($dataissue) = @_;
1745 my $dbh = C4
::Context
->dbh;
1746 ### TODO Add itemdeletion. Would need to get itemnumbers. Should be in a pref ?
1751 AND subscriptionid
= ?
1753 my $mainsth = $dbh->prepare($query);
1754 $mainsth->execute( $dataissue->{'serialid'}, $dataissue->{'subscriptionid'} );
1756 #Delete element from subscription history
1757 $query = "SELECT * FROM subscription WHERE subscriptionid = ?";
1758 my $sth = $dbh->prepare($query);
1759 $sth->execute( $dataissue->{'subscriptionid'} );
1760 my $val = $sth->fetchrow_hashref;
1761 unless ( $val->{manualhistory
} ) {
1763 SELECT
* FROM subscriptionhistory
1764 WHERE subscriptionid
= ?
1766 my $sth = $dbh->prepare($query);
1767 $sth->execute( $dataissue->{'subscriptionid'} );
1768 my $data = $sth->fetchrow_hashref;
1769 my $serialseq = $dataissue->{'serialseq'};
1770 $data->{'missinglist'} =~ s/\b$serialseq\b//;
1771 $data->{'recievedlist'} =~ s/\b$serialseq\b//;
1772 my $strsth = "UPDATE subscriptionhistory SET " . join( ",", map { join( "=", $_, $dbh->quote( $data->{$_} ) ) } keys %$data ) . " WHERE subscriptionid=?";
1773 $sth = $dbh->prepare($strsth);
1774 $sth->execute( $dataissue->{'subscriptionid'} );
1777 return $mainsth->rows;
1780 =head2 GetLateOrMissingIssues
1782 @issuelist = GetLateMissingIssues($supplierid,$serialid)
1784 this function selects missing issues on database - where serial.status = MISSING* or serial.status = LATE or planneddate<now
1787 the issuelist as an array of hash refs. Each element of this array contains
1788 name,title,planneddate,serialseq,serial.subscriptionid from tables : subscription, serial & biblio
1792 sub GetLateOrMissingIssues
{
1793 my ( $supplierid, $serialid, $order ) = @_;
1795 return unless ( $supplierid or $serialid );
1797 my $dbh = C4
::Context
->dbh;
1802 $byserial = "and serialid = " . $serialid;
1805 $order .= ", title";
1809 my $missing_statuses_string = join ',', (MISSING_STATUSES
);
1811 $sth = $dbh->prepare(
1813 serialid, aqbooksellerid, name,
1814 biblio.title, biblioitems.issn, planneddate, serialseq,
1815 serial.status, serial.subscriptionid, claimdate, claims_count,
1816 subscription.branchcode
1818 LEFT JOIN subscription ON serial.subscriptionid=subscription.subscriptionid
1819 LEFT JOIN biblio ON subscription.biblionumber=biblio.biblionumber
1820 LEFT JOIN biblioitems ON subscription.biblionumber=biblioitems.biblionumber
1821 LEFT JOIN aqbooksellers ON subscription.aqbooksellerid = aqbooksellers.id
1822 WHERE subscription.subscriptionid = serial.subscriptionid
1823 AND (serial.STATUS IN ($missing_statuses_string) OR ((planneddate < now() AND serial.STATUS = ?) OR serial.STATUS = ? OR serial.STATUS = ?))
1824 AND subscription.aqbooksellerid=$supplierid
1829 $sth = $dbh->prepare(
1831 serialid, aqbooksellerid, name,
1832 biblio.title, planneddate, serialseq,
1833 serial.status, serial.subscriptionid, claimdate, claims_count,
1834 subscription.branchcode
1836 LEFT JOIN subscription ON serial.subscriptionid=subscription.subscriptionid
1837 LEFT JOIN biblio ON subscription.biblionumber=biblio.biblionumber
1838 LEFT JOIN aqbooksellers ON subscription.aqbooksellerid = aqbooksellers.id
1839 WHERE subscription.subscriptionid = serial.subscriptionid
1840 AND (serial.STATUS IN ($missing_statuses_string) OR ((planneddate < now() AND serial.STATUS = ?) OR serial.STATUS = ? OR serial.STATUS = ?))
1845 $sth->execute( EXPECTED
, LATE
, CLAIMED
);
1847 while ( my $line = $sth->fetchrow_hashref ) {
1849 if ($line->{planneddate
} && $line->{planneddate
} !~/^0+\-/) {
1850 $line->{planneddateISO
} = $line->{planneddate
};
1851 $line->{planneddate
} = output_pref
( { dt
=> dt_from_string
( $line->{"planneddate"} ), dateonly
=> 1 } );
1853 if ($line->{claimdate
} && $line->{claimdate
} !~/^0+\-/) {
1854 $line->{claimdateISO
} = $line->{claimdate
};
1855 $line->{claimdate
} = output_pref
( { dt
=> dt_from_string
( $line->{"claimdate"} ), dateonly
=> 1 } );
1857 $line->{"status".$line->{status
}} = 1;
1859 my $additional_field_values = Koha
::AdditionalField
->fetch_all_values({
1860 record_id
=> $line->{subscriptionid
},
1861 tablename
=> 'subscription'
1863 %$line = ( %$line, additional_fields
=> $additional_field_values->{$line->{subscriptionid
}} );
1865 push @issuelist, $line;
1872 &updateClaim($serialid)
1874 this function updates the time when a claim is issued for late/missing items
1876 called from claims.pl file
1881 my ($serialid) = @_;
1882 my $dbh = C4
::Context
->dbh;
1885 SET claimdate
= NOW
(),
1886 claims_count
= claims_count
+ 1
1892 =head2 getsupplierbyserialid
1894 $result = getsupplierbyserialid($serialid)
1896 this function is used to find the supplier id given a serial id
1899 hashref containing serialid, subscriptionid, and aqbooksellerid
1903 sub getsupplierbyserialid
{
1904 my ($serialid) = @_;
1905 my $dbh = C4
::Context
->dbh;
1906 my $sth = $dbh->prepare(
1907 "SELECT serialid, serial.subscriptionid, aqbooksellerid
1909 LEFT JOIN subscription ON serial.subscriptionid = subscription.subscriptionid
1913 $sth->execute($serialid);
1914 my $line = $sth->fetchrow_hashref;
1915 my $result = $line->{'aqbooksellerid'};
1919 =head2 check_routing
1921 $result = &check_routing($subscriptionid)
1923 this function checks to see if a serial has a routing list and returns the count of routingid
1924 used to show either an 'add' or 'edit' link
1929 my ($subscriptionid) = @_;
1931 return unless ($subscriptionid);
1933 my $dbh = C4
::Context
->dbh;
1934 my $sth = $dbh->prepare(
1935 "SELECT count(routingid) routingids FROM subscription LEFT JOIN subscriptionroutinglist
1936 ON subscription.subscriptionid = subscriptionroutinglist.subscriptionid
1937 WHERE subscription.subscriptionid = ? ORDER BY ranking ASC
1940 $sth->execute($subscriptionid);
1941 my $line = $sth->fetchrow_hashref;
1942 my $result = $line->{'routingids'};
1946 =head2 addroutingmember
1948 addroutingmember($borrowernumber,$subscriptionid)
1950 this function takes a borrowernumber and subscriptionid and adds the member to the
1951 routing list for that serial subscription and gives them a rank on the list
1952 of either 1 or highest current rank + 1
1956 sub addroutingmember
{
1957 my ( $borrowernumber, $subscriptionid ) = @_;
1959 return unless ($borrowernumber and $subscriptionid);
1962 my $dbh = C4
::Context
->dbh;
1963 my $sth = $dbh->prepare( "SELECT max(ranking) rank FROM subscriptionroutinglist WHERE subscriptionid = ?" );
1964 $sth->execute($subscriptionid);
1965 while ( my $line = $sth->fetchrow_hashref ) {
1966 if ( $line->{'rank'} > 0 ) {
1967 $rank = $line->{'rank'} + 1;
1972 $sth = $dbh->prepare( "INSERT INTO subscriptionroutinglist (subscriptionid,borrowernumber,ranking) VALUES (?,?,?)" );
1973 $sth->execute( $subscriptionid, $borrowernumber, $rank );
1976 =head2 reorder_members
1978 reorder_members($subscriptionid,$routingid,$rank)
1980 this function is used to reorder the routing list
1982 it takes the routingid of the member one wants to re-rank and the rank it is to move to
1983 - it gets all members on list puts their routingid's into an array
1984 - removes the one in the array that is $routingid
1985 - then reinjects $routingid at point indicated by $rank
1986 - then update the database with the routingids in the new order
1990 sub reorder_members
{
1991 my ( $subscriptionid, $routingid, $rank ) = @_;
1992 my $dbh = C4
::Context
->dbh;
1993 my $sth = $dbh->prepare( "SELECT * FROM subscriptionroutinglist WHERE subscriptionid = ? ORDER BY ranking ASC" );
1994 $sth->execute($subscriptionid);
1996 while ( my $line = $sth->fetchrow_hashref ) {
1997 push( @result, $line->{'routingid'} );
2000 # To find the matching index
2002 my $key = -1; # to allow for 0 being a valid response
2003 for ( $i = 0 ; $i < @result ; $i++ ) {
2004 if ( $routingid == $result[$i] ) {
2005 $key = $i; # save the index
2010 # if index exists in array then move it to new position
2011 if ( $key > -1 && $rank > 0 ) {
2012 my $new_rank = $rank - 1; # $new_rank is what you want the new index to be in the array
2013 my $moving_item = splice( @result, $key, 1 );
2014 splice( @result, $new_rank, 0, $moving_item );
2016 for ( my $j = 0 ; $j < @result ; $j++ ) {
2017 my $sth = $dbh->prepare( "UPDATE subscriptionroutinglist SET ranking = '" . ( $j + 1 ) . "' WHERE routingid = '" . $result[$j] . "'" );
2023 =head2 delroutingmember
2025 delroutingmember($routingid,$subscriptionid)
2027 this function either deletes one member from routing list if $routingid exists otherwise
2028 deletes all members from the routing list
2032 sub delroutingmember
{
2034 # if $routingid exists then deletes that row otherwise deletes all with $subscriptionid
2035 my ( $routingid, $subscriptionid ) = @_;
2036 my $dbh = C4
::Context
->dbh;
2038 my $sth = $dbh->prepare("DELETE FROM subscriptionroutinglist WHERE routingid = ?");
2039 $sth->execute($routingid);
2040 reorder_members
( $subscriptionid, $routingid );
2042 my $sth = $dbh->prepare("DELETE FROM subscriptionroutinglist WHERE subscriptionid = ?");
2043 $sth->execute($subscriptionid);
2048 =head2 getroutinglist
2050 @routinglist = getroutinglist($subscriptionid)
2052 this gets the info from the subscriptionroutinglist for $subscriptionid
2055 the routinglist as an array. Each element of the array contains a hash_ref containing
2056 routingid - a unique id, borrowernumber, ranking, and biblionumber of subscription
2060 sub getroutinglist
{
2061 my ($subscriptionid) = @_;
2062 my $dbh = C4
::Context
->dbh;
2063 my $sth = $dbh->prepare(
2064 'SELECT routingid, borrowernumber, ranking, biblionumber
2066 JOIN subscriptionroutinglist ON subscription.subscriptionid = subscriptionroutinglist.subscriptionid
2067 WHERE subscription.subscriptionid = ? ORDER BY ranking ASC'
2069 $sth->execute($subscriptionid);
2070 my $routinglist = $sth->fetchall_arrayref({});
2071 return @
{$routinglist};
2074 =head2 countissuesfrom
2076 $result = countissuesfrom($subscriptionid,$startdate)
2078 Returns a count of serial rows matching the given subsctiptionid
2079 with published date greater than startdate
2083 sub countissuesfrom
{
2084 my ( $subscriptionid, $startdate ) = @_;
2085 my $dbh = C4
::Context
->dbh;
2089 WHERE subscriptionid
=?
2090 AND serial
.publisheddate
>?
2092 my $sth = $dbh->prepare($query);
2093 $sth->execute( $subscriptionid, $startdate );
2094 my ($countreceived) = $sth->fetchrow;
2095 return $countreceived;
2100 $result = CountIssues($subscriptionid)
2102 Returns a count of serial rows matching the given subsctiptionid
2107 my ($subscriptionid) = @_;
2108 my $dbh = C4
::Context
->dbh;
2112 WHERE subscriptionid
=?
2114 my $sth = $dbh->prepare($query);
2115 $sth->execute($subscriptionid);
2116 my ($countreceived) = $sth->fetchrow;
2117 return $countreceived;
2122 $result = HasItems($subscriptionid)
2124 returns a count of items from serial matching the subscriptionid
2129 my ($subscriptionid) = @_;
2130 my $dbh = C4
::Context
->dbh;
2132 SELECT COUNT
(serialitems
.itemnumber
)
2134 LEFT JOIN serialitems USING
(serialid
)
2135 WHERE subscriptionid
=? AND serialitems
.serialid IS NOT NULL
2137 my $sth=$dbh->prepare($query);
2138 $sth->execute($subscriptionid);
2139 my ($countitems)=$sth->fetchrow_array();
2143 =head2 abouttoexpire
2145 $result = abouttoexpire($subscriptionid)
2147 this function alerts you to the penultimate issue for a serial subscription
2149 returns 1 - if this is the penultimate issue
2155 my ($subscriptionid) = @_;
2156 my $dbh = C4
::Context
->dbh;
2157 my $subscription = GetSubscription
($subscriptionid);
2158 my $per = $subscription->{'periodicity'};
2159 my $frequency = C4
::Serials
::Frequency
::GetSubscriptionFrequency
($per);
2160 if ($frequency and $frequency->{unit
}){
2162 my $expirationdate = GetExpirationDate
($subscriptionid);
2164 my ($res) = $dbh->selectrow_array('select max(planneddate) from serial where subscriptionid = ?', undef, $subscriptionid);
2165 my $nextdate = GetNextDate
($subscription, $res);
2167 # only compare dates if both dates exist.
2168 if ($nextdate and $expirationdate) {
2169 if(Date
::Calc
::Delta_Days
(
2170 split( /-/, $nextdate ),
2171 split( /-/, $expirationdate )
2177 } elsif ($subscription->{numberlength
}>0) {
2178 return (countissuesfrom
($subscriptionid,$subscription->{'startdate'}) >=$subscription->{numberlength
}-1);
2184 sub in_array
{ # used in next sub down
2185 my ( $val, @elements ) = @_;
2186 foreach my $elem (@elements) {
2187 if ( $val == $elem ) {
2194 =head2 GetSubscriptionsFromBorrower
2196 ($count,@routinglist) = GetSubscriptionsFromBorrower($borrowernumber)
2198 this gets the info from subscriptionroutinglist for each $subscriptionid
2201 a count of the serial subscription routing lists to which a patron belongs,
2202 with the titles of those serial subscriptions as an array. Each element of the array
2203 contains a hash_ref with subscriptionID and title of subscription.
2207 sub GetSubscriptionsFromBorrower
{
2208 my ($borrowernumber) = @_;
2209 my $dbh = C4
::Context
->dbh;
2210 my $sth = $dbh->prepare(
2211 "SELECT subscription.subscriptionid, biblio.title
2213 JOIN biblio ON biblio.biblionumber = subscription.biblionumber
2214 JOIN subscriptionroutinglist USING (subscriptionid)
2215 WHERE subscriptionroutinglist.borrowernumber = ? ORDER BY title ASC
2218 $sth->execute($borrowernumber);
2221 while ( my $line = $sth->fetchrow_hashref ) {
2223 push( @routinglist, $line );
2225 return ( $count, @routinglist );
2229 =head2 GetFictiveIssueNumber
2231 $issueno = GetFictiveIssueNumber($subscription, $publishedate);
2233 Get the position of the issue published at $publisheddate, considering the
2234 first issue (at firstacquidate) is at position 1, the next is at position 2, etc...
2235 This issuenumber doesn't take into account irregularities, so, for instance, if the 3rd
2236 issue is declared as 'irregular' (will be skipped at receipt), the next issue number
2237 will be 4, not 3. It's why it is called 'fictive'. It is NOT a serial seq, and is not
2238 depending on how many rows are in serial table.
2239 The issue number calculation is based on subscription frequency, first acquisition
2240 date, and $publisheddate.
2244 sub GetFictiveIssueNumber
{
2245 my ($subscription, $publisheddate) = @_;
2247 my $frequency = GetSubscriptionFrequency
($subscription->{'periodicity'});
2248 my $unit = $frequency->{unit
} ?
lc $frequency->{'unit'} : undef;
2252 my ($year, $month, $day) = split /-/, $publisheddate;
2253 my ($fa_year, $fa_month, $fa_day) = split /-/, $subscription->{'firstacquidate'};
2257 if($unit eq 'day') {
2258 $delta = Delta_Days
($fa_year, $fa_month, $fa_day, $year, $month, $day);
2259 } elsif($unit eq 'week') {
2260 ($wkno, $year) = Week_of_Year
($year, $month, $day);
2261 my ($fa_wkno, $fa_yr) = Week_of_Year
($fa_year, $fa_month, $fa_day);
2262 $delta = ($fa_yr == $year) ?
($wkno - $fa_wkno) : ( ($year-$fa_yr-1)*52 + (52-$fa_wkno+$wkno) );
2263 } elsif($unit eq 'month') {
2264 $delta = ($fa_year == $year)
2265 ?
($month - $fa_month)
2266 : ( ($year-$fa_year-1)*12 + (12-$fa_month+$month) );
2267 } elsif($unit eq 'year') {
2268 $delta = $year - $fa_year;
2270 if($frequency->{'unitsperissue'} == 1) {
2271 $issueno = $delta * $frequency->{'issuesperunit'} + $subscription->{'countissuesperunit'};
2273 # Assuming issuesperunit == 1
2274 $issueno = int( ($delta + $frequency->{'unitsperissue'}) / $frequency->{'unitsperissue'} );
2280 sub _get_next_date_day
{
2281 my ($subscription, $freqdata, $year, $month, $day) = @_;
2283 if ($subscription->{countissuesperunit
} + 1 > $freqdata->{issuesperunit
}){
2284 ($year,$month,$day) = Add_Delta_Days
($year,$month, $day , $freqdata->{unitsperissue
} );
2285 $subscription->{countissuesperunit
} = 1;
2287 $subscription->{countissuesperunit
}++;
2290 return ($year, $month, $day);
2293 sub _get_next_date_week
{
2294 my ($subscription, $freqdata, $year, $month, $day) = @_;
2296 my ($wkno, $yr) = Week_of_Year
($year, $month, $day);
2297 my $fa_dow = Day_of_Week
(split /-/, $subscription->{firstacquidate
});
2299 if ($subscription->{countissuesperunit
} + 1 > $freqdata->{issuesperunit
}){
2300 $subscription->{countissuesperunit
} = 1;
2301 $wkno += $freqdata->{unitsperissue
};
2306 ($year,$month,$day) = Monday_of_Week
($wkno, $yr);
2307 ($year,$month,$day) = Add_Delta_Days
($year, $month, $day, $fa_dow - 1);
2309 # Try to guess the next day of week
2310 my $delta_days = int((7 - ($fa_dow - 1)) / $freqdata->{issuesperunit
});
2311 ($year,$month,$day) = Add_Delta_Days
($year, $month, $day, $delta_days);
2312 $subscription->{countissuesperunit
}++;
2315 return ($year, $month, $day);
2318 sub _get_next_date_month
{
2319 my ($subscription, $freqdata, $year, $month, $day) = @_;
2322 (undef, undef, $fa_day) = split /-/, $subscription->{firstacquidate
};
2324 if ($subscription->{countissuesperunit
} + 1 > $freqdata->{issuesperunit
}){
2325 $subscription->{countissuesperunit
} = 1;
2326 ($year,$month,$day) = Add_Delta_YM
($year,$month,$day, 0,
2327 $freqdata->{unitsperissue
});
2328 my $days_in_month = Days_in_Month
($year, $month);
2329 $day = $fa_day <= $days_in_month ?
$fa_day : $days_in_month;
2331 # Try to guess the next day in month
2332 my $days_in_month = Days_in_Month
($year, $month);
2333 my $delta_days = int(($days_in_month - ($fa_day - 1)) / $freqdata->{issuesperunit
});
2334 ($year,$month,$day) = Add_Delta_Days
($year, $month, $day, $delta_days);
2335 $subscription->{countissuesperunit
}++;
2338 return ($year, $month, $day);
2341 sub _get_next_date_year
{
2342 my ($subscription, $freqdata, $year, $month, $day) = @_;
2344 my ($fa_year, $fa_month, $fa_day) = split /-/, $subscription->{firstacquidate
};
2346 if ($subscription->{countissuesperunit
} + 1 > $freqdata->{issuesperunit
}){
2347 $subscription->{countissuesperunit
} = 1;
2348 ($year) = Add_Delta_YM
($year,$month,$day, $freqdata->{"unitsperissue"},0);
2350 my $days_in_month = Days_in_Month
($year, $month);
2351 $day = $fa_day <= $days_in_month ?
$fa_day : $days_in_month;
2353 # Try to guess the next day in year
2354 my $days_in_year = Days_in_Year
($year,12); #Sum the days of all the months of this year
2355 my $delta_days = int(($days_in_year - ($fa_day - 1)) / $freqdata->{issuesperunit
});
2356 ($year,$month,$day) = Add_Delta_Days
($year, $month, $day, $delta_days);
2357 $subscription->{countissuesperunit
}++;
2360 return ($year, $month, $day);
2365 $resultdate = GetNextDate($publisheddate,$subscription)
2367 this function it takes the publisheddate and will return the next issue's date
2368 and will skip dates if there exists an irregularity.
2369 $publisheddate has to be an ISO date
2370 $subscription is a hashref containing at least 'periodicity', 'firstacquidate', 'irregularity', and 'countissuesperunit'
2371 $updatecount is a boolean value which, when set to true, update the 'countissuesperunit' in database
2372 - eg if periodicity is monthly and $publisheddate is 2007-02-10 but if March and April is to be
2373 skipped then the returned date will be 2007-05-10
2376 $resultdate - then next date in the sequence (ISO date)
2378 Return undef if subscription is irregular
2383 my ( $subscription, $publisheddate, $updatecount ) = @_;
2385 return unless $subscription and $publisheddate;
2387 my $freqdata = GetSubscriptionFrequency
($subscription->{'periodicity'});
2389 if ($freqdata->{'unit'}) {
2390 my ( $year, $month, $day ) = split /-/, $publisheddate;
2392 # Process an irregularity Hash
2393 # Suppose that irregularities are stored in a string with this structure
2394 # irreg1;irreg2;irreg3
2395 # where irregX is the number of issue which will not be received
2396 # (the first issue takes the number 1, the 2nd the number 2 and so on)
2398 if ( $subscription->{irregularity
} ) {
2399 my @irreg = split /;/, $subscription->{'irregularity'} ;
2400 foreach my $irregularity (@irreg) {
2401 $irregularities{$irregularity} = 1;
2405 # Get the 'fictive' next issue number
2406 # It is used to check if next issue is an irregular issue.
2407 my $issueno = GetFictiveIssueNumber
($subscription, $publisheddate) + 1;
2409 # Then get the next date
2410 my $unit = lc $freqdata->{'unit'};
2411 if ($unit eq 'day') {
2412 while ($irregularities{$issueno}) {
2413 ($year, $month, $day) = _get_next_date_day
($subscription,
2414 $freqdata, $year, $month, $day);
2417 ($year, $month, $day) = _get_next_date_day
($subscription, $freqdata,
2418 $year, $month, $day);
2420 elsif ($unit eq 'week') {
2421 while ($irregularities{$issueno}) {
2422 ($year, $month, $day) = _get_next_date_week
($subscription,
2423 $freqdata, $year, $month, $day);
2426 ($year, $month, $day) = _get_next_date_week
($subscription,
2427 $freqdata, $year, $month, $day);
2429 elsif ($unit eq 'month') {
2430 while ($irregularities{$issueno}) {
2431 ($year, $month, $day) = _get_next_date_month
($subscription,
2432 $freqdata, $year, $month, $day);
2435 ($year, $month, $day) = _get_next_date_month
($subscription,
2436 $freqdata, $year, $month, $day);
2438 elsif ($unit eq 'year') {
2439 while ($irregularities{$issueno}) {
2440 ($year, $month, $day) = _get_next_date_year
($subscription,
2441 $freqdata, $year, $month, $day);
2444 ($year, $month, $day) = _get_next_date_year
($subscription,
2445 $freqdata, $year, $month, $day);
2449 my $dbh = C4
::Context
->dbh;
2452 SET countissuesperunit
= ?
2453 WHERE subscriptionid
= ?
2455 my $sth = $dbh->prepare($query);
2456 $sth->execute($subscription->{'countissuesperunit'}, $subscription->{'subscriptionid'});
2459 return sprintf("%04d-%02d-%02d", $year, $month, $day);
2465 $string = &_numeration($value,$num_type,$locale);
2467 _numeration returns the string corresponding to $value in the num_type
2477 my ($value, $num_type, $locale) = @_;
2482 if ( $num_type =~ /^dayname$/ ) {
2483 # 1970-11-01 was a Sunday
2484 $value = $value % 7;
2485 my $dt = DateTime
->new(
2491 $string = $dt->strftime("%A");
2492 } elsif ( $num_type =~ /^monthname$/ ) {
2493 $value = $value % 12;
2494 my $dt = DateTime
->new(
2496 month
=> $value + 1,
2499 $string = $dt->strftime("%B");
2500 } elsif ( $num_type =~ /^season$/ ) {
2501 my @seasons= qw( Spring Summer Fall Winter );
2502 $value = $value % 4;
2503 $string = $seasons[$value];
2511 =head2 is_barcode_in_use
2513 Returns number of occurrences of the barcode in the items table
2514 Can be used as a boolean test of whether the barcode has
2515 been deployed as yet
2519 sub is_barcode_in_use
{
2520 my $barcode = shift;
2521 my $dbh = C4
::Context
->dbh;
2522 my $occurrences = $dbh->selectall_arrayref(
2523 'SELECT itemnumber from items where barcode = ?',
2528 return @
{$occurrences};
2531 =head2 CloseSubscription
2532 Close a subscription given a subscriptionid
2534 sub CloseSubscription
{
2535 my ( $subscriptionid ) = @_;
2536 return unless $subscriptionid;
2537 my $dbh = C4
::Context
->dbh;
2538 my $sth = $dbh->prepare( q{
2541 WHERE subscriptionid = ?
2543 $sth->execute( $subscriptionid );
2545 # Set status = missing when status = stopped
2546 $sth = $dbh->prepare( q{
2549 WHERE subscriptionid = ?
2552 $sth->execute( STOPPED
, $subscriptionid, EXPECTED
);
2555 =head2 ReopenSubscription
2556 Reopen a subscription given a subscriptionid
2558 sub ReopenSubscription
{
2559 my ( $subscriptionid ) = @_;
2560 return unless $subscriptionid;
2561 my $dbh = C4
::Context
->dbh;
2562 my $sth = $dbh->prepare( q{
2565 WHERE subscriptionid = ?
2567 $sth->execute( $subscriptionid );
2569 # Set status = expected when status = stopped
2570 $sth = $dbh->prepare( q{
2573 WHERE subscriptionid = ?
2576 $sth->execute( EXPECTED
, $subscriptionid, STOPPED
);
2579 =head2 subscriptionCurrentlyOnOrder
2581 $bool = subscriptionCurrentlyOnOrder( $subscriptionid );
2583 Return 1 if subscription is currently on order else 0.
2587 sub subscriptionCurrentlyOnOrder
{
2588 my ( $subscriptionid ) = @_;
2589 my $dbh = C4
::Context
->dbh;
2591 SELECT COUNT
(*) FROM aqorders
2592 WHERE subscriptionid
= ?
2593 AND datereceived IS NULL
2594 AND datecancellationprinted IS NULL
2596 my $sth = $dbh->prepare( $query );
2597 $sth->execute($subscriptionid);
2598 return $sth->fetchrow_array;
2601 =head2 can_claim_subscription
2603 $can = can_claim_subscription( $subscriptionid[, $userid] );
2605 Return 1 if the subscription can be claimed by the current logged user (or a given $userid), else 0.
2609 sub can_claim_subscription
{
2610 my ( $subscription, $userid ) = @_;
2611 return _can_do_on_subscription
( $subscription, $userid, 'claim_serials' );
2614 =head2 can_edit_subscription
2616 $can = can_edit_subscription( $subscriptionid[, $userid] );
2618 Return 1 if the subscription can be edited by the current logged user (or a given $userid), else 0.
2622 sub can_edit_subscription
{
2623 my ( $subscription, $userid ) = @_;
2624 return _can_do_on_subscription
( $subscription, $userid, 'edit_subscription' );
2627 =head2 can_show_subscription
2629 $can = can_show_subscription( $subscriptionid[, $userid] );
2631 Return 1 if the subscription can be shown by the current logged user (or a given $userid), else 0.
2635 sub can_show_subscription
{
2636 my ( $subscription, $userid ) = @_;
2637 return _can_do_on_subscription
( $subscription, $userid, '*' );
2640 sub _can_do_on_subscription
{
2641 my ( $subscription, $userid, $permission ) = @_;
2642 return 0 unless C4
::Context
->userenv;
2643 my $flags = C4
::Context
->userenv->{flags
};
2644 $userid ||= C4
::Context
->userenv->{'id'};
2646 if ( C4
::Context
->preference('IndependentBranches') ) {
2648 if C4
::Context
->IsSuperLibrarian()
2650 C4
::Auth
::haspermission
( $userid, { serials
=> 'superserials' } )
2652 C4
::Auth
::haspermission
( $userid,
2653 { serials
=> $permission } )
2654 and ( not defined $subscription->{branchcode
}
2655 or $subscription->{branchcode
} eq ''
2656 or $subscription->{branchcode
} eq
2657 C4
::Context
->userenv->{'branch'} )
2662 if C4
::Context
->IsSuperLibrarian()
2664 C4
::Auth
::haspermission
( $userid, { serials
=> 'superserials' } )
2665 or C4
::Auth
::haspermission
(
2666 $userid, { serials
=> $permission }
2678 Koha Development Team <http://koha-community.org/>