X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=C4%2FSerials.pm;h=f8c17b918950e83b95e23b426901a0bfbb48579e;hb=refs%2Fheads%2Fkoha_ffzg;hp=e9ac3d89c89852cb235eb767c8dcf8b459807d82;hpb=3285e34dc2924bdbe0f1573b5d1a6da5032ab5f3;p=koha.git diff --git a/C4/Serials.pm b/C4/Serials.pm index e9ac3d89c8..f8c17b9189 100644 --- a/C4/Serials.pm +++ b/C4/Serials.pm @@ -5,61 +5,86 @@ 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; use C4::Serials::Frequency; use C4::Serials::Numberpattern; - -use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); +use Koha::AdditionalFieldValues; +use Koha::DateUtils; +use Koha::Serial; +use Koha::Subscriptions; +use Koha::Subscription::Histories; +use Koha::SharedContent; + +use vars qw(@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 &HasSubscriptionStrictlyExpired &HasSubscriptionExpired &GetExpirationDate &abouttoexpire &GetSubscriptionHistoryFromSubscriptionId - &GetNextSeq &GetSeq &NewIssue &ItemizeSerials &GetSerials + &GetNextSeq &GetSeq &NewIssue &GetSerials &GetLatestSerials &ModSerialStatus &GetNextDate &GetSerials2 - &ReNewSubscription &GetLateIssues &GetLateOrMissingIssues + &ReNewSubscription &GetLateOrMissingIssues &GetSerialInformation &AddItem2Serial &PrepareSerialsData &GetNextExpected &ModNextExpected + &GetPreviousSerialid - &UpdateClaimdateIssues - &GetSuppliersWithLateIssues &getsupplierbyserialid - &GetDistributedTo &SetDistributedTo + &GetSuppliersWithLateIssues &getroutinglist &delroutingmember &addroutingmember &reorder_members - &check_routing &updateClaim &removeMissingIssue + &check_routing &updateClaim &CountIssues HasItems - &GetSubscriptionsFromBorrower &subscriptionCurrentlyOnOrder ); @@ -94,79 +119,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 IN (3, 4, 41, 42, 43, 44) + 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) = @_; - - return unless ($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; - while ( my $line = $sth->fetchrow_hashref ) { - $line->{title} = "" if $last_title and $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); @@ -194,29 +162,8 @@ sub GetSubscriptionHistoryFromSubscriptionId { return $results; } -=head2 GetSerialStatusFromSerialId - -$sth = GetSerialStatusFromSerialId(); -this function returns a statement handle -After this function, don't forget to execute it by using $sth->execute($serialid) -return : -$sth = $dbh->prepare($query). - -=cut - -sub GetSerialStatusFromSerialId { - my $dbh = C4::Context->dbh; - my $query = qq| - SELECT status - FROM serial - WHERE serialid = ? - |; - return $dbh->prepare($query); -} - =head2 GetSerialInformation - $data = GetSerialInformation($serialid); returns a hash_ref containing : items : items marcrecord (can be an array) @@ -292,36 +239,12 @@ sub AddItem2Serial { return $rq->rows; } -=head2 UpdateClaimdateIssues - -UpdateClaimdateIssues($serialids,[$date]); - -Update Claimdate for issues in @$serialids list with date $date -(Take Today if none) - -=cut - -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 ) . ")"; - my $rq = $dbh->prepare($query); - $rq->execute($date, @$serialids); - return $rq->rows; -} - =head2 GetSubscription $subs = GetSubscription($subscriptionid) this function returns the subscription which has $subscriptionid as id. return : -a hashref. This hash containts +a hashref. This hash contains subscription, subscriptionhistory, aqbooksellers.name, biblio.title =cut @@ -346,7 +269,17 @@ sub GetSubscription { my $sth = $dbh->prepare($query); $sth->execute($subscriptionid); my $subscription = $sth->fetchrow_hashref; + + return unless $subscription; + $subscription->{cannotedit} = not can_edit_subscription( $subscription ); + + if ( my $mana_id = $subscription->{mana_id} ) { + my $mana_subscription = Koha::SharedContent::get_entity_by_id( + 'subscription', $mana_id, {usecomments => 1}); + $subscription->{comments} = $mana_subscription->{data}->{comments}; + } + return $subscription; } @@ -368,6 +301,7 @@ sub GetFullSubscription { serial.serialseq, serial.planneddate, serial.publisheddate, + serial.publisheddatetext, serial.status, serial.notes as notes, year(IF(serial.publisheddate="00-00-0000",serial.planneddate,serial.publisheddate)) as year, @@ -389,8 +323,9 @@ sub GetFullSubscription { my $sth = $dbh->prepare($query); $sth->execute($subscriptionid); my $subscriptions = $sth->fetchall_arrayref( {} ); + my $cannotedit = not can_edit_subscription( $subscriptions->[0] ) if scalar @$subscriptions; for my $subscription ( @$subscriptions ) { - $subscription->{cannotedit} = not can_edit_subscription( $subscription ); + $subscription->{cannotedit} = $cannotedit; } return $subscriptions; } @@ -425,7 +360,7 @@ sub PrepareSerialsData { } } $subs->{ "status" . $subs->{'status'} } = 1; - if ( grep { $_ == $subs->{status} } qw( 1 3 4 41 42 43 44 7 ) ) { + if ( grep { $_ == $subs->{status} } ( EXPECTED, LATE, MISSING_STATUSES, CLAIMED ) ) { $subs->{"checked"} = 1; } @@ -486,9 +421,13 @@ sub GetSubscriptionsFromBiblionumber { $sth->execute($biblionumber); my @res; while ( my $subs = $sth->fetchrow_hashref ) { - $subs->{startdate} = format_date( $subs->{startdate} ); - $subs->{histstartdate} = format_date( $subs->{histstartdate} ); - $subs->{histenddate} = format_date( $subs->{histenddate} ); + $subs->{startdate} = output_pref( { dt => dt_from_string( $subs->{startdate} ), dateonly => 1 } ); + $subs->{histstartdate} = output_pref( { dt => dt_from_string( $subs->{histstartdate} ), dateonly => 1 } ); + if ( defined $subs->{histenddate} ) { + $subs->{histenddate} = output_pref( { dt => dt_from_string( $subs->{histenddate} ), dateonly => 1 } ); + } else { + $subs->{histenddate} = ""; + } $subs->{opacnote} =~ s/\n/\/g; $subs->{missinglist} =~ s/\n/\/g; $subs->{recievedlist} =~ s/\n/\/g; @@ -496,10 +435,10 @@ sub GetSubscriptionsFromBiblionumber { $subs->{ "numberpattern" . $subs->{numberpattern} } = 1; $subs->{ "status" . $subs->{'status'} } = 1; - if ( $subs->{enddate} eq '0000-00-00' ) { + if (not defined $subs->{enddate} ) { $subs->{enddate} = ''; } else { - $subs->{enddate} = format_date( $subs->{enddate} ); + $subs->{enddate} = output_pref( { dt => dt_from_string( $subs->{enddate}), dateonly => 1 } ); } $subs->{'abouttoexpire'} = abouttoexpire( $subs->{'subscriptionid'} ); $subs->{'subscriptionexpired'} = HasSubscriptionExpired( $subs->{'subscriptionid'} ); @@ -524,6 +463,7 @@ sub GetFullSubscriptionsFromBiblionumber { serial.serialseq, serial.planneddate, serial.publisheddate, + serial.publisheddatetext, serial.status, serial.notes as notes, year(IF(serial.publisheddate="00-00-0000",serial.planneddate,serial.publisheddate)) as year, @@ -543,91 +483,13 @@ sub GetFullSubscriptionsFromBiblionumber { my $sth = $dbh->prepare($query); $sth->execute($biblionumber); my $subscriptions = $sth->fetchall_arrayref( {} ); + my $cannotedit = not can_edit_subscription( $subscriptions->[0] ) if scalar @$subscriptions; for my $subscription ( @$subscriptions ) { - $subscription->{cannotedit} = not can_edit_subscription( $subscription ); + $subscription->{cannotedit} = $cannotedit; } return $subscriptions; } -=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 ) . "))"; - } - 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 $subscriptions = $sth->fetchall_arrayref( {} ); - for my $subscription ( @$subscriptions ) { - $subscription->{cannotedit} = not can_edit_subscription( $subscription ); - } - return @$subscriptions; -} - =head2 SearchSubscriptions @results = SearchSubscriptions($args); @@ -657,27 +519,43 @@ subscription expiration date. sub SearchSubscriptions { my ( $args ) = @_; - my $query = qq{ + my $additional_fields = $args->{additional_fields} // []; + my $matching_record_ids_for_additional_fields = []; + if ( @$additional_fields ) { + my @subscriptions = Koha::Subscriptions->filter_by_additional_fields($additional_fields); + + return () unless @subscriptions; + + $matching_record_ids_for_additional_fields = [ map { + $_->subscriptionid + } @subscriptions ]; + } + + my $query = q| SELECT subscription.notes AS publicnotes, - subscription.*, subscriptionhistory.*, + subscription.*, biblio.notes AS biblionotes, biblio.title, biblio.author, + biblio.biblionumber, + aqbooksellers.name AS vendorname, biblioitems.issn FROM subscription LEFT JOIN subscriptionhistory USING(subscriptionid) LEFT JOIN biblio ON biblio.biblionumber = subscription.biblionumber LEFT JOIN biblioitems ON biblioitems.biblionumber = subscription.biblionumber LEFT JOIN aqbooksellers ON subscription.aqbooksellerid = aqbooksellers.id - }; + |; + $query .= q| WHERE 1|; my @where_strs; my @where_args; if( $args->{biblionumber} ) { push @where_strs, "biblio.biblionumber = ?"; push @where_args, $args->{biblionumber}; } + if( $args->{title} ){ my @words = split / /, $args->{title}; my (@strs, @args); @@ -726,19 +604,31 @@ sub SearchSubscriptions { push @where_strs, "subscription.closed = ?"; push @where_args, "$args->{closed}"; } + if(@where_strs){ - $query .= " WHERE " . join(" AND ", @where_strs); + $query .= ' AND ' . join(' AND ', @where_strs); + } + if ( @$additional_fields ) { + $query .= ' AND subscriptionid IN (' + . join( ', ', @$matching_record_ids_for_additional_fields ) + . ')'; } + $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; + my $results = $sth->fetchall_arrayref( {} ); for my $subscription ( @$results ) { $subscription->{cannotedit} = not can_edit_subscription( $subscription ); $subscription->{cannotdisplay} = not can_show_subscription( $subscription ); + + my $subscription_object = Koha::Subscriptions->find($subscription->{subscriptionid}); + $subscription->{additional_fields} = { map { $_->field->name => $_->value } + $subscription_object->additional_field_values->as_list }; + } return @$results; @@ -767,9 +657,11 @@ sub GetSerials { my $counter = 0; $count = 5 unless ($count); my @serials; - my $query = "SELECT serialid,serialseq, status, publisheddate, planneddate,notes, routingnotes + my $statuses = join( ',', ( ARRIVED, MISSING_STATUSES, NOT_ISSUED ) ); + my $query = "SELECT serialid,serialseq, status, publisheddate, + publisheddatetext, planneddate,notes, routingnotes FROM serial - WHERE subscriptionid = ? AND status NOT IN (2, 4, 41, 42, 43, 44, 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); @@ -778,7 +670,7 @@ sub GetSerials { $line->{ "status" . $line->{status} } = 1; # fills a "statusX" value, used for template status select list for my $datefield ( qw( planneddate publisheddate) ) { if ($line->{$datefield} && $line->{$datefield}!~m/^00/) { - $line->{$datefield} = format_date( $line->{$datefield}); + $line->{$datefield} = output_pref( { dt => dt_from_string( $line->{$datefield} ), dateonly => 1 } ); } else { $line->{$datefield} = q{}; } @@ -787,10 +679,11 @@ sub GetSerials { } # OK, now add the last 5 issues arrives/missing - $query = "SELECT serialid,serialseq, status, planneddate, publisheddate,notes, routingnotes + $query = "SELECT serialid,serialseq, status, planneddate, publisheddate, + publisheddatetext, notes, routingnotes FROM serial WHERE subscriptionid = ? - AND (status in (2, 4, 41, 42, 43, 44, 5)) + AND status IN ( $statuses ) ORDER BY IF(publisheddate<>'0000-00-00',publisheddate,planneddate) DESC "; $sth = $dbh->prepare($query); @@ -800,7 +693,7 @@ sub GetSerials { $line->{ "status" . $line->{status} } = 1; # fills a "statusX" value, used for template status select list for my $datefield ( qw( planneddate publisheddate) ) { if ($line->{$datefield} && $line->{$datefield}!~m/^00/) { - $line->{$datefield} = format_date( $line->{$datefield}); + $line->{$datefield} = output_pref( { dt => dt_from_string( $line->{$datefield} ), dateonly => 1 } ); } else { $line->{$datefield} = q{}; } @@ -818,39 +711,45 @@ 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 $status); + return unless ($subscription and @$statuses); my $dbh = C4::Context->dbh; - my $query = qq| - SELECT serialid,serialseq, status, planneddate, publisheddate,notes, routingnotes + my $query = q| + SELECT serialid,serialseq, status, planneddate, publisheddate, + publisheddatetext, notes, routingnotes FROM serial - WHERE subscriptionid=$subscription AND status IN ($status) + WHERE subscriptionid=? + | + . q| AND status IN (| . join( ",", ('?') x @$statuses ) . q|)| + . q| ORDER BY publisheddate,serialid DESC - |; + |; $debug and warn "GetSerials2 query: $query"; my $sth = $dbh->prepare($query); - $sth->execute; + $sth->execute( $subscription, @$statuses ); my @serials; while ( my $line = $sth->fetchrow_hashref ) { $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 { - $line->{$datefield} = format_date( $line->{$datefield} ); + $line->{$datefield} = output_pref( { dt => dt_from_string( $line->{$datefield} ), dateonly => 1 } ); } } push @serials, $line; @@ -874,11 +773,11 @@ sub GetLatestSerials { my $dbh = C4::Context->dbh; - # status = 2 is "arrived" + my $statuses = join( ',', ( ARRIVED, MISSING_STATUSES ) ); my $strsth = "SELECT serialid,serialseq, status, planneddate, publisheddate, notes FROM serial WHERE subscriptionid = ? - AND status IN (2, 4, 41, 42, 43, 44) + AND status IN ($statuses) ORDER BY publisheddate DESC LIMIT 0,$limit "; my $sth = $dbh->prepare($strsth); @@ -886,32 +785,43 @@ sub GetLatestSerials { my @serials; 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"} ); + $line->{planneddate} = output_pref( { dt => dt_from_string( $line->{planneddate} ), dateonly => 1 } ); + $line->{publisheddate} = output_pref( { dt => dt_from_string( $line->{publisheddate} ), dateonly => 1 } ); push @serials, $line; } return \@serials; } -=head2 GetDistributedTo +=head2 GetPreviousSerialid -$distributedto=GetDistributedTo($subscriptionid) -This function returns the field distributedto for the subscription matching subscriptionid +$serialid = GetPreviousSerialid($subscriptionid, $nth) +get the $nth's previous serial for the given subscriptionid +return : +the serialid =cut -sub GetDistributedTo { +sub GetPreviousSerialid { + my ( $subscriptionid, $nth ) = @_; + $nth ||= 1; my $dbh = C4::Context->dbh; - my $distributedto; - my ($subscriptionid) = @_; + my $return = undef; - return unless ($subscriptionid); - - my $query = "SELECT distributedto FROM subscription WHERE subscriptionid=?"; - my $sth = $dbh->prepare($query); + # Status 2: Arrived + my $strsth = "SELECT serialid + FROM serial + WHERE subscriptionid = ? + AND status = 2 + ORDER BY serialid DESC LIMIT $nth,1 + "; + my $sth = $dbh->prepare($strsth); $sth->execute($subscriptionid); - return ($distributedto) = $sth->fetchrow; + my @serials; + my $line = $sth->fetchrow_hashref; + $return = $line->{'serialid'} if ($line); + + return $return; } =head2 GetNextSeq @@ -919,19 +829,20 @@ sub GetDistributedTo { my ( $nextseq, $newlastvalue1, $newlastvalue2, $newlastvalue3, $newinnerloop1, $newinnerloop2, $newinnerloop3 - ) = GetNextSeq( $subscription, $pattern, $planneddate ); + ) = GetNextSeq( $subscription, $pattern, $frequency, $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. +$frequency is a hashref containing all the attributes of the table 'subscription_frequencies' +$planneddate is a date string in iso format. This function get the next issue for the subscription given on input arg =cut sub GetNextSeq { - my ($subscription, $pattern, $planneddate) = @_; + my ($subscription, $pattern, $frequency, $planneddate) = @_; return unless ($subscription and $pattern); @@ -944,7 +855,7 @@ sub GetNextSeq { if(@irreg > 0) { my $irregularities = {}; $irregularities->{$_} = 1 foreach(@irreg); - my $issueno = GetFictiveIssueNumber($subscription, $planneddate) + 1; + my $issueno = GetFictiveIssueNumber($subscription, $planneddate, $frequency) + 1; while($irregularities->{$issueno}) { $count++; $issueno++; @@ -1076,7 +987,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} ) { @@ -1085,7 +998,7 @@ sub GetExpirationDate { #calculate the date of the last issue. for ( my $i = 1 ; $i <= $length ; $i++ ) { - $enddate = GetNextDate( $subscription, $enddate ); + $enddate = GetNextDate( $subscription, $enddate, $frequency ); } } elsif ( $subscription->{monthlength} ) { if ( $$subscription{startdate} ) { @@ -1156,53 +1069,10 @@ 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,41,42,43,44,5"); - my $missinglist; - foreach my $missingserial (@missingserials) { - if ( grep { $_ == $missingserial->{status} } qw( 4 41 42 43 44 ) ) { - $missinglist .= $missingserial->{'serialseq'} . "; "; - } elsif($missingserial->{'status'} == 5) { - $missinglist .= "not issued " . $missingserial->{'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) + ModSerialStatus($serialid, $serialseq, $planneddate, $publisheddate, + $publisheddatetext, $status, $notes); This function modify the serial status. Serial status is a number.(eg 2 is "arrived") Note : if we change from "waited" to something else,then we will have to create a new "waited" entry @@ -1210,7 +1080,8 @@ Note : if we change from "waited" to something else,then we will have to create =cut sub ModSerialStatus { - my ( $serialid, $serialseq, $planneddate, $publisheddate, $status, $notes ) = @_; + my ($serialid, $serialseq, $planneddate, $publisheddate, $publisheddatetext, + $status, $notes) = @_; return unless ($serialid); @@ -1228,57 +1099,80 @@ sub ModSerialStatus { # change status & update subscriptionhistory my $val; - if ( $status == 6 ) { + if ( $status == DELETED ) { DelIssue( { 'serialid' => $serialid, 'subscriptionid' => $subscriptionid, 'serialseq' => $serialseq } ); } else { - my $query = 'UPDATE serial SET serialseq=?,publisheddate=?,planneddate=?,status=?,notes=? WHERE serialid = ?'; + my $query = ' + UPDATE serial + SET serialseq = ?, publisheddate = ?, publisheddatetext = ?, + planneddate = ?, status = ?, notes = ? + WHERE serialid = ? + '; $sth = $dbh->prepare($query); - $sth->execute( $serialseq, $publisheddate, $planneddate, $status, $notes, $serialid ); + $sth->execute( $serialseq, $publisheddate, $publisheddatetext, + $planneddate, $status, $notes, $serialid ); $query = "SELECT * FROM subscription WHERE subscriptionid = ?"; $sth = $dbh->prepare($query); $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(?=;|$)/); } - my @missing_statuses = qw( 4 41 42 43 44 ); - if ( ( grep { $_ == $status } ( @missing_statuses, 5 ) ) - || ( - ( grep { $_ == $oldstatus } @missing_statuses ) - && ! ( grep { $_ == $status } @missing_statuses ) ) - || ($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 ) { + # create new expected entry if needed (ie : was "expected" and has changed) + my $otherIssueExpected = scalar findSerialsByStatus(EXPECTED, $subscriptionid); + if ( !$otherIssueExpected && $oldstatus == EXPECTED && $status != EXPECTED ) { my $subscription = GetSubscription($subscriptionid); my $pattern = C4::Serials::Numberpattern::GetSubscriptionNumberpattern($subscription->{numberpattern}); + my $frequency = C4::Serials::Frequency::GetSubscriptionFrequency($subscription->{periodicity}); # next issue number my ( $newserialseq, $newlastvalue1, $newlastvalue2, $newlastvalue3, $newinnerloop1, $newinnerloop2, $newinnerloop3 ) - = GetNextSeq( $subscription, $pattern, $publisheddate ); + = GetNextSeq( $subscription, $pattern, $frequency, $publisheddate ); # next date (calculated from actual date & frequency parameters) - my $nextpublisheddate = GetNextDate($subscription, $publisheddate, 1); + my $nextpublisheddate = GetNextDate($subscription, $publisheddate, $frequency, 1); my $nextpubdate = $nextpublisheddate; - 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 ); + NewIssue( $newserialseq, $subscriptionid, $subscription->{'biblionumber'}, 1, $nextpubdate, $nextpubdate ); + # check if an alert must be sent... (= a letter is defined & status became "arrived" - if ( $subscription->{letter} && $status == 2 && $oldstatus != 2 ) { + if ( $subscription->{letter} && $status == ARRIVED && $oldstatus != ARRIVED ) { require C4::Letters; - C4::Letters::SendAlerts( 'issue', $subscription->{subscriptionid}, $subscription->{letter} ); + C4::Letters::SendAlerts( 'issue', $serialid, $subscription->{letter} ); } } @@ -1313,8 +1207,8 @@ 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{ @@ -1361,8 +1255,8 @@ 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; } @@ -1413,7 +1307,8 @@ sub ModSubscription { $lastvalue2, $innerloop2, $lastvalue3, $innerloop3, $status, $biblionumber, $callnumber, $notes, $letter, $manualhistory, $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount, - $graceperiod, $location, $enddate, $subscriptionid, $skip_serialseq + $graceperiod, $location, $enddate, $subscriptionid, $skip_serialseq, + $itemtype, $previousitemtype, $mana_id ) = @_; my $dbh = C4::Context->dbh; @@ -1426,7 +1321,7 @@ sub ModSubscription { callnumber=?, notes=?, letter=?, manualhistory=?, internalnotes=?, serialsadditems=?, staffdisplaycount=?, opacdisplaycount=?, graceperiod=?, location = ?, enddate=?, - skip_serialseq=? + skip_serialseq=?, itemtype=?, previousitemtype=?, mana_id=? WHERE subscriptionid = ?"; my $sth = $dbh->prepare($query); @@ -1440,6 +1335,7 @@ sub ModSubscription { $letter, ($manualhistory ? $manualhistory : 0), $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate, $skip_serialseq, + $itemtype, $previousitemtype, $mana_id, $subscriptionid ); my $rows = $sth->rows; @@ -1455,7 +1351,8 @@ $subscriptionid = &NewSubscription($auser,branchcode,$aqbooksellerid,$cost,$aqbu $lastvalue1,$innerloop1,$lastvalue2,$innerloop2,$lastvalue3,$innerloop3, $status, $notes, $letter, $firstacquidate, $irregularity, $numberpattern, $locale, $callnumber, $manualhistory, $internalnotes, $serialsadditems, - $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate, $skip_serialseq); + $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate, + $skip_serialseq, $itemtype, $previousitemtype); Create a new subscription with value given on input args. @@ -1472,7 +1369,7 @@ sub NewSubscription { $innerloop3, $status, $notes, $letter, $firstacquidate, $irregularity, $numberpattern, $locale, $callnumber, $manualhistory, $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount, $graceperiod, - $location, $enddate, $skip_serialseq + $location, $enddate, $skip_serialseq, $itemtype, $previousitemtype, $mana_id ) = @_; my $dbh = C4::Context->dbh; @@ -1485,8 +1382,9 @@ sub NewSubscription { lastvalue3, innerloop3, status, notes, letter, firstacquidate, irregularity, numberpattern, locale, callnumber, manualhistory, internalnotes, serialsadditems, staffdisplaycount, - opacdisplaycount, graceperiod, location, enddate, skip_serialseq) - VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) + opacdisplaycount, graceperiod, location, enddate, skip_serialseq, + itemtype, previousitemtype, mana_id) + VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?, ?) |; my $sth = $dbh->prepare($query); $sth->execute( @@ -1496,7 +1394,8 @@ sub NewSubscription { $lastvalue3, $innerloop3, $status, $notes, $letter, $firstacquidate, $irregularity, $numberpattern, $locale, $callnumber, $manualhistory, $internalnotes, $serialsadditems, $staffdisplaycount, - $opacdisplaycount, $graceperiod, $location, $enddate, $skip_serialseq + $opacdisplaycount, $graceperiod, $location, $enddate, $skip_serialseq, + $itemtype, $previousitemtype, $mana_id ); my $subscriptionid = $dbh->{'mysql_insertid'}; @@ -1514,11 +1413,11 @@ sub NewSubscription { # then create the 1st expected number $query = qq( INSERT INTO subscriptionhistory - (biblionumber, subscriptionid, histstartdate, opacnote, librariannote) - VALUES (?,?,?,?,?) + (biblionumber, subscriptionid, histstartdate, missinglist, recievedlist) + 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) my $subscription = GetSubscription($subscriptionid); @@ -1526,25 +1425,32 @@ sub NewSubscription { # calculate issue number 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 ); + + Koha::Serial->new( + { + serialseq => $serialseq, + serialseq_x => $subscription->{'lastvalue1'}, + serialseq_y => $subscription->{'lastvalue2'}, + serialseq_z => $subscription->{'lastvalue3'}, + subscriptionid => $subscriptionid, + biblionumber => $biblionumber, + status => EXPECTED, + planneddate => $firstacquidate, + publisheddate => $firstacquidate, + } + )->store(); logaction( "SERIAL", "ADD", $subscriptionid, "" ) if C4::Context->preference("SubscriptionLog"); #set serial flag on biblio if not already set. - my $bib = GetBiblio($biblionumber); - if ( $bib and !$bib->{'serial'} ) { - my $record = GetMarcBiblio($biblionumber); - my ( $tag, $subf ) = GetMarcFromKohaField( 'biblio.serial', $bib->{'frameworkcode'} ); + my $biblio = Koha::Biblios->find( $biblionumber ); + if ( $biblio and !$biblio->serial ) { + my $record = GetMarcBiblio({ biblionumber => $biblionumber }); + my ( $tag, $subf ) = GetMarcFromKohaField( 'biblio.serial', $biblio->frameworkcode ); if ($tag) { eval { $record->field($tag)->update( $subf => 1 ); }; } - ModBiblio( $record, $biblionumber, $bib->{'frameworkcode'} ); + ModBiblio( $record, $biblionumber, $biblio->frameworkcode ); } return $subscriptionid; } @@ -1584,6 +1490,9 @@ sub ReNewSubscription { ); } + $numberlength ||= 0; # Should not we raise an exception instead? + $weeklength ||= 0; + # renew subscription $query = qq| UPDATE subscription @@ -1601,13 +1510,6 @@ sub ReNewSubscription { |; $sth = $dbh->prepare($query); $sth->execute( $enddate, $subscriptionid ); - $query = qq| - UPDATE subscriptionhistory - SET histenddate=? - WHERE subscriptionid=? - |; - $sth = $dbh->prepare($query); - $sth->execute( $enddate, $subscriptionid ); logaction( "SERIAL", "RENEW", $subscriptionid, "" ) if C4::Context->preference("SubscriptionLog"); return; @@ -1624,183 +1526,56 @@ returns the serial id =cut sub NewIssue { - my ( $serialseq, $subscriptionid, $biblionumber, $status, $planneddate, $publisheddate, $notes ) = @_; + my ( $serialseq, $subscriptionid, $biblionumber, $status, $planneddate, + $publisheddate, $publisheddatetext, $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 - (serialseq,subscriptionid,biblionumber,status,publisheddate,planneddate,notes) - VALUES (?,?,?,?,?,?,?) - |; - my $sth = $dbh->prepare($query); - $sth->execute( $serialseq, $subscriptionid, $biblionumber, $status, $publisheddate, $planneddate, $notes ); - my $serialid = $dbh->{'mysql_insertid'}; - $query = qq| - SELECT missinglist,recievedlist - FROM subscriptionhistory - WHERE subscriptionid=? - |; - $sth = $dbh->prepare($query); - $sth->execute($subscriptionid); - my ( $missinglist, $recievedlist ) = $sth->fetchrow; + my $schema = Koha::Database->new()->schema(); + + my $subscription = Koha::Subscriptions->find( $subscriptionid ); + + my $serial = Koha::Serial->new( + { + serialseq => $serialseq, + serialseq_x => $subscription->lastvalue1(), + serialseq_y => $subscription->lastvalue2(), + serialseq_z => $subscription->lastvalue3(), + subscriptionid => $subscriptionid, + biblionumber => $biblionumber, + status => $status, + planneddate => $planneddate, + publisheddate => $publisheddate, + publisheddatetext => $publisheddatetext, + notes => $notes, + } + )->store(); + + my $serialid = $serial->id(); + + my $subscription_history = Koha::Subscription::Histories->find($subscriptionid); + my $missinglist = $subscription_history->missinglist(); + my $recievedlist = $subscription_history->recievedlist(); - if ( $status == 2 ) { - ### 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 == 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 ) { - $missinglist .= "; $serialseq" unless (index($missinglist,$serialseq)>0); + if ( grep { /^$status$/ } (MISSING_STATUSES) ) { + $missinglist .= "; $serialseq" unless ( index( $missinglist, $serialseq ) > 0 ); } - $query = qq| - UPDATE subscriptionhistory - SET recievedlist=?, missinglist=? - WHERE subscriptionid=? - |; - $sth = $dbh->prepare($query); + $recievedlist =~ s/^; //; $missinglist =~ s/^; //; - $sth->execute( $recievedlist, $missinglist, $subscriptionid ); - return $serialid; -} - -=head2 ItemizeSerials - -ItemizeSerials($serialid, $info); -$info is a hashref containing barcode branch, itemcallnumber, status, location -$serialid the serialid -return : -1 if the itemize is a succes. -0 and @error otherwise. @error containts the list of errors found. - -=cut - -sub ItemizeSerials { - my ( $serialid, $info ) = @_; - - return unless ($serialid); - my $now = POSIX::strftime( "%Y-%m-%d", localtime ); + $subscription_history->recievedlist($recievedlist); + $subscription_history->missinglist($missinglist); + $subscription_history->store(); - my $dbh = C4::Context->dbh; - my $query = qq| - SELECT * - FROM serial - WHERE serialid=? - |; - my $sth = $dbh->prepare($query); - $sth->execute($serialid); - my $data = $sth->fetchrow_hashref; - if ( C4::Context->preference("RoutingSerials") ) { - - # check for existing biblioitem relating to serial issue - my ( $count, @results ) = GetBiblioItemByBiblioNumber( $data->{'biblionumber'} ); - my $bibitemno = 0; - for ( my $i = 0 ; $i < $count ; $i++ ) { - if ( $results[$i]->{'volumeddesc'} eq $data->{'serialseq'} . ' (' . $data->{'planneddate'} . ')' ) { - $bibitemno = $results[$i]->{'biblioitemnumber'}; - last; - } - } - if ( $bibitemno == 0 ) { - my $sth = $dbh->prepare( "SELECT * FROM biblioitems WHERE biblionumber = ? ORDER BY biblioitemnumber DESC" ); - $sth->execute( $data->{'biblionumber'} ); - my $biblioitem = $sth->fetchrow_hashref; - $biblioitem->{'volumedate'} = $data->{planneddate}; - $biblioitem->{'volumeddesc'} = $data->{serialseq} . ' (' . format_date( $data->{'planneddate'} ) . ')'; - $biblioitem->{'dewey'} = $info->{itemcallnumber}; - } - } - - my $fwk = GetFrameworkCode( $data->{'biblionumber'} ); - if ( $info->{barcode} ) { - my @errors; - if ( is_barcode_in_use( $info->{barcode} ) ) { - push @errors, 'barcode_not_unique'; - } else { - my $marcrecord = MARC::Record->new(); - my ( $tag, $subfield ) = GetMarcFromKohaField( "items.barcode", $fwk ); - my $newField = MARC::Field->new( "$tag", '', '', "$subfield" => $info->{barcode} ); - $marcrecord->insert_fields_ordered($newField); - if ( $info->{branch} ) { - my ( $tag, $subfield ) = GetMarcFromKohaField( "items.homebranch", $fwk ); - - #warn "items.homebranch : $tag , $subfield"; - if ( $marcrecord->field($tag) ) { - $marcrecord->field($tag)->add_subfields( "$subfield" => $info->{branch} ); - } else { - my $newField = MARC::Field->new( "$tag", '', '', "$subfield" => $info->{branch} ); - $marcrecord->insert_fields_ordered($newField); - } - ( $tag, $subfield ) = GetMarcFromKohaField( "items.holdingbranch", $fwk ); - - #warn "items.holdingbranch : $tag , $subfield"; - if ( $marcrecord->field($tag) ) { - $marcrecord->field($tag)->add_subfields( "$subfield" => $info->{branch} ); - } else { - my $newField = MARC::Field->new( "$tag", '', '', "$subfield" => $info->{branch} ); - $marcrecord->insert_fields_ordered($newField); - } - } - if ( $info->{itemcallnumber} ) { - my ( $tag, $subfield ) = GetMarcFromKohaField( "items.itemcallnumber", $fwk ); - - if ( $marcrecord->field($tag) ) { - $marcrecord->field($tag)->add_subfields( "$subfield" => $info->{itemcallnumber} ); - } else { - my $newField = MARC::Field->new( "$tag", '', '', "$subfield" => $info->{itemcallnumber} ); - $marcrecord->insert_fields_ordered($newField); - } - } - if ( $info->{notes} ) { - my ( $tag, $subfield ) = GetMarcFromKohaField( "items.itemnotes", $fwk ); - - if ( $marcrecord->field($tag) ) { - $marcrecord->field($tag)->add_subfields( "$subfield" => $info->{notes} ); - } else { - my $newField = MARC::Field->new( "$tag", '', '', "$subfield" => $info->{notes} ); - $marcrecord->insert_fields_ordered($newField); - } - } - if ( $info->{location} ) { - my ( $tag, $subfield ) = GetMarcFromKohaField( "items.location", $fwk ); - - if ( $marcrecord->field($tag) ) { - $marcrecord->field($tag)->add_subfields( "$subfield" => $info->{location} ); - } else { - my $newField = MARC::Field->new( "$tag", '', '', "$subfield" => $info->{location} ); - $marcrecord->insert_fields_ordered($newField); - } - } - if ( $info->{status} ) { - my ( $tag, $subfield ) = GetMarcFromKohaField( "items.notforloan", $fwk ); - - if ( $marcrecord->field($tag) ) { - $marcrecord->field($tag)->add_subfields( "$subfield" => $info->{status} ); - } else { - my $newField = MARC::Field->new( "$tag", '', '', "$subfield" => $info->{status} ); - $marcrecord->insert_fields_ordered($newField); - } - } - if ( C4::Context->preference("RoutingSerials") ) { - my ( $tag, $subfield ) = GetMarcFromKohaField( "items.dateaccessioned", $fwk ); - if ( $marcrecord->field($tag) ) { - $marcrecord->field($tag)->add_subfields( "$subfield" => $now ); - } else { - my $newField = MARC::Field->new( "$tag", '', '', "$subfield" => $now ); - $marcrecord->insert_fields_ordered($newField); - } - } - require C4::Items; - C4::Items::AddItemFromMarc( $marcrecord, $data->{'biblionumber'} ); - return 1; - } - return ( 0, @errors ); - } + return $serialid; } =head2 HasSubscriptionStrictlyExpired @@ -1904,26 +1679,6 @@ sub HasSubscriptionExpired { return 0; # Notice that you'll never get here. } -=head2 SetDistributedto - -SetDistributedto($distributedto,$subscriptionid); -This function update the value of distributedto for a subscription given on input arg. - -=cut - -sub SetDistributedto { - my ( $distributedto, $subscriptionid ) = @_; - my $dbh = C4::Context->dbh; - my $query = qq| - UPDATE subscription - SET distributedto=? - WHERE subscriptionid=? - |; - my $sth = $dbh->prepare($query); - $sth->execute( $distributedto, $subscriptionid ); - return; -} - =head2 DelSubscription DelSubscription($subscriptionid) @@ -1934,10 +1689,14 @@ this function deletes subscription which has $subscriptionid as id. sub DelSubscription { my ($subscriptionid) = @_; my $dbh = C4::Context->dbh; - $subscriptionid = $dbh->quote($subscriptionid); - $dbh->do("DELETE FROM subscription WHERE subscriptionid=$subscriptionid"); - $dbh->do("DELETE FROM subscriptionhistory WHERE subscriptionid=$subscriptionid"); - $dbh->do("DELETE FROM serial WHERE subscriptionid=$subscriptionid"); + $dbh->do("DELETE FROM subscription WHERE subscriptionid=?", undef, $subscriptionid); + $dbh->do("DELETE FROM subscriptionhistory WHERE subscriptionid=?", undef, $subscriptionid); + $dbh->do("DELETE FROM serial WHERE subscriptionid=?", undef, $subscriptionid); + + Koha::AdditionalFieldValues->search({ + 'field.tablename' => 'subscription', + 'me.record_id' => $subscriptionid, + }, { join => 'field' })->delete; logaction( "SERIAL", "DELETE", $subscriptionid, "" ) if C4::Context->preference("SubscriptionLog"); } @@ -1992,7 +1751,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 = ''; if ($serialid) { @@ -2016,96 +1776,63 @@ sub GetLateOrMissingIssues { } else { $order = "title"; } + my $missing_statuses_string = join ',', (MISSING_STATUSES); if ($supplierid) { $sth = $dbh->prepare( "SELECT serialid, aqbooksellerid, name, biblio.title, biblioitems.issn, 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 biblioitems ON subscription.biblionumber=biblioitems.biblionumber LEFT JOIN aqbooksellers ON subscription.aqbooksellerid = aqbooksellers.id - WHERE subscription.subscriptionid = serial.subscriptionid - AND (serial.STATUS IN (4, 41, 42, 43, 44) 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 IN (4, 41, 42, 43, 44) 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->{planneddate} = format_date( $line->{planneddate} ); + $line->{planneddateISO} = $line->{planneddate}; + $line->{planneddate} = output_pref( { dt => dt_from_string( $line->{"planneddate"} ), dateonly => 1 } ); } if ($line->{claimdate} && $line->{claimdate} !~/^0+\-/) { - $line->{claimdate} = format_date( $line->{claimdate} ); + $line->{claimdateISO} = $line->{claimdate}; + $line->{claimdate} = output_pref( { dt => dt_from_string( $line->{"claimdate"} ), dateonly => 1 } ); } $line->{"status".$line->{status}} = 1; - push @issuelist, $line; - } - return @issuelist; -} -=head2 removeMissingIssue + my $subscription_object = Koha::Subscriptions->find($line->{subscriptionid}); + $line->{additional_fields} = { map { $_->field->name => $_->value } + $subscription_object->additional_field_values->as_list }; -removeMissingIssue($subscriptionid) - -this function removes an issue from being part of the missing string in -subscriptionlist.missinglist column - -called when a missing issue is found from the serials-recieve.pl file - -=cut - -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); - my $data = $sth->fetchrow_hashref; - my $missinglist = $data->{'missinglist'}; - my $missinglistbefore = $missinglist; - - # warn $missinglist." before"; - $missinglist =~ s/($sequence)//; - - # warn $missinglist." after"; - if ( $missinglist ne $missinglistbefore ) { - $missinglist =~ s/\|\s\|/\|/g; - $missinglist =~ s/^\| //g; - $missinglist =~ s/\|$//g; - my $sth2 = $dbh->prepare( - "UPDATE subscriptionhistory - SET missinglist = ? - WHERE subscriptionid = ?" - ); - $sth2->execute( $missinglist, $subscriptionid ); + push @issuelist, $line; } - return; + return @issuelist; } =head2 updateClaim @@ -2119,42 +1846,19 @@ called from claims.pl file =cut sub updateClaim { - my ($serialid) = @_; - my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare( - "UPDATE serial SET claimdate = now() - WHERE serialid = ? - " - ); - $sth->execute($serialid); - return; -} - -=head2 getsupplierbyserialid - -$result = getsupplierbyserialid($serialid) - -this function is used to find the supplier id given a serial id - -return : -hashref containing serialid, subscriptionid, and aqbooksellerid - -=cut - -sub getsupplierbyserialid { - my ($serialid) = @_; - my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare( - "SELECT serialid, serial.subscriptionid, aqbooksellerid - FROM serial - LEFT JOIN subscription ON serial.subscriptionid = subscription.subscriptionid - WHERE serialid = ? - " - ); - $sth->execute($serialid); - my $line = $sth->fetchrow_hashref; - my $result = $line->{'aqbooksellerid'}; - return $result; + my ($serialids) = @_; + return unless $serialids; + unless ( ref $serialids ) { + $serialids = [ $serialids ]; + } + my $dbh = C4::Context->dbh; + return $dbh->do(q| + UPDATE serial + SET claimdate = NOW(), + claims_count = claims_count + 1, + status = ? + WHERE serialid in (| . join( q|,|, (q|?|) x @$serialids ) . q|)|, + {}, CLAIMED, @$serialids ); } =head2 check_routing @@ -2399,69 +2103,32 @@ 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; + my $nextdate = GetNextDate($subscription, $res, $frequency); + + # 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; -} -sub in_array { # used in next sub down - my ( $val, @elements ) = @_; - foreach my $elem (@elements) { - if ( $val == $elem ) { - return 1; - } - } return 0; } -=head2 GetSubscriptionsFromBorrower - -($count,@routinglist) = GetSubscriptionsFromBorrower($borrowernumber) - -this gets the info from subscriptionroutinglist for each $subscriptionid - -return : -a count of the serial subscription routing lists to which a patron belongs, -with the titles of those serial subscriptions as an array. Each element of the array -contains a hash_ref with subscriptionID and title of subscription. - -=cut - -sub GetSubscriptionsFromBorrower { - my ($borrowernumber) = @_; - my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare( - "SELECT subscription.subscriptionid, biblio.title - FROM subscription - JOIN biblio ON biblio.biblionumber = subscription.biblionumber - JOIN subscriptionroutinglist USING (subscriptionid) - WHERE subscriptionroutinglist.borrowernumber = ? ORDER BY title ASC - " - ); - $sth->execute($borrowernumber); - my @routinglist; - my $count = 0; - while ( my $line = $sth->fetchrow_hashref ) { - $count++; - push( @routinglist, $line ); - } - return ( $count, @routinglist ); -} - - =head2 GetFictiveIssueNumber -$issueno = GetFictiveIssueNumber($subscription, $publishedate); +$issueno = GetFictiveIssueNumber($subscription, $publishedate, $frequency); Get the position of the issue published at $publisheddate, considering the first issue (at firstacquidate) is at position 1, the next is at position 2, etc... @@ -2472,52 +2139,166 @@ depending on how many rows are in serial table. The issue number calculation is based on subscription frequency, first acquisition date, and $publisheddate. +Returns undef when called for irregular frequencies. + +The routine is used to skip irregularities when calculating the next issue +date (in GetNextDate) or the next issue number (in GetNextSeq). + =cut sub GetFictiveIssueNumber { - my ($subscription, $publisheddate) = @_; + my ($subscription, $publisheddate, $frequency) = @_; - my $frequency = GetSubscriptionFrequency($subscription->{'periodicity'}); my $unit = $frequency->{unit} ? lc $frequency->{'unit'} : undef; - my $issueno = 0; - - if($unit) { - my ($year, $month, $day) = split /-/, $publisheddate; - my ($fa_year, $fa_month, $fa_day) = split /-/, $subscription->{'firstacquidate'}; - my $wkno; - my $delta; - - if($unit eq 'day') { - $delta = Delta_Days($fa_year, $fa_month, $fa_day, $year, $month, $day); - } elsif($unit eq 'week') { - ($wkno, $year) = Week_of_Year($year, $month, $day); - my ($fa_wkno, $fa_yr) = Week_of_Year($fa_year, $fa_month, $fa_day); - $delta = ($fa_yr == $year) ? ($wkno - $fa_wkno) : ( ($year-$fa_yr-1)*52 + (52-$fa_wkno+$wkno) ); - } elsif($unit eq 'month') { - $delta = ($fa_year == $year) - ? ($month - $fa_month) - : ( ($year-$fa_year-1)*12 + (12-$fa_month+$month) ); - } elsif($unit eq 'year') { - $delta = $year - $fa_year; - } - if($frequency->{'unitsperissue'} == 1) { - $issueno = $delta * $frequency->{'issuesperunit'} + $subscription->{'countissuesperunit'}; - } else { - # Assuming issuesperunit == 1 - $issueno = int( ($delta + $frequency->{'unitsperissue'}) / $frequency->{'unitsperissue'} ); - } + return if !$unit; + my $issueno; + + my ( $year, $month, $day ) = split /-/, $publisheddate; + my ( $fa_year, $fa_month, $fa_day ) = split /-/, $subscription->{'firstacquidate'}; + my $delta = _delta_units( [$fa_year, $fa_month, $fa_day], [$year, $month, $day], $unit ); + + if( $frequency->{'unitsperissue'} == 1 ) { + $issueno = $delta * $frequency->{'issuesperunit'} + $subscription->{'countissuesperunit'}; + } else { # issuesperunit == 1 + $issueno = 1 + int( $delta / $frequency->{'unitsperissue'} ); } return $issueno; } +sub _delta_units { + my ( $date1, $date2, $unit ) = @_; + # date1 and date2 are array refs in the form [ yy, mm, dd ] + + if( $unit eq 'day' ) { + return Delta_Days( @$date1, @$date2 ); + } elsif( $unit eq 'week' ) { + return int( Delta_Days( @$date1, @$date2 ) / 7 ); + } + + # In case of months or years, this is a wrapper around N_Delta_YMD. + # Note that N_Delta_YMD returns 29 days between e.g. 22-2-72 and 22-3-72 + # while we expect 1 month. + my @delta = N_Delta_YMD( @$date1, @$date2 ); + if( $delta[2] > 27 ) { + # Check if we could add a month + my @jump = Add_Delta_YM( @$date1, $delta[0], 1 + $delta[1] ); + if( Delta_Days( @jump, @$date2 ) >= 0 ) { + $delta[1]++; + } + } + if( $delta[1] >= 12 ) { + $delta[0]++; + $delta[1] -= 12; + } + # if unit is year, we only return full years + return $unit eq 'month' ? $delta[0] * 12 + $delta[1] : $delta[0]; +} + +sub _get_next_date_day { + my ($subscription, $freqdata, $year, $month, $day) = @_; + + my @newissue; # ( yy, mm, dd ) + # We do not need $delta_days here, since it would be zero where used + + if( $freqdata->{issuesperunit} == 1 ) { + # Add full days + @newissue = Add_Delta_Days( + $year, $month, $day, $freqdata->{"unitsperissue"} ); + } elsif ( $subscription->{countissuesperunit} < $freqdata->{issuesperunit} ) { + # Add zero days + @newissue = ( $year, $month, $day ); + $subscription->{countissuesperunit}++; + } else { + # We finished a cycle of issues within a unit. + # No subtraction of zero needed, just add one day + @newissue = Add_Delta_Days( $year, $month, $day, 1 ); + $subscription->{countissuesperunit} = 1; + } + return @newissue; +} + +sub _get_next_date_week { + my ($subscription, $freqdata, $year, $month, $day) = @_; + + my @newissue; # ( yy, mm, dd ) + my $delta_days = int( 7 / $freqdata->{issuesperunit} ); + + if( $freqdata->{issuesperunit} == 1 ) { + # Add full weeks (of 7 days) + @newissue = Add_Delta_Days( + $year, $month, $day, 7 * $freqdata->{"unitsperissue"} ); + } elsif ( $subscription->{countissuesperunit} < $freqdata->{issuesperunit} ) { + # Add rounded number of days based on frequency. + @newissue = Add_Delta_Days( $year, $month, $day, $delta_days ); + $subscription->{countissuesperunit}++; + } else { + # We finished a cycle of issues within a unit. + # Subtract delta * (issues - 1), add 1 week + @newissue = Add_Delta_Days( $year, $month, $day, + -$delta_days * ($freqdata->{issuesperunit} - 1) ); + @newissue = Add_Delta_Days( @newissue, 7 ); + $subscription->{countissuesperunit} = 1; + } + return @newissue; +} + +sub _get_next_date_month { + my ($subscription, $freqdata, $year, $month, $day) = @_; + + my @newissue; # ( yy, mm, dd ) + my $delta_days = int( 30 / $freqdata->{issuesperunit} ); + + if( $freqdata->{issuesperunit} == 1 ) { + # Add full months + @newissue = Add_Delta_YM( + $year, $month, $day, 0, $freqdata->{"unitsperissue"} ); + } elsif ( $subscription->{countissuesperunit} < $freqdata->{issuesperunit} ) { + # Add rounded number of days based on frequency. + @newissue = Add_Delta_Days( $year, $month, $day, $delta_days ); + $subscription->{countissuesperunit}++; + } else { + # We finished a cycle of issues within a unit. + # Subtract delta * (issues - 1), add 1 month + @newissue = Add_Delta_Days( $year, $month, $day, + -$delta_days * ($freqdata->{issuesperunit} - 1) ); + @newissue = Add_Delta_YM( @newissue, 0, 1 ); + $subscription->{countissuesperunit} = 1; + } + return @newissue; +} + +sub _get_next_date_year { + my ($subscription, $freqdata, $year, $month, $day) = @_; + + my @newissue; # ( yy, mm, dd ) + my $delta_days = int( 365 / $freqdata->{issuesperunit} ); + + if( $freqdata->{issuesperunit} == 1 ) { + # Add full years + @newissue = Add_Delta_YM( $year, $month, $day, $freqdata->{"unitsperissue"}, 0 ); + } elsif ( $subscription->{countissuesperunit} < $freqdata->{issuesperunit} ) { + # Add rounded number of days based on frequency. + @newissue = Add_Delta_Days( $year, $month, $day, $delta_days ); + $subscription->{countissuesperunit}++; + } else { + # We finished a cycle of issues within a unit. + # Subtract delta * (issues - 1), add 1 year + @newissue = Add_Delta_Days( $year, $month, $day, -$delta_days * ($freqdata->{issuesperunit} - 1) ); + @newissue = Add_Delta_YM( @newissue, 1, 0 ); + $subscription->{countissuesperunit} = 1; + } + return @newissue; +} + =head2 GetNextDate -$resultdate = GetNextDate($publisheddate,$subscription) +$resultdate = GetNextDate($publisheddate,$subscription,$freqdata,$updatecount) this function it takes the publisheddate and will return the next issue's date and will skip dates if there exists an irregularity. $publisheddate has to be an ISO date -$subscription is a hashref containing at least 'periodicity', 'firstacquidate', 'irregularity', and 'countissuesperunit' +$subscription is a hashref containing at least 'firstacquidate', 'irregularity', and 'countissuesperunit' +$frequency is a hashref containing frequency informations $updatecount is a boolean value which, when set to true, update the 'countissuesperunit' in database - eg if periodicity is monthly and $publisheddate is 2007-02-10 but if March and April is to be skipped then the returned date will be 2007-05-10 @@ -2530,11 +2311,10 @@ Return undef if subscription is irregular =cut sub GetNextDate { - my ( $subscription, $publisheddate, $updatecount ) = @_; + my ( $subscription, $publisheddate, $freqdata, $updatecount ) = @_; return unless $subscription and $publisheddate; - my $freqdata = GetSubscriptionFrequency($subscription->{'periodicity'}); if ($freqdata->{'unit'}) { my ( $year, $month, $day ) = split /-/, $publisheddate; @@ -2544,121 +2324,57 @@ 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 # It is used to check if next issue is an irregular issue. - my $issueno = GetFictiveIssueNumber($subscription, $publisheddate) + 1; + my $issueno = GetFictiveIssueNumber($subscription, $publisheddate, $freqdata) + 1; # Then get the next date my $unit = lc $freqdata->{'unit'}; if ($unit eq 'day') { while ($irregularities{$issueno}) { - if ($subscription->{'countissuesperunit'} + 1 > $freqdata->{'issuesperunit'}){ - ($year,$month,$day) = Add_Delta_Days($year,$month, $day , $freqdata->{'unitsperissue'} ); - $subscription->{'countissuesperunit'} = 1; - } else { - $subscription->{'countissuesperunit'}++; - } + ($year, $month, $day) = _get_next_date_day($subscription, + $freqdata, $year, $month, $day); $issueno++; } - if ($subscription->{'countissuesperunit'} + 1 > $freqdata->{'issuesperunit'}){ - ($year,$month,$day) = Add_Delta_Days($year,$month, $day , $freqdata->{"unitsperissue"} ); - $subscription->{'countissuesperunit'} = 1; - } else { - $subscription->{'countissuesperunit'}++; - } + ($year, $month, $day) = _get_next_date_day($subscription, $freqdata, + $year, $month, $day); } elsif ($unit eq 'week') { - my ($wkno, $yr) = Week_of_Year($year, $month, $day); while ($irregularities{$issueno}) { - if ($subscription->{'countissuesperunit'} + 1 > $freqdata->{'issuesperunit'}){ - $subscription->{'countissuesperunit'} = 1; - $wkno += $freqdata->{"unitsperissue"}; - if($wkno > 52){ - $wkno = $wkno % 52; - $yr++; - } - my $dow = Day_of_Week($year, $month, $day); - ($year,$month,$day) = Monday_of_Week($wkno, $yr); - if($freqdata->{'issuesperunit'} == 1) { - ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $dow - 1); - } - } else { - $subscription->{'countissuesperunit'}++; - } + ($year, $month, $day) = _get_next_date_week($subscription, + $freqdata, $year, $month, $day); $issueno++; } - if ($subscription->{'countissuesperunit'} + 1 > $freqdata->{'issuesperunit'}){ - $subscription->{'countissuesperunit'} = 1; - $wkno += $freqdata->{"unitsperissue"}; - if($wkno > 52){ - $wkno = $wkno % 52 ; - $yr++; - } - my $dow = Day_of_Week($year, $month, $day); - ($year,$month,$day) = Monday_of_Week($wkno, $yr); - if($freqdata->{'issuesperunit'} == 1) { - ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $dow - 1); - } - } else { - $subscription->{'countissuesperunit'}++; - } + ($year, $month, $day) = _get_next_date_week($subscription, + $freqdata, $year, $month, $day); } elsif ($unit eq 'month') { while ($irregularities{$issueno}) { - if ($subscription->{'countissuesperunit'} + 1 > $freqdata->{'issuesperunit'}){ - $subscription->{'countissuesperunit'} = 1; - ($year,$month,$day) = Add_Delta_YM($year,$month,$day, 0,$freqdata->{"unitsperissue"}); - unless($freqdata->{'issuesperunit'} == 1) { - $day = 1; # Jumping to the first day of month, because we don't know what day is expected - } - } else { - $subscription->{'countissuesperunit'}++; - } + ($year, $month, $day) = _get_next_date_month($subscription, + $freqdata, $year, $month, $day); $issueno++; } - if ($subscription->{'countissuesperunit'} + 1 > $freqdata->{'issuesperunit'}){ - $subscription->{'countissuesperunit'} = 1; - ($year,$month,$day) = Add_Delta_YM($year,$month,$day, 0,$freqdata->{"unitsperissue"}); - unless($freqdata->{'issuesperunit'} == 1) { - $day = 1; # Jumping to the first day of month, because we don't know what day is expected - } - } else { - $subscription->{'countissuesperunit'}++; - } + ($year, $month, $day) = _get_next_date_month($subscription, + $freqdata, $year, $month, $day); } elsif ($unit eq 'year') { while ($irregularities{$issueno}) { - if ($subscription->{'countissuesperunit'} + 1 > $freqdata->{'issuesperunit'}){ - $subscription->{'countissuesperunit'} = 1; - ($year,$month,$day) = Add_Delta_YM($year,$month,$day, $freqdata->{"unitsperissue"},0); - unless($freqdata->{'issuesperunit'} == 1) { - # Jumping to the first day of year, because we don't know what day is expected - $month = 1; - $day = 1; - } - } else { - $subscription->{'countissuesperunit'}++; - } + ($year, $month, $day) = _get_next_date_year($subscription, + $freqdata, $year, $month, $day); $issueno++; } - if ($subscription->{'countissuesperunit'} + 1 > $freqdata->{'issuesperunit'}){ - $subscription->{'countissuesperunit'} = 1; - ($year,$month,$day) = Add_Delta_YM($year,$month,$day, $freqdata->{"unitsperissue"},0); - unless($freqdata->{'issuesperunit'} == 1) { - # Jumping to the first day of year, because we don't know what day is expected - $month = 1; - $day = 1; - } - } else { - $subscription->{'countissuesperunit'}++; - } + ($year, $month, $day) = _get_next_date_year($subscription, + $freqdata, $year, $month, $day); } + if ($updatecount){ my $dbh = C4::Context->dbh; my $query = qq{ @@ -2669,6 +2385,7 @@ sub GetNextDate { my $sth = $dbh->prepare($query); $sth->execute($subscription->{'countissuesperunit'}, $subscription->{'subscriptionid'}); } + return sprintf("%04d-%02d-%02d", $year, $month, $day); } } @@ -2680,84 +2397,68 @@ sub GetNextDate { _numeration returns the string corresponding to $value in the num_type num_type can take : -dayname + -dayabrv -monthname + -monthabrv -season -=cut + -seasonabrv -#' +=cut 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$/ or $num_type =~ /^dayabrv$/ ) { + # 1970-11-01 was a Sunday + $value = $value % 7; + my $dt = DateTime->new( + year => 1970, + month => 11, + day => $value + 1, + locale => $locale, + ); + $string = $num_type =~ /^dayname$/ + ? $dt->strftime("%A") + : $dt->strftime("%a"); + } elsif ( $num_type =~ /^monthname$/ or $num_type =~ /^monthabrv$/ ) { + $value = $value % 12; + my $dt = DateTime->new( + year => 1970, + month => $value + 1, + locale => $locale, + ); + $string = $num_type =~ /^monthname$/ + ? $dt->strftime("%B") + : $dt->strftime("%b"); + } elsif ( $num_type =~ /^season$/ ) { + my @seasons= qw( Spring Summer Fall Winter ); + $value = $value % 4; + $string = $seasons[$value]; + } elsif ( $num_type =~ /^seasonabrv$/ ) { + my @seasonsabrv= qw( Spr Sum Fal Win ); + $value = $value % 4; + $string = $seasonsabrv[$value]; + } else { + $string = $value; } + return $string; } -=head2 is_barcode_in_use +=head2 CloseSubscription -Returns number of occurence of the barcode in the items table -Can be used as a boolean test of whether the barcode has -been deployed as yet +Close a subscription given a subscriptionid =cut -sub is_barcode_in_use { - my $barcode = shift; - my $dbh = C4::Context->dbh; - my $occurences = $dbh->selectall_arrayref( - 'SELECT itemnumber from items where barcode = ?', - {}, $barcode - - ); - - return @{$occurences}; -} - -=head2 CloseSubscription -Close a subscription given a subscriptionid -=cut 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 = ? @@ -2765,23 +2466,26 @@ 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 + Reopen a subscription given a subscriptionid + =cut + 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 = ? @@ -2789,13 +2493,13 @@ 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 @@ -2820,6 +2524,19 @@ sub subscriptionCurrentlyOnOrder { return $sth->fetchrow_array; } +=head2 can_claim_subscription + + $can = can_claim_subscription( $subscriptionid[, $userid] ); + +Return 1 if the subscription can be claimed by the current logged user (or a given $userid), else 0. + +=cut + +sub can_claim_subscription { + my ( $subscription, $userid ) = @_; + return _can_do_on_subscription( $subscription, $userid, 'claim_serials' ); +} + =head2 can_edit_subscription $can = can_edit_subscription( $subscriptionid[, $userid] ); @@ -2879,6 +2596,25 @@ sub _can_do_on_subscription { return 0; } +=head2 findSerialsByStatus + + @serials = findSerialsByStatus($status, $subscriptionid); + + Returns an array of serials matching a given status and subscription id. + +=cut + +sub findSerialsByStatus { + my ( $status, $subscriptionid ) = @_; + my $dbh = C4::Context->dbh; + my $query = q| SELECT * from serial + WHERE status = ? + AND subscriptionid = ? + |; + my $serials = $dbh->selectall_arrayref( $query, { Slice => {} }, $status, $subscriptionid ); + return @$serials; +} + 1; __END__