X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=C4%2FSerials.pm;h=b52b7a9c026e80aec96e07a32dae3876011ef50c;hb=7c5c6b3ca9b6b74512505ad5a603447856af31f9;hp=3cbd0424ad8a783a81b2bcec6343bfdc6aad9069;hpb=dc9ff3c53d4a659ec278cff4bff07cf18100b884;p=srvgit diff --git a/C4/Serials.pm b/C4/Serials.pm index 3cbd0424ad..b52b7a9c02 100644 --- a/C4/Serials.pm +++ b/C4/Serials.pm @@ -5,24 +5,27 @@ package C4::Serials; # # This file is part of Koha. # -# Koha is free software; you can redistribute it and/or modify it under the -# terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. # -# Koha is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. # -# You should have received a copy of the GNU General Public License along -# with Koha; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . use Modern::Perl; +use C4::Auth qw(haspermission); +use C4::Context; use C4::Dates qw(format_date format_date_in_iso); +use DateTime; use Date::Calc qw(:all); -use POSIX qw(strftime setlocale LC_TIME); +use POSIX qw(strftime); use C4::Biblio; use C4::Log; # logaction use C4::Debug; @@ -31,12 +34,34 @@ use C4::Serials::Numberpattern; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); +# Define statuses +use constant { + EXPECTED => 1, + ARRIVED => 2, + LATE => 3, + MISSING => 4, + MISSING_NEVER_RECIEVED => 41, + MISSING_SOLD_OUT => 42, + MISSING_DAMAGED => 43, + MISSING_LOST => 44, + NOT_ISSUED => 5, + DELETED => 6, + CLAIMED => 7, + STOPPED => 8, +}; + +use constant MISSING_STATUSES => ( + MISSING, MISSING_NEVER_RECIEVED, + MISSING_SOLD_OUT, MISSING_DAMAGED, + MISSING_LOST +); + BEGIN { $VERSION = 3.07.00.049; # set version for version checking require Exporter; @ISA = qw(Exporter); @EXPORT = qw( - &NewSubscription &ModSubscription &DelSubscription &GetSubscriptions + &NewSubscription &ModSubscription &DelSubscription &GetSubscription &CountSubscriptionFromBiblionumber &GetSubscriptionsFromBiblionumber &SearchSubscriptions &GetFullSubscriptionsFromBiblionumber &GetFullSubscription &ModSubscriptionHistory @@ -45,7 +70,7 @@ BEGIN { &GetNextSeq &GetSeq &NewIssue &ItemizeSerials &GetSerials &GetLatestSerials &ModSerialStatus &GetNextDate &GetSerials2 - &ReNewSubscription &GetLateIssues &GetLateOrMissingIssues + &ReNewSubscription &GetLateOrMissingIssues &GetSerialInformation &AddItem2Serial &PrepareSerialsData &GetNextExpected &ModNextExpected @@ -58,6 +83,7 @@ BEGIN { &CountIssues HasItems &GetSubscriptionsFromBorrower + &subscriptionCurrentlyOnOrder ); } @@ -91,78 +117,22 @@ the array is in name order sub GetSuppliersWithLateIssues { my $dbh = C4::Context->dbh; + my $statuses = join(',', ( LATE, MISSING_STATUSES, CLAIMED ) ); my $query = qq| - SELECT DISTINCT id, name + SELECT DISTINCT id, name FROM subscription LEFT JOIN serial ON serial.subscriptionid=subscription.subscriptionid LEFT JOIN aqbooksellers ON subscription.aqbooksellerid = aqbooksellers.id WHERE id > 0 AND ( (planneddate < now() AND serial.status=1) - OR serial.STATUS = 3 OR serial.STATUS = 4 + OR serial.STATUS IN ( $statuses ) ) AND subscription.closed = 0 ORDER BY name|; return $dbh->selectall_arrayref($query, { Slice => {} }); } -=head2 GetLateIssues - -@issuelist = GetLateIssues($supplierid) - -this function selects late issues from the database - -return : -the issuelist as an array. Each element of this array contains a hashi_ref containing -name,title,planneddate,serialseq,serial.subscriptionid from tables : subscription, serial & biblio - -=cut - -sub GetLateIssues { - my ($supplierid) = @_; - my $dbh = C4::Context->dbh; - my $sth; - if ($supplierid) { - my $query = qq| - SELECT name,title,planneddate,serialseq,serial.subscriptionid - FROM subscription - LEFT JOIN serial ON subscription.subscriptionid = serial.subscriptionid - LEFT JOIN biblio ON biblio.biblionumber = subscription.biblionumber - LEFT JOIN aqbooksellers ON subscription.aqbooksellerid = aqbooksellers.id - WHERE ((planneddate < now() AND serial.STATUS =1) OR serial.STATUS = 3) - AND subscription.aqbooksellerid=? - AND subscription.closed = 0 - ORDER BY title - |; - $sth = $dbh->prepare($query); - $sth->execute($supplierid); - } else { - my $query = qq| - SELECT name,title,planneddate,serialseq,serial.subscriptionid - FROM subscription - LEFT JOIN serial ON subscription.subscriptionid = serial.subscriptionid - LEFT JOIN biblio ON biblio.biblionumber = subscription.biblionumber - LEFT JOIN aqbooksellers ON subscription.aqbooksellerid = aqbooksellers.id - WHERE ((planneddate < now() AND serial.STATUS =1) OR serial.STATUS = 3) - AND subscription.closed = 0 - ORDER BY title - |; - $sth = $dbh->prepare($query); - $sth->execute; - } - my @issuelist; - my $last_title; - my $odd = 0; - while ( my $line = $sth->fetchrow_hashref ) { - $odd++ unless $line->{title} eq $last_title; - $line->{title} = "" if $line->{title} eq $last_title; - $last_title = $line->{title} if ( $line->{title} ); - $line->{planneddate} = format_date( $line->{planneddate} ); - push @issuelist, $line; - } - return @issuelist; -} - =head2 GetSubscriptionHistoryFromSubscriptionId $history = GetSubscriptionHistoryFromSubscriptionId($subscriptionid); @@ -226,15 +196,7 @@ sub GetSerialInformation { my ($serialid) = @_; my $dbh = C4::Context->dbh; my $query = qq| - SELECT serial.*, serial.notes as sernotes, serial.status as serstatus,subscription.*,subscription.subscriptionid as subsid |; - if ( C4::Context->preference('IndependantBranches') - && C4::Context->userenv - && C4::Context->userenv->{'flags'} != 1 - && C4::Context->userenv->{'branch'} ) { - $query .= " - , ((subscription.branchcode <>\"" . C4::Context->userenv->{'branch'} . "\") and subscription.branchcode <>\"\" and subscription.branchcode IS NOT NULL) as cannotedit "; - } - $query .= qq| + SELECT serial.*, serial.notes as sernotes, serial.status as serstatus,subscription.*,subscription.subscriptionid as subsid FROM serial LEFT JOIN subscription ON subscription.subscriptionid=serial.subscriptionid WHERE serialid = ? |; @@ -273,6 +235,7 @@ sub GetSerialInformation { $data->{ "status" . $data->{'serstatus'} } = 1; $data->{'subscriptionexpired'} = HasSubscriptionExpired( $data->{'subscriptionid'} ) && $data->{'status'} == 1; $data->{'abouttoexpire'} = abouttoexpire( $data->{'subscriptionid'} ); + $data->{cannotedit} = not can_edit_subscription( $data ); return $data; } @@ -286,6 +249,9 @@ returns the number of rows affected sub AddItem2Serial { my ( $serialid, $itemnumber ) = @_; + + return unless ($serialid and $itemnumber); + my $dbh = C4::Context->dbh; my $rq = $dbh->prepare("INSERT INTO `serialitems` SET serialid=? , itemnumber=?"); $rq->execute( $serialid, $itemnumber ); @@ -303,13 +269,20 @@ Update Claimdate for issues in @$serialids list with date $date sub UpdateClaimdateIssues { my ( $serialids, $date ) = @_; + + return unless ($serialids); + my $dbh = C4::Context->dbh; $date = strftime( "%Y-%m-%d", localtime ) unless ($date); my $query = " - UPDATE serial SET claimdate = ?, status = 7 - WHERE serialid in (" . join( ",", map { '?' } @$serialids ) . ")"; + UPDATE serial + SET claimdate = ?, + status = ?, + claims_count = claims_count + 1 + WHERE serialid in (" . join( ",", map { '?' } @$serialids ) . ") + "; my $rq = $dbh->prepare($query); - $rq->execute($date, @$serialids); + $rq->execute($date, CLAIMED, @$serialids); return $rq->rows; } @@ -331,15 +304,7 @@ sub GetSubscription { subscriptionhistory.*, aqbooksellers.name AS aqbooksellername, biblio.title AS bibliotitle, - subscription.biblionumber as bibnum); - if ( C4::Context->preference('IndependantBranches') - && C4::Context->userenv - && C4::Context->userenv->{'flags'} != 1 - && C4::Context->userenv->{'branch'} ) { - $query .= " - , ((subscription.branchcode <>\"" . C4::Context->userenv->{'branch'} . "\") and subscription.branchcode <>\"\" and subscription.branchcode IS NOT NULL) as cannotedit "; - } - $query .= qq( + subscription.biblionumber as bibnum FROM subscription LEFT JOIN subscriptionhistory ON subscription.subscriptionid=subscriptionhistory.subscriptionid LEFT JOIN aqbooksellers ON subscription.aqbooksellerid=aqbooksellers.id @@ -347,16 +312,12 @@ sub GetSubscription { WHERE subscription.subscriptionid = ? ); - # if (C4::Context->preference('IndependantBranches') && - # C4::Context->userenv && - # C4::Context->userenv->{'flags'} != 1){ - # # $debug and warn "flags: ".C4::Context->userenv->{'flags'}; - # $query.=" AND subscription.branchcode IN ('".C4::Context->userenv->{'branch'}."',\"\")"; - # } $debug and warn "query : $query\nsubsid :$subscriptionid"; my $sth = $dbh->prepare($query); $sth->execute($subscriptionid); - return $sth->fetchrow_hashref; + my $subscription = $sth->fetchrow_hashref; + $subscription->{cannotedit} = not can_edit_subscription( $subscription ); + return $subscription; } =head2 GetFullSubscription @@ -368,6 +329,9 @@ sub GetSubscription { sub GetFullSubscription { my ($subscriptionid) = @_; + + return unless ($subscriptionid); + my $dbh = C4::Context->dbh; my $query = qq| SELECT serial.serialid, @@ -380,15 +344,7 @@ sub GetFullSubscription { aqbooksellers.name as aqbooksellername, biblio.title as bibliotitle, subscription.branchcode AS branchcode, - subscription.subscriptionid AS subscriptionid |; - if ( C4::Context->preference('IndependantBranches') - && C4::Context->userenv - && C4::Context->userenv->{'flags'} != 1 - && C4::Context->userenv->{'branch'} ) { - $query .= " - , ((subscription.branchcode <>\"" . C4::Context->userenv->{'branch'} . "\") and subscription.branchcode <>\"\" and subscription.branchcode IS NOT NULL) as cannotedit "; - } - $query .= qq| + subscription.subscriptionid AS subscriptionid FROM serial LEFT JOIN subscription ON (serial.subscriptionid=subscription.subscriptionid ) @@ -402,7 +358,11 @@ sub GetFullSubscription { $debug and warn "GetFullSubscription query: $query"; my $sth = $dbh->prepare($query); $sth->execute($subscriptionid); - return $sth->fetchall_arrayref( {} ); + my $subscriptions = $sth->fetchall_arrayref( {} ); + for my $subscription ( @$subscriptions ) { + $subscription->{cannotedit} = not can_edit_subscription( $subscription ); + } + return $subscriptions; } =head2 PrepareSerialsData @@ -414,6 +374,9 @@ sub GetFullSubscription { sub PrepareSerialsData { my ($lines) = @_; + + return unless ($lines); + my %tmpresults; my $year; my @res; @@ -426,16 +389,15 @@ sub PrepareSerialsData { foreach my $subs (@{$lines}) { for my $datefield ( qw(publisheddate planneddate) ) { - # handle both undef and undef returned as 0000-00-00 - if (!defined $subs->{$datefield} or $subs->{$datefield}=~m/^00/) { - $subs->{$datefield} = 'XXX'; - } - else { - $subs->{$datefield} = format_date( $subs->{$datefield} ); + # handle 0000-00-00 dates + if (defined $subs->{$datefield} and $subs->{$datefield} =~ m/^00/) { + $subs->{$datefield} = undef; } } $subs->{ "status" . $subs->{'status'} } = 1; - $subs->{"checked"} = $subs->{'status'} =~ /1|3|4|7/; + if ( grep { $_ == $subs->{status} } ( EXPECTED, LATE, MISSING_STATUSES, CLAIMED ) ) { + $subs->{"checked"} = 1; + } if ( $subs->{'year'} && $subs->{'year'} ne "" ) { $year = $subs->{'year'}; @@ -473,6 +435,9 @@ startdate, histstartdate,opacnote,missinglist,recievedlist,periodicity,status & sub GetSubscriptionsFromBiblionumber { my ($biblionumber) = @_; + + return unless ($biblionumber); + my $dbh = C4::Context->dbh; my $query = qq( SELECT subscription.*, @@ -500,13 +465,6 @@ sub GetSubscriptionsFromBiblionumber { $subs->{ "periodicity" . $subs->{periodicity} } = 1; $subs->{ "numberpattern" . $subs->{numberpattern} } = 1; $subs->{ "status" . $subs->{'status'} } = 1; - $subs->{'cannotedit'} = - ( C4::Context->preference('IndependantBranches') - && C4::Context->userenv - && C4::Context->userenv->{flags} % 2 != 1 - && C4::Context->userenv->{branch} - && $subs->{branchcode} - && ( C4::Context->userenv->{branch} ne $subs->{branchcode} ) ); if ( $subs->{enddate} eq '0000-00-00' ) { $subs->{enddate} = ''; @@ -515,6 +473,7 @@ sub GetSubscriptionsFromBiblionumber { } $subs->{'abouttoexpire'} = abouttoexpire( $subs->{'subscriptionid'} ); $subs->{'subscriptionexpired'} = HasSubscriptionExpired( $subs->{'subscriptionid'} ); + $subs->{cannotedit} = not can_edit_subscription( $subs ); push @res, $subs; } return \@res; @@ -540,16 +499,7 @@ sub GetFullSubscriptionsFromBiblionumber { year(IF(serial.publisheddate="00-00-0000",serial.planneddate,serial.publisheddate)) as year, biblio.title as bibliotitle, subscription.branchcode AS branchcode, - subscription.subscriptionid AS subscriptionid|; - if ( C4::Context->preference('IndependantBranches') - && C4::Context->userenv - && C4::Context->userenv->{'flags'} != 1 - && C4::Context->userenv->{'branch'} ) { - $query .= " - , ((subscription.branchcode <>\"" . C4::Context->userenv->{'branch'} . "\") and subscription.branchcode <>\"\" and subscription.branchcode IS NOT NULL) as cannotedit "; - } - - $query .= qq| + subscription.subscriptionid AS subscriptionid FROM serial LEFT JOIN subscription ON (serial.subscriptionid=subscription.subscriptionid) @@ -562,113 +512,52 @@ sub GetFullSubscriptionsFromBiblionumber { |; my $sth = $dbh->prepare($query); $sth->execute($biblionumber); - return $sth->fetchall_arrayref( {} ); -} - -=head2 GetSubscriptions - -@results = GetSubscriptions($title,$ISSN,$ean,$biblionumber); -this function gets all subscriptions which have title like $title,ISSN like $ISSN,EAN like $ean and biblionumber like $biblionumber. -return: -a table of hashref. Each hash containt the subscription. - -=cut - -sub GetSubscriptions { - my ( $string, $issn, $ean, $biblionumber ) = @_; - - #return unless $title or $ISSN or $biblionumber; - my $dbh = C4::Context->dbh; - my $sth; - my $sql = qq( - SELECT subscriptionhistory.*, subscription.*, biblio.title,biblioitems.issn,biblio.biblionumber - FROM subscription - LEFT JOIN subscriptionhistory USING(subscriptionid) - LEFT JOIN biblio ON biblio.biblionumber = subscription.biblionumber - LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber - ); - my @bind_params; - my $sqlwhere = q{}; - if ($biblionumber) { - $sqlwhere = " WHERE biblio.biblionumber=?"; - push @bind_params, $biblionumber; - } - if ($string) { - my @sqlstrings; - my @strings_to_search; - @strings_to_search = map { "%$_%" } split( / /, $string ); - foreach my $index (qw(biblio.title subscription.callnumber subscription.location subscription.notes subscription.internalnotes)) { - push @bind_params, @strings_to_search; - my $tmpstring = "AND $index LIKE ? " x scalar(@strings_to_search); - $debug && warn "$tmpstring"; - $tmpstring =~ s/^AND //; - push @sqlstrings, $tmpstring; - } - $sqlwhere .= ( $sqlwhere ? " AND " : " WHERE " ) . "((" . join( ") OR (", @sqlstrings ) . "))"; + my $subscriptions = $sth->fetchall_arrayref( {} ); + for my $subscription ( @$subscriptions ) { + $subscription->{cannotedit} = not can_edit_subscription( $subscription ); } - if ($issn) { - my @sqlstrings; - my @strings_to_search; - @strings_to_search = map { "%$_%" } split( / /, $issn ); - foreach my $index ( qw(biblioitems.issn subscription.callnumber)) { - push @bind_params, @strings_to_search; - my $tmpstring = "OR $index LIKE ? " x scalar(@strings_to_search); - $debug && warn "$tmpstring"; - $tmpstring =~ s/^OR //; - push @sqlstrings, $tmpstring; - } - $sqlwhere .= ( $sqlwhere ? " AND " : " WHERE " ) . "((" . join( ") OR (", @sqlstrings ) . "))"; - } - if ($ean) { - my @sqlstrings; - my @strings_to_search; - @strings_to_search = map { "$_" } split( / /, $ean ); - foreach my $index ( qw(biblioitems.ean) ) { - push @bind_params, @strings_to_search; - my $tmpstring = "OR $index = ? " x scalar(@strings_to_search); - $debug && warn "$tmpstring"; - $tmpstring =~ s/^OR //; - push @sqlstrings, $tmpstring; - } - $sqlwhere .= ( $sqlwhere ? " AND " : " WHERE " ) . "((" . join( ") OR (", @sqlstrings ) . "))"; - } - - $sql .= "$sqlwhere ORDER BY title"; - $debug and warn "GetSubscriptions query: $sql params : ", join( " ", @bind_params ); - $sth = $dbh->prepare($sql); - $sth->execute(@bind_params); - my @results; - - while ( my $line = $sth->fetchrow_hashref ) { - $line->{'cannotedit'} = - ( C4::Context->preference('IndependantBranches') - && C4::Context->userenv - && C4::Context->userenv->{flags} % 2 != 1 - && C4::Context->userenv->{branch} - && $line->{branchcode} - && ( C4::Context->userenv->{branch} ne $line->{branchcode} ) ); - push @results, $line; - } - return @results; + return $subscriptions; } =head2 SearchSubscriptions -@results = SearchSubscriptions($args); -$args is a hashref. Its keys can be contained: title, issn, ean, publisher, bookseller and branchcode + @results = SearchSubscriptions($args); -this function gets all subscriptions which have title like $title, ISSN like $issn, EAN like $ean, publisher like $publisher, bookseller like $bookseller AND branchcode eq $branch. +This function returns a list of hashrefs, one for each subscription +that meets the conditions specified by the $args hashref. -return: -a table of hashref. Each hash containt the subscription. +The valid search fields are: + + biblionumber + title + issn + ean + callnumber + location + publisher + bookseller + branch + expiration_date + closed + +The expiration_date search field is special; it specifies the maximum +subscription expiration date. =cut sub SearchSubscriptions { my ( $args ) = @_; - my $query = qq{ - SELECT subscription.*, subscriptionhistory.*, biblio.*, biblioitems.issn + my $query = q{ + SELECT + subscription.notes AS publicnotes, + subscriptionhistory.*, + subscription.*, + biblio.notes AS biblionotes, + biblio.title, + biblio.author, + biblio.biblionumber, + biblioitems.issn FROM subscription LEFT JOIN subscriptionhistory USING(subscriptionid) LEFT JOIN biblio ON biblio.biblionumber = subscription.biblionumber @@ -701,6 +590,10 @@ sub SearchSubscriptions { push @where_strs, "biblioitems.ean LIKE ?"; push @where_args, "%$args->{ean}%"; } + if ( $args->{callnumber} ) { + push @where_strs, "subscription.callnumber LIKE ?"; + push @where_args, "%$args->{callnumber}%"; + } if( $args->{publisher} ){ push @where_strs, "biblioitems.publishercode LIKE ?"; push @where_args, "%$args->{publisher}%"; @@ -713,6 +606,14 @@ sub SearchSubscriptions { push @where_strs, "subscription.branchcode = ?"; push @where_args, "$args->{branch}"; } + if ( $args->{location} ) { + push @where_strs, "subscription.location = ?"; + push @where_args, "$args->{location}"; + } + if ( $args->{expiration_date} ) { + push @where_strs, "subscription.enddate <= ?"; + push @where_args, "$args->{expiration_date}"; + } if( defined $args->{closed} ){ push @where_strs, "subscription.closed = ?"; push @where_args, "$args->{closed}"; @@ -721,12 +622,19 @@ sub SearchSubscriptions { $query .= " WHERE " . join(" AND ", @where_strs); } + $query .= " ORDER BY " . $args->{orderby} if $args->{orderby}; + my $dbh = C4::Context->dbh; my $sth = $dbh->prepare($query); $sth->execute(@where_args); my $results = $sth->fetchall_arrayref( {} ); $sth->finish; + for my $subscription ( @$results ) { + $subscription->{cannotedit} = not can_edit_subscription( $subscription ); + $subscription->{cannotdisplay} = not can_show_subscription( $subscription ); + } + return @$results; } @@ -744,15 +652,19 @@ FIXME: We should return \@serials. sub GetSerials { my ( $subscriptionid, $count ) = @_; + + return unless $subscriptionid; + my $dbh = C4::Context->dbh; # status = 2 is "arrived" my $counter = 0; $count = 5 unless ($count); my @serials; + my $statuses = join( ',', ( ARRIVED, MISSING_STATUSES, NOT_ISSUED ) ); my $query = "SELECT serialid,serialseq, status, publisheddate, planneddate,notes, routingnotes FROM serial - WHERE subscriptionid = ? AND status NOT IN (2,4,5) + WHERE subscriptionid = ? AND status NOT IN ( $statuses ) ORDER BY IF(publisheddate<>'0000-00-00',publisheddate,planneddate) DESC"; my $sth = $dbh->prepare($query); $sth->execute($subscriptionid); @@ -773,7 +685,7 @@ sub GetSerials { $query = "SELECT serialid,serialseq, status, planneddate, publisheddate,notes, routingnotes FROM serial WHERE subscriptionid = ? - AND (status in (2,4,5)) + AND status IN ( $statuses ) ORDER BY IF(publisheddate<>'0000-00-00',publisheddate,planneddate) DESC "; $sth = $dbh->prepare($query); @@ -801,20 +713,27 @@ sub GetSerials { =head2 GetSerials2 -@serials = GetSerials2($subscriptionid,$status); +@serials = GetSerials2($subscriptionid,$statuses); this function returns every serial waited for a given subscription as well as the number of issues registered in the database (all types) this number is used to see if a subscription can be deleted (=it must have only 1 issue) +$statuses is an arrayref of statuses and is mandatory. + =cut sub GetSerials2 { - my ( $subscription, $status ) = @_; + my ( $subscription, $statuses ) = @_; + + return unless ($subscription and @$statuses); + + my $statuses_string = join ',', @$statuses; + my $dbh = C4::Context->dbh; my $query = qq| SELECT serialid,serialseq, status, planneddate, publisheddate,notes, routingnotes FROM serial - WHERE subscriptionid=$subscription AND status IN ($status) + WHERE subscriptionid=$subscription AND status IN ($statuses_string) ORDER BY publisheddate,serialid DESC |; $debug and warn "GetSerials2 query: $query"; @@ -826,7 +745,7 @@ sub GetSerials2 { $line->{ "status" . $line->{status} } = 1; # fills a "statusX" value, used for template status select list # Format dates for display for my $datefield ( qw( planneddate publisheddate ) ) { - if ($line->{$datefield} =~m/^00/) { + if (!defined($line->{$datefield}) || $line->{$datefield} =~m/^00/) { $line->{$datefield} = q{}; } else { @@ -849,13 +768,16 @@ a ref to an array which contains all of the latest serials stored into a hash. sub GetLatestSerials { my ( $subscriptionid, $limit ) = @_; + + return unless ($subscriptionid and $limit); + my $dbh = C4::Context->dbh; - # status = 2 is "arrived" - my $strsth = "SELECT serialid,serialseq, status, planneddate, notes + my $statuses = join( ',', ( ARRIVED, MISSING_STATUSES ) ); + my $strsth = "SELECT serialid,serialseq, status, planneddate, publisheddate, notes FROM serial WHERE subscriptionid = ? - AND (status =2 or status=4) + AND status IN ($statuses) ORDER BY publisheddate DESC LIMIT 0,$limit "; my $sth = $dbh->prepare($strsth); @@ -864,6 +786,7 @@ sub GetLatestSerials { while ( my $line = $sth->fetchrow_hashref ) { $line->{ "status" . $line->{status} } = 1; # fills a "statusX" value, used for template status select list $line->{"planneddate"} = format_date( $line->{"planneddate"} ); + $line->{"publisheddate"} = format_date( $line->{"publisheddate"} ); push @serials, $line; } @@ -880,7 +803,10 @@ This function returns the field distributedto for the subscription matching subs sub GetDistributedTo { my $dbh = C4::Context->dbh; my $distributedto; - my $subscriptionid = @_; + my ($subscriptionid) = @_; + + return unless ($subscriptionid); + my $query = "SELECT distributedto FROM subscription WHERE subscriptionid=?"; my $sth = $dbh->prepare($query); $sth->execute($subscriptionid); @@ -889,26 +815,35 @@ sub GetDistributedTo { =head2 GetNextSeq -GetNextSeq($val) -$val is a hashref containing all the attributes of the table 'subscription' + my ( + $nextseq, $newlastvalue1, $newlastvalue2, $newlastvalue3, + $newinnerloop1, $newinnerloop2, $newinnerloop3 + ) = GetNextSeq( $subscription, $pattern, $planneddate ); + +$subscription is a hashref containing all the attributes of the table +'subscription'. +$pattern is a hashref containing all the attributes of the table +'subscription_numberpatterns'. +$planneddate is a C4::Dates object. This function get the next issue for the subscription given on input arg -return: -a list containing all the input params updated. =cut sub GetNextSeq { - my ($val, $planneddate) = @_; - my ( $calculated, $newlastvalue1, $newlastvalue2, $newlastvalue3, + my ($subscription, $pattern, $planneddate) = @_; + + return unless ($subscription and $pattern); + + my ( $newlastvalue1, $newlastvalue2, $newlastvalue3, $newinnerloop1, $newinnerloop2, $newinnerloop3 ); my $count = 1; - if($val->{'skip_serialseq'}) { - my @irreg = split /;/, $val->{'irregularity'}; + if ($subscription->{'skip_serialseq'}) { + my @irreg = split /;/, $subscription->{'irregularity'}; if(@irreg > 0) { my $irregularities = {}; $irregularities->{$_} = 1 foreach(@irreg); - my $issueno = GetFictiveIssueNumber($val, $planneddate) + 1; + my $issueno = GetFictiveIssueNumber($subscription, $planneddate) + 1; while($irregularities->{$issueno}) { $count++; $issueno++; @@ -916,64 +851,67 @@ sub GetNextSeq { } } - my $pattern = $val->{numberpattern}; - $calculated = $val->{numberingmethod}; - my $locale = $val->{locale}; - $newlastvalue1 = $val->{lastvalue1} || 0; - $newlastvalue2 = $val->{lastvalue2} || 0; - $newlastvalue3 = $val->{lastvalue3} || 0; - $newinnerloop1 = $val->{innerloop1} || 0; - $newinnerloop2 = $val->{innerloop2} || 0; - $newinnerloop3 = $val->{innerloop3} || 0; - my %calc; - foreach(qw/X Y Z/) { - $calc{$_} = 1 if ($val->{'numberingmethod'} =~ /\{$_\}/); - } + my $numberingmethod = $pattern->{numberingmethod}; + my $calculated = ""; + if ($numberingmethod) { + $calculated = $numberingmethod; + my $locale = $subscription->{locale}; + $newlastvalue1 = $subscription->{lastvalue1} || 0; + $newlastvalue2 = $subscription->{lastvalue2} || 0; + $newlastvalue3 = $subscription->{lastvalue3} || 0; + $newinnerloop1 = $subscription->{innerloop1} || 0; + $newinnerloop2 = $subscription->{innerloop2} || 0; + $newinnerloop3 = $subscription->{innerloop3} || 0; + my %calc; + foreach(qw/X Y Z/) { + $calc{$_} = 1 if ($numberingmethod =~ /\{$_\}/); + } - for(my $i = 0; $i < $count; $i++) { - if($calc{'X'}) { - # check if we have to increase the new value. - $newinnerloop1 += 1; - if ($newinnerloop1 >= $val->{every1}) { - $newinnerloop1 = 0; - $newlastvalue1 += $val->{add1}; + for(my $i = 0; $i < $count; $i++) { + if($calc{'X'}) { + # check if we have to increase the new value. + $newinnerloop1 += 1; + if ($newinnerloop1 >= $pattern->{every1}) { + $newinnerloop1 = 0; + $newlastvalue1 += $pattern->{add1}; + } + # reset counter if needed. + $newlastvalue1 = $pattern->{setto1} if ($newlastvalue1 > $pattern->{whenmorethan1}); + } + if($calc{'Y'}) { + # check if we have to increase the new value. + $newinnerloop2 += 1; + if ($newinnerloop2 >= $pattern->{every2}) { + $newinnerloop2 = 0; + $newlastvalue2 += $pattern->{add2}; + } + # reset counter if needed. + $newlastvalue2 = $pattern->{setto2} if ($newlastvalue2 > $pattern->{whenmorethan2}); + } + if($calc{'Z'}) { + # check if we have to increase the new value. + $newinnerloop3 += 1; + if ($newinnerloop3 >= $pattern->{every3}) { + $newinnerloop3 = 0; + $newlastvalue3 += $pattern->{add3}; + } + # reset counter if needed. + $newlastvalue3 = $pattern->{setto3} if ($newlastvalue3 > $pattern->{whenmorethan3}); } - # reset counter if needed. - $newlastvalue1 = $val->{setto1} if ($newlastvalue1 > $val->{whenmorethan1}); + } + if($calc{'X'}) { + my $newlastvalue1string = _numeration( $newlastvalue1, $pattern->{numbering1}, $locale ); + $calculated =~ s/\{X\}/$newlastvalue1string/g; } if($calc{'Y'}) { - # check if we have to increase the new value. - $newinnerloop2 += 1; - if ($newinnerloop2 >= $val->{every2}) { - $newinnerloop2 = 0; - $newlastvalue2 += $val->{add2}; - } - # reset counter if needed. - $newlastvalue2 = $val->{setto2} if ($newlastvalue2 > $val->{whenmorethan2}); + my $newlastvalue2string = _numeration( $newlastvalue2, $pattern->{numbering2}, $locale ); + $calculated =~ s/\{Y\}/$newlastvalue2string/g; } if($calc{'Z'}) { - # check if we have to increase the new value. - $newinnerloop3 += 1; - if ($newinnerloop3 >= $val->{every3}) { - $newinnerloop3 = 0; - $newlastvalue3 += $val->{add3}; - } - # reset counter if needed. - $newlastvalue3 = $val->{setto3} if ($newlastvalue3 > $val->{whenmorethan3}); + my $newlastvalue3string = _numeration( $newlastvalue3, $pattern->{numbering3}, $locale ); + $calculated =~ s/\{Z\}/$newlastvalue3string/g; } } - if($calc{'X'}) { - my $newlastvalue1string = _numeration( $newlastvalue1, $val->{numbering1}, $locale ); - $calculated =~ s/\{X\}/$newlastvalue1string/g; - } - if($calc{'Y'}) { - my $newlastvalue2string = _numeration( $newlastvalue2, $val->{numbering2}, $locale ); - $calculated =~ s/\{Y\}/$newlastvalue2string/g; - } - if($calc{'Z'}) { - my $newlastvalue3string = _numeration( $newlastvalue3, $val->{numbering3}, $locale ); - $calculated =~ s/\{Z\}/$newlastvalue3string/g; - } return ($calculated, $newlastvalue1, $newlastvalue2, $newlastvalue3, @@ -982,31 +920,34 @@ sub GetNextSeq { =head2 GetSeq -$calculated = GetSeq($val) -$val is a hashref containing all the attributes of the table 'subscription' +$calculated = GetSeq($subscription, $pattern) +$subscription is a hashref containing all the attributes of the table 'subscription' +$pattern is a hashref containing all the attributes of the table 'subscription_numberpatterns' this function transforms {X},{Y},{Z} to 150,0,0 for example. return: -the sequence in integer format +the sequence in string format =cut sub GetSeq { - my ($val) = @_; - my $locale = $val->{locale}; + my ($subscription, $pattern) = @_; + + return unless ($subscription and $pattern); + + my $locale = $subscription->{locale}; - my $pattern = $val->{numberpattern}; - my $calculated = $val->{numberingmethod}; + my $calculated = $pattern->{numberingmethod}; - my $newlastvalue1 = $val->{'lastvalue1'} || 0; - $newlastvalue1 = _numeration($newlastvalue1, $val->{numbering1}, $locale) if ($val->{numbering1}); # reset counter if needed. + my $newlastvalue1 = $subscription->{'lastvalue1'} || 0; + $newlastvalue1 = _numeration($newlastvalue1, $pattern->{numbering1}, $locale) if ($pattern->{numbering1}); # reset counter if needed. $calculated =~ s/\{X\}/$newlastvalue1/g; - my $newlastvalue2 = $val->{'lastvalue2'} || 0; - $newlastvalue2 = _numeration($newlastvalue2, $val->{numbering2}, $locale) if ($val->{numbering2}); # reset counter if needed. + my $newlastvalue2 = $subscription->{'lastvalue2'} || 0; + $newlastvalue2 = _numeration($newlastvalue2, $pattern->{numbering2}, $locale) if ($pattern->{numbering2}); # reset counter if needed. $calculated =~ s/\{Y\}/$newlastvalue2/g; - my $newlastvalue3 = $val->{'lastvalue3'} || 0; - $newlastvalue3 = _numeration($newlastvalue3, $val->{numbering3}, $locale) if ($val->{numbering3}); # reset counter if needed. + my $newlastvalue3 = $subscription->{'lastvalue3'} || 0; + $newlastvalue3 = _numeration($newlastvalue3, $pattern->{numbering3}, $locale) if ($pattern->{numbering3}); # reset counter if needed. $calculated =~ s/\{Z\}/$newlastvalue3/g; return $calculated; } @@ -1024,6 +965,9 @@ the enddate or undef sub GetExpirationDate { my ( $subscriptionid, $startdate ) = @_; + + return unless ($subscriptionid); + my $dbh = C4::Context->dbh; my $subscription = GetSubscription($subscriptionid); my $enddate; @@ -1031,7 +975,9 @@ sub GetExpirationDate { # we don't do the same test if the subscription is based on X numbers or on X weeks/months $enddate = $startdate || $subscription->{startdate}; my @date = split( /-/, $enddate ); + return if ( scalar(@date) != 3 || not check_date(@date) ); + my $frequency = C4::Serials::Frequency::GetSubscriptionFrequency($subscription->{periodicity}); if ( $frequency and $frequency->{unit} ) { @@ -1073,6 +1019,9 @@ the number of subscriptions sub CountSubscriptionFromBiblionumber { my ($biblionumber) = @_; + + return unless ($biblionumber); + my $dbh = C4::Context->dbh; my $query = "SELECT count(*) FROM subscription WHERE biblionumber=?"; my $sth = $dbh->prepare($query); @@ -1092,6 +1041,9 @@ returns the number of rows affected sub ModSubscriptionHistory { my ( $subscriptionid, $histstartdate, $enddate, $receivedlist, $missinglist, $opacnote, $librariannote ) = @_; + + return unless ($subscriptionid); + my $dbh = C4::Context->dbh; my $query = "UPDATE subscriptionhistory SET histstartdate=?,histenddate=?,recievedlist=?,missinglist=?,opacnote=?,librariannote=? @@ -1105,50 +1057,6 @@ sub ModSubscriptionHistory { return $sth->rows; } -# Update missinglist field, used by ModSerialStatus -sub _update_missinglist { - my $subscriptionid = shift; - - my $dbh = C4::Context->dbh; - my @missingserials = GetSerials2($subscriptionid, "4,5"); - my $missinglist; - foreach (@missingserials) { - if($_->{'status'} == 4) { - $missinglist .= $_->{'serialseq'} . "; "; - } elsif($_->{'status'} == 5) { - $missinglist .= "not issued " . $_->{'serialseq'} . "; "; - } - } - $missinglist =~ s/; $//; - my $query = qq{ - UPDATE subscriptionhistory - SET missinglist = ? - WHERE subscriptionid = ? - }; - my $sth = $dbh->prepare($query); - $sth->execute($missinglist, $subscriptionid); -} - -# Update recievedlist field, used by ModSerialStatus -sub _update_receivedlist { - my $subscriptionid = shift; - - my $dbh = C4::Context->dbh; - my @receivedserials = GetSerials2($subscriptionid, "2"); - my $receivedlist; - foreach (@receivedserials) { - $receivedlist .= $_->{'serialseq'} . "; "; - } - $receivedlist =~ s/; $//; - my $query = qq{ - UPDATE subscriptionhistory - SET recievedlist = ? - WHERE subscriptionid = ? - }; - my $sth = $dbh->prepare($query); - $sth->execute($receivedlist, $subscriptionid); -} - =head2 ModSerialStatus ModSerialStatus($serialid,$serialseq, $planneddate,$publisheddate,$status,$notes) @@ -1161,6 +1069,7 @@ Note : if we change from "waited" to something else,then we will have to create sub ModSerialStatus { my ( $serialid, $serialseq, $planneddate, $publisheddate, $status, $notes ) = @_; + return unless ($serialid); #It is a usual serial # 1st, get previous status : @@ -1176,14 +1085,10 @@ sub ModSerialStatus { # change status & update subscriptionhistory my $val; - if ( $status == 6 ) { + if ( $status == DELETED ) { DelIssue( { 'serialid' => $serialid, 'subscriptionid' => $subscriptionid, 'serialseq' => $serialseq } ); } else { - unless ($frequency->{'unit'}) { - if ( not $planneddate or $planneddate eq '0000-00-00' ) { $planneddate = C4::Dates->new()->output('iso') }; - if ( not $publisheddate or $publisheddate eq '0000-00-00' ) { $publisheddate = C4::Dates->new()->output('iso') }; - } my $query = 'UPDATE serial SET serialseq=?,publisheddate=?,planneddate=?,status=?,notes=? WHERE serialid = ?'; $sth = $dbh->prepare($query); $sth->execute( $serialseq, $publisheddate, $planneddate, $status, $notes, $serialid ); @@ -1192,47 +1097,59 @@ sub ModSerialStatus { $sth->execute($subscriptionid); my $val = $sth->fetchrow_hashref; unless ( $val->{manualhistory} ) { - if ( $status == 2 || ($oldstatus == 2 && $status != 2) ) { - _update_receivedlist($subscriptionid); + $query = "SELECT missinglist,recievedlist FROM subscriptionhistory WHERE subscriptionid=?"; + $sth = $dbh->prepare($query); + $sth->execute($subscriptionid); + my ( $missinglist, $recievedlist ) = $sth->fetchrow; + + if ( $status == ARRIVED || ($oldstatus == ARRIVED && $status != ARRIVED) ) { + $recievedlist .= "; $serialseq" + if ($recievedlist !~ /(^|;)\s*$serialseq(?=;|$)/); } - if($status == 4 || $status == 5 - || ($oldstatus == 4 && $status != 4) - || ($oldstatus == 5 && $status != 5)) { - _update_missinglist($subscriptionid); + + # in case serial has been previously marked as missing + if (grep /$status/, (EXPECTED, ARRIVED, LATE, CLAIMED)) { + $missinglist=~ s/(^|;)\s*$serialseq(?=;|$)//g; } + + $missinglist .= "; $serialseq" + if ( ( grep { $_ == $status } ( MISSING_STATUSES ) ) && ( $missinglist !~/(^|;)\s*$serialseq(?=;|$)/ ) ); + $missinglist .= "; not issued $serialseq" + if ( $status == NOT_ISSUED && $missinglist !~ /(^|;)\s*$serialseq(?=;|$)/ ); + + $query = "UPDATE subscriptionhistory SET recievedlist=?, missinglist=? WHERE subscriptionid=?"; + $sth = $dbh->prepare($query); + $recievedlist =~ s/^; //; + $missinglist =~ s/^; //; + $sth->execute( $recievedlist, $missinglist, $subscriptionid ); } } # create new waited entry if needed (ie : was a "waited" and has changed) - if ( $oldstatus == 1 && $status != 1 ) { - my $query = qq{ - SELECT subscription.*, subscription_numberpatterns.*, - subscription_frequencies.* - FROM subscription - LEFT JOIN subscription_numberpatterns ON subscription.numberpattern = subscription_numberpatterns.id - LEFT JOIN subscription_frequencies ON subscription.periodicity = subscription_frequencies.id - WHERE subscriptionid = ? - }; - $sth = $dbh->prepare($query); - $sth->execute($subscriptionid); - my $val = $sth->fetchrow_hashref; + if ( $oldstatus == EXPECTED && $status != EXPECTED ) { + my $subscription = GetSubscription($subscriptionid); + my $pattern = C4::Serials::Numberpattern::GetSubscriptionNumberpattern($subscription->{numberpattern}); # next issue number - my ( $newserialseq, $newlastvalue1, $newlastvalue2, $newlastvalue3, $newinnerloop1, $newinnerloop2, $newinnerloop3 ) = GetNextSeq($val, $publisheddate); + my ( + $newserialseq, $newlastvalue1, $newlastvalue2, $newlastvalue3, + $newinnerloop1, $newinnerloop2, $newinnerloop3 + ) + = GetNextSeq( $subscription, $pattern, $publisheddate ); # next date (calculated from actual date & frequency parameters) - my $nextpublisheddate = GetNextDate($val, $publisheddate, 1); + my $nextpublisheddate = GetNextDate($subscription, $publisheddate, 1); my $nextpubdate = $nextpublisheddate; - NewIssue( $newserialseq, $subscriptionid, $val->{'biblionumber'}, 1, $nextpubdate, $nextpubdate ); + NewIssue( $newserialseq, $subscriptionid, $subscription->{'biblionumber'}, 1, $nextpubdate, $nextpubdate ); $query = "UPDATE subscription SET lastvalue1=?, lastvalue2=?, lastvalue3=?, innerloop1=?, innerloop2=?, innerloop3=? WHERE subscriptionid = ?"; $sth = $dbh->prepare($query); $sth->execute( $newlastvalue1, $newlastvalue2, $newlastvalue3, $newinnerloop1, $newinnerloop2, $newinnerloop3, $subscriptionid ); # check if an alert must be sent... (= a letter is defined & status became "arrived" - if ( $val->{letter} && $status == 2 && $oldstatus != 2 ) { + if ( $subscription->{letter} && $status == ARRIVED && $oldstatus != ARRIVED ) { require C4::Letters; - C4::Letters::SendAlerts( 'issue', $val->{subscriptionid}, $val->{letter} ); + C4::Letters::SendAlerts( 'issue', $subscription->{subscriptionid}, $subscription->{letter} ); } } @@ -1267,15 +1184,15 @@ sub GetNextExpected { }; my $sth = $dbh->prepare($query); - # Each subscription has only one 'expected' issue, with serial.status==1. - $sth->execute( $subscriptionid, 1 ); + # Each subscription has only one 'expected' issue. + $sth->execute( $subscriptionid, EXPECTED ); my $nextissue = $sth->fetchrow_hashref; if ( !$nextissue ) { $query = qq{ SELECT * FROM serial WHERE subscriptionid = ? - ORDER BY planneddate DESC + ORDER BY publisheddate DESC LIMIT 1 }; $sth = $dbh->prepare($query); @@ -1315,15 +1232,15 @@ sub ModNextExpected { #FIXME: Would expect to only set planneddate, but we set both on new issue creation, so updating it here my $sth = $dbh->prepare('UPDATE serial SET planneddate=?,publisheddate=? WHERE subscriptionid=? AND status=?'); - # Each subscription has only one 'expected' issue, with serial.status==1. - $sth->execute( $date, $date, $subscriptionid, 1 ); + # Each subscription has only one 'expected' issue. + $sth->execute( $date, $date, $subscriptionid, EXPECTED ); return 0; } =head2 GetSubscriptionIrregularities -=over4 +=over 4 =item @irreg = &GetSubscriptionIrregularities($subscriptionid); get the list of irregularities for a subscription @@ -1335,7 +1252,7 @@ get the list of irregularities for a subscription sub GetSubscriptionIrregularities { my $subscriptionid = shift; - return undef unless $subscriptionid; + return unless $subscriptionid; my $dbh = C4::Context->dbh; my $query = qq{ @@ -1405,10 +1322,10 @@ sub ModSubscription { =head2 NewSubscription $subscriptionid = &NewSubscription($auser,branchcode,$aqbooksellerid,$cost,$aqbudgetid,$biblionumber, - $startdate,$periodicity,$dow,$numberlength,$weeklength,$monthlength, + $startdate,$periodicity,$numberlength,$weeklength,$monthlength, $lastvalue1,$innerloop1,$lastvalue2,$innerloop2,$lastvalue3,$innerloop3, $status, $notes, $letter, $firstacquidate, $irregularity, $numberpattern, - $callnumber, $hemisphere, $manualhistory, $internalnotes, $serialsadditems, + $locale, $callnumber, $manualhistory, $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate, $skip_serialseq); Create a new subscription with value given on input args. @@ -1468,32 +1385,25 @@ sub NewSubscription { # then create the 1st expected number $query = qq( INSERT INTO subscriptionhistory - (biblionumber, subscriptionid, histstartdate, opacnote, librariannote) - VALUES (?,?,?,?,?) + (biblionumber, subscriptionid, histstartdate) + VALUES (?,?,?) ); $sth = $dbh->prepare($query); - $sth->execute( $biblionumber, $subscriptionid, $startdate, $notes, $internalnotes ); + $sth->execute( $biblionumber, $subscriptionid, $startdate); # reread subscription to get a hash (for calculation of the 1st issue number) - $query = qq( - SELECT * - FROM subscription - LEFT JOIN subscription_numberpatterns ON subscription.numberpattern = subscription_numberpatterns.id - WHERE subscriptionid = ? - ); - $sth = $dbh->prepare($query); - $sth->execute($subscriptionid); - my $val = $sth->fetchrow_hashref; + my $subscription = GetSubscription($subscriptionid); + my $pattern = C4::Serials::Numberpattern::GetSubscriptionNumberpattern($subscription->{numberpattern}); # calculate issue number - my $serialseq = GetSeq($val); + my $serialseq = GetSeq($subscription, $pattern) || q{}; $query = qq| INSERT INTO serial (serialseq,subscriptionid,biblionumber,status, planneddate, publisheddate) VALUES (?,?,?,?,?,?) |; $sth = $dbh->prepare($query); - $sth->execute( "$serialseq", $subscriptionid, $biblionumber, 1, $firstacquidate, $firstacquidate ); + $sth->execute( $serialseq, $subscriptionid, $biblionumber, EXPECTED, $firstacquidate, $firstacquidate ); logaction( "SERIAL", "ADD", $subscriptionid, "" ) if C4::Context->preference("SubscriptionLog"); @@ -1548,7 +1458,7 @@ sub ReNewSubscription { # renew subscription $query = qq| UPDATE subscription - SET startdate=?,numberlength=?,weeklength=?,monthlength=? + SET startdate=?,numberlength=?,weeklength=?,monthlength=?,reneweddate=NOW() WHERE subscriptionid=? |; $sth = $dbh->prepare($query); @@ -1588,6 +1498,8 @@ sub NewIssue { my ( $serialseq, $subscriptionid, $biblionumber, $status, $planneddate, $publisheddate, $notes ) = @_; ### FIXME biblionumber CAN be provided by subscriptionid. So Do we STILL NEED IT ? + return unless ($subscriptionid); + my $dbh = C4::Context->dbh; my $query = qq| INSERT INTO serial @@ -1606,13 +1518,13 @@ sub NewIssue { $sth->execute($subscriptionid); my ( $missinglist, $recievedlist ) = $sth->fetchrow; - if ( $status == 2 ) { + if ( $status == ARRIVED ) { ### TODO Add a feature that improves recognition and description. ### As such count (serialseq) i.e. : N18,2(N19),N20 ### Would use substr and index But be careful to previous presence of () $recievedlist .= "; $serialseq" unless (index($recievedlist,$serialseq)>0); } - if ( $status == 4 ) { + if ( grep {/^$status$/} ( MISSING_STATUSES ) ) { $missinglist .= "; $serialseq" unless (index($missinglist,$serialseq)>0); } $query = qq| @@ -1640,6 +1552,9 @@ return : sub ItemizeSerials { my ( $serialid, $info ) = @_; + + return unless ($serialid); + my $now = POSIX::strftime( "%Y-%m-%d", localtime ); my $dbh = C4::Context->dbh; @@ -1774,6 +1689,9 @@ sub HasSubscriptionStrictlyExpired { # Getting end of subscription date my ($subscriptionid) = @_; + + return unless ($subscriptionid); + my $dbh = C4::Context->dbh; my $subscription = GetSubscription($subscriptionid); my $expirationdate = $subscription->{enddate} || GetExpirationDate($subscriptionid); @@ -1815,6 +1733,9 @@ return : sub HasSubscriptionExpired { my ($subscriptionid) = @_; + + return unless ($subscriptionid); + my $dbh = C4::Context->dbh; my $subscription = GetSubscription($subscriptionid); my $frequency = C4::Serials::Frequency::GetSubscriptionFrequency($subscription->{periodicity}); @@ -1942,7 +1863,7 @@ sub DelIssue { @issuelist = GetLateMissingIssues($supplierid,$serialid) -this function selects missing issues on database - where serial.status = 4 or serial.status=3 or planneddatedbh; my $sth; my $byserial = ''; @@ -1963,48 +1887,52 @@ sub GetLateOrMissingIssues { } else { $order = "title"; } + my $missing_statuses_string = join ',', (MISSING_STATUSES); if ($supplierid) { $sth = $dbh->prepare( "SELECT serialid, aqbooksellerid, name, - biblio.title, planneddate, serialseq, - serial.status, serial.subscriptionid, claimdate, + biblio.title, biblioitems.issn, planneddate, serialseq, + serial.status, serial.subscriptionid, claimdate, claims_count, subscription.branchcode - FROM serial - LEFT JOIN subscription ON serial.subscriptionid=subscription.subscriptionid + FROM serial + LEFT JOIN subscription ON serial.subscriptionid=subscription.subscriptionid LEFT JOIN biblio ON subscription.biblionumber=biblio.biblionumber + LEFT JOIN biblioitems ON subscription.biblionumber=biblioitems.biblionumber LEFT JOIN aqbooksellers ON subscription.aqbooksellerid = aqbooksellers.id - WHERE subscription.subscriptionid = serial.subscriptionid - AND (serial.STATUS = 4 OR ((planneddate < now() AND serial.STATUS =1) OR serial.STATUS = 3 OR serial.STATUS = 7)) + WHERE subscription.subscriptionid = serial.subscriptionid + AND (serial.STATUS IN ($missing_statuses_string) OR ((planneddate < now() AND serial.STATUS = ?) OR serial.STATUS = ? OR serial.STATUS = ?)) AND subscription.aqbooksellerid=$supplierid $byserial ORDER BY $order" ); } else { $sth = $dbh->prepare( - "SELECT + "SELECT serialid, aqbooksellerid, name, biblio.title, planneddate, serialseq, - serial.status, serial.subscriptionid, claimdate, + serial.status, serial.subscriptionid, claimdate, claims_count, subscription.branchcode - FROM serial - LEFT JOIN subscription ON serial.subscriptionid=subscription.subscriptionid + FROM serial + LEFT JOIN subscription ON serial.subscriptionid=subscription.subscriptionid LEFT JOIN biblio ON subscription.biblionumber=biblio.biblionumber LEFT JOIN aqbooksellers ON subscription.aqbooksellerid = aqbooksellers.id - WHERE subscription.subscriptionid = serial.subscriptionid - AND (serial.STATUS = 4 OR ((planneddate < now() AND serial.STATUS =1) OR serial.STATUS = 3 OR serial.STATUS = 7)) + WHERE subscription.subscriptionid = serial.subscriptionid + AND (serial.STATUS IN ($missing_statuses_string) OR ((planneddate < now() AND serial.STATUS = ?) OR serial.STATUS = ? OR serial.STATUS = ?)) $byserial ORDER BY $order" ); } - $sth->execute; + $sth->execute( EXPECTED, LATE, CLAIMED ); my @issuelist; while ( my $line = $sth->fetchrow_hashref ) { if ($line->{planneddate} && $line->{planneddate} !~/^0+\-/) { + $line->{planneddateISO} = $line->{planneddate}; $line->{planneddate} = format_date( $line->{planneddate} ); } if ($line->{claimdate} && $line->{claimdate} !~/^0+\-/) { + $line->{claimdateISO} = $line->{claimdate}; $line->{claimdate} = format_date( $line->{claimdate} ); } $line->{"status".$line->{status}} = 1; @@ -2026,6 +1954,9 @@ called when a missing issue is found from the serials-recieve.pl file sub removeMissingIssue { my ( $sequence, $subscriptionid ) = @_; + + return unless ($sequence and $subscriptionid); + my $dbh = C4::Context->dbh; my $sth = $dbh->prepare("SELECT * FROM subscriptionhistory WHERE subscriptionid = ?"); $sth->execute($subscriptionid); @@ -2064,12 +1995,12 @@ called from claims.pl file sub updateClaim { my ($serialid) = @_; my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare( - "UPDATE serial SET claimdate = now() - WHERE serialid = ? - " - ); - $sth->execute($serialid); + $dbh->do(q| + UPDATE serial + SET claimdate = NOW(), + claims_count = claims_count + 1 + WHERE serialid = ? + |, {}, $serialid ); return; } @@ -2111,6 +2042,9 @@ used to show either an 'add' or 'edit' link sub check_routing { my ($subscriptionid) = @_; + + return unless ($subscriptionid); + my $dbh = C4::Context->dbh; my $sth = $dbh->prepare( "SELECT count(routingid) routingids FROM subscription LEFT JOIN subscriptionroutinglist @@ -2136,6 +2070,9 @@ of either 1 or highest current rank + 1 sub addroutingmember { my ( $borrowernumber, $subscriptionid ) = @_; + + return unless ($borrowernumber and $subscriptionid); + my $rank; my $dbh = C4::Context->dbh; my $sth = $dbh->prepare( "SELECT max(ranking) rank FROM subscriptionroutinglist WHERE subscriptionid = ?" ); @@ -2336,18 +2273,26 @@ sub abouttoexpire { my $per = $subscription->{'periodicity'}; my $frequency = C4::Serials::Frequency::GetSubscriptionFrequency($per); if ($frequency and $frequency->{unit}){ + my $expirationdate = GetExpirationDate($subscriptionid); + my ($res) = $dbh->selectrow_array('select max(planneddate) from serial where subscriptionid = ?', undef, $subscriptionid); my $nextdate = GetNextDate($subscription, $res); - if(Date::Calc::Delta_Days( - split( /-/, $nextdate ), - split( /-/, $expirationdate ) - ) <= 0) { - return 1; + + # only compare dates if both dates exist. + if ($nextdate and $expirationdate) { + if(Date::Calc::Delta_Days( + split( /-/, $nextdate ), + split( /-/, $expirationdate ) + ) <= 0) { + return 1; + } } + } elsif ($subscription->{numberlength}>0) { return (countissuesfrom($subscriptionid,$subscription->{'startdate'}) >=$subscription->{numberlength}-1); } + return 0; } @@ -2462,13 +2407,15 @@ skipped then the returned date will be 2007-05-10 return : $resultdate - then next date in the sequence (ISO date) -Return $publisheddate if subscription is irregular +Return undef if subscription is irregular =cut sub GetNextDate { my ( $subscription, $publisheddate, $updatecount ) = @_; + return unless $subscription and $publisheddate; + my $freqdata = GetSubscriptionFrequency($subscription->{'periodicity'}); if ($freqdata->{'unit'}) { @@ -2479,10 +2426,12 @@ sub GetNextDate { # irreg1;irreg2;irreg3 # where irregX is the number of issue which will not be received # (the first issue takes the number 1, the 2nd the number 2 and so on) - my @irreg = split /;/, $subscription->{'irregularity'} ; my %irregularities; - foreach my $irregularity (@irreg) { - $irregularities{$irregularity} = 1; + if ( $subscription->{irregularity} ) { + my @irreg = split /;/, $subscription->{'irregularity'} ; + foreach my $irregularity (@irreg) { + $irregularities{$irregularity} = 1; + } } # Get the 'fictive' next issue number @@ -2606,9 +2555,6 @@ sub GetNextDate { } return sprintf("%04d-%02d-%02d", $year, $month, $day); } - else { - return $publisheddate; - } } =head2 _numeration @@ -2627,44 +2573,35 @@ num_type can take : sub _numeration { my ($value, $num_type, $locale) = @_; $value ||= 0; - my $initlocale = setlocale(LC_TIME); - if($locale and $locale ne $initlocale) { - $locale = setlocale(LC_TIME, $locale); - } - $locale ||= $initlocale; - my $string; $num_type //= ''; - given ($num_type) { - when (/^dayname$/) { - $value = $value % 7; - $string = POSIX::strftime("%A",0,0,0,0,0,0,$value); - } - when (/^monthname$/) { - $value = $value % 12; - $string = POSIX::strftime("%B",0,0,0,1,$value,0,0,0,0); - } - when (/^season$/) { - my $seasonlocale = ($locale) - ? (substr $locale,0,2) - : "en"; - my %seasons=( - "en" => - [qw(Spring Summer Fall Winter)], - "fr"=> - [qw(Printemps Été Automne Hiver)], - ); - $value = $value % 4; - $string = ($seasons{$seasonlocale}) - ? $seasons{$seasonlocale}->[$value] - : $seasons{'en'}->[$value]; - } - default { - $string = $value; - } - } - if($locale ne $initlocale) { - setlocale(LC_TIME, $initlocale); + $locale ||= 'en'; + my $string; + if ( $num_type =~ /^dayname$/ ) { + # 1970-11-01 was a Sunday + $value = $value % 7; + my $dt = DateTime->new( + year => 1970, + month => 11, + day => $value + 1, + locale => $locale, + ); + $string = $dt->strftime("%A"); + } elsif ( $num_type =~ /^monthname$/ ) { + $value = $value % 12; + my $dt = DateTime->new( + year => 1970, + month => $value + 1, + locale => $locale, + ); + $string = $dt->strftime("%B"); + } elsif ( $num_type =~ /^season$/ ) { + my @seasons= qw( Spring Summer Fall Winter ); + $value = $value % 4; + $string = $seasons[$value]; + } else { + $string = $value; } + return $string; } @@ -2695,7 +2632,7 @@ sub CloseSubscription { my ( $subscriptionid ) = @_; return unless $subscriptionid; my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare( qq{ + my $sth = $dbh->prepare( q{ UPDATE subscription SET closed = 1 WHERE subscriptionid = ? @@ -2703,13 +2640,13 @@ sub CloseSubscription { $sth->execute( $subscriptionid ); # Set status = missing when status = stopped - $sth = $dbh->prepare( qq{ + $sth = $dbh->prepare( q{ UPDATE serial - SET status = 8 + SET status = ? WHERE subscriptionid = ? - AND status = 1 + AND status = ? } ); - $sth->execute( $subscriptionid ); + $sth->execute( STOPPED, $subscriptionid, EXPECTED ); } =head2 ReopenSubscription @@ -2719,7 +2656,7 @@ sub ReopenSubscription { my ( $subscriptionid ) = @_; return unless $subscriptionid; my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare( qq{ + my $sth = $dbh->prepare( q{ UPDATE subscription SET closed = 0 WHERE subscriptionid = ? @@ -2727,13 +2664,94 @@ sub ReopenSubscription { $sth->execute( $subscriptionid ); # Set status = expected when status = stopped - $sth = $dbh->prepare( qq{ + $sth = $dbh->prepare( q{ UPDATE serial - SET status = 1 + SET status = ? WHERE subscriptionid = ? - AND status = 8 + AND status = ? } ); - $sth->execute( $subscriptionid ); + $sth->execute( EXPECTED, $subscriptionid, STOPPED ); +} + +=head2 subscriptionCurrentlyOnOrder + + $bool = subscriptionCurrentlyOnOrder( $subscriptionid ); + +Return 1 if subscription is currently on order else 0. + +=cut + +sub subscriptionCurrentlyOnOrder { + my ( $subscriptionid ) = @_; + my $dbh = C4::Context->dbh; + my $query = qq| + SELECT COUNT(*) FROM aqorders + WHERE subscriptionid = ? + AND datereceived IS NULL + AND datecancellationprinted IS NULL + |; + my $sth = $dbh->prepare( $query ); + $sth->execute($subscriptionid); + return $sth->fetchrow_array; +} + +=head2 can_edit_subscription + + $can = can_edit_subscription( $subscriptionid[, $userid] ); + +Return 1 if the subscription can be edited by the current logged user (or a given $userid), else 0. + +=cut + +sub can_edit_subscription { + my ( $subscription, $userid ) = @_; + return _can_do_on_subscription( $subscription, $userid, 'edit_subscription' ); +} + +=head2 can_show_subscription + + $can = can_show_subscription( $subscriptionid[, $userid] ); + +Return 1 if the subscription can be shown by the current logged user (or a given $userid), else 0. + +=cut + +sub can_show_subscription { + my ( $subscription, $userid ) = @_; + return _can_do_on_subscription( $subscription, $userid, '*' ); +} + +sub _can_do_on_subscription { + my ( $subscription, $userid, $permission ) = @_; + return 0 unless C4::Context->userenv; + my $flags = C4::Context->userenv->{flags}; + $userid ||= C4::Context->userenv->{'id'}; + + if ( C4::Context->preference('IndependentBranches') ) { + return 1 + if C4::Context->IsSuperLibrarian() + or + C4::Auth::haspermission( $userid, { serials => 'superserials' } ) + or ( + C4::Auth::haspermission( $userid, + { serials => $permission } ) + and ( not defined $subscription->{branchcode} + or $subscription->{branchcode} eq '' + or $subscription->{branchcode} eq + C4::Context->userenv->{'branch'} ) + ); + } + else { + return 1 + if C4::Context->IsSuperLibrarian() + or + C4::Auth::haspermission( $userid, { serials => 'superserials' } ) + or C4::Auth::haspermission( + $userid, { serials => $permission } + ), + ; + } + return 0; } 1;