X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=C4%2FSerials.pm;h=75c9d7f19fd845204994e440f911acf79a5acef9;hb=eded6edacc5e3bf8dd0be21ed05842c3b78aadce;hp=c001f9025336cfb3cd7887e19b6af6734468eb7e;hpb=e8b2f04638ca4bcccf85d53f8c540c43b7615716;p=koha-ffzg.git diff --git a/C4/Serials.pm b/C4/Serials.pm index c001f90253..75c9d7f19f 100644 --- a/C4/Serials.pm +++ b/C4/Serials.pm @@ -20,20 +20,29 @@ package C4::Serials; use Modern::Perl; -use C4::Auth qw(haspermission); +use C4::Auth qw( haspermission ); use C4::Context; use DateTime; -use Date::Calc qw(:all); -use POSIX qw(strftime); -use C4::Biblio; -use C4::Log; # logaction -use C4::Debug; -use C4::Serials::Frequency; +use Date::Calc qw( + Add_Delta_Days + Add_Delta_YM + check_date + Delta_Days + N_Delta_YMD + Today +); +use POSIX qw( strftime ); +use C4::Biblio qw( GetMarcFromKohaField ModBiblio ); +use C4::Log qw( logaction ); # logaction +use C4::Serials::Frequency qw( GetSubscriptionFrequency ); use C4::Serials::Numberpattern; -use Koha::AdditionalField; -use Koha::DateUtils; - -use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); +use Koha::AdditionalFieldValues; +use Koha::Biblios; +use Koha::Serial; +use Koha::Subscriptions; +use Koha::Subscription::Histories; +use Koha::SharedContent; +use Scalar::Util qw( looks_like_number ); # Define statuses use constant { @@ -57,34 +66,39 @@ use constant MISSING_STATUSES => ( MISSING_LOST ); +our (@ISA, @EXPORT_OK); BEGIN { - $VERSION = 3.07.00.049; # set version for version checking require Exporter; @ISA = qw(Exporter); - @EXPORT = qw( - &NewSubscription &ModSubscription &DelSubscription - &GetSubscription &CountSubscriptionFromBiblionumber &GetSubscriptionsFromBiblionumber - &SearchSubscriptions - &GetFullSubscriptionsFromBiblionumber &GetFullSubscription &ModSubscriptionHistory - &HasSubscriptionStrictlyExpired &HasSubscriptionExpired &GetExpirationDate &abouttoexpire - &GetSubscriptionHistoryFromSubscriptionId - - &GetNextSeq &GetSeq &NewIssue &GetSerials - &GetLatestSerials &ModSerialStatus &GetNextDate &GetSerials2 - &ReNewSubscription &GetLateOrMissingIssues - &GetSerialInformation &AddItem2Serial - &PrepareSerialsData &GetNextExpected &ModNextExpected - - &UpdateClaimdateIssues - &GetSuppliersWithLateIssues &getsupplierbyserialid - &GetDistributedTo &SetDistributedTo - &getroutinglist &delroutingmember &addroutingmember - &reorder_members - &check_routing &updateClaim - &CountIssues + @EXPORT_OK = qw( + NewSubscription ModSubscription DelSubscription + GetSubscription CountSubscriptionFromBiblionumber GetSubscriptionsFromBiblionumber + SearchSubscriptions + GetFullSubscriptionsFromBiblionumber GetFullSubscription ModSubscriptionHistory + HasSubscriptionStrictlyExpired HasSubscriptionExpired GetExpirationDate abouttoexpire + GetFictiveIssueNumber + GetSubscriptionHistoryFromSubscriptionId + + GetNextSeq GetSeq NewIssue GetSerials + GetLatestSerials ModSerialStatus GetNextDate + CloseSubscription ReopenSubscription + subscriptionCurrentlyOnOrder + can_claim_subscription can_edit_subscription can_show_subscription + GetSerials2 + GetSubscriptionLength ReNewSubscription GetLateOrMissingIssues + GetSerialInformation AddItem2Serial + PrepareSerialsData GetNextExpected ModNextExpected + GetSubscriptionIrregularities + GetPreviousSerialid + + GetSuppliersWithLateIssues + getroutinglist delroutingmember addroutingmember + reorder_members + check_routing updateClaim + CountIssues HasItems - &GetSubscriptionsFromBorrower - &subscriptionCurrentlyOnOrder + + findSerialsByStatus ); } @@ -161,29 +175,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) @@ -216,7 +209,6 @@ sub GetSerialInformation { #It is ASSUMED that GetMarcItem ALWAYS WORK... #Maybe GetMarcItem should return values on failure - $debug and warn "itemnumber :$itemnum->[0], bibnum :" . $data->{'biblionumber'}; my $itemprocessed = C4::Items::PrepareItemrecordDisplay( $data->{'biblionumber'}, $itemnum->[0], $data ); $itemprocessed->{'itemnumber'} = $itemnum->[0]; $itemprocessed->{'itemid'} = $itemnum->[0]; @@ -259,40 +251,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 @@ -305,6 +269,7 @@ sub GetSubscription { subscriptionhistory.*, aqbooksellers.name AS aqbooksellername, biblio.title AS bibliotitle, + biblio.subtitle AS bibliosubtitle, subscription.biblionumber as bibnum FROM subscription LEFT JOIN subscriptionhistory ON subscription.subscriptionid=subscriptionhistory.subscriptionid @@ -313,19 +278,19 @@ sub GetSubscription { WHERE subscription.subscriptionid = ? ); - $debug and warn "query : $query\nsubsid :$subscriptionid"; my $sth = $dbh->prepare($query); $sth->execute($subscriptionid); my $subscription = $sth->fetchrow_hashref; + return unless $subscription; + $subscription->{cannotedit} = not can_edit_subscription( $subscription ); - # Add additional fields to the subscription into a new key "additional_fields" - my $additional_field_values = Koha::AdditionalField->fetch_all_values({ - tablename => 'subscription', - record_id => $subscriptionid, - }); - $subscription->{additional_fields} = $additional_field_values->{$subscriptionid}; + 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; } @@ -351,7 +316,7 @@ sub GetFullSubscription { serial.publisheddatetext, serial.status, serial.notes as notes, - year(IF(serial.publisheddate="00-00-0000",serial.planneddate,serial.publisheddate)) as year, + year(IF(serial.publisheddate IS NULL,serial.planneddate,serial.publisheddate)) as year, aqbooksellers.name as aqbooksellername, biblio.title as bibliotitle, subscription.branchcode AS branchcode, @@ -363,16 +328,19 @@ sub GetFullSubscription { LEFT JOIN biblio on biblio.biblionumber=subscription.biblionumber WHERE serial.subscriptionid = ? ORDER BY year DESC, - IF(serial.publisheddate="00-00-0000",serial.planneddate,serial.publisheddate) DESC, + IF(serial.publisheddate IS NULL,serial.planneddate,serial.publisheddate) DESC, serial.subscriptionid |; - $debug and warn "GetFullSubscription query: $query"; my $sth = $dbh->prepare($query); $sth->execute($subscriptionid); my $subscriptions = $sth->fetchall_arrayref( {} ); - for my $subscription ( @$subscriptions ) { - $subscription->{cannotedit} = not can_edit_subscription( $subscription ); + if (scalar @$subscriptions) { + my $cannotedit = not can_edit_subscription( $subscriptions->[0] ); + for my $subscription ( @$subscriptions ) { + $subscription->{cannotedit} = $cannotedit; + } } + return $subscriptions; } @@ -392,19 +360,10 @@ sub PrepareSerialsData { my $year; my @res; my $startdate; - my $aqbooksellername; - my $bibliotitle; - my @loopissues; my $first; my $previousnote = ""; foreach my $subs (@{$lines}) { - for my $datefield ( qw(publisheddate planneddate) ) { - # handle 0000-00-00 dates - if (defined $subs->{$datefield} and $subs->{$datefield} =~ m/^00/) { - $subs->{$datefield} = undef; - } - } $subs->{ "status" . $subs->{'status'} } = 1; if ( grep { $_ == $subs->{status} } ( EXPECTED, LATE, MISSING_STATUSES, CLAIMED ) ) { $subs->{"checked"} = 1; @@ -467,21 +426,11 @@ sub GetSubscriptionsFromBiblionumber { $sth->execute($biblionumber); my @res; while ( my $subs = $sth->fetchrow_hashref ) { - $subs->{startdate} = output_pref( { dt => dt_from_string( $subs->{startdate} ), dateonly => 1 } ); - $subs->{histstartdate} = output_pref( { dt => dt_from_string( $subs->{histstartdate} ), dateonly => 1 } ); - $subs->{histenddate} = output_pref( { dt => dt_from_string( $subs->{histenddate} ), dateonly => 1 } ); - $subs->{opacnote} =~ s/\n/\/g; - $subs->{missinglist} =~ s/\n/\/g; - $subs->{recievedlist} =~ s/\n/\/g; + $subs->{opacnote} //= ""; $subs->{ "periodicity" . $subs->{periodicity} } = 1; $subs->{ "numberpattern" . $subs->{numberpattern} } = 1; $subs->{ "status" . $subs->{'status'} } = 1; - if ( $subs->{enddate} eq '0000-00-00' ) { - $subs->{enddate} = ''; - } else { - $subs->{enddate} = output_pref( { dt => dt_from_string( $subs->{enddate}), dateonly => 1 } ); - } $subs->{'abouttoexpire'} = abouttoexpire( $subs->{'subscriptionid'} ); $subs->{'subscriptionexpired'} = HasSubscriptionExpired( $subs->{'subscriptionid'} ); $subs->{cannotedit} = not can_edit_subscription( $subs ); @@ -508,10 +457,11 @@ sub GetFullSubscriptionsFromBiblionumber { serial.publisheddatetext, serial.status, serial.notes as notes, - year(IF(serial.publisheddate="00-00-0000",serial.planneddate,serial.publisheddate)) as year, + year(IF(serial.publisheddate IS NULL,serial.planneddate,serial.publisheddate)) as year, biblio.title as bibliotitle, subscription.branchcode AS branchcode, - subscription.subscriptionid AS subscriptionid + subscription.subscriptionid AS subscriptionid, + subscription.location AS location FROM serial LEFT JOIN subscription ON (serial.subscriptionid=subscription.subscriptionid) @@ -519,15 +469,19 @@ sub GetFullSubscriptionsFromBiblionumber { LEFT JOIN biblio on biblio.biblionumber=subscription.biblionumber WHERE subscription.biblionumber = ? ORDER BY year DESC, - IF(serial.publisheddate="00-00-0000",serial.planneddate,serial.publisheddate) DESC, + IF(serial.publisheddate IS NULL,serial.planneddate,serial.publisheddate) DESC, serial.subscriptionid |; my $sth = $dbh->prepare($query); $sth->execute($biblionumber); my $subscriptions = $sth->fetchall_arrayref( {} ); - for my $subscription ( @$subscriptions ) { - $subscription->{cannotedit} = not can_edit_subscription( $subscription ); + if (scalar @$subscriptions) { + my $cannotedit = not can_edit_subscription( $subscriptions->[0] ); + for my $subscription ( @$subscriptions ) { + $subscription->{cannotedit} = $cannotedit; + } } + return $subscriptions; } @@ -563,12 +517,13 @@ sub SearchSubscriptions { my $additional_fields = $args->{additional_fields} // []; my $matching_record_ids_for_additional_fields = []; if ( @$additional_fields ) { - $matching_record_ids_for_additional_fields = Koha::AdditionalField->get_matching_record_ids({ - fields => $additional_fields, - tablename => 'subscription', - exact_match => 0, - }); - return () unless @$matching_record_ids_for_additional_fields; + my @subscriptions = Koha::Subscriptions->filter_by_additional_fields($additional_fields)->as_list; + + return () unless @subscriptions; + + $matching_record_ids_for_additional_fields = [ map { + $_->subscriptionid + } @subscriptions ]; } my $query = q| @@ -578,8 +533,10 @@ sub SearchSubscriptions { subscription.*, biblio.notes AS biblionotes, biblio.title, + biblio.subtitle, biblio.author, biblio.biblionumber, + aqbooksellers.name AS vendorname, biblioitems.issn FROM subscription LEFT JOIN subscriptionhistory USING(subscriptionid) @@ -664,11 +621,10 @@ sub SearchSubscriptions { $subscription->{cannotedit} = not can_edit_subscription( $subscription ); $subscription->{cannotdisplay} = not can_show_subscription( $subscription ); - my $additional_field_values = Koha::AdditionalField->fetch_all_values({ - record_id => $subscription->{subscriptionid}, - tablename => 'subscription' - }); - $subscription->{additional_fields} = $additional_field_values->{$subscription->{subscriptionid}}; + my $subscription_object = Koha::Subscriptions->find($subscription->{subscriptionid}); + $subscription->{additional_fields} = { map { $_->field->name => $_->value } + $subscription_object->additional_field_values->as_list }; + } return @$results; @@ -702,19 +658,12 @@ sub GetSerials { publisheddatetext, planneddate,notes, routingnotes FROM serial WHERE subscriptionid = ? AND status NOT IN ( $statuses ) - ORDER BY IF(publisheddate<>'0000-00-00',publisheddate,planneddate) DESC"; + ORDER BY IF(publisheddate IS NULL,planneddate,publisheddate) DESC"; my $sth = $dbh->prepare($query); $sth->execute($subscriptionid); while ( my $line = $sth->fetchrow_hashref ) { $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} = output_pref( { dt => dt_from_string( $line->{$datefield} ), dateonly => 1 } ); - } else { - $line->{$datefield} = q{}; - } - } push @serials, $line; } @@ -724,20 +673,13 @@ sub GetSerials { FROM serial WHERE subscriptionid = ? AND status IN ( $statuses ) - ORDER BY IF(publisheddate<>'0000-00-00',publisheddate,planneddate) DESC + ORDER BY IF(publisheddate IS NULL,planneddate,publisheddate) DESC "; $sth = $dbh->prepare($query); $sth->execute($subscriptionid); while ( ( my $line = $sth->fetchrow_hashref ) && $counter < $count ) { $counter++; $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} = output_pref( { dt => dt_from_string( $line->{$datefield} ), dateonly => 1 } ); - } else { - $line->{$datefield} = q{}; - } - } push @serials, $line; } @@ -765,32 +707,23 @@ sub GetSerials2 { return unless ($subscription and @$statuses); - my $statuses_string = join ',', @$statuses; - my $dbh = C4::Context->dbh; - my $query = qq| + 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 ) { $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 (!defined($line->{$datefield}) || $line->{$datefield} =~m/^00/) { - $line->{$datefield} = q{}; - } - else { - $line->{$datefield} = output_pref( { dt => dt_from_string( $line->{$datefield} ), dateonly => 1 } ); - } - } push @serials, $line; } return @serials; @@ -824,32 +757,41 @@ 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} = 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 @@ -857,19 +799,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 date sting in iso format. +$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); @@ -882,7 +825,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++; @@ -1025,7 +968,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} ) { @@ -1115,13 +1058,13 @@ sub ModSerialStatus { #It is a usual serial # 1st, get previous status : my $dbh = C4::Context->dbh; - my $query = "SELECT serial.subscriptionid,serial.status,subscription.periodicity + my $query = "SELECT serial.subscriptionid,serial.status,subscription.periodicity,serial.routingnotes FROM serial, subscription WHERE serial.subscriptionid=subscription.subscriptionid AND serialid=?"; my $sth = $dbh->prepare($query); $sth->execute($serialid); - my ( $subscriptionid, $oldstatus, $periodicity ) = $sth->fetchrow; + my ( $subscriptionid, $oldstatus, $periodicity, $routingnotes ) = $sth->fetchrow; my $frequency = GetSubscriptionFrequency($periodicity); # change status & update subscriptionhistory @@ -1129,16 +1072,15 @@ sub ModSerialStatus { if ( $status == DELETED ) { DelIssue( { 'serialid' => $serialid, 'subscriptionid' => $subscriptionid, 'serialseq' => $serialseq } ); } else { - my $query = ' UPDATE serial SET serialseq = ?, publisheddate = ?, publisheddatetext = ?, - planneddate = ?, status = ?, notes = ? + planneddate = ?, status = ?, notes = ?, routingnotes = ? WHERE serialid = ? '; $sth = $dbh->prepare($query); $sth->execute( $serialseq, $publisheddate, $publisheddatetext, - $planneddate, $status, $notes, $serialid ); + $planneddate, $status, $notes, $routingnotes, $serialid ); $query = "SELECT * FROM subscription WHERE subscriptionid = ?"; $sth = $dbh->prepare($query); $sth->execute($subscriptionid); @@ -1150,19 +1092,16 @@ sub ModSerialStatus { my ( $missinglist, $recievedlist ) = $sth->fetchrow; if ( $status == ARRIVED || ($oldstatus == ARRIVED && $status != ARRIVED) ) { - $recievedlist .= "; $serialseq" - if ($recievedlist !~ /(^|;)\s*$serialseq(?=;|$)/); + $recievedlist = _handle_seqno($serialseq, $recievedlist); } # in case serial has been previously marked as missing if (grep /$status/, (EXPECTED, ARRIVED, LATE, CLAIMED)) { - $missinglist=~ s/(^|;)\s*$serialseq(?=;|$)//g; + $missinglist = _handle_seqno($serialseq, $missinglist, 'REMOVE'); } - $missinglist .= "; $serialseq" - if ( ( grep { $_ == $status } ( MISSING_STATUSES ) ) && ( $missinglist !~/(^|;)\s*$serialseq(?=;|$)/ ) ); - $missinglist .= "; not issued $serialseq" - if ( $status == NOT_ISSUED && $missinglist !~ /(^|;)\s*$serialseq(?=;|$)/ ); + $missinglist = _handle_seqno($serialseq, $missinglist) if grep { $_ == $status } MISSING_STATUSES; + $missinglist .= "; not issued $serialseq" if $status == NOT_ISSUED and not _handle_seqno($serialseq, $missinglist, 'CHECK'); $query = "UPDATE subscriptionhistory SET recievedlist=?, missinglist=? WHERE subscriptionid=?"; $sth = $dbh->prepare($query); @@ -1172,27 +1111,29 @@ 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 ); - + my $newnote = C4::Context->preference('PreserveSerialNotes') ? $notes : ""; + NewIssue( $newserialseq, $subscriptionid, $subscription->{'biblionumber'}, 1, $nextpubdate, $nextpubdate, undef, $newnote, $routingnotes ); # check if an alert must be sent... (= a letter is defined & status became "arrived" if ( $subscription->{letter} && $status == ARRIVED && $oldstatus != ARRIVED ) { require C4::Letters; @@ -1203,6 +1144,24 @@ sub ModSerialStatus { return; } +sub _handle_seqno { +# Adds or removes seqno from list when needed; returns list +# Or checks and returns true when present + + my ( $seq, $list, $op ) = @_; # op = ADD | REMOVE | CHECK (default: ADD) + my $seq_r = $seq; + $seq_r =~ s/([()])/\\$1/g; # Adjust disturbing parentheses for regex, maybe extend in future + + if( !$op or $op eq 'ADD' ) { + $list .= "; $seq" if $list !~ /(^|;)\s*$seq_r(?=;|$)/; + } elsif( $op eq 'REMOVE' ) { + $list=~ s/(^|;)\s*(not issued )?$seq_r(?=;|$)//g; + } else { # CHECK + return $list =~ /(^|;)\s*$seq_r(?=;|$)/ ? 1 : q{}; + } + return $list; +} + =head2 GetNextExpected $nextexpected = GetNextExpected($subscriptionid) @@ -1247,13 +1206,8 @@ sub GetNextExpected { $nextissue = $sth->fetchrow_hashref; } foreach(qw/planneddate publisheddate/) { - if ( !defined $nextissue->{$_} ) { - # or should this default to 1st Jan ??? - $nextissue->{$_} = strftime( '%Y-%m-%d', localtime ); - } - $nextissue->{$_} = ($nextissue->{$_} ne '0000-00-00') - ? $nextissue->{$_} - : undef; + # or should this default to 1st Jan ??? + $nextissue->{$_} //= strftime( '%Y-%m-%d', localtime ); } return $nextissue; @@ -1331,39 +1285,61 @@ 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, $ccode ) = @_; - my $dbh = C4::Context->dbh; - my $query = "UPDATE subscription - SET librarian=?, branchcode=?, aqbooksellerid=?, cost=?, aqbudgetid=?, - startdate=?, periodicity=?, firstacquidate=?, irregularity=?, - numberpattern=?, locale=?, numberlength=?, weeklength=?, monthlength=?, - lastvalue1=?, innerloop1=?, lastvalue2=?, innerloop2=?, - lastvalue3=?, innerloop3=?, status=?, biblionumber=?, - callnumber=?, notes=?, letter=?, manualhistory=?, - internalnotes=?, serialsadditems=?, staffdisplaycount=?, - opacdisplaycount=?, graceperiod=?, location = ?, enddate=?, - skip_serialseq=? - WHERE subscriptionid = ?"; - - my $sth = $dbh->prepare($query); - $sth->execute( - $auser, $branchcode, $aqbooksellerid, $cost, - $aqbudgetid, $startdate, $periodicity, $firstacquidate, - $irregularity, $numberpattern, $locale, $numberlength, - $weeklength, $monthlength, $lastvalue1, $innerloop1, - $lastvalue2, $innerloop2, $lastvalue3, $innerloop3, - $status, $biblionumber, $callnumber, $notes, - $letter, ($manualhistory ? $manualhistory : 0), - $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount, - $graceperiod, $location, $enddate, $skip_serialseq, - $subscriptionid - ); - my $rows = $sth->rows; + my $subscription = Koha::Subscriptions->find($subscriptionid); + $subscription->set( + { + librarian => $auser, + branchcode => $branchcode, + aqbooksellerid => $aqbooksellerid, + cost => $cost, + aqbudgetid => $aqbudgetid, + biblionumber => $biblionumber, + startdate => $startdate, + periodicity => $periodicity, + numberlength => $numberlength, + weeklength => $weeklength, + monthlength => $monthlength, + lastvalue1 => $lastvalue1, + innerloop1 => $innerloop1, + lastvalue2 => $lastvalue2, + innerloop2 => $innerloop2, + lastvalue3 => $lastvalue3, + innerloop3 => $innerloop3, + status => $status, + notes => $notes, + letter => $letter, + firstacquidate => $firstacquidate, + irregularity => $irregularity, + numberpattern => $numberpattern, + locale => $locale, + callnumber => $callnumber, + manualhistory => $manualhistory, + internalnotes => $internalnotes, + serialsadditems => $serialsadditems, + staffdisplaycount => $staffdisplaycount, + opacdisplaycount => $opacdisplaycount, + graceperiod => $graceperiod, + location => $location, + enddate => $enddate, + skip_serialseq => $skip_serialseq, + itemtype => $itemtype, + previousitemtype => $previousitemtype, + mana_id => $mana_id, + ccode => $ccode, + } + )->store; + # FIXME Must be $subscription->serials + # FIXME We shouldn't need serial.subscription (instead use serial->subscription->biblionumber) + Koha::Serials->search({ subscriptionid => $subscriptionid })->update({ biblionumber => $biblionumber }); logaction( "SERIAL", "MODIFY", $subscriptionid, "" ) if C4::Context->preference("SubscriptionLog"); - return $rows; + + $subscription->discard_changes; + return $subscription; } =head2 NewSubscription @@ -1373,7 +1349,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. @@ -1390,34 +1367,55 @@ 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, $ccode ) = @_; my $dbh = C4::Context->dbh; - #save subscription (insert into database) - my $query = qq| - INSERT INTO subscription - (librarian, branchcode, aqbooksellerid, cost, aqbudgetid, - biblionumber, startdate, periodicity, numberlength, weeklength, - monthlength, lastvalue1, innerloop1, lastvalue2, innerloop2, - lastvalue3, innerloop3, status, notes, letter, firstacquidate, - irregularity, numberpattern, locale, callnumber, - manualhistory, internalnotes, serialsadditems, staffdisplaycount, - opacdisplaycount, graceperiod, location, enddate, skip_serialseq) - VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) - |; - my $sth = $dbh->prepare($query); - $sth->execute( - $auser, $branchcode, $aqbooksellerid, $cost, $aqbudgetid, $biblionumber, - $startdate, $periodicity, $numberlength, $weeklength, - $monthlength, $lastvalue1, $innerloop1, $lastvalue2, $innerloop2, - $lastvalue3, $innerloop3, $status, $notes, $letter, - $firstacquidate, $irregularity, $numberpattern, $locale, $callnumber, - $manualhistory, $internalnotes, $serialsadditems, $staffdisplaycount, - $opacdisplaycount, $graceperiod, $location, $enddate, $skip_serialseq - ); - - my $subscriptionid = $dbh->{'mysql_insertid'}; + my $subscription = Koha::Subscription->new( + { + librarian => $auser, + branchcode => $branchcode, + aqbooksellerid => $aqbooksellerid, + cost => $cost, + aqbudgetid => $aqbudgetid, + biblionumber => $biblionumber, + startdate => $startdate, + periodicity => $periodicity, + numberlength => $numberlength, + weeklength => $weeklength, + monthlength => $monthlength, + lastvalue1 => $lastvalue1, + innerloop1 => $innerloop1, + lastvalue2 => $lastvalue2, + innerloop2 => $innerloop2, + lastvalue3 => $lastvalue3, + innerloop3 => $innerloop3, + status => $status, + notes => $notes, + letter => $letter, + firstacquidate => $firstacquidate, + irregularity => $irregularity, + numberpattern => $numberpattern, + locale => $locale, + callnumber => $callnumber, + manualhistory => $manualhistory, + internalnotes => $internalnotes, + serialsadditems => $serialsadditems, + staffdisplaycount => $staffdisplaycount, + opacdisplaycount => $opacdisplaycount, + graceperiod => $graceperiod, + location => $location, + enddate => $enddate, + skip_serialseq => $skip_serialseq, + itemtype => $itemtype, + previousitemtype => $previousitemtype, + mana_id => $mana_id, + ccode => $ccode + } + )->store; + $subscription->discard_changes; + my $subscriptionid = $subscription->subscriptionid; + my ( $query, $sth ); unless ($enddate) { $enddate = GetExpirationDate( $subscriptionid, $startdate ); $query = qq| @@ -1432,51 +1430,91 @@ 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); # reread subscription to get a hash (for calculation of the 1st issue number) - my $subscription = GetSubscription($subscriptionid); + $subscription = GetSubscription($subscriptionid); # We should not do that my $pattern = C4::Serials::Numberpattern::GetSubscriptionNumberpattern($subscription->{numberpattern}); # 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 = $biblio->metadata->record; + my ( $tag, $subf ) = GetMarcFromKohaField( 'biblio.serial' ); if ($tag) { eval { $record->field($tag)->update( $subf => 1 ); }; } - ModBiblio( $record, $biblionumber, $bib->{'frameworkcode'} ); + ModBiblio( $record, $biblionumber, $biblio->frameworkcode ); } return $subscriptionid; } +=head2 GetSubscriptionLength + +my ($numberlength, $weeklength, $monthlength) = GetSubscriptionLength( $subtype, $sublength ); + +This function calculates the subscription length. + +=cut + +sub GetSubscriptionLength { + my ($subtype, $length) = @_; + + return unless looks_like_number($length); + + return + ( + $subtype eq 'issues' ? $length : 0, + $subtype eq 'weeks' ? $length : 0, + $subtype eq 'months' ? $length : 0, + ); +} + + =head2 ReNewSubscription -ReNewSubscription($subscriptionid,$user,$startdate,$numberlength,$weeklength,$monthlength,$note) +ReNewSubscription($params); + +$params is a hashref with the following keys: subscriptionid, user, startdate, numberlength, weeklength, monthlength, note, branchcode this function renew a subscription with values given on input args. =cut sub ReNewSubscription { - my ( $subscriptionid, $user, $startdate, $numberlength, $weeklength, $monthlength, $note ) = @_; + my ( $params ) = @_; + my $subscriptionid = $params->{subscriptionid}; + my $user = $params->{user}; + my $startdate = $params->{startdate}; + my $numberlength = $params->{numberlength}; + my $weeklength = $params->{weeklength}; + my $monthlength = $params->{monthlength}; + my $note = $params->{note}; + my $branchcode = $params->{branchcode}; + my $dbh = C4::Context->dbh; my $subscription = GetSubscription($subscriptionid); my $query = qq| @@ -1496,12 +1534,16 @@ sub ReNewSubscription { 'title' => $subscription->{bibliotitle}, 'author' => $biblio->{author}, 'publishercode' => $biblio->{publishercode}, - 'note' => $biblio->{note}, - 'biblionumber' => $subscription->{biblionumber} + 'note' => $note, + 'biblionumber' => $subscription->{biblionumber}, + 'branchcode' => $branchcode, } ); } + $numberlength ||= 0; # Should not we raise an exception instead? + $weeklength ||= 0; + # renew subscription $query = qq| UPDATE subscription @@ -1511,7 +1553,6 @@ sub ReNewSubscription { $sth = $dbh->prepare($query); $sth->execute( $startdate, $numberlength, $weeklength, $monthlength, $subscriptionid ); my $enddate = GetExpirationDate($subscriptionid); - $debug && warn "enddate :$enddate"; $query = qq| UPDATE subscription SET enddate=? @@ -1519,13 +1560,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; @@ -1533,7 +1567,7 @@ sub ReNewSubscription { =head2 NewIssue -NewIssue($serialseq,$subscriptionid,$biblionumber,$status, $planneddate, $publisheddate, $notes) +NewIssue($serialseq,$subscriptionid,$biblionumber,$status, $planneddate, $publisheddate, $notes, $routingnotes) Create a new issue stored on the database. Note : we have to update the recievedlist and missinglist on subscriptionhistory for this subscription. @@ -1543,48 +1577,55 @@ returns the serial id sub NewIssue { my ( $serialseq, $subscriptionid, $biblionumber, $status, $planneddate, - $publisheddate, $publisheddatetext, $notes ) = @_; + $publisheddate, $publisheddatetext, $notes, $routingnotes ) = @_; ### 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, publisheddatetext, planneddate, notes) - VALUES (?,?,?,?,?,?,?,?) - |; - my $sth = $dbh->prepare($query); - $sth->execute( $serialseq, $subscriptionid, $biblionumber, $status, - $publisheddate, $publisheddatetext, $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, + routingnotes => $routingnotes + } + )->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 { $_ eq $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 ); + + $subscription_history->recievedlist($recievedlist); + $subscription_history->missinglist($missinglist); + $subscription_history->store(); + return $serialid; } @@ -1689,26 +1730,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) @@ -1720,13 +1741,11 @@ sub DelSubscription { my ($subscriptionid) = @_; my $dbh = C4::Context->dbh; $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); - my $afs = Koha::AdditionalField->all({tablename => 'subscription'}); - foreach my $af (@$afs) { - $af->delete_values({record_id => $subscriptionid}); - } + Koha::AdditionalFieldValues->search({ + 'field.tablename' => 'subscription', + 'me.record_id' => $subscriptionid, + }, { join => 'field' })->delete; logaction( "SERIAL", "DELETE", $subscriptionid, "" ) if C4::Context->preference("SubscriptionLog"); } @@ -1813,7 +1832,7 @@ sub GetLateOrMissingIssues { serialid, aqbooksellerid, name, biblio.title, biblioitems.issn, planneddate, serialseq, serial.status, serial.subscriptionid, claimdate, claims_count, - subscription.branchcode + subscription.branchcode, serial.publisheddate FROM serial LEFT JOIN subscription ON serial.subscriptionid=subscription.subscriptionid LEFT JOIN biblio ON subscription.biblionumber=biblio.biblionumber @@ -1831,7 +1850,7 @@ sub GetLateOrMissingIssues { serialid, aqbooksellerid, name, biblio.title, planneddate, serialseq, serial.status, serial.subscriptionid, claimdate, claims_count, - subscription.branchcode + subscription.branchcode, serial.publisheddate FROM serial LEFT JOIN subscription ON serial.subscriptionid=subscription.subscriptionid LEFT JOIN biblio ON subscription.biblionumber=biblio.biblionumber @@ -1845,22 +1864,11 @@ sub GetLateOrMissingIssues { $sth->execute( EXPECTED, LATE, CLAIMED ); my @issuelist; while ( my $line = $sth->fetchrow_hashref ) { - - if ($line->{planneddate} && $line->{planneddate} !~/^0+\-/) { - $line->{planneddateISO} = $line->{planneddate}; - $line->{planneddate} = output_pref( { dt => dt_from_string( $line->{"planneddate"} ), dateonly => 1 } ); - } - if ($line->{claimdate} && $line->{claimdate} !~/^0+\-/) { - $line->{claimdateISO} = $line->{claimdate}; - $line->{claimdate} = output_pref( { dt => dt_from_string( $line->{"claimdate"} ), dateonly => 1 } ); - } $line->{"status".$line->{status}} = 1; - my $additional_field_values = Koha::AdditionalField->fetch_all_values({ - record_id => $line->{subscriptionid}, - tablename => 'subscription' - }); - %$line = ( %$line, additional_fields => $additional_field_values->{$line->{subscriptionid}} ); + my $subscription_object = Koha::Subscriptions->find($line->{subscriptionid}); + $line->{additional_fields} = { map { $_->field->name => $_->value } + $subscription_object->additional_field_values->as_list }; push @issuelist, $line; } @@ -1878,42 +1886,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 @@ -1934,7 +1919,7 @@ sub check_routing { my $sth = $dbh->prepare( "SELECT count(routingid) routingids FROM subscription LEFT JOIN subscriptionroutinglist ON subscription.subscriptionid = subscriptionroutinglist.subscriptionid - WHERE subscription.subscriptionid = ? ORDER BY ranking ASC + WHERE subscription.subscriptionid = ? GROUP BY routingid ORDER BY ranking ASC " ); $sth->execute($subscriptionid); @@ -2162,7 +2147,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) { @@ -2174,61 +2159,16 @@ sub abouttoexpire { } } - } elsif ($subscription->{numberlength}>0) { + } elsif ( $subscription->{numberlength} && $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... @@ -2239,135 +2179,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) = @_; - if ($subscription->{countissuesperunit} + 1 > $freqdata->{issuesperunit}){ - ($year,$month,$day) = Add_Delta_Days($year,$month, $day , $freqdata->{unitsperissue} ); - $subscription->{countissuesperunit} = 1; - } else { + 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 ($year, $month, $day); + return @newissue; } sub _get_next_date_week { my ($subscription, $freqdata, $year, $month, $day) = @_; - my ($wkno, $yr) = Week_of_Year($year, $month, $day); - my $fa_dow = Day_of_Week(split /-/, $subscription->{firstacquidate}); + my @newissue; # ( yy, mm, dd ) + my $delta_days = int( 7 / $freqdata->{issuesperunit} ); - if ($subscription->{countissuesperunit} + 1 > $freqdata->{issuesperunit}){ - $subscription->{countissuesperunit} = 1; - $wkno += $freqdata->{unitsperissue}; - if($wkno > 52){ - $wkno = $wkno % 52; - $yr++; - } - ($year,$month,$day) = Monday_of_Week($wkno, $yr); - ($year,$month,$day) = Add_Delta_Days($year, $month, $day, $fa_dow - 1); - } else { - # Try to guess the next day of week - my $delta_days = int((7 - ($fa_dow - 1)) / $freqdata->{issuesperunit}); - ($year,$month,$day) = Add_Delta_Days($year, $month, $day, $delta_days); + 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 ($year, $month, $day); + return @newissue; } sub _get_next_date_month { my ($subscription, $freqdata, $year, $month, $day) = @_; - my $fa_day; - (undef, undef, $fa_day) = split /-/, $subscription->{firstacquidate}; + my @newissue; # ( yy, mm, dd ) + my $delta_days = int( 30 / $freqdata->{issuesperunit} ); - if ($subscription->{countissuesperunit} + 1 > $freqdata->{issuesperunit}){ - $subscription->{countissuesperunit} = 1; - ($year,$month,$day) = Add_Delta_YM($year,$month,$day, 0, - $freqdata->{unitsperissue}); - my $days_in_month = Days_in_Month($year, $month); - $day = $fa_day <= $days_in_month ? $fa_day : $days_in_month; - } else { - # Try to guess the next day in month - my $days_in_month = Days_in_Month($year, $month); - my $delta_days = int(($days_in_month - ($fa_day - 1)) / $freqdata->{issuesperunit}); - ($year,$month,$day) = Add_Delta_Days($year, $month, $day, $delta_days); + 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 ($year, $month, $day); + return @newissue; } sub _get_next_date_year { my ($subscription, $freqdata, $year, $month, $day) = @_; - my ($fa_year, $fa_month, $fa_day) = split /-/, $subscription->{firstacquidate}; + my @newissue; # ( yy, mm, dd ) + my $delta_days = int( 365 / $freqdata->{issuesperunit} ); - if ($subscription->{countissuesperunit} + 1 > $freqdata->{issuesperunit}){ - $subscription->{countissuesperunit} = 1; - ($year) = Add_Delta_YM($year,$month,$day, $freqdata->{"unitsperissue"},0); - $month = $fa_month; - my $days_in_month = Days_in_Month($year, $month); - $day = $fa_day <= $days_in_month ? $fa_day : $days_in_month; - } else { - # Try to guess the next day in year - my $days_in_year = Days_in_Year($year,12); #Sum the days of all the months of this year - my $delta_days = int(($days_in_year - ($fa_day - 1)) / $freqdata->{issuesperunit}); - ($year,$month,$day) = Add_Delta_Days($year, $month, $day, $delta_days); + 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 ($year, $month, $day); + 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 @@ -2380,11 +2351,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; @@ -2404,7 +2374,7 @@ 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'}; @@ -2467,11 +2437,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) = @_; @@ -2479,7 +2451,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( @@ -2488,19 +2460,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->format_cldr( "LLLL" ) + : $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; } @@ -2508,29 +2488,12 @@ sub _numeration { return $string; } -=head2 is_barcode_in_use +=head2 CloseSubscription -Returns number of occurrences 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 $occurrences = $dbh->selectall_arrayref( - 'SELECT itemnumber from items where barcode = ?', - {}, $barcode - - ); - - return @{$occurrences}; -} - -=head2 CloseSubscription -Close a subscription given a subscriptionid -=cut sub CloseSubscription { my ( $subscriptionid ) = @_; return unless $subscriptionid; @@ -2553,8 +2516,11 @@ sub CloseSubscription { } =head2 ReopenSubscription + Reopen a subscription given a subscriptionid + =cut + sub ReopenSubscription { my ( $subscriptionid ) = @_; return unless $subscriptionid; @@ -2670,6 +2636,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__