X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=C4%2FSerials.pm;h=f8c17b918950e83b95e23b426901a0bfbb48579e;hb=refs%2Fheads%2Fkoha_ffzg;hp=83884d4f613123c75993d55b7a6c82536d78b01b;hpb=89bfc422e6b229aeadae4efc3c9a9182e64e19ea;p=koha.git diff --git a/C4/Serials.pm b/C4/Serials.pm index 83884d4f61..f8c17b9189 100644 --- a/C4/Serials.pm +++ b/C4/Serials.pm @@ -22,7 +22,6 @@ 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); @@ -31,8 +30,14 @@ use C4::Log; # logaction use C4::Debug; use C4::Serials::Frequency; use C4::Serials::Numberpattern; +use Koha::AdditionalFieldValues; +use Koha::DateUtils; +use Koha::Serial; +use Koha::Subscriptions; +use Koha::Subscription::Histories; +use Koha::SharedContent; -use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); +use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); # Define statuses use constant { @@ -57,7 +62,6 @@ use constant MISSING_STATUSES => ( ); BEGIN { - $VERSION = 3.07.00.049; # set version for version checking require Exporter; @ISA = qw(Exporter); @EXPORT = qw( @@ -68,21 +72,19 @@ BEGIN { &HasSubscriptionStrictlyExpired &HasSubscriptionExpired &GetExpirationDate &abouttoexpire &GetSubscriptionHistoryFromSubscriptionId - &GetNextSeq &GetSeq &NewIssue &ItemizeSerials &GetSerials + &GetNextSeq &GetSeq &NewIssue &GetSerials &GetLatestSerials &ModSerialStatus &GetNextDate &GetSerials2 &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 ); @@ -160,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) @@ -258,40 +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 = ?, - claims_count = claims_count + 1 - WHERE serialid in (" . join( ",", map { '?' } @$serialids ) . ") - "; - my $rq = $dbh->prepare($query); - $rq->execute($date, CLAIMED, @$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 @@ -316,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; } @@ -338,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, @@ -359,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; } @@ -456,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; @@ -466,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'} ); @@ -494,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, @@ -513,8 +483,9 @@ 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; } @@ -548,7 +519,19 @@ subscription expiration date. sub SearchSubscriptions { my ( $args ) = @_; - my $query = q{ + 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, subscriptionhistory.*, @@ -557,19 +540,22 @@ sub SearchSubscriptions { 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); @@ -618,8 +604,14 @@ 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}; @@ -627,12 +619,16 @@ sub SearchSubscriptions { 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; @@ -662,7 +658,8 @@ sub GetSerials { $count = 5 unless ($count); my @serials; my $statuses = join( ',', ( ARRIVED, MISSING_STATUSES, NOT_ISSUED ) ); - my $query = "SELECT serialid,serialseq, status, publisheddate, planneddate,notes, routingnotes + my $query = "SELECT serialid,serialseq, status, publisheddate, + publisheddatetext, planneddate,notes, routingnotes FROM serial WHERE subscriptionid = ? AND status NOT IN ( $statuses ) ORDER BY IF(publisheddate<>'0000-00-00',publisheddate,planneddate) DESC"; @@ -673,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{}; } @@ -682,7 +679,8 @@ 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 ( $statuses ) @@ -695,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{}; } @@ -718,7 +716,7 @@ 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. +$statuses is an arrayref of statuses and is mandatory. =cut @@ -727,18 +725,20 @@ sub GetSerials2 { 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 + my $query = q| + SELECT serialid,serialseq, status, planneddate, publisheddate, + publisheddatetext, notes, routingnotes FROM serial - WHERE subscriptionid=$subscription AND status IN ($statuses_string) + 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 ) { @@ -749,7 +749,7 @@ sub GetSerials2 { $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; @@ -785,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) = @_; - - return unless ($subscriptionid); + my $return = undef; - 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 @@ -818,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); @@ -843,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++; @@ -986,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} ) { @@ -1059,7 +1071,8 @@ sub ModSubscriptionHistory { =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 @@ -1067,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); @@ -1089,9 +1103,15 @@ sub ModSerialStatus { 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); @@ -1125,31 +1145,34 @@ sub ModSerialStatus { } } - # create new waited entry if needed (ie : was a "waited" and has changed) - if ( $oldstatus == EXPECTED && $status != EXPECTED ) { + # 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 == ARRIVED && $oldstatus != ARRIVED ) { require C4::Letters; - C4::Letters::SendAlerts( 'issue', $subscription->{subscriptionid}, $subscription->{letter} ); + C4::Letters::SendAlerts( 'issue', $serialid, $subscription->{letter} ); } } @@ -1284,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; @@ -1297,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); @@ -1311,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; @@ -1326,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. @@ -1343,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; @@ -1356,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( @@ -1367,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'}; @@ -1385,8 +1413,8 @@ sub NewSubscription { # then create the 1st expected number $query = qq( INSERT INTO subscriptionhistory - (biblionumber, subscriptionid, histstartdate) - VALUES (?,?,?) + (biblionumber, subscriptionid, histstartdate, missinglist, recievedlist) + VALUES (?,?,?, '', '') ); $sth = $dbh->prepare($query); $sth->execute( $biblionumber, $subscriptionid, $startdate); @@ -1397,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, EXPECTED, $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; } @@ -1455,6 +1490,9 @@ sub ReNewSubscription { ); } + $numberlength ||= 0; # Should not we raise an exception instead? + $weeklength ||= 0; + # renew subscription $query = qq| UPDATE subscription @@ -1472,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; @@ -1495,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 == 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); + ### 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 ( grep {/^$status$/} ( MISSING_STATUSES ) ) { - $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 ); - - 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}; - } - } + $subscription_history->recievedlist($recievedlist); + $subscription_history->missinglist($missinglist); + $subscription_history->store(); - 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 @@ -1775,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) @@ -1805,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"); } @@ -1877,6 +1765,7 @@ sub GetLateOrMissingIssues { return unless ( $supplierid or $serialid ); my $dbh = C4::Context->dbh; + my $sth; my $byserial = ''; if ($serialid) { @@ -1929,57 +1818,21 @@ sub GetLateOrMissingIssues { if ($line->{planneddate} && $line->{planneddate} !~/^0+\-/) { $line->{planneddateISO} = $line->{planneddate}; - $line->{planneddate} = format_date( $line->{planneddate} ); + $line->{planneddate} = output_pref( { dt => dt_from_string( $line->{"planneddate"} ), dateonly => 1 } ); } if ($line->{claimdate} && $line->{claimdate} !~/^0+\-/) { $line->{claimdateISO} = $line->{claimdate}; - $line->{claimdate} = format_date( $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 - -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 ) = @_; + my $subscription_object = Koha::Subscriptions->find($line->{subscriptionid}); + $line->{additional_fields} = { map { $_->field->name => $_->value } + $subscription_object->additional_field_values->as_list }; - 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 @@ -1993,42 +1846,19 @@ called from claims.pl file =cut sub updateClaim { - my ($serialid) = @_; - my $dbh = C4::Context->dbh; - $dbh->do(q| + 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 - WHERE serialid = ? - |, {}, $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; + claims_count = claims_count + 1, + status = ? + WHERE serialid in (| . join( q|,|, (q|?|) x @$serialids ) . q|)|, + {}, CLAIMED, @$serialids ); } =head2 check_routing @@ -2277,7 +2107,7 @@ sub abouttoexpire { my $expirationdate = GetExpirationDate($subscriptionid); my ($res) = $dbh->selectrow_array('select max(planneddate) from serial where subscriptionid = ?', undef, $subscriptionid); - my $nextdate = GetNextDate($subscription, $res); + my $nextdate = GetNextDate($subscription, $res, $frequency); # only compare dates if both dates exist. if ($nextdate and $expirationdate) { @@ -2296,54 +2126,9 @@ sub abouttoexpire { 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... @@ -2354,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 @@ -2412,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; @@ -2436,113 +2334,47 @@ sub GetNextDate { # 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{ @@ -2553,6 +2385,7 @@ sub GetNextDate { my $sth = $dbh->prepare($query); $sth->execute($subscription->{'countissuesperunit'}, $subscription->{'subscriptionid'}); } + return sprintf("%04d-%02d-%02d", $year, $month, $day); } } @@ -2564,11 +2397,13 @@ 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) = @_; @@ -2576,7 +2411,7 @@ sub _numeration { $num_type //= ''; $locale ||= 'en'; my $string; - if ( $num_type =~ /^dayname$/ ) { + if ( $num_type =~ /^dayname$/ or $num_type =~ /^dayabrv$/ ) { # 1970-11-01 was a Sunday $value = $value % 7; my $dt = DateTime->new( @@ -2585,19 +2420,27 @@ sub _numeration { day => $value + 1, locale => $locale, ); - $string = $dt->strftime("%A"); - } elsif ( $num_type =~ /^monthname$/ ) { + $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 = $dt->strftime("%B"); + $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; } @@ -2605,29 +2448,12 @@ sub _numeration { 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; @@ -2650,8 +2476,11 @@ sub CloseSubscription { } =head2 ReopenSubscription + Reopen a subscription given a subscriptionid + =cut + sub ReopenSubscription { my ( $subscriptionid ) = @_; return unless $subscriptionid; @@ -2695,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] ); @@ -2754,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__