From a2a46db44c5d05d0b402e2b97df7787158c16d66 Mon Sep 17 00:00:00 2001 From: Julian Maurice Date: Fri, 9 Mar 2012 18:00:16 +0100 Subject: [PATCH 2/2] Bug 7688: Change subscription numbering pattern and frequencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Serials numbering pattern and frequencies are no more hard-coded. Now it's possible to create, edit and delete numbering patterns (and frequencies). This implies new sql tables (subscription_numberpatterns and subscription_frequencies) Numbering patterns behave almost as before, there are still the same values to configure (addX, everyX, settoX, whenmorethanX). lastvalueX and innerloopX remain in subscription tables. There is a new value in numbering patterns: numberingX. For each "column" (X, Y or Z) you can tell how to format the number. Actually numberingX can be set to: - 'dayname' (name of the day) (0-6 or 1-7 depending on which day is the first of the week) - 'monthname' (name of the month) (0-11) - 'season' (name of the season) (0-3) (0 is Spring) These names are localized by using POSIX::setlocale and POSIX::strftime and setting a 'locale' value to the subscription. Locale have to be installed on the system. Frequencies can be configured using 3 parameters: - 'unit': one of 'day', 'week', 'month', 'year' - 'issuesperunit': integer >= 1, the number of received issues per 'unit' - 'unitsperissue': integer >= 1, the number of 'unit' between two issues One of 'issuesperunit' and 'unitsperissue' must be equal to 1. Examples: unit = 'day', issuesperunit=3, unitsperissue=1 => 3 issues per day unit = 'week', issuesperunit=1, unitsperissue=3 => 1 issue each 3 weeks Prediction pattern is now computed server-side and is more consistent with what Koha will do. The publication date is displayed alongside the serial number. Irregularities can now be checked one by one, in the prediction pattern table, or if frequency is 'day-based' (unit is 'day'), there is the possibility to check all issues for a week day at once. When an irregularity is found, there is the possibility to keep the serial number unchanged, or to skip it. It is configured at subscription creation or modification. For instance, with a daily subscription you can have: skip serial number | keep serial number ----------------------+---------------------- 2012-01-01 ¦ No 1 | 2012-01-01 ¦ No 1 2012-01-03 ¦ No 3 | 2012-01-03 ¦ No 2 To lighten the subscription modification page, manual history has been moved in its own page subscription-history.pl which is accessible on subscription-detail.pl, tab 'Planning'. Important note: updatedatabase.pl script takes into account existing subscriptions and create a numbering pattern for each one. Frequency is mapped to the correct entry in subscription_frequencies table === TEST PLAN: === Create a new subscription: - Go to Serials module and click "New subscription" button - On the first page, choose a biblio and click next to go to the second page - Pick a first issue publication date - Choose frequency '1/day' - Choose a subscription length of 15 issues - Choose a subscription start date - Choose numbering pattern 'Volume, Number' - A table appears, fill 'Begins with' cells with '1' - Click on 'Test prediction pattern' button The prediction pattern is displayed at the right of the page. You can see in it the serial number, the publication date and a checkbox to allow you to choose which serials will not be received (irregularities). You can see that serial number start from "Vol 1, No 1" continue to "Vol 1, No 12" and then restart with "Vol 2, No 1". Frequency is '1/day' so you can see that publication date is incremented by one day line after line. - Now you can play a little with frequencies and numbering patterns, change one of them (or both) and click again on 'Test prediction pattern' - For example, choose frequency '3/weeks' and click on 'Test prediction pattern' button'. There is a little behaviour change compared with current master. Publication date will not be guessed within the week. Koha can't know when you will receive issues. So the publication date stay the same (monday of each week) for 3 consecutive issues and then jump to the next week. - Now choose frequency '1/3 months' and numbering pattern 'Seasonal' - Fill 'Begins with' cells with '2012' for Year and '0' for Season - Click on 'Test prediction pattern' - You should have something like 'Spring 2012', 'Summer 2012', ..., 'Winter 2012', 'Spring 2013' - Note that you can have seasons for south hemisphere by entering '2' in 'Year/Inner counter' - 2nd note: if you have some locales installed on your system, you can type its name in the 'Locale' field (actually it does not work for seasons name, only for month names and day names) If you want to modify the numbering pattern you can still do it here: - Click on 'Show/Hide advanced pattern' link. The advanced pattern table is shown but all fields are readonly - Click on 'Modify pattern' button. All readonly fields are now editable. Note that 'Begins with' and 'Inner counter' line are repeated here and any modifications in the small table will be replicated in the big table, and vice versa. - Pattern name is emptied, if you type a new name, a new pattern will be created, and if you type the same name as an existing numbering pattern, this one will be modified (with a confirmation message) - There is two new lines in this table: - Label: it's what is displayed in the smaller table headers above - Numbering: used to format numbers in different ways. can be 'seasons', 'monthname' or 'dayname'. Month name and day name can be localized using the 'Locale' field. Seasons can't (values for english and french are hard-coded in Serials.pm) - You can modify what you want in the table and click on 'Test prediction pattern' button each time you want to see your modifications. (Note that checkboxes for irregularities aren't displayed in this mode, and you can't save the subscription until you have saved or cancelled your changes). - To cancel your modifications, just click on 'Cancel modifications' button. - To save them, click on 'Save as new pattern'. If the pattern name is already existing, a confirmation box will ask you if you want to modify the existing numbering pattern. Otherwise a new pattern will be created and automatically selected. Once you have finished modifying numbering pattern. You can click again on 'Test prediction pattern' to define irregularities, and then click on 'Save subscription'. Now you can check the serials module still works correctly: - Check the subscription detail page to confirm that nothing is missing. Especially the 'Frequency' and 'Number pattern' infos - Try to receive some issues. Check that the serial number is correctly generated and if irregularities you have defined are taken into account (if you have defined some). - Check that receiving is blocked once you have reached the number of issues you have defined in subscription length (or once you have reached the subscription end date) In serials menu (to the left of almost each page of serials menu) you have two new links: 'Manage frequencies' and 'Manage numbering patterns'. 'Manage numbering patterns' lead to a page which list all numbering patterns and allow you to create, edit or delete them. The interface is almost the same as numbering pattern modification in subscription-add.pl 'Manage frequencies' lead to a page which list all frequencies and allow you to create, edit or delete them. Try to create a new frequency: - Click on 'Manage frequencies' link in the serials menu and then click on 'New frequency': - Fill in the description (mandatory). - Unit is one of 'day', 'week', 'month', year' or 'None' ('None' is for an irregular subscription) - If unit is different from 'None' you have to fill the two following fields (Issues per unit, and Units per issue) - Note that at least one of those must be equal to 1 - Issues per unit is the number of received issues by 'unit' and Units per issue is the number of 'unit' between two issues - Display order is used to build the drop-down list. Leave empty and it will be set to 0 (top of the list) - Then click on 'Save' - Check that this new frequency appears in the frequencies table and in the drop-down list in subscription-add.pl Subscription history has been moved in its own page. To test if it still works, choose a subscription with manual history enabled (or modify an existing subscription to turn on manual history). - On the detail page, tab 'Planning', you should have a link 'Edit history'. - Click on it - Modify history and click on Save - In tab 'Summary' you should have the infos you just entered And finally, you can check that old subscriptions (by old I mean subscriptions that existed before the update) are correctly linked to an existing numbering pattern and an existing frequency. Numbering patterns should be named 'Backup pattern X' where X is a number. --- C4/Serials.pm | 945 +++++++----- C4/Serials/Frequency.pm | 255 +++ C4/Serials/Numberpattern.pm | 266 ++++ installer/data/mysql/kohastructure.sql | 2 +- installer/data/mysql/updatedatabase.pl | 2 +- .../prog/en/includes/serials-menu.inc | 10 + .../prog/en/modules/serials/serials-collection.tt | 63 +- .../en/modules/serials/showpredictionpattern.tt | 83 + .../prog/en/modules/serials/subscription-add.tt | 1641 +++++++++----------- .../prog/en/modules/serials/subscription-detail.tt | 145 +-- .../en/modules/serials/subscription-frequencies.tt | 185 +++ .../en/modules/serials/subscription-history.tt | 60 + .../modules/serials/subscription-numberpatterns.tt | 289 ++++ serials/create-numberpattern.pl | 42 + serials/serials-collection.pl | 10 +- serials/serials-recieve.pl | 9 +- serials/showpredictionpattern.pl | 194 +++ serials/subscription-add.pl | 232 ++-- serials/subscription-detail.pl | 22 +- serials/subscription-frequencies.pl | 104 ++ serials/subscription-frequency.pl | 19 + serials/subscription-history.pl | 88 ++ serials/subscription-numberpattern.pl | 15 + serials/subscription-numberpatterns.pl | 130 ++ 24 files changed, 3276 insertions(+), 1535 deletions(-) create mode 100644 C4/Serials/Frequency.pm create mode 100644 C4/Serials/Numberpattern.pm create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/serials/showpredictionpattern.tt create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-frequencies.tt create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-history.tt create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-numberpatterns.tt create mode 100755 serials/create-numberpattern.pl create mode 100755 serials/showpredictionpattern.pl create mode 100755 serials/subscription-frequencies.pl create mode 100755 serials/subscription-frequency.pl create mode 100755 serials/subscription-history.pl create mode 100755 serials/subscription-numberpattern.pl create mode 100755 serials/subscription-numberpatterns.pl diff --git a/C4/Serials.pm b/C4/Serials.pm index 58b6078..ade3286 100644 --- a/C4/Serials.pm +++ b/C4/Serials.pm @@ -18,14 +18,16 @@ package C4::Serials; # with Koha; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -use strict; -use warnings; +use Modern::Perl; + use C4::Dates qw(format_date format_date_in_iso); use Date::Calc qw(:all); -use POSIX qw(strftime); +use POSIX qw(strftime setlocale LC_TIME); use C4::Biblio; use C4::Log; # logaction use C4::Debug; +use C4::Serials::Frequency; +use C4::Serials::Numberpattern; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); @@ -38,8 +40,9 @@ BEGIN { &GetSubscription &CountSubscriptionFromBiblionumber &GetSubscriptionsFromBiblionumber &GetFullSubscriptionsFromBiblionumber &GetFullSubscription &ModSubscriptionHistory &HasSubscriptionStrictlyExpired &HasSubscriptionExpired &GetExpirationDate &abouttoexpire + &GetSubscriptionHistoryFromSubscriptionId - &GetNextSeq &NewIssue &ItemizeSerials &GetSerials + &GetNextSeq &GetSeq &NewIssue &ItemizeSerials &GetSerials &GetLatestSerials &ModSerialStatus &GetNextDate &GetSerials2 &ReNewSubscription &GetLateIssues &GetLateOrMissingIssues &GetSerialInformation &AddItem2Serial @@ -152,20 +155,29 @@ sub GetLateIssues { =head2 GetSubscriptionHistoryFromSubscriptionId -$sth = GetSubscriptionHistoryFromSubscriptionId() -this function prepares the SQL request and returns the statement handle -After this function, don't forget to execute it by using $sth->execute($subscriptionid) +$history = GetSubscriptionHistoryFromSubscriptionId($subscriptionid); + +This function returns the subscription history as a hashref =cut -sub GetSubscriptionHistoryFromSubscriptionId() { +sub GetSubscriptionHistoryFromSubscriptionId { + my ($subscriptionid) = @_; + + return unless $subscriptionid; + my $dbh = C4::Context->dbh; my $query = qq| SELECT * FROM subscriptionhistory WHERE subscriptionid = ? |; - return $dbh->prepare($query); + my $sth = $dbh->prepare($query); + $sth->execute($subscriptionid); + my $results = $sth->fetchrow_hashref; + $sth->finish; + + return $results; } =head2 GetSerialStatusFromSerialId @@ -559,7 +571,7 @@ sub GetSubscriptions { my $dbh = C4::Context->dbh; my $sth; my $sql = qq( - SELECT subscription.*, subscriptionhistory.*, biblio.title,biblioitems.issn,biblio.biblionumber + SELECT subscriptionhistory.*, subscription.*, biblio.title,biblioitems.issn,biblio.biblionumber FROM subscription LEFT JOIN subscriptionhistory USING(subscriptionid) LEFT JOIN biblio ON biblio.biblionumber = subscription.biblionumber @@ -796,85 +808,87 @@ a list containing all the input params updated. =cut -# sub GetNextSeq { -# my ($val) =@_; -# my ($calculated,$newlastvalue1,$newlastvalue2,$newlastvalue3,$newinnerloop1,$newinnerloop2,$newinnerloop3); -# $calculated = $val->{numberingmethod}; -# # calculate the (expected) value of the next issue recieved. -# $newlastvalue1 = $val->{lastvalue1}; -# # check if we have to increase the new value. -# $newinnerloop1 = $val->{innerloop1}+1; -# $newinnerloop1=0 if ($newinnerloop1 >= $val->{every1}); -# $newlastvalue1 += $val->{add1} if ($newinnerloop1<1); # <1 to be true when 0 or empty. -# $newlastvalue1=$val->{setto1} if ($newlastvalue1>$val->{whenmorethan1}); # reset counter if needed. -# $calculated =~ s/\{X\}/$newlastvalue1/g; -# -# $newlastvalue2 = $val->{lastvalue2}; -# # check if we have to increase the new value. -# $newinnerloop2 = $val->{innerloop2}+1; -# $newinnerloop2=0 if ($newinnerloop2 >= $val->{every2}); -# $newlastvalue2 += $val->{add2} if ($newinnerloop2<1); # <1 to be true when 0 or empty. -# $newlastvalue2=$val->{setto2} if ($newlastvalue2>$val->{whenmorethan2}); # reset counter if needed. -# $calculated =~ s/\{Y\}/$newlastvalue2/g; -# -# $newlastvalue3 = $val->{lastvalue3}; -# # check if we have to increase the new value. -# $newinnerloop3 = $val->{innerloop3}+1; -# $newinnerloop3=0 if ($newinnerloop3 >= $val->{every3}); -# $newlastvalue3 += $val->{add3} if ($newinnerloop3<1); # <1 to be true when 0 or empty. -# $newlastvalue3=$val->{setto3} if ($newlastvalue3>$val->{whenmorethan3}); # reset counter if needed. -# $calculated =~ s/\{Z\}/$newlastvalue3/g; -# return ($calculated,$newlastvalue1,$newlastvalue2,$newlastvalue3,$newinnerloop1,$newinnerloop2,$newinnerloop3); -# } - sub GetNextSeq { - my ($val) = @_; - my ( $calculated, $newlastvalue1, $newlastvalue2, $newlastvalue3, $newinnerloop1, $newinnerloop2, $newinnerloop3 ); - my $pattern = $val->{numberpattern}; - my @seasons = ( 'nothing', 'Winter', 'Spring', 'Summer', 'Autumn' ); - my @southern_seasons = ( '', 'Summer', 'Autumn', 'Winter', 'Spring' ); - $calculated = $val->{numberingmethod}; - $newlastvalue1 = $val->{lastvalue1}; - $newlastvalue2 = $val->{lastvalue2}; - $newlastvalue3 = $val->{lastvalue3}; - $newlastvalue1 = $val->{lastvalue1}; - - # check if we have to increase the new value. - $newinnerloop1 = $val->{innerloop1} + 1; - $newinnerloop1 = 0 if ( $newinnerloop1 >= $val->{every1} ); - $newlastvalue1 += $val->{add1} if ( $newinnerloop1 < 1 ); # <1 to be true when 0 or empty. - $newlastvalue1 = $val->{setto1} if ( $newlastvalue1 > $val->{whenmorethan1} ); # reset counter if needed. - $calculated =~ s/\{X\}/$newlastvalue1/g; - - $newlastvalue2 = $val->{lastvalue2}; - - # check if we have to increase the new value. - $newinnerloop2 = $val->{innerloop2} + 1; - $newinnerloop2 = 0 if ( $newinnerloop2 >= $val->{every2} ); - $newlastvalue2 += $val->{add2} if ( $newinnerloop2 < 1 ); # <1 to be true when 0 or empty. - $newlastvalue2 = $val->{setto2} if ( $newlastvalue2 > $val->{whenmorethan2} ); # reset counter if needed. - if ( $pattern == 6 ) { - if ( $val->{hemisphere} == 2 ) { - my $newlastvalue2seq = $southern_seasons[$newlastvalue2]; - $calculated =~ s/\{Y\}/$newlastvalue2seq/g; - } else { - my $newlastvalue2seq = $seasons[$newlastvalue2]; - $calculated =~ s/\{Y\}/$newlastvalue2seq/g; + my ($val, $planneddate) = @_; + my ( $calculated, $newlastvalue1, $newlastvalue2, $newlastvalue3, + $newinnerloop1, $newinnerloop2, $newinnerloop3 ); + my $count = 1; + + if($val->{'skip_serialseq'}) { + my @irreg = split /;/, $val->{'irregularity'}; + if(@irreg > 0) { + my $irregularities = {}; + $irregularities->{$_} = 1 foreach(@irreg); + my $issueno = GetFictiveIssueNumber($val, $planneddate) + 1; + while($irregularities->{$issueno}) { + $count++; + $issueno++; + } } - } else { - $calculated =~ s/\{Y\}/$newlastvalue2/g; } - $newlastvalue3 = $val->{lastvalue3}; + my $pattern = $val->{numberpattern}; + $calculated = $val->{numberingmethod}; + my $locale = $val->{locale}; + $newlastvalue1 = $val->{lastvalue1} || 0; + $newlastvalue2 = $val->{lastvalue2} || 0; + $newlastvalue3 = $val->{lastvalue3} || 0; + $newinnerloop1 = $val->{innerloop1} || 0; + $newinnerloop2 = $val->{innerloop2} || 0; + $newinnerloop3 = $val->{innerloop3} || 0; + my %calc; + foreach(qw/X Y Z/) { + $calc{$_} = 1 if ($val->{'numberingmethod'} =~ /\{$_\}/); + } - # check if we have to increase the new value. - $newinnerloop3 = $val->{innerloop3} + 1; - $newinnerloop3 = 0 if ( $newinnerloop3 >= $val->{every3} ); - $newlastvalue3 += $val->{add3} if ( $newinnerloop3 < 1 ); # <1 to be true when 0 or empty. - $newlastvalue3 = $val->{setto3} if ( $newlastvalue3 > $val->{whenmorethan3} ); # reset counter if needed. - $calculated =~ s/\{Z\}/$newlastvalue3/g; + for(my $i = 0; $i < $count; $i++) { + if($calc{'X'}) { + # check if we have to increase the new value. + $newinnerloop1 += 1; + if ($newinnerloop1 >= $val->{every1}) { + $newinnerloop1 = 0; + $newlastvalue1 += $val->{add1}; + } + # reset counter if needed. + $newlastvalue1 = $val->{setto1} if ($newlastvalue1 > $val->{whenmorethan1}); + } + if($calc{'Y'}) { + # check if we have to increase the new value. + $newinnerloop2 += 1; + if ($newinnerloop2 >= $val->{every2}) { + $newinnerloop2 = 0; + $newlastvalue2 += $val->{add2}; + } + # reset counter if needed. + $newlastvalue2 = $val->{setto2} if ($newlastvalue2 > $val->{whenmorethan2}); + } + if($calc{'Z'}) { + # check if we have to increase the new value. + $newinnerloop3 += 1; + if ($newinnerloop3 >= $val->{every3}) { + $newinnerloop3 = 0; + $newlastvalue3 += $val->{add3}; + } + # reset counter if needed. + $newlastvalue3 = $val->{setto3} if ($newlastvalue3 > $val->{whenmorethan3}); + } + } + if($calc{'X'}) { + my $newlastvalue1string = _numeration( $newlastvalue1, $val->{numbering1}, $locale ); + $calculated =~ s/\{X\}/$newlastvalue1string/g; + } + if($calc{'Y'}) { + my $newlastvalue2string = _numeration( $newlastvalue2, $val->{numbering2}, $locale ); + $calculated =~ s/\{Y\}/$newlastvalue2string/g; + } + if($calc{'Z'}) { + my $newlastvalue3string = _numeration( $newlastvalue3, $val->{numbering3}, $locale ); + $calculated =~ s/\{Z\}/$newlastvalue3string/g; + } - return ( $calculated, $newlastvalue1, $newlastvalue2, $newlastvalue3, $newinnerloop1, $newinnerloop2, $newinnerloop3 ); + return ($calculated, + $newlastvalue1, $newlastvalue2, $newlastvalue3, + $newinnerloop1, $newinnerloop2, $newinnerloop3); } =head2 GetSeq @@ -889,27 +903,22 @@ the sequence in integer format sub GetSeq { my ($val) = @_; + my $locale = $val->{locale}; + my $pattern = $val->{numberpattern}; - my @seasons = ( 'nothing', 'Winter', 'Spring', 'Summer', 'Autumn' ); - my @southern_seasons = ( '', 'Summer', 'Autumn', 'Winter', 'Spring' ); - my $calculated = $val->{numberingmethod}; - my $x = $val->{'lastvalue1'}; - $calculated =~ s/\{X\}/$x/g; - my $newlastvalue2 = $val->{'lastvalue2'}; - - if ( $pattern == 6 ) { - if ( $val->{hemisphere} == 2 ) { - my $newlastvalue2seq = $southern_seasons[$newlastvalue2]; - $calculated =~ s/\{Y\}/$newlastvalue2seq/g; - } else { - my $newlastvalue2seq = $seasons[$newlastvalue2]; - $calculated =~ s/\{Y\}/$newlastvalue2seq/g; - } - } else { - $calculated =~ s/\{Y\}/$newlastvalue2/g; - } - my $z = $val->{'lastvalue3'}; - $calculated =~ s/\{Z\}/$z/g; + my $calculated = $val->{numberingmethod}; + + my $newlastvalue1 = $val->{'lastvalue1'} || 0; + $newlastvalue1 = _numeration($newlastvalue1, $val->{numbering1}, $locale) if ($val->{numbering1}); # reset counter if needed. + $calculated =~ s/\{X\}/$newlastvalue1/g; + + my $newlastvalue2 = $val->{'lastvalue2'} || 0; + $newlastvalue2 = _numeration($newlastvalue2, $val->{numbering2}, $locale) if ($val->{numbering2}); # reset counter if needed. + $calculated =~ s/\{Y\}/$newlastvalue2/g; + + my $newlastvalue3 = $val->{'lastvalue3'} || 0; + $newlastvalue3 = _numeration($newlastvalue3, $val->{numbering3}, $locale) if ($val->{numbering3}); # reset counter if needed. + $calculated =~ s/\{Z\}/$newlastvalue3/g; return $calculated; } @@ -934,14 +943,15 @@ sub GetExpirationDate { $enddate = $startdate || $subscription->{startdate}; my @date = split( /-/, $enddate ); return if ( scalar(@date) != 3 || not check_date(@date) ); - if ( ( $subscription->{periodicity} % 16 ) > 0 ) { - + my $frequency = C4::Serials::Frequency::GetSubscriptionFrequency($subscription->{periodicity}); + if ( $frequency and $frequency->{unit} ) { + # If Not Irregular if ( my $length = $subscription->{numberlength} ) { #calculate the date of the last issue. for ( my $i = 1 ; $i <= $length ; $i++ ) { - $enddate = GetNextDate( $enddate, $subscription ); + $enddate = GetNextDate( $subscription, $enddate ); } } elsif ( $subscription->{monthlength} ) { if ( $$subscription{startdate} ) { @@ -954,10 +964,12 @@ sub GetExpirationDate { my @enddate = Add_Delta_Days( $date[0], $date[1], $date[2], $subscription->{weeklength} * 7 ); $enddate = sprintf( "%04d-%02d-%02d", $enddate[0], $enddate[1], $enddate[2] ); } + } else { + $enddate = $subscription->{enddate}; } return $enddate; } else { - return; + return $subscription->{enddate}; } } @@ -990,20 +1002,64 @@ returns the number of rows affected =cut sub ModSubscriptionHistory { - my ( $subscriptionid, $histstartdate, $enddate, $recievedlist, $missinglist, $opacnote, $librariannote ) = @_; + my ( $subscriptionid, $histstartdate, $enddate, $receivedlist, $missinglist, $opacnote, $librariannote ) = @_; my $dbh = C4::Context->dbh; my $query = "UPDATE subscriptionhistory SET histstartdate=?,histenddate=?,recievedlist=?,missinglist=?,opacnote=?,librariannote=? WHERE subscriptionid=? "; my $sth = $dbh->prepare($query); - $recievedlist =~ s/^; //; - $missinglist =~ s/^; //; - $opacnote =~ s/^; //; - $sth->execute( $histstartdate, $enddate, $recievedlist, $missinglist, $opacnote, $librariannote, $subscriptionid ); + $receivedlist =~ s/^; // if $receivedlist; + $missinglist =~ s/^; // if $missinglist; + $opacnote =~ s/^; // if $opacnote; + $sth->execute( $histstartdate, $enddate, $receivedlist, $missinglist, $opacnote, $librariannote, $subscriptionid ); return $sth->rows; } +# Update missinglist field, used by ModSerialStatus +sub _update_missinglist { + my $subscriptionid = shift; + + my $dbh = C4::Context->dbh; + my @missingserials = GetSerials2($subscriptionid, "4,5"); + my $missinglist; + foreach (@missingserials) { + if($_->{'status'} == 4) { + $missinglist .= $_->{'serialseq'} . "; "; + } elsif($_->{'status'} == 5) { + $missinglist .= "not issued " . $_->{'serialseq'} . "; "; + } + } + $missinglist =~ s/; $//; + my $query = qq{ + UPDATE subscriptionhistory + SET missinglist = ? + WHERE subscriptionid = ? + }; + my $sth = $dbh->prepare($query); + $sth->execute($missinglist, $subscriptionid); +} + +# Update recievedlist field, used by ModSerialStatus +sub _update_receivedlist { + my $subscriptionid = shift; + + my $dbh = C4::Context->dbh; + my @receivedserials = GetSerials2($subscriptionid, "2"); + my $receivedlist; + foreach (@receivedserials) { + $receivedlist .= $_->{'serialseq'} . "; "; + } + $receivedlist =~ s/; $//; + my $query = qq{ + UPDATE subscriptionhistory + SET recievedlist = ? + WHERE subscriptionid = ? + }; + my $sth = $dbh->prepare($query); + $sth->execute($receivedlist, $subscriptionid); +} + =head2 ModSerialStatus ModSerialStatus($serialid,$serialseq, $planneddate,$publisheddate,$status,$notes) @@ -1016,22 +1072,30 @@ Note : if we change from "waited" to something else,then we will have to create sub ModSerialStatus { my ( $serialid, $serialseq, $planneddate, $publisheddate, $status, $notes ) = @_; + #It is a usual serial # 1st, get previous status : my $dbh = C4::Context->dbh; - my $query = "SELECT subscriptionid,status FROM serial WHERE serialid=?"; + my $query = "SELECT serial.subscriptionid,serial.status,subscription.periodicity + FROM serial, subscription + WHERE serial.subscriptionid=subscription.subscriptionid + AND serialid=?"; my $sth = $dbh->prepare($query); $sth->execute($serialid); - my ( $subscriptionid, $oldstatus ) = $sth->fetchrow; + my ( $subscriptionid, $oldstatus, $periodicity ) = $sth->fetchrow; + my $frequency = GetSubscriptionFrequency($periodicity); # change status & update subscriptionhistory my $val; if ( $status == 6 ) { - DelIssue( {'serialid'=>$serialid, 'subscriptionid'=>$subscriptionid,'serialseq'=>$serialseq} ); - } - else { - my $query = -'UPDATE serial SET serialseq=?,publisheddate=?,planneddate=?,status=?,notes=? WHERE serialid = ?'; + DelIssue( { 'serialid' => $serialid, 'subscriptionid' => $subscriptionid, 'serialseq' => $serialseq } ); + } else { + + unless ($frequency->{'unit'}) { + if ( not $planneddate or $planneddate eq '0000-00-00' ) { $planneddate = C4::Dates->new()->output('iso') }; + if ( not $publisheddate or $publisheddate eq '0000-00-00' ) { $publisheddate = C4::Dates->new()->output('iso') }; + } + my $query = 'UPDATE serial SET serialseq=?,publisheddate=?,planneddate=?,status=?,notes=? WHERE serialid = ?'; $sth = $dbh->prepare($query); $sth->execute( $serialseq, $publisheddate, $planneddate, $status, $notes, $serialid ); $query = "SELECT * FROM subscription WHERE subscriptionid = ?"; @@ -1039,58 +1103,50 @@ sub ModSerialStatus { $sth->execute($subscriptionid); my $val = $sth->fetchrow_hashref; unless ( $val->{manualhistory} ) { - $query = "SELECT missinglist,recievedlist FROM subscriptionhistory WHERE subscriptionid=?"; - $sth = $dbh->prepare($query); - $sth->execute($subscriptionid); - my ( $missinglist, $recievedlist ) = $sth->fetchrow; - if ( $status == 2 ) { - - $recievedlist .= "; $serialseq" - unless ( index( "$recievedlist", "$serialseq" ) >= 0 ); + if ( $status == 2 || ($oldstatus == 2 && $status != 2) ) { + _update_receivedlist($subscriptionid); + } + if($status == 4 || $status == 5 + || ($oldstatus == 4 && $status != 4) + || ($oldstatus == 5 && $status != 5)) { + _update_missinglist($subscriptionid); } - - # warn "missinglist : $missinglist serialseq :$serialseq, ".index("$missinglist","$serialseq"); - $missinglist .= "; $serialseq" - if ( $status == 4 - and not index( "$missinglist", "$serialseq" ) >= 0 ); - $missinglist .= "; not issued $serialseq" - if ( $status == 5 - and index( "$missinglist", "$serialseq" ) >= 0 ); - $query = "UPDATE subscriptionhistory SET recievedlist=?, missinglist=? WHERE subscriptionid=?"; - $sth = $dbh->prepare($query); - $recievedlist =~ s/^; //; - $missinglist =~ s/^; //; - $sth->execute( $recievedlist, $missinglist, $subscriptionid ); } } # create new waited entry if needed (ie : was a "waited" and has changed) if ( $oldstatus == 1 && $status != 1 ) { - my $query = "SELECT * FROM subscription WHERE subscriptionid = ?"; + my $query = qq{ + SELECT subscription.*, subscription_numberpatterns.*, + subscription_frequencies.* + FROM subscription + LEFT JOIN subscription_numberpatterns ON subscription.numberpattern = subscription_numberpatterns.id + LEFT JOIN subscription_frequencies ON subscription.periodicity = subscription_frequencies.id + WHERE subscriptionid = ? + }; $sth = $dbh->prepare($query); $sth->execute($subscriptionid); my $val = $sth->fetchrow_hashref; # next issue number - my ( - $newserialseq, $newlastvalue1, $newlastvalue2, $newlastvalue3, - $newinnerloop1, $newinnerloop2, $newinnerloop3 - ) = GetNextSeq($val); + my ( $newserialseq, $newlastvalue1, $newlastvalue2, $newlastvalue3, $newinnerloop1, $newinnerloop2, $newinnerloop3 ) = GetNextSeq($val, $publisheddate); # next date (calculated from actual date & frequency parameters) - my $nextpublisheddate = GetNextDate( $publisheddate, $val ); - NewIssue( $newserialseq, $subscriptionid, $val->{'biblionumber'}, 1, $nextpublisheddate, $nextpublisheddate ); + my $nextpublisheddate = GetNextDate($val, $publisheddate, 1); + my $nextpubdate = $nextpublisheddate; + NewIssue( $newserialseq, $subscriptionid, $val->{'biblionumber'}, 1, $nextpubdate, $nextpubdate ); $query = "UPDATE subscription SET lastvalue1=?, lastvalue2=?, lastvalue3=?, innerloop1=?, innerloop2=?, innerloop3=? WHERE subscriptionid = ?"; $sth = $dbh->prepare($query); $sth->execute( $newlastvalue1, $newlastvalue2, $newlastvalue3, $newinnerloop1, $newinnerloop2, $newinnerloop3, $subscriptionid ); -# check if an alert must be sent... (= a letter is defined & status became "arrived" + # check if an alert must be sent... (= a letter is defined & status became "arrived" if ( $val->{letter} && $status == 2 && $oldstatus != 2 ) { require C4::Letters; C4::Letters::SendAlerts( 'issue', $val->{subscriptionid}, $val->{letter} ); } } + return; } @@ -1104,31 +1160,50 @@ returns a hashref: $nextexepected = { serialid => int - planneddate => C4::Dates object + planneddate => ISO date } =cut sub GetNextExpected($) { my ($subscriptionid) = @_; - my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare('SELECT serialid, planneddate FROM serial WHERE subscriptionid=? AND status=?'); + + my $dbh = C4::Context->dbh; + my $query = qq{ + SELECT * + FROM serial + WHERE subscriptionid = ? + AND status = ? + LIMIT 1 + }; + my $sth = $dbh->prepare($query); # Each subscription has only one 'expected' issue, with serial.status==1. $sth->execute( $subscriptionid, 1 ); - my ( $nextissue ) = $sth->fetchrow_hashref; - if( !$nextissue){ - $sth = $dbh->prepare('SELECT serialid,planneddate FROM serial WHERE subscriptionid = ? ORDER BY planneddate DESC LIMIT 1'); - $sth->execute( $subscriptionid ); - $nextissue = $sth->fetchrow_hashref; + my $nextissue = $sth->fetchrow_hashref; + if ( !$nextissue ) { + $query = qq{ + SELECT * + FROM serial + WHERE subscriptionid = ? + ORDER BY planneddate DESC + LIMIT 1 + }; + $sth = $dbh->prepare($query); + $sth->execute($subscriptionid); + $nextissue = $sth->fetchrow_hashref; } - if (!defined $nextissue->{planneddate}) { - # or should this default to 1st Jan ??? - $nextissue->{planneddate} = strftime('%Y-%m-%d',localtime); + 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; } - $nextissue->{planneddate} = C4::Dates->new($nextissue->{planneddate},'iso'); - return $nextissue; + return $nextissue; } =head2 ModNextExpected @@ -1138,7 +1213,7 @@ ModNextExpected($subscriptionid,$date) Update the planneddate for the current expected issue of the subscription. This will modify all future prediction results. -C<$date> is a C4::Dates object. +C<$date> is an ISO date. returns 0 @@ -1152,11 +1227,42 @@ sub ModNextExpected($$) { my $sth = $dbh->prepare('UPDATE serial SET planneddate=?,publisheddate=? WHERE subscriptionid=? AND status=?'); # Each subscription has only one 'expected' issue, with serial.status==1. - $sth->execute( $date->output('iso'), $date->output('iso'), $subscriptionid, 1 ); + $sth->execute( $date, $date, $subscriptionid, 1 ); return 0; } +=head2 GetSubscriptionIrregularities + +=over4 + +=item @irreg = &GetSubscriptionIrregularities($subscriptionid); +get the list of irregularities for a subscription + +=back + +=cut + +sub GetSubscriptionIrregularities { + my $subscriptionid = shift; + + return undef unless $subscriptionid; + + my $dbh = C4::Context->dbh; + my $query = qq{ + SELECT irregularity + FROM subscription + WHERE subscriptionid = ? + }; + my $sth = $dbh->prepare($query); + $sth->execute($subscriptionid); + + my ($result) = $sth->fetchrow_array; + my @irreg = split /;/, $result; + + return @irreg; +} + =head2 ModSubscription this function modifies a subscription. Put all new values on input args. @@ -1165,43 +1271,41 @@ returns the number of rows affected =cut sub ModSubscription { - my ($auser, $branchcode, $aqbooksellerid, $cost, $aqbudgetid, $startdate, $periodicity, $firstacquidate, - $dow, $irregularity, $numberpattern, $numberlength, $weeklength, $monthlength, $add1, $every1, - $whenmorethan1, $setto1, $lastvalue1, $innerloop1, $add2, $every2, $whenmorethan2, $setto2, - $lastvalue2, $innerloop2, $add3, $every3, $whenmorethan3, $setto3, $lastvalue3, $innerloop3, - $numberingmethod, $status, $biblionumber, $callnumber, $notes, $letter, $hemisphere, $manualhistory, - $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate, $subscriptionid + my ( + $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, + $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount, + $graceperiod, $location, $enddate, $subscriptionid, $skip_serialseq ) = @_; - # warn $irregularity; my $dbh = C4::Context->dbh; my $query = "UPDATE subscription - SET librarian=?, branchcode=?,aqbooksellerid=?,cost=?,aqbudgetid=?,startdate=?, - periodicity=?,firstacquidate=?,dow=?,irregularity=?, numberpattern=?, numberlength=?,weeklength=?,monthlength=?, - add1=?,every1=?,whenmorethan1=?,setto1=?,lastvalue1=?,innerloop1=?, - add2=?,every2=?,whenmorethan2=?,setto2=?,lastvalue2=?,innerloop2=?, - add3=?,every3=?,whenmorethan3=?,setto3=?,lastvalue3=?,innerloop3=?, - numberingmethod=?, status=?, biblionumber=?, callnumber=?, notes=?, - letter=?, hemisphere=?,manualhistory=?,internalnotes=?,serialsadditems=?, - staffdisplaycount = ?,opacdisplaycount = ?, graceperiod = ?, location = ? - ,enddate=? - WHERE subscriptionid = ?"; - - #warn "query :".$query; + 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, - $dow, "$irregularity", $numberpattern, $numberlength, - $weeklength, $monthlength, $add1, $every1, - $whenmorethan1, $setto1, $lastvalue1, $innerloop1, - $add2, $every2, $whenmorethan2, $setto2, - $lastvalue2, $innerloop2, $add3, $every3, - $whenmorethan3, $setto3, $lastvalue3, $innerloop3, - $numberingmethod, $status, $biblionumber, $callnumber, - $notes, $letter, $hemisphere, ( $manualhistory ? $manualhistory : 0 ), + $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, $subscriptionid + $graceperiod, $location, $enddate, $skip_serialseq, + $subscriptionid ); my $rows = $sth->rows; @@ -1213,11 +1317,10 @@ sub ModSubscription { $subscriptionid = &NewSubscription($auser,branchcode,$aqbooksellerid,$cost,$aqbudgetid,$biblionumber, $startdate,$periodicity,$dow,$numberlength,$weeklength,$monthlength, - $add1,$every1,$whenmorethan1,$setto1,$lastvalue1,$innerloop1, - $add2,$every2,$whenmorethan2,$setto2,$lastvalue2,$innerloop2, - $add3,$every3,$whenmorethan3,$setto3,$lastvalue3,$innerloop3, - $numberingmethod, $status, $notes, $serialsadditems, - $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate); + $lastvalue1,$innerloop1,$lastvalue2,$innerloop2,$lastvalue3,$innerloop3, + $status, $notes, $letter, $firstacquidate, $irregularity, $numberpattern, + $callnumber, $hemisphere, $manualhistory, $internalnotes, $serialsadditems, + $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate, $skip_serialseq); Create a new subscription with value given on input args. @@ -1227,42 +1330,44 @@ the id of this new subscription =cut sub NewSubscription { - my ($auser, $branchcode, $aqbooksellerid, $cost, $aqbudgetid, $biblionumber, $startdate, $periodicity, - $dow, $numberlength, $weeklength, $monthlength, $add1, $every1, $whenmorethan1, $setto1, - $lastvalue1, $innerloop1, $add2, $every2, $whenmorethan2, $setto2, $lastvalue2, $innerloop2, - $add3, $every3, $whenmorethan3, $setto3, $lastvalue3, $innerloop3, $numberingmethod, $status, - $notes, $letter, $firstacquidate, $irregularity, $numberpattern, $callnumber, $hemisphere, $manualhistory, - $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate + my ( + $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 $dbh = C4::Context->dbh; #save subscription (insert into database) my $query = qq| INSERT INTO subscription - (librarian,branchcode,aqbooksellerid,cost,aqbudgetid,biblionumber, - startdate,periodicity,dow,numberlength,weeklength,monthlength, - add1,every1,whenmorethan1,setto1,lastvalue1,innerloop1, - add2,every2,whenmorethan2,setto2,lastvalue2,innerloop2, - add3,every3,whenmorethan3,setto3,lastvalue3,innerloop3, - numberingmethod, status, notes, letter,firstacquidate,irregularity, - numberpattern, callnumber, hemisphere,manualhistory,internalnotes,serialsadditems, - staffdisplaycount,opacdisplaycount,graceperiod,location,enddate) - VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) + (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, - $dow, $numberlength, $weeklength, $monthlength, $add1, $every1, $whenmorethan1, $setto1, - $lastvalue1, $innerloop1, $add2, $every2, $whenmorethan2, $setto2, $lastvalue2, $innerloop2, - $add3, $every3, $whenmorethan3, $setto3, $lastvalue3, $innerloop3, $numberingmethod, "$status", - $notes, $letter, $firstacquidate, $irregularity, $numberpattern, $callnumber, $hemisphere, $manualhistory, - $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate + $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'}; - unless ($enddate){ - $enddate = GetExpirationDate($subscriptionid,$startdate); - $query = q| + unless ($enddate) { + $enddate = GetExpirationDate( $subscriptionid, $startdate ); + $query = qq| UPDATE subscription SET enddate=? WHERE subscriptionid=? @@ -1270,7 +1375,8 @@ sub NewSubscription { $sth = $dbh->prepare($query); $sth->execute( $enddate, $subscriptionid ); } - #then create the 1st waited number + + # then create the 1st expected number $query = qq( INSERT INTO subscriptionhistory (biblionumber, subscriptionid, histstartdate, opacnote, librariannote) @@ -1283,6 +1389,7 @@ sub NewSubscription { $query = qq( SELECT * FROM subscription + LEFT JOIN subscription_numberpatterns ON subscription.numberpattern = subscription_numberpatterns.id WHERE subscriptionid = ? ); $sth = $dbh->prepare($query); @@ -1302,8 +1409,8 @@ sub NewSubscription { logaction( "SERIAL", "ADD", $subscriptionid, "" ) if C4::Context->preference("SubscriptionLog"); #set serial flag on biblio if not already set. - my ( $null, ($bib) ) = GetBiblio($biblionumber); - if ( !$bib->{'serial'} ) { + my $bib = GetBiblioData($biblionumber); + if ( $bib and !$bib->{'serial'} ) { my $record = GetMarcBiblio($biblionumber); my ( $tag, $subf ) = GetMarcFromKohaField( 'biblio.serial', $bib->{'frameworkcode'} ); if ($tag) { @@ -1621,7 +1728,8 @@ sub HasSubscriptionExpired { my ($subscriptionid) = @_; my $dbh = C4::Context->dbh; my $subscription = GetSubscription($subscriptionid); - if ( ( $subscription->{periodicity} % 16 ) > 0 ) { + my $frequency = C4::Serials::Frequency::GetSubscriptionFrequency($subscription->{periodicity}); + if ( $frequency and $frequency->{unit} ) { my $expirationdate = $subscription->{enddate} || GetExpirationDate($subscriptionid); if (!defined $expirationdate) { $expirationdate = q{}; @@ -1645,6 +1753,7 @@ sub HasSubscriptionExpired { || ( !$res ) ); return 0; } else { + # Irregular if ( $subscription->{'numberlength'} ) { my $countreceived = countissuesfrom( $subscriptionid, $subscription->{'startdate'} ); return 1 if ( $countreceived > $subscription->{'numberlength'} ); @@ -2136,29 +2245,17 @@ sub abouttoexpire { my $dbh = C4::Context->dbh; my $subscription = GetSubscription($subscriptionid); my $per = $subscription->{'periodicity'}; - if ($per && $per % 16 > 0){ - my $expirationdate = GetExpirationDate($subscriptionid); + my $frequency = C4::Serials::Frequency::GetSubscriptionFrequency($per); + if ($frequency and $frequency->{unit}){ + my $expirationdate = GetExpirationDate($subscriptionid); my ($res) = $dbh->selectrow_array('select max(planneddate) from serial where subscriptionid = ?', undef, $subscriptionid); - my @res; - if (defined $res) { - @res=split (/-/,$res); - @res=Date::Calc::Today if ($res[0]*$res[1]==0); - } else { # default an undefined value - @res=Date::Calc::Today; + my $nextdate = GetNextDate($subscription, $res); + if(Date::Calc::Delta_Days( + split( /-/, $nextdate ), + split( /-/, $expirationdate ) + ) <= 0) { + return 1; } - my @endofsubscriptiondate=split(/-/,$expirationdate); - my @per_list = (0, 7, 7, 14, 21, 31, 62, 93, 93, 190, 365, 730, 0, 124, 0, 0); - my @datebeforeend; - @datebeforeend = Add_Delta_Days( $endofsubscriptiondate[0],$endofsubscriptiondate[1],$endofsubscriptiondate[2], - - (3 * $per_list[$per])) if (@endofsubscriptiondate && $endofsubscriptiondate[0]*$endofsubscriptiondate[1]*$endofsubscriptiondate[2]); - return 1 if ( @res && - (@datebeforeend && - Delta_Days($res[0],$res[1],$res[2], - $datebeforeend[0],$datebeforeend[1],$datebeforeend[2]) <= 0) && - (@endofsubscriptiondate && - Delta_Days($res[0],$res[1],$res[2], - $endofsubscriptiondate[0],$endofsubscriptiondate[1],$endofsubscriptiondate[2]) >= 0) ); - return 0; } elsif ($subscription->{numberlength}>0) { return (countissuesfrom($subscriptionid,$subscription->{'startdate'}) >=$subscription->{numberlength}-1); } @@ -2175,170 +2272,276 @@ sub in_array { # used in next sub down return 0; } +=head2 GetFictiveIssueNumber + +$issueno = GetFictiveIssueNumber($subscription, $publishedate); + +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... +This issuenumber doesn't take into account irregularities, so, for instance, if the 3rd +issue is declared as 'irregular' (will be skipped at receipt), the next issue number +will be 4, not 3. It's why it is called 'fictive'. It is NOT a serial seq, and is not +depending on how many rows are in serial table. +The issue number calculation is based on subscription frequency, first acquisition +date, and $publisheddate. + +=cut + +sub GetFictiveIssueNumber { + my ($subscription, $publisheddate) = @_; + + 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 $issueno; +} + =head2 GetNextDate -$resultdate = GetNextDate($planneddate,$subscription) +$resultdate = GetNextDate($publisheddate,$subscription) -this function it takes the planneddate and will return the next issue's date and will skip dates if there -exists an irregularity -- eg if periodicity is monthly and $planneddate is 2007-02-10 but if March and April is to be +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' +$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 return : -$resultdate - then next date in the sequence +$resultdate - then next date in the sequence (ISO date) -Return 0 if periodicity==0 +Return $publisheddate if subscription is irregular =cut -sub GetNextDate(@) { - my ( $planneddate, $subscription ) = @_; - my @irreg = split( /\,/, $subscription->{irregularity} ); +sub GetNextDate { + my ( $subscription, $publisheddate, $updatecount ) = @_; - #date supposed to be in ISO. + my $freqdata = GetSubscriptionFrequency($subscription->{'periodicity'}); - my ( $year, $month, $day ) = split( /-/, $planneddate ); - $month = 1 unless ($month); - $day = 1 unless ($day); - my @resultdate; + if ($freqdata->{'unit'}) { + my ( $year, $month, $day ) = split /-/, $publisheddate; - # warn "DOW $dayofweek"; - if ( $subscription->{periodicity} % 16 == 0 ) { # 'without regularity' || 'irregular' - return 0; - } - - # daily : n / week - # Since we're interpreting irregularity here as which days of the week to skip an issue, - # renaming this pattern from 1/day to " n / week ". - if ( $subscription->{periodicity} == 1 ) { - my $dayofweek = eval { Day_of_Week( $year, $month, $day ) }; - if ($@) { warn "year month day : $year $month $day $subscription->{subscriptionid} : $@"; } - else { - for ( my $i = 0 ; $i < @irreg ; $i++ ) { - $dayofweek = 0 if ( $dayofweek == 7 ); - if ( in_array( ( $dayofweek + 1 ), @irreg ) ) { - ( $year, $month, $day ) = Add_Delta_Days( $year, $month, $day, 1 ); - $dayofweek++; - } - } - @resultdate = Add_Delta_Days( $year, $month, $day, 1 ); + # Process an irregularity Hash + # Suppose that irregularities are stored in a string with this structure + # irreg1;irreg2;irreg3 + # where irregX is the number of issue which will not be received + # (the first issue takes the number 1, the 2nd the number 2 and so on) + my @irreg = split /;/, $subscription->{'irregularity'} ; + my %irregularities; + foreach my $irregularity (@irreg) { + $irregularities{$irregularity} = 1; } - } - # 1 week - if ( $subscription->{periodicity} == 2 ) { - my ( $wkno, $year ) = eval { Week_of_Year( $year, $month, $day ) }; - if ($@) { warn "year month day : $year $month $day $subscription->{subscriptionid} : $@"; } - else { - for ( my $i = 0 ; $i < @irreg ; $i++ ) { - - #FIXME: if two consecutive irreg, do we only skip one? - if ( $irreg[$i] == ( ( $wkno != 51 ) ? ( $wkno + 1 ) % 52 : 52 ) ) { - ( $year, $month, $day ) = Add_Delta_Days( $year, $month, $day, 7 ); - $wkno = ( ( $wkno != 51 ) ? ( $wkno + 1 ) % 52 : 52 ); + # Get the 'fictive' next issue number + # It is used to check if next issue is an irregular issue. + my $issueno = GetFictiveIssueNumber($subscription, $publisheddate) + 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'}++; } + $issueno++; } - @resultdate = Add_Delta_Days( $year, $month, $day, 7 ); - } - } - - # 1 / 2 weeks - if ( $subscription->{periodicity} == 3 ) { - my ( $wkno, $year ) = eval { Week_of_Year( $year, $month, $day ) }; - if ($@) { warn "year month day : $year $month $day $subscription->{subscriptionid} : $@"; } - else { - for ( my $i = 0 ; $i < @irreg ; $i++ ) { - if ( $irreg[$i] == ( ( $wkno != 50 ) ? ( $wkno + 2 ) % 52 : 52 ) ) { - ### BUGFIX was previously +1 ^ - ( $year, $month, $day ) = Add_Delta_Days( $year, $month, $day, 14 ); - $wkno = ( ( $wkno != 50 ) ? ( $wkno + 2 ) % 52 : 52 ); - } + if ($subscription->{'countissuesperunit'} + 1 > $freqdata->{'issuesperunit'}){ + ($year,$month,$day) = Add_Delta_Days($year,$month, $day , $freqdata->{"unitsperissue"} ); + $subscription->{'countissuesperunit'} = 1; + } else { + $subscription->{'countissuesperunit'}++; } - @resultdate = Add_Delta_Days( $year, $month, $day, 14 ); } - } - - # 1 / 3 weeks - if ( $subscription->{periodicity} == 4 ) { - my ( $wkno, $year ) = eval { Week_of_Year( $year, $month, $day ) }; - if ($@) { warn "année mois jour : $year $month $day $subscription->{subscriptionid} : $@"; } - else { - for ( my $i = 0 ; $i < @irreg ; $i++ ) { - if ( $irreg[$i] == ( ( $wkno != 49 ) ? ( $wkno + 3 ) % 52 : 52 ) ) { - ( $year, $month, $day ) = Add_Delta_Days( $year, $month, $day, 21 ); - $wkno = ( ( $wkno != 49 ) ? ( $wkno + 3 ) % 52 : 52 ); + 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'}++; } + $issueno++; } - @resultdate = Add_Delta_Days( $year, $month, $day, 21 ); - } - } - my $tmpmonth = $month; - if ( $year && $month && $day ) { - if ( $subscription->{periodicity} == 5 ) { - for ( my $i = 0 ; $i < @irreg ; $i++ ) { - if ( $irreg[$i] == ( ( $tmpmonth != 11 ) ? ( $tmpmonth + 1 ) % 12 : 12 ) ) { - ( $year, $month, $day ) = Add_Delta_YMD( $year, $month, $day, 0, 1, 0 ); - $tmpmonth = ( ( $tmpmonth != 11 ) ? ( $tmpmonth + 1 ) % 12 : 12 ); + if ($subscription->{'countissuesperunit'} + 1 > $freqdata->{'issuesperunit'}){ + $subscription->{'countissuesperunit'} = 1; + $wkno += $freqdata->{"unitsperissue"}; + if($wkno > 52){ + $wkno = $wkno % 52 ; + $yr++; } - } - @resultdate = Add_Delta_YMD( $year, $month, $day, 0, 1, 0 ); - } - if ( $subscription->{periodicity} == 6 ) { - for ( my $i = 0 ; $i < @irreg ; $i++ ) { - if ( $irreg[$i] == ( ( $tmpmonth != 10 ) ? ( $tmpmonth + 2 ) % 12 : 12 ) ) { - ( $year, $month, $day ) = Add_Delta_YMD( $year, $month, $day, 0, 2, 0 ); - $tmpmonth = ( ( $tmpmonth != 10 ) ? ( $tmpmonth + 2 ) % 12 : 12 ); + 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'}++; } - @resultdate = Add_Delta_YMD( $year, $month, $day, 0, 2, 0 ); } - if ( $subscription->{periodicity} == 7 ) { - for ( my $i = 0 ; $i < @irreg ; $i++ ) { - if ( $irreg[$i] == ( ( $tmpmonth != 9 ) ? ( $tmpmonth + 3 ) % 12 : 12 ) ) { - ( $year, $month, $day ) = Add_Delta_YMD( $year, $month, $day, 0, 3, 0 ); - $tmpmonth = ( ( $tmpmonth != 9 ) ? ( $tmpmonth + 3 ) % 12 : 12 ); + 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'}++; } + $issueno++; } - @resultdate = Add_Delta_YMD( $year, $month, $day, 0, 3, 0 ); - } - if ( $subscription->{periodicity} == 8 ) { - for ( my $i = 0 ; $i < @irreg ; $i++ ) { - if ( $irreg[$i] == ( ( $tmpmonth != 9 ) ? ( $tmpmonth + 3 ) % 12 : 12 ) ) { - ( $year, $month, $day ) = Add_Delta_YMD( $year, $month, $day, 0, 3, 0 ); - $tmpmonth = ( ( $tmpmonth != 9 ) ? ( $tmpmonth + 3 ) % 12 : 12 ); + 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'}++; } - @resultdate = Add_Delta_YMD( $year, $month, $day, 0, 3, 0 ); } - if ( $subscription->{periodicity} == 13 ) { - for ( my $i = 0 ; $i < @irreg ; $i++ ) { - if ( $irreg[$i] == ( ( $tmpmonth != 8 ) ? ( $tmpmonth + 4 ) % 12 : 12 ) ) { - ( $year, $month, $day ) = Add_Delta_YMD( $year, $month, $day, 0, 4, 0 ); - $tmpmonth = ( ( $tmpmonth != 8 ) ? ( $tmpmonth + 4 ) % 12 : 12 ); + 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'}++; } + $issueno++; } - @resultdate = Add_Delta_YMD( $year, $month, $day, 0, 4, 0 ); - } - if ( $subscription->{periodicity} == 9 ) { - for ( my $i = 0 ; $i < @irreg ; $i++ ) { - if ( $irreg[$i] == ( ( $tmpmonth != 9 ) ? ( $tmpmonth + 3 ) % 12 : 12 ) ) { - ### BUFIX Seems to need more Than One ? - ( $year, $month, $day ) = Add_Delta_YM( $year, $month, $day, 0, 6 ); - $tmpmonth = ( ( $tmpmonth != 6 ) ? ( $tmpmonth + 6 ) % 12 : 12 ); + 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'}++; } - @resultdate = Add_Delta_YM( $year, $month, $day, 0, 6 ); - } - if ( $subscription->{periodicity} == 10 ) { - @resultdate = Add_Delta_YM( $year, $month, $day, 1, 0 ); } - if ( $subscription->{periodicity} == 11 ) { - @resultdate = Add_Delta_YM( $year, $month, $day, 2, 0 ); + if ($updatecount){ + my $dbh = C4::Context->dbh; + my $query = qq{ + UPDATE subscription + SET countissuesperunit = ? + WHERE subscriptionid = ? + }; + my $sth = $dbh->prepare($query); + $sth->execute($subscription->{'countissuesperunit'}, $subscription->{'subscriptionid'}); } + return sprintf("%04d-%02d-%02d", $year, $month, $day); + } + else { + return $publisheddate; } - my $resultdate = sprintf( "%04d-%02d-%02d", $resultdate[0], $resultdate[1], $resultdate[2] ); +} + +=head2 _numeration - return "$resultdate"; + $string = &_numeration($value,$num_type,$locale); + +_numeration returns the string corresponding to $value in the num_type +num_type can take : + -dayname + -monthname + -season +=cut + +#' + +sub _numeration { + my ($value, $num_type, $locale) = @_; + $value ||= 0; + my $initlocale = setlocale(LC_TIME); + if($locale and $locale ne $initlocale) { + $locale = setlocale(LC_TIME, $locale); + } + $locale ||= $initlocale; + my $string; + $num_type //= ''; + given ($num_type) { + when (/^dayname$/) { + $value = $value % 7; + $string = POSIX::strftime("%A",0,0,0,0,0,0,$value); + } + when (/^monthname$/) { + $value = $value % 12; + $string = POSIX::strftime("%B",0,0,0,1,$value,0,0,0,0); + } + when (/^season$/) { + my $seasonlocale = ($locale) + ? (substr $locale,0,2) + : "en"; + my %seasons=( + "en" => + [qw(Spring Summer Fall Winter)], + "fr"=> + [qw(Printemps Été Automne Hiver)], + ); + $value = $value % 4; + $string = ($seasons{$seasonlocale}) + ? $seasons{$seasonlocale}->[$value] + : $seasons{'en'}->[$value]; + } + default { + $string = $value; + } + } + if($locale ne $initlocale) { + setlocale(LC_TIME, $initlocale); + } + return $string; } =head2 is_barcode_in_use diff --git a/C4/Serials/Frequency.pm b/C4/Serials/Frequency.pm new file mode 100644 index 0000000..0559d03 --- /dev/null +++ b/C4/Serials/Frequency.pm @@ -0,0 +1,255 @@ +package C4::Serials::Frequency; + +# Copyright 2000-2002 Biblibre SARL +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use strict; +use warnings; + +use C4::Context; + +use vars qw($VERSION @ISA @EXPORT); + +BEGIN { + # set the version for version checking + $VERSION = 3.01; + require Exporter; + @ISA = qw(Exporter); + @EXPORT = qw( + &GetSubscriptionFrequencies + &GetSubscriptionFrequency + &AddSubscriptionFrequency + &ModSubscriptionFrequency + &DelSubscriptionFrequency + ); +} + +=head3 GetSubscriptionFrequencies + +=over 4 + +=item C<@frequencies> = &GetSubscriptionFrequencies(); + +gets frequencies restricted on filters + +=back + +=cut + +sub GetSubscriptionFrequencies { + my $dbh = C4::Context->dbh; + my $query = qq{ + SELECT * + FROM subscription_frequencies + ORDER BY displayorder + }; + my $sth = $dbh->prepare($query); + $sth->execute(); + + my $results = $sth->fetchall_arrayref( {} ); + return @$results; +} + +=head3 GetSubscriptionFrequency + +=over 4 + +=item $frequency = &GetSubscriptionFrequency($frequencyid); + +gets frequency where $frequencyid is the identifier + +=back + +=cut + +sub GetSubscriptionFrequency { + my ($frequencyid) = @_; + + my $dbh = C4::Context->dbh; + my $query = qq{ + SELECT * + FROM subscription_frequencies + WHERE id = ? + }; + my $sth = $dbh->prepare($query); + $sth->execute($frequencyid); + + return $sth->fetchrow_hashref; +} + +=head3 AddSubscriptionFrequency + +=over 4 + +=item C<$frequencyid> = &AddSubscriptionFrequency($frequency); + +Add a new frequency + +=item C<$frequency> is a hashref that can contains the following keys + +=over 2 + +=item * description + +=item * unit + +=item * issuesperunit + +=item * unitsperissue + +=item * expectedissuesayear + +=item * displayorder + +=back + +Only description is mandatory. + +=back + +=cut + +sub AddSubscriptionFrequency { + my $frequency = shift; + + unless(ref($frequency) eq 'HASH' && defined $frequency->{'description'} && $frequency->{'description'} ne '') { + return undef; + } + + my @keys; + my @values; + foreach (qw/ description unit issuesperunit unitsperissue expectedissuesayear displayorder /) { + if(exists $frequency->{$_}) { + push @keys, $_; + push @values, $frequency->{$_}; + } + } + + my $dbh = C4::Context->dbh; + my $query = "INSERT INTO subscription_frequencies"; + $query .= '(' . join(',', @keys) . ')'; + $query .= ' VALUES (' . ('?,' x (scalar(@keys)-1)) . '?)'; + my $sth = $dbh->prepare($query); + my $rv = $sth->execute(@values); + + if(defined $rv) { + return $dbh->last_insert_id(undef, undef, "subscription_frequencies", undef); + } + + return $rv; +} + +=head3 ModSubscriptionFrequency + +=over 4 + +=item &ModSubscriptionFrequency($frequency); + +Modifies a frequency + +=item C<$frequency> is a hashref that can contains the following keys + +=over 2 + +=item * id + +=item * description + +=item * unit + +=item * issuesperunit + +=item * unitsperissue + +=item * expectedissuesayear + +=item * displayorder + +=back + +Only id is mandatory. + +=back + +=cut + +sub ModSubscriptionFrequency { + my $frequency = shift; + + unless( + ref($frequency) eq 'HASH' + && defined $frequency->{'id'} && $frequency->{'id'} > 0 + && ( + (defined $frequency->{'description'} + && $frequency->{'description'} ne '') + || !defined $frequency->{'description'} + ) + ) { + return undef; + } + + my @keys; + my @values; + foreach (qw/ description unit issuesperunit unitsperissue expectedissuesayear displayorder /) { + if(exists $frequency->{$_}) { + push @keys, $_; + push @values, $frequency->{$_}; + } + } + + my $dbh = C4::Context->dbh; + my $query = "UPDATE subscription_frequencies"; + $query .= ' SET ' . join(' = ?,', @keys) . ' = ?'; + $query .= ' WHERE id = ?'; + my $sth = $dbh->prepare($query); + + return $sth->execute(@values, $frequency->{'id'}); +} + +=head3 DelSubscriptionFrequency + +=over 4 + +=item &DelSubscriptionFrequency($frequencyid); + +Delete a frequency + +=back + +=cut + +sub DelSubscriptionFrequency { + my $frequencyid = shift; + + my $dbh = C4::Context->dbh; + my $query = qq{ + DELETE FROM subscription_frequencies + WHERE id = ? + }; + my $sth = $dbh->prepare($query); + $sth->execute($frequencyid); +} + +1; + +__END__ + +=head1 AUTHOR + +Koha Developement team + +=cut diff --git a/C4/Serials/Numberpattern.pm b/C4/Serials/Numberpattern.pm new file mode 100644 index 0000000..1fb5ea9 --- /dev/null +++ b/C4/Serials/Numberpattern.pm @@ -0,0 +1,266 @@ +package C4::Serials::Numberpattern; + +# Copyright 2000-2002 Biblibre SARL +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use strict; +use warnings; + +use C4::Context; + +use vars qw($VERSION @ISA @EXPORT); + +BEGIN { + + # set the version for version checking + $VERSION = 3.01; + require Exporter; + @ISA = qw(Exporter); + @EXPORT = qw( + &GetSubscriptionNumberpatterns + &GetSubscriptionNumberpattern + &GetSubscriptionNumberpatternByName + &AddSubscriptionNumberpattern + &ModSubscriptionNumberpattern + &DelSubscriptionNumberpattern + + ); +} + +=head3 GetSubscriptionNumberpatterns + +=over 4 + +@results = GetSubscriptionNumberpatterns; +this function get all subscription number patterns entered in table + +=back + +=cut + +sub GetSubscriptionNumberpatterns { + my $dbh = C4::Context->dbh; + my $query = qq{ + SELECT * + FROM subscription_numberpatterns + ORDER by displayorder + }; + my $sth = $dbh->prepare($query); + $sth->execute; + my $results = $sth->fetchall_arrayref({}); + + return @$results; +} + +=head3 GetSubscriptionNumberpattern + +=over 4 + +$result = GetSubscriptionNumberpattern($numberpatternid); +this function get the data of the subscription numberpatterns which id is $numberpatternid + +=back + +=cut + +sub GetSubscriptionNumberpattern { + my $numberpatternid = shift; + my $dbh = C4::Context->dbh; + my $query = qq( + SELECT * + FROM subscription_numberpatterns + WHERE id = ? + ); + my $sth = $dbh->prepare($query); + $sth->execute($numberpatternid); + + return $sth->fetchrow_hashref; +} + +=head3 GetSubscriptionNumberpatternByName + +=over 4 + +$result = GetSubscriptionNumberpatternByName($name); +this function get the data of the subscription numberpatterns which name is $name + +=back + +=cut + +sub GetSubscriptionNumberpatternByName { + my $name = shift; + my $dbh = C4::Context->dbh; + my $query = qq( + SELECT * + FROM subscription_numberpatterns + WHERE label = ? + ); + my $sth = $dbh->prepare($query); + my $rv = $sth->execute($name); + + return $sth->fetchrow_hashref; +} + +=head3 AddSubscriptionNumberpattern + +=over 4 + +=item C<$numberpatternid> = &AddSubscriptionNumberpattern($numberpattern) + +Add a new numberpattern + +=item C<$frequency> is a hashref that contains values of the number pattern + +=item Only label and numberingmethod are mandatory + +=back + +=cut + +sub AddSubscriptionNumberpattern { + my $numberpattern = shift; + + unless( + ref($numberpattern) eq 'HASH' + && defined $numberpattern->{'label'} + && $numberpattern->{'label'} ne '' + && defined $numberpattern->{'numberingmethod'} + && $numberpattern->{'numberingmethod'} ne '' + ) { + return undef; + } + + my @keys; + my @values; + foreach (qw/ label description numberingmethod displayorder + label1 label2 label3 add1 add2 add3 every1 every2 every3 + setto1 setto2 setto3 whenmorethan1 whenmorethan2 whenmorethan3 + numbering1 numbering2 numbering3 /) { + if(exists $numberpattern->{$_}) { + push @keys, $_; + push @values, $numberpattern->{$_}; + } + } + + my $dbh = C4::Context->dbh; + my $query = "INSERT INTO subscription_numberpatterns"; + $query .= '(' . join(',', @keys) . ')'; + $query .= ' VALUES (' . ('?,' x (scalar(@keys)-1)) . '?)'; + my $sth = $dbh->prepare($query); + my $rv = $sth->execute(@values); + + if(defined $rv) { + return $dbh->last_insert_id(undef, undef, "subscription_numberpatterns", undef); + } + + return $rv; +} + +=head3 ModSubscriptionNumberpattern + +=over 4 + +=item &ModSubscriptionNumberpattern($numberpattern) + +Modifies a numberpattern + +=item C<$frequency> is a hashref that contains values of the number pattern + +=item Only id is mandatory + +=back + +=cut + +sub ModSubscriptionNumberpattern { + my $numberpattern = shift; + + unless( + ref($numberpattern) eq 'HASH' + && defined $numberpattern->{'id'} + && $numberpattern->{'id'} > 0 + && ( + (defined $numberpattern->{'label'} + && $numberpattern->{'label'} ne '') + || !defined $numberpattern->{'label'} + ) + && ( + (defined $numberpattern->{'numberingmethod'} + && $numberpattern->{'numberingmethod'} ne '') + || !defined $numberpattern->{'numberingmethod'} + ) + ) { + return undef; + } + + my @keys; + my @values; + foreach (qw/ label description numberingmethod displayorder + label1 label2 label3 add1 add2 add3 every1 every2 every3 + setto1 setto2 setto3 whenmorethan1 whenmorethan2 whenmorethan3 + numbering1 numbering2 numbering3 /) { + if(exists $numberpattern->{$_}) { + push @keys, $_; + push @values, $numberpattern->{$_}; + } + } + + my $dbh = C4::Context->dbh; + my $query = "UPDATE subscription_numberpatterns"; + $query .= ' SET ' . join(' = ?,', @keys) . ' = ?'; + $query .= ' WHERE id = ?'; + my $sth = $dbh->prepare($query); + + return $sth->execute(@values, $numberpattern->{'id'}); +} + +=head3 DelSubscriptionNumberpattern + +=over 4 + +=item &DelSubscriptionNumberpattern($numberpatternid) + +Delete a number pattern + +=back + +=cut + +sub DelSubscriptionNumberpattern { + my $numberpatternid = shift; + + my $dbh = C4::Context->dbh; + my $query = qq{ + DELETE FROM subscription_numberpatterns + WHERE id = ? + }; + my $sth = $dbh->prepare($query); + $sth->execute($numberpatternid); +} + + + +1; + +__END__ + +=head1 AUTHOR + +Koha Developement team + +=cut diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index 1674b97..75cd46e 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -1895,7 +1895,7 @@ CREATE TABLE `subscription` ( `monthlength` int(11) default 0, `numberlength` int(11) default 0, `periodicity` tinyint(4) default 0, - countissuesperunit INTEGER NOT NULL DEFAULT 0, + countissuesperunit INTEGER NOT NULL DEFAULT 1, `notes` mediumtext, `status` varchar(100) NOT NULL default '', `lastvalue1` int(11) default NULL, diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index 1e55fb9..9c53a35 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -5658,7 +5658,7 @@ if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { DROP COLUMN dow, DROP COLUMN issuesatonce, DROP COLUMN hemisphere, - ADD COLUMN countissuesperunit INTEGER NOT NULL DEFAULT 0 AFTER periodicity, + ADD COLUMN countissuesperunit INTEGER NOT NULL DEFAULT 1 AFTER periodicity, ADD COLUMN skip_serialseq BOOLEAN NOT NULL DEFAULT 0 AFTER irregularity, ADD COLUMN locale VARCHAR(80) DEFAULT NULL AFTER numberpattern, ADD CONSTRAINT subscription_ibfk_1 FOREIGN KEY (periodicity) REFERENCES subscription_frequencies (id), diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/serials-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/serials-menu.inc index 0feafda..4d131bf 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/serials-menu.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/serials-menu.inc @@ -18,4 +18,14 @@ [% IF ( CAN_user_serials_check_expiration ) %]
  • Check expiration
  • [% END %] +
  • + + Manage frequencies + +
  • +
  • + + Manage numbering patterns + +
  • diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-collection.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-collection.tt index 23b496b..4078f8c 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-collection.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-collection.tt @@ -88,64 +88,11 @@ $(document).ready(function() { [% FOREACH subscription IN subscriptions %] [% UNLESS ( loop.odd ) %][% ELSE %][% END %] - # [% subscription.subscriptionid %] - [% IF ( subscription.periodicity1 ) %] - 1/day - [% END %] - [% IF ( subscription.periodicity2 ) %] - 1/week - [% END %] - [% IF ( subscription.periodicity3 ) %] - 1/2 weeks - [% END %] - [% IF ( subscription.periodicity4 ) %] - 1/3 weeks - [% END %] - [% IF ( subscription.periodicity5 ) %] - 1/Month - [% END %] - [% IF ( subscription.periodicity6 ) %] - 1/2 Months (6/year) - [% END %] - [% IF ( subscription.periodicity7 ) %] - 1/quarter - [% END %] - [% IF ( subscription.periodicity8 ) %] - 1/quarter - [% END %] - [% IF ( subscription.periodicity9 ) %] - 2/year - [% END %] - [% IF ( subscription.periodicity10 ) %] - 1/year - [% END %] - [% IF ( subscription.periodicity11 ) %] - 1/2 years - [% END %] - - [% IF ( subscription.numberpattern1 ) %] - Number - [% END %] - [% IF ( subscription.numberpattern2 ) %] - Volume, number, issue - [% END %] - [% IF ( subscription.numberpattern3 ) %] - Volume, number - [% END %] - [% IF ( subscription.numberpattern4 ) %] - Volume, issue - [% END %] - [% IF ( subscription.numberpattern5 ) %] - Number, issue - [% END %] - [% IF ( subscription.numberpattern6 ) %] - Seasonal only - [% END %] - [% IF ( subscription.numberpattern7 ) %] - None of the above - [% END %] - [% subscription.branchcode %] - [% subscription.callnumber %] + # [% subscription.subscriptionid %] + [% subscription.frequency.description %] + [% subscription.numberpattern.label %] + [% subscription.branchcode %] + [% subscription.callnumber %] [% subscription.notes %] [% IF ( subscription.subscriptionexpired ) %]
    Subscription expired [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/showpredictionpattern.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/showpredictionpattern.tt new file mode 100644 index 0000000..a44bc9a --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/showpredictionpattern.tt @@ -0,0 +1,83 @@ +[% USE KohaDates %] + +

    Prediction pattern

    +[% IF (not_consistent_end_date) %] +

    End date is not consistent with subscription length.

    +[% END %] +[% IF (ask_for_irregularities) %] +

    Please check issues that are NOT published (irregularities)

    + [% IF (daily_options) %] + +

    + If there is a day (or more) in the week where issues are never + published, you can check corresponding boxes below. +

    + + + + + + + + + + + + + + + [% END %] +[% END %] +[% IF (predictions_loop) %] + + + + + + [% IF (ask_for_irregularities) %] + + [% END %] + + + + [% FOREACH prediction IN predictions_loop %] + + + + [% IF (ask_for_irregularities) %] + + [% END %] + [% END %] + + [% END %] + +
    NumberPublication DateNot published
    [% prediction.number %] + [% IF (prediction.publicationdate) %] + [% prediction.publicationdate | $KohaDates %] + [% ELSE %] + unknown + [% END %] + + [% UNLESS (loop.first) %] + [% IF (prediction.not_published) %] + + [% ELSE %] + + [% END %] +
    +[% END %] + diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-add.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-add.tt index 4ab5c11..43de538 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-add.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-add.tt @@ -1,3 +1,5 @@ +[% USE KohaDates %] + [% INCLUDE 'doc-head-open.inc' %] Koha › Serials › [% IF ( modify ) %][% bibliotitle |html %] › Modify subscription[% ELSE %]New subscription[% END %] [% INCLUDE 'doc-head-close.inc' %] @@ -11,952 +13,420 @@ fieldset.rows li.radio { width: 100%; } /* override staff-global.css */ @@ -978,6 +450,7 @@ $(document).ready(function() {
    +<<<<<<< HEAD

    [% IF ( modify ) %] Modify subscription for [% bibliotitle |html %][% ELSE %]Add a new subscription[% END %]

    @@ -1211,9 +684,19 @@ $(document).ready(function() { [% END %] [% IF ( periodicity13 ) %] +======= +
    +
    +

    [% IF ( modify ) %] Modify subscription for [% bibliotitle |html %][% ELSE %]Add a new subscription[% END %] (1/2)

    +
    + [% IF ( modify ) %] + + +>>>>>>> Bug 7688: Change subscription numbering pattern and frequencies [% ELSE %] - + [% END %] +<<<<<<< HEAD [% IF ( periodicity9 ) %] @@ -1387,6 +870,418 @@ $(document).ready(function() {
    +======= + + + +
    +
    +
    + Subscription details +
      + [% IF ( subscriptionid ) %] +
    1. Subscription # [% subscriptionid %]
    2. + [% END %] +
    3. + + () Search for a vendor +
    4. +
    5. + + + () Required +
      Search for Biblio + [% IF ( CAN_user_editcatalogue ) %] + [% IF ( modify ) %] + | Edit biblio + [% ELSE %] + | Create Biblio + [% END %] + [% END %] +
      +
    6. +
    7. + [% IF ( serialsadditems ) %] +

      +

      + [% ELSE %] +

      +

      + [% END %] +
    8. +
    9. +

      When there is an irregular issue:

      + [% IF (skip_serialseq) %] +

      + + +

      +

      + + +

      + [% ELSE %] +

      + + +

      +

      + + +

      + [% END %] +
    10. +
    11. + + [% IF (manualhistory) %] + + [% ELSE %] + + [% END %] +
    12. +
    13. + + +
    14. +
    15. + + (select a library) +
    16. +
    17. + + +
    18. +
    19. + + +
    20. +
    21. + [% IF ( letterloop ) %] + + +
      Select a notice and patrons on the routing list will be notified when new issues are received.
      + [% ELSE %] + Patron notification: +
      To notify patrons of new serial issues, you must define a notice.
      + [% END %] +
    22. +
    23. + + +
    24. +
    25. + + day(s) +
    26. +
    27. + + +
    28. +
    29. + + +
    30. +
    +
    +
    + +
    +
    +
    + +
    +
    +
    +
    + Serials planning +
      +
    1. + + [% UNLESS (more_than_one_serial) %] + + Show Calendar + + + + [% ELSE %] + [% firstacquidate %] + + [% END %] +
    2. + [% IF (more_than_one_serial) %] +
    3. + + + Show Calendar + + +
    4. + [% END %] +
    5. + + +
    6. +
    7. + + + (enter amount in numerals) + +
    8. +
    9. + + + Show Calendar + + + +
    10. +
    11. + + + Χ + Show Calendar + + + +
    12. +
    13. + + +
    14. +
    15. + + + If empty, system locale is used +
    16. +
    17. + + + + + + + + + + + + + + + + + + + + + + + +
          
      + [% IF (more_than_one_serial) %] + Last value + [% ELSE %] + Begins with + [% END %] +
      Inner counter
      +
    18. +
    19. Show/Hide advanced pattern
    20. + +
    +
    +
    + + + +
    +
    +
    +
    +
  • +
    +
    + +
    +
    +>>>>>>> Bug 7688: Change subscription numbering pattern and frequencies
    [% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-detail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-detail.tt index 1afd0c1..c41f96d 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-detail.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-detail.tt @@ -8,21 +8,6 @@ var text = new Array(_("Number"),_("Volume"),_("Issue"),_("Month"),_("Week"),_(" "Autumn"),_("Winter"),_("Spring"),_("Summer"),_("Fall"),_("Season"),_("Year")); -// to display the options section -function options(x,y,z){ -var textbox = ''; - // alert("X: "+x+"Y: "+y+"Z: "+z); - if(x){ - document.f.xfield.value = x; - if(y){ - document.f.yfield.value = y; - if(z){ - document.f.zfield.value = z; - } - } - } -} - function confirm_deletion() { var is_confirmed = confirm(_("Are you sure you want to delete this subscription?")); if (is_confirmed) { @@ -103,6 +88,14 @@ $(document).ready(function() { [% ELSE %]
  • Items: Serial receipt does not create an item record.
  • [% END %] +
  • + Serial number: + [% IF skip_serialseq %] + Serial number is skipped when an irregularity is found. + [% ELSE %] + Serial number is kept when an irregularity is found. + [% END %] +
  • Grace period: [% graceperiod %]
  • @@ -132,118 +125,44 @@ $(document).ready(function() {
    1. Beginning date: [% startdate %]
    2. -
    3. Frequency (*): - [% IF ( periodicity16 ) %] - Without regularity - [% END %] - [% IF ( periodicity32 ) %] - Irregular - [% END %] - [% IF ( periodicity0 ) %] - Unknown - [% END %] - [% IF ( periodicity12 ) %] - 2/day - [% END %] - [% IF ( periodicity1 ) %] - 1/day - [% END %] - [% IF ( periodicity13 ) %] - 1/4 months (3/year) - [% END %] - [% IF ( periodicity2 ) %] - 1/week - [% END %] - [% IF ( periodicity3 ) %] - 1/2 weeks - [% END %] - [% IF ( periodicity4 ) %] - 1/3 weeks - [% END %] - [% IF ( periodicity5 ) %] - 1/month - [% END %] - [% IF ( periodicity6 ) %] - 1/2 months (6/year) - [% END %] - [% IF ( periodicity7 ) %] - 1/quarter - [% END %] - [% IF ( periodicity8 ) %] - 1/quarter - [% END %] - [% IF ( periodicity9 ) %] - 2/year - [% END %] - [% IF ( periodicity10 ) %] - 1/year - [% END %] - [% IF ( periodicity11 ) %] - 1/2 years - [% END %] +
    4. Frequency: + [% frequency.description %]
    5. Manual history: [% IF ( manualhistory ) %] - Disabled + Enabled Edit history [% ELSE %] - Enabled + Disabled [% END %]
    6. Number pattern: - [% IF ( numberpattern1 ) %] - Number only - [% END %] - [% IF ( numberpattern2 ) %] - Volume, number, issue - [% END %] - [% IF ( numberpattern3 ) %] - Volume, number + [% numberpattern.label %] +
    7. +
    8. + + + [% IF (has_X) %] + [% END %] - [% IF ( numberpattern4 ) %] - Volume, issue + [% IF (has_Y) %] + [% END %] - [% IF ( numberpattern5 ) %] - Number, issue + [% IF (has_Z) %] + [% END %] - [% IF ( numberpattern8 ) %] - Year/Number + + + + [% IF (has_X) %] + [% END %] - [% IF ( numberpattern6 ) %] - Seasonal only + [% IF (has_Y) %] + [% END %] - [% IF ( numberpattern7 ) %] - None of the above + [% IF (has_Z) %] + [% END %] - -
    9. Starting with:[% lastvalue1 %][% lastvalue2 %][% lastvalue3 %]
      Rollover:[% numberpattern.whenmorethan1 %][% numberpattern.whenmorethan2 %][% numberpattern.whenmorethan3 %]
      - - - [% IF ( lastvalue2 ) %] - - [% END %] - [% IF ( lastvalue3 ) %] - - [% END %] - - - - [% IF ( whenmorethan2 ) %] - - [% END %] - [% IF ( whenmorethan3 ) %] - - [% END %]
      Starting with:[% lastvalue1 %]  - [% lastvalue2 %] -   - [% lastvalue3 %] -
      Rollover: - [% IF ( whenmorethan1 < 9999999 ) %][% whenmorethan1 %][% ELSE %]Never[% END %] -   - [% IF ( whenmorethan2 < 9999999 ) %][% whenmorethan2 %][% ELSE %]Never[% END %] -   - [% IF ( whenmorethan3 < 9999999 ) %][% whenmorethan3 %][% ELSE %]Never[% END %] -
    10. [% IF ( irregular_issues ) %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-frequencies.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-frequencies.tt new file mode 100644 index 0000000..d390042 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-frequencies.tt @@ -0,0 +1,185 @@ +[% INCLUDE 'doc-head-open.inc' %] +Koha › Serials › Frequencies +[% INCLUDE 'doc-head-close.inc' %] + + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'serials-search.inc' %] + + + +
      + +
      +
      +
      + [% IF (new or modify) %] + [% IF (new) %] +

      New frequency

      + [% ELSE %] +

      Modify frequency: [% description %]

      + [% END %] +
      + [% IF (modify) %] + + + [% ELSE %] + + [% END %] +
      +
        +
      1. + + +
      2. +
      3. + + +
      4. +
      5. Note: one of the two following fields must be equal to 1
      6. +
      7. + + [% IF (new) %] + + [% ELSE %] + + [% END %] +
      8. +
      9. + + [% IF (new) %] + + [% ELSE %] + + [% END %] +
      10. +
      11. + + +
      12. +
      +
      +
      + + +
      +
      + [% ELSE %] + New frenquency + + [% IF (frequencies_loop.size) %] +

      Frenquencies

      + + + + + + + + + + + + + [% FOREACH frequency IN frequencies_loop %] + + + + + + + + + [% END %] + +
      DescriptionUnitIssues per unitUnits per issueDisplay order 
      [% frequency.description %][% frequency.unit %][% frequency.issuesperunit %][% frequency.unitsperissue %][% frequency.displayorder %] + Modify | + Delete +
      + [% ELSE %] +

      There is no defined frequency.

      + [% END %] + [% END %] + +
      +
      +
      + [% INCLUDE 'serials-menu.inc' %] +
      +
      +[% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-history.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-history.tt new file mode 100644 index 0000000..ef35f31 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-history.tt @@ -0,0 +1,60 @@ +[% USE KohaDates %] + +[% INCLUDE 'doc-head-open.inc' %] +Koha › Serials › Subscription history +[% INCLUDE 'doc-head-close.inc' %] + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'serials-search.inc' %] + + + +
      + +
      +
      +
      +

      Subscription history for [% title %]

      +
      +
      + + +

      Hint : you can update the serial history manually. This can be useful for an old subscription or to clean the existing history. Modify those fields with care, as future serial recieve will continue to update them automatically.

      + + + + + + + + + + + + + + + + + + + + + + + + + +
      Subscription start date (start date of the 1st subscription)
      Subscription end date(if empty, subscription is still active)
      Received issues
      Missing issues
      Note for OPAC
      Note for staff
      + +
      +
      +
      +
      +
      + [% INCLUDE 'serials-menu.inc' %] +
      +
      +[% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-numberpatterns.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-numberpatterns.tt new file mode 100644 index 0000000..72a3885 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-numberpatterns.tt @@ -0,0 +1,289 @@ +[% INCLUDE 'doc-head-open.inc' %] +Koha › Serials › Number patterns +[% INCLUDE 'doc-head-close.inc' %] +[% INCLUDE 'calendar.inc' %] + + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'serials-search.inc' %] + + + +
      + +
      +
      +
      + [% IF (new or modify) %] +
      + [% IF (new) %] +

      New number pattern

      + [% IF (error_existing_numberpattern) %] +
      +

      A pattern with this name already exists.

      +
      + [% END %] + [% ELSE %] +

      Modify pattern: [% label %]

      + [% IF (error_existing_numberpattern) %] +
      +

      Another pattern with this name already exists.

      +
      + [% END %] + [% END %] +
      +
      +
      + [% IF (new) %] + + [% ELSE %] + + + [% END %] +
      +
        +
      1. + + +
      2. +
      3. + + +
      4. +
      5. + + +
      6. +
      7. + + +
      8. +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
       XYZ
      Label
      Add
      Every
      Set back to
      When more than
      Numbering
      +
      +
      + + + +
      +
      +
      +
      +
      +
      + Test prediction pattern +
        +
      1. + + +
      2. +
      3. + + + Show Calendar + +
      4. +
      5. + + + +
      6. +
      7. + + + If empty, system locale is used +
      8. +
      + + + + + + + + + + + + + + + + + + + + + + + +
       XYZ
      Begins with
      Inner counter
      +
      + +
      +
      +
      +
      +
      + [% ELSE %] +

      Number patterns

      + New numbering pattern + [% IF (numberpatterns_loop.size) %] + + + + + + + + + + + + [% FOREACH numberpattern IN numberpatterns_loop %] + + + + + + + + [% END %] + +
      NameDescriptionNumbering formulaDisplay order 
      [% numberpattern.label %][% numberpattern.description %][% numberpattern.numberingmethod %][% numberpattern.displayorder %] + Edit | + Delete +
      + [% ELSE %] +

      There is no existing patterns.

      + [% END %] + [% END %] +
      +
      +
      + [% INCLUDE 'serials-menu.inc' %] +
      +
      +[% INCLUDE 'intranet-bottom.inc' %] diff --git a/serials/create-numberpattern.pl b/serials/create-numberpattern.pl new file mode 100755 index 0000000..d5e6abf --- /dev/null +++ b/serials/create-numberpattern.pl @@ -0,0 +1,42 @@ +#!/usr/bin/perl + +use CGI; +use C4::Context; +use C4::Serials::Numberpattern; +use URI::Escape; +use strict; +use warnings; + +my $input = new CGI; + +my $numberpattern; +foreach (qw/ numberingmethod label1 label2 label3 add1 add2 add3 + every1 every2 every3 setto1 setto2 setto3 whenmorethan1 whenmorethan2 + whenmorethan3 numbering1 numbering2 numbering3 locale /) { + $numberpattern->{$_} = $input->param($_); +} +# patternname is label in database +$numberpattern->{'label'} = $input->param('patternname'); + +# Check if pattern already exist in database +my $dbh = C4::Context->dbh; +my $query = qq{ + SELECT id + FROM subscription_numberpatterns + WHERE STRCMP(label, ?) = 0 +}; +my $sth = $dbh->prepare($query); +my $rv = $sth->execute($numberpattern->{'label'}); +my $numberpatternid; +if($rv == 0) { + # Pattern does not exists + $numberpatternid = AddSubscriptionNumberpattern($numberpattern); +} else { + ($numberpatternid) = $sth->fetchrow_array; + $numberpattern->{'id'} = $numberpatternid; + ModSubscriptionNumberpattern($numberpattern); +} + +binmode STDOUT, ":utf8"; +print $input->header(-type => 'text/plain', -charset => 'UTF-8'); +print "{\"numberpatternid\":\"$numberpatternid\"}"; diff --git a/serials/serials-collection.pl b/serials/serials-collection.pl index 610de60..2a802fa 100755 --- a/serials/serials-collection.pl +++ b/serials/serials-collection.pl @@ -103,9 +103,6 @@ if (@subscriptionid){ $subs->{missinglist} =~ s/\n/\/g; $subs->{recievedlist} =~ s/\n/\/g; ##these are display information - $subs->{ "periodicity" . $subs->{periodicity} } = 1; - $subs->{ "numberpattern" . $subs->{numberpattern} } = 1; - $subs->{ "status" . $subs->{'status'} } = 1; $subs->{startdate} = format_date( $subs->{startdate} ); $subs->{histstartdate} = format_date( $subs->{histstartdate} ); if ( !defined $subs->{enddate} || $subs->{enddate} eq '0000-00-00' ) { @@ -119,6 +116,10 @@ if (@subscriptionid){ $subs->{'subscriptionid'} = $subscriptionid; # FIXME - why was this lost ? $location = GetAuthorisedValues('LOC', $subs->{'location'}); $callnumber = $subs->{callnumber}; + my $frequency = C4::Serials::Frequency::GetSubscriptionFrequency($subs->{periodicity}); + my $numberpattern = C4::Serials::Numberpattern::GetSubscriptionNumberpattern($subs->{numberpattern}); + $subs->{frequency} = $frequency; + $subs->{numberpattern} = $numberpattern; push @$subscriptiondescs,$subs; my $tmpsubscription= GetFullSubscription($subscriptionid); @subscriptioninformation=(@$tmpsubscription,@subscriptioninformation); @@ -147,6 +148,7 @@ foreach (@$location) { $locationlib = $_->{'lib'} if $_->{'selected'}; } + chop $subscriptionidlist; $template->param( subscriptionidlist => $subscriptionidlist, @@ -164,6 +166,6 @@ $template->param( location => $locationlib, callnumber => $callnumber, uc(C4::Context->preference("marcflavour")) => 1 - ); +); output_html_with_http_headers $query, $cookie, $template->output; diff --git a/serials/serials-recieve.pl b/serials/serials-recieve.pl index 770d10d..c14e4d0 100755 --- a/serials/serials-recieve.pl +++ b/serials/serials-recieve.pl @@ -192,10 +192,7 @@ for(my $i=0;$i<$count;$i++){ $serialslist[$i]->{'barcode'} = "TEMP" . sprintf("%.0f",$temp); } -my $sth= C4::Serials::GetSubscriptionHistoryFromSubscriptionId(); - -$sth->execute($subscriptionid); -my $solhistory = $sth->fetchrow_hashref; +my $solhistory = GetSubscriptionHistoryFromSubscriptionId($subscriptionid); $subs = &GetSubscription($subscriptionid); ($totalissues,@serialslist) = GetSerials($subscriptionid); @@ -253,9 +250,7 @@ if (C4::Context->preference("serialsadditems")){ $template->param(branchloop=>[],itemstatusloop=>[],itemlocationloop=>[]) ; } -$sth= C4::Serials::GetSubscriptionHistoryFromSubscriptionId(); -$sth->execute($subscriptionid); -$solhistory = $sth->fetchrow_hashref; +$solhistory = GetSubscriptionHistoryFromSubscriptionId($subscriptionid); $template->param( user => $auser, diff --git a/serials/showpredictionpattern.pl b/serials/showpredictionpattern.pl new file mode 100755 index 0000000..e56695c --- /dev/null +++ b/serials/showpredictionpattern.pl @@ -0,0 +1,194 @@ +#!/usr/bin/perl + +# Copyright 2011 BibLibre SARL +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +=head1 NAME + +showpredictionpattern.pl + +=head1 DESCRIPTION + +This script calculate numbering of serials based on numbering pattern, and +publication date, based on frequency and first publication date. + +=cut + +use Modern::Perl; + +use CGI; +use Date::Calc qw(Today Day_of_Year Week_of_Year Day_of_Week Days_in_Year Delta_Days Add_Delta_Days Add_Delta_YM); +use C4::Auth; +use C4::Output; +use C4::Serials; +use C4::Serials::Frequency; + +my $input = new CGI; +my ($template, $loggedinuser, $cookie, $flags) = get_template_and_user( { + template_name => 'serials/showpredictionpattern.tt', + query => $input, + type => 'intranet', + authnotrequired => 0, + flagsrequired => { 'serials' => '*' }, +} ); + +my $subscriptionid = $input->param('subscriptionid'); +my $frequencyid = $input->param('frequency'); +my $firstacquidate = $input->param('firstacquidate'); +my $nextacquidate = $input->param('nextacquidate'); +my $enddate = $input->param('enddate'); +my $subtype = $input->param('subtype'); +my $sublength = $input->param('sublength'); +my $custompattern = $input->param('custompattern'); + + +my %val = ( + locale => $input->param('locale') // '', + numberingmethod => $input->param('numberingmethod') // '', + numbering1 => $input->param('numbering1') // '', + numbering2 => $input->param('numbering2') // '', + numbering3 => $input->param('numbering3') // '', + lastvalue1 => $input->param('lastvalue1') // '', + lastvalue2 => $input->param('lastvalue2') // '', + lastvalue3 => $input->param('lastvalue3') // '', + add1 => $input->param('add1') // '', + add2 => $input->param('add2') // '', + add3 => $input->param('add3') // '', + whenmorethan1 => $input->param('whenmorethan1') // '', + whenmorethan2 => $input->param('whenmorethan2') // '', + whenmorethan3 => $input->param('whenmorethan3') // '', + setto1 => $input->param('setto1') // '', + setto2 => $input->param('setto2') // '', + setto3 => $input->param('setto3') // '', + every1 => $input->param('every1') // '', + every2 => $input->param('every2') // '', + every3 => $input->param('every3') // '', + innerloop1 => $input->param('innerloop1') // '', + innerloop2 => $input->param('innerloop2') // '', + innerloop3 => $input->param('innerloop3') // '', +); + +if(!defined $firstacquidate || $firstacquidate eq ''){ + my ($year, $month, $day) = Today(); + $firstacquidate = sprintf "%04d-%02d-%02d", $year, $month, $day; +} else { + $firstacquidate = C4::Dates->new($firstacquidate)->output('iso'); +} + +if($enddate){ + $enddate = C4::Dates->new($enddate)->output('iso'); +} + +if($nextacquidate) { + $nextacquidate = C4::Dates->new($nextacquidate)->output('iso'); +} else { + $nextacquidate = $firstacquidate; +} +my $date = $nextacquidate; + +my %subscription = ( + irregularity => '', + periodicity => $frequencyid, + countissuesperunit => 1, + firstacquidate => $firstacquidate, +); + +my $issuenumber; +if(defined $subscriptionid) { + ($issuenumber) = C4::Serials::GetFictiveIssueNumber(\%subscription, $date); +} else { + $issuenumber = 1; +} + +my @predictions_loop; +my ($calculated) = GetSeq(\%val); +push @predictions_loop, { + number => $calculated, + publicationdate => $date, + issuenumber => $issuenumber, + dow => Day_of_Week(split /-/, $date), +}; +my @irreg = (); +if(defined $subscriptionid) { + @irreg = C4::Serials::GetSubscriptionIrregularities($subscriptionid); + while(@irreg && $issuenumber > $irreg[0]) { + shift @irreg; + } + if(@irreg && $issuenumber == $irreg[0]){ + $predictions_loop[0]->{'not_published'} = 1; + shift @irreg; + } +} + +my $i = 1; +while( $i < 1000 ) { + my %line; + + if(defined $date){ + $date = GetNextDate(\%subscription, $date); + } + if(defined $date){ + $line{'publicationdate'} = $date; + $line{'dow'} = Day_of_Week(split /-/, $date); + } + + # Check if we don't have exceed end date + if($sublength){ + if($subtype eq "issues" && $i >= $sublength){ + last; + } elsif($subtype eq "weeks" && $date && Delta_Days( split(/-/, $date), Add_Delta_Days( split(/-/, $firstacquidate), 7*$sublength - 1 ) ) < 0) { + last; + } elsif($subtype eq "months" && $date && (Delta_Days( split(/-/, $date), Add_Delta_YM( split(/-/, $firstacquidate), 0, $sublength) ) - 1) < 0 ) { + last; + } + } + if($enddate && $date && Delta_Days( split(/-/, $date), split(/-/, $enddate) ) <= 0 ) { + last; + } + + ($calculated, $val{'lastvalue1'}, $val{'lastvalue2'}, $val{'lastvalue3'}, $val{'innerloop1'}, $val{'innerloop2'}, $val{'innerloop3'}) = GetNextSeq(\%val); + $issuenumber++; + $line{'number'} = $calculated; + $line{'issuenumber'} = $issuenumber; + if(@irreg && $issuenumber == $irreg[0]){ + $line{'not_published'} = 1; + shift @irreg; + } + push @predictions_loop, \%line; + + $i++; +} + +$template->param( + predictions_loop => \@predictions_loop, +); + +my $frequency = GetSubscriptionFrequency($frequencyid); + +if ( $frequency->{unit} and not $custompattern ) { + $template->param( ask_for_irregularities => 1 ); + if ( $frequency->{unit} eq 'day' and $frequency->{unitsperissue} == 1 ) { + $template->param( daily_options => 1 ); + } +} + +if ( ( $date && $enddate && $date ne $enddate ) + or ( $subtype eq 'issues' && $i < $sublength ) ) +{ + $template->param( not_consistent_end_date => 1 ); +} + +output_html_with_http_headers $input, $cookie, $template->output; diff --git a/serials/subscription-add.pl b/serials/subscription-add.pl index a3306ea..a02643f 100755 --- a/serials/subscription-add.pl +++ b/serials/subscription-add.pl @@ -19,7 +19,7 @@ use strict; use warnings; use CGI; -use Date::Calc qw(Today Day_of_Year Week_of_Year Add_Delta_Days); +use Date::Calc qw(Today Day_of_Year Week_of_Year Add_Delta_Days Add_Delta_YM); use C4::Koha; use C4::Biblio; use C4::Auth; @@ -29,6 +29,8 @@ use C4::Output; use C4::Context; use C4::Branch; # GetBranches use C4::Serials; +use C4::Serials::Frequency; +use C4::Serials::Numberpattern; use C4::Letters; use Carp; @@ -46,7 +48,7 @@ my @budgets; my $permission = ($op eq "modify") ? "edit_subscription" : "create_subscription"; my ($template, $loggedinuser, $cookie) -= get_template_and_user({template_name => "serials/subscription-add.tmpl", += get_template_and_user({template_name => "serials/subscription-add.tt", query => $query, type => "intranet", authnotrequired => 0, @@ -57,9 +59,7 @@ my ($template, $loggedinuser, $cookie) my $sub_on; -my @subscription_types = ( - 'issues', 'weeks', 'months' - ); +my @subscription_types = (qw(issues weeks months)); my @sub_type_data; my $subs; @@ -89,10 +89,10 @@ if ($op eq 'modify' || $op eq 'dup' || $op eq 'modsubscription') { } letter_loop($subs->{'letter'}, $template); my $nextexpected = GetNextExpected($subscriptionid); - $nextexpected->{'isfirstissue'} = $nextexpected->{planneddate}->output('iso') eq $firstissuedate ; - $subs->{nextacquidate} = $nextexpected->{planneddate}->output() if($op eq 'modify'); + $nextexpected->{'isfirstissue'} = $nextexpected->{planneddate} eq $firstissuedate ; + $subs->{nextacquidate} = $nextexpected->{planneddate} if($op eq 'modify'); unless($op eq 'modsubscription') { - foreach my $length_unit qw(numberlength weeklength monthlength){ + foreach my $length_unit (qw(numberlength weeklength monthlength)){ if ($subs->{$length_unit}){ $sub_length=$subs->{$length_unit}; $sub_on=$length_unit; @@ -101,16 +101,20 @@ if ($op eq 'modify' || $op eq 'dup' || $op eq 'modsubscription') { } $template->param( %{$subs} ); - $template->param("dow".$subs->{'dow'} => 1) if defined $subs->{'dow'}; $template->param( $op => 1, "subtype_$sub_on" => 1, sublength =>$sub_length, history => ($op eq 'modify'), - "periodicity".$subs->{'periodicity'} => 1, - "numberpattern".$subs->{'numberpattern'} => 1, firstacquiyear => substr($firstissuedate,0,4), ); + + if($op eq 'modify') { + my ($serials_number) = GetSerials($subscriptionid); + if($serials_number > 1) { + $template->param(more_than_one_serial => 1); + } + } } if ( $op eq 'dup' ) { @@ -175,8 +179,38 @@ if ($op eq 'addsubscription') { $template->param(bibliotitle => $bib->{title}); } } - $template->param((uc(C4::Context->preference("marcflavour"))) => 1); - output_html_with_http_headers $query, $cookie, $template->output; + + $template->param((uc(C4::Context->preference("marcflavour"))) => 1); + + my @frequencies = GetSubscriptionFrequencies; + my @frqloop; + foreach my $freq (@frequencies) { + my $selected = 0; + $selected = 1 if ($subs->{periodicity} and $freq->{id} eq $subs->{periodicity}); + my $row = { + id => $freq->{'id'}, + selected => $selected, + label => $freq->{'description'}, + }; + push @frqloop, $row; + } + $template->param(frequencies => \@frqloop); + + my @numpatterns = GetSubscriptionNumberpatterns; + my @numberpatternloop; + foreach my $numpattern (@numpatterns) { + my $selected = 0; + $selected = 1 if($subs->{numberpattern} and $numpattern->{id} eq $subs->{numberpattern}); + my $row = { + id => $numpattern->{'id'}, + selected => $selected, + label => $numpattern->{'label'}, + }; + push @numberpatternloop, $row; + } + $template->param(numberpatterns => \@numberpatternloop); + + output_html_with_http_headers $query, $cookie, $template->output; } sub letter_loop { @@ -198,76 +232,96 @@ sub _get_sub_length { my ($type, $length) = @_; return ( - $type eq 'numberlength' ? $length : 0, - $type eq 'weeklength' ? $length : 0, - $type eq 'monthlength' ? $length : 0, + $type eq 'issues' ? $length : 0, + $type eq 'weeks' ? $length : 0, + $type eq 'months' ? $length : 0, ); } +sub _guess_enddate { + my ($startdate_iso, $frequencyid, $numberlength, $weeklength, $monthlength) = @_; + my ($year, $month, $day); + my $enddate; + if($numberlength != 0) { + my $frequency = GetSubscriptionFrequency($frequencyid); + if($frequency->{'unit'} eq 'day') { + ($year, $month, $day) = Add_Delta_Days(split(/-/, $startdate_iso), $numberlength * $frequency->{'unitsperissue'} / $frequency->{'issuesperunit'}); + } elsif($frequency->{'unit'} eq 'week') { + ($year, $month, $day) = Add_Delta_Days(split(/-/, $startdate_iso), $numberlength * 7 * $frequency->{'unitsperissue'} / $frequency->{'issuesperunit'}); + } elsif($frequency->{'unit'} eq 'month') { + ($year, $month, $day) = Add_Delta_YM(split(/-/, $startdate_iso), 0, $numberlength * $frequency->{'unitsperissue'} / $frequency->{'issuesperunit'}); + } elsif($frequency->{'unit'} eq 'year') { + ($year, $month, $day) = Add_Delta_YM(split(/-/, $startdate_iso), $numberlength * $frequency->{'unitsperissue'} / $frequency->{'issuesperunit'}, 0); + } + } elsif($weeklength != 0) { + ($year, $month, $day) = Add_Delta_Days(split(/-/, $startdate_iso), $weeklength * 7); + } elsif($monthlength != 0) { + ($year, $month, $day) = Add_Delta_YM(split(/-/, $startdate_iso), 0, $monthlength); + } + if(defined $year) { + $enddate = sprintf("%04d-%02d-%02d", $year, $month, $day); + } else { + undef $enddate; + } + return $enddate; +} + sub redirect_add_subscription { my $auser = $query->param('user'); my $branchcode = $query->param('branchcode'); my $aqbooksellerid = $query->param('aqbooksellerid'); my $cost = $query->param('cost'); my $aqbudgetid = $query->param('aqbudgetid'); - my $periodicity = $query->param('periodicity'); - my $dow = $query->param('dow'); - my @irregularity = $query->param('irregularity_select'); + my $periodicity = $query->param('frequency'); + my @irregularity = $query->param('irregularity'); my $numberpattern = $query->param('numbering_pattern'); + my $locale = $query->param('locale'); my $graceperiod = $query->param('graceperiod') || 0; + my $subtype = $query->param('subtype'); + my $sublength = $query->param('sublength'); my ( $numberlength, $weeklength, $monthlength ) - = _get_sub_length( $query->param('subtype'), $query->param('sublength') ); + = _get_sub_length( $subtype, $sublength ); my $add1 = $query->param('add1'); - my $every1 = $query->param('every1'); - my $whenmorethan1 = $query->param('whenmorethan1'); - my $setto1 = $query->param('setto1'); my $lastvalue1 = $query->param('lastvalue1'); my $innerloop1 = $query->param('innerloop1'); - my $add2 = $query->param('add2'); - my $every2 = $query->param('every2'); - my $whenmorethan2 = $query->param('whenmorethan2'); - my $setto2 = $query->param('setto2'); my $innerloop2 = $query->param('innerloop2'); my $lastvalue2 = $query->param('lastvalue2'); - my $add3 = $query->param('add3'); - my $every3 = $query->param('every3'); - my $whenmorethan3 = $query->param('whenmorethan3'); - my $setto3 = $query->param('setto3'); my $lastvalue3 = $query->param('lastvalue3'); my $innerloop3 = $query->param('innerloop3'); - my $numberingmethod = $query->param('numberingmethod'); my $status = 1; my $biblionumber = $query->param('biblionumber'); my $callnumber = $query->param('callnumber'); my $notes = $query->param('notes'); my $internalnotes = $query->param('internalnotes'); - my $hemisphere = $query->param('hemisphere') || 1; my $letter = $query->param('letter'); - my $manualhistory = $query->param('manualhist'); + my $manualhistory = $query->param('manualhist') ? 1 : 0; my $serialsadditems = $query->param('serialsadditems'); my $staffdisplaycount = $query->param('staffdisplaycount'); my $opacdisplaycount = $query->param('opacdisplaycount'); my $location = $query->param('location'); + my $skip_serialseq = $query->param('skip_serialseq'); my $startdate = format_date_in_iso( $query->param('startdate') ); my $enddate = format_date_in_iso( $query->param('enddate') ); my $firstacquidate = format_date_in_iso($query->param('firstacquidate')); - my $histenddate = format_date_in_iso($query->param('histenddate')); - my $histstartdate = format_date_in_iso($query->param('histstartdate')); - my $recievedlist = $query->param('recievedlist'); - my $missinglist = $query->param('missinglist'); - my $opacnote = $query->param('opacnote'); - my $librariannote = $query->param('librariannote'); - my $subscriptionid = NewSubscription($auser,$branchcode,$aqbooksellerid,$cost,$aqbudgetid,$biblionumber, - $startdate,$periodicity,$dow,$numberlength,$weeklength,$monthlength, - $add1,$every1,$whenmorethan1,$setto1,$lastvalue1,$innerloop1, - $add2,$every2,$whenmorethan2,$setto2,$lastvalue2,$innerloop2, - $add3,$every3,$whenmorethan3,$setto3,$lastvalue3,$innerloop3, - $numberingmethod, $status, $notes,$letter,$firstacquidate,join(",",@irregularity), - $numberpattern, $callnumber, $hemisphere,($manualhistory?$manualhistory:0),$internalnotes, - $serialsadditems,$staffdisplaycount,$opacdisplaycount,$graceperiod,$location,$enddate - ); - ModSubscriptionHistory ($subscriptionid,$histstartdate,$histenddate,$recievedlist,$missinglist,$opacnote,$librariannote); + if(!defined $enddate || $enddate eq '') { + if($subtype eq "issues") { + $enddate = _guess_enddate($firstacquidate, $periodicity, $numberlength, $weeklength, $monthlength); + } else { + $enddate = _guess_enddate($startdate, $periodicity, $numberlength, $weeklength, $monthlength); + } + } + + my $subscriptionid = NewSubscription( + $auser, $branchcode, $aqbooksellerid, $cost, $aqbudgetid, $biblionumber, + $startdate, $periodicity, $numberlength, $weeklength, + $monthlength, $lastvalue1, $innerloop1, $lastvalue2, $innerloop2, + $lastvalue3, $innerloop3, $status, $notes, $letter, $firstacquidate, + join(";",@irregularity), $numberpattern, $locale, $callnumber, + $manualhistory, $internalnotes, $serialsadditems, + $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate, + $skip_serialseq + ); print $query->redirect("/cgi-bin/koha/serials/subscription-detail.pl?subscriptionid=$subscriptionid"); return; @@ -275,7 +329,7 @@ sub redirect_add_subscription { sub redirect_mod_subscription { my $subscriptionid = $query->param('subscriptionid'); - my @irregularity = $query->param('irregularity_select'); + my @irregularity = $query->param('irregularity'); my $auser = $query->param('user'); my $librarian => $query->param('librarian'), my $branchcode = $query->param('branchcode'); @@ -284,76 +338,66 @@ sub redirect_mod_subscription { my $biblionumber = $query->param('biblionumber'); my $aqbudgetid = $query->param('aqbudgetid'); my $startdate = format_date_in_iso($query->param('startdate')); + my $firstacquidate = format_date_in_iso( $query->param('firstacquidate') ); my $nextacquidate = $query->param('nextacquidate') ? format_date_in_iso($query->param('nextacquidate')): - format_date_in_iso($query->param('startdate')); + $firstacquidate; my $enddate = format_date_in_iso($query->param('enddate')); - my $periodicity = $query->param('periodicity'); - my $dow = $query->param('dow'); + my $periodicity = $query->param('frequency'); + my $subtype = $query->param('subtype'); + my $sublength = $query->param('sublength'); my ($numberlength, $weeklength, $monthlength) - = _get_sub_length( $query->param('subtype'), $query->param('sublength') ); + = _get_sub_length( $subtype, $sublength ); my $numberpattern = $query->param('numbering_pattern'); - my $add1 = $query->param('add1'); - my $every1 = $query->param('every1'); - my $whenmorethan1 = $query->param('whenmorethan1'); - my $setto1 = $query->param('setto1'); + my $locale = $query->param('locale'); my $lastvalue1 = $query->param('lastvalue1'); my $innerloop1 = $query->param('innerloop1'); - my $add2 = $query->param('add2'); - my $every2 = $query->param('every2'); - my $whenmorethan2 = $query->param('whenmorethan2'); - my $setto2 = $query->param('setto2'); my $lastvalue2 = $query->param('lastvalue2'); my $innerloop2 = $query->param('innerloop2'); - my $add3 = $query->param('add3'); - my $every3 = $query->param('every3'); - my $whenmorethan3 = $query->param('whenmorethan3'); - my $setto3 = $query->param('setto3'); my $lastvalue3 = $query->param('lastvalue3'); my $innerloop3 = $query->param('innerloop3'); - my $numberingmethod = $query->param('numberingmethod'); my $status = 1; my $callnumber = $query->param('callnumber'); my $notes = $query->param('notes'); my $internalnotes = $query->param('internalnotes'); - my $hemisphere = $query->param('hemisphere'); my $letter = $query->param('letter'); - my $manualhistory = $query->param('manualhist'); + my $manualhistory = $query->param('manualhist') ? 1 : 0; my $serialsadditems = $query->param('serialsadditems'); - # subscription history - my $histenddate = format_date_in_iso($query->param('histenddate')); - my $histstartdate = format_date_in_iso($query->param('histstartdate')); - my $recievedlist = $query->param('recievedlist'); - my $missinglist = $query->param('missinglist'); - my $opacnote = $query->param('opacnote'); - my $librariannote = $query->param('librariannote'); my $staffdisplaycount = $query->param('staffdisplaycount'); my $opacdisplaycount = $query->param('opacdisplaycount'); my $graceperiod = $query->param('graceperiod') || 0; my $location = $query->param('location'); + my $skip_serialseq = $query->param('skip_serialseq'); + + # Guess end date + if(!defined $enddate || $enddate eq '') { + if($subtype eq "issues") { + $enddate = _guess_enddate($nextacquidate, $periodicity, $numberlength, $weeklength, $monthlength); + } else { + $enddate = _guess_enddate($startdate, $periodicity, $numberlength, $weeklength, $monthlength); + } + } + my $nextexpected = GetNextExpected($subscriptionid); - # If it's a mod, we need to check the current 'expected' issue, and mod it in the serials table if necessary. - if ( $nextacquidate ne $nextexpected->{planneddate}->output('iso') ) { - ModNextExpected($subscriptionid,C4::Dates->new($nextacquidate,'iso')); + # If it's a mod, we need to check the current 'expected' issue, and mod it in the serials table if necessary. + if ( $nextexpected->{planneddate} && $nextacquidate ne $nextexpected->{planneddate} ) { + ModNextExpected($subscriptionid, $nextacquidate); # if we have not received any issues yet, then we also must change the firstacquidate for the subs. $firstissuedate = $nextacquidate if($nextexpected->{isfirstissue}); } - ModSubscription( - $auser, $branchcode, $aqbooksellerid, $cost, - $aqbudgetid, $startdate, $periodicity, $firstissuedate, - $dow, join(q{,},@irregularity), $numberpattern, $numberlength, - $weeklength, $monthlength, $add1, $every1, - $whenmorethan1, $setto1, $lastvalue1, $innerloop1, - $add2, $every2, $whenmorethan2, $setto2, - $lastvalue2, $innerloop2, $add3, $every3, - $whenmorethan3, $setto3, $lastvalue3, $innerloop3, - $numberingmethod, $status, $biblionumber, $callnumber, - $notes, $letter, $hemisphere, $manualhistory,$internalnotes, - $serialsadditems, $staffdisplaycount,$opacdisplaycount,$graceperiod,$location,$enddate,$subscriptionid - ); - ModSubscriptionHistory ($subscriptionid,$histstartdate,$histenddate,$recievedlist,$missinglist,$opacnote,$librariannote); + ModSubscription( + $auser, $branchcode, $aqbooksellerid, $cost, $aqbudgetid, $startdate, + $periodicity, $firstacquidate, join(";",@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, $subscriptionid, + $skip_serialseq + ); + print $query->redirect("/cgi-bin/koha/serials/subscription-detail.pl?subscriptionid=$subscriptionid"); return; } diff --git a/serials/subscription-detail.pl b/serials/subscription-detail.pl index ae85c51..af0744c 100755 --- a/serials/subscription-detail.pl +++ b/serials/subscription-detail.pl @@ -100,7 +100,7 @@ my $hasRouting = check_routing($subscriptionid); # COMMENT hdl : IMHO, we should think about passing more and more data hash to template->param rather than duplicating code a new coding Guideline ? -for my $date qw(startdate enddate firstacquidate histstartdate histenddate){ +for my $date (qw(startdate enddate firstacquidate histstartdate histenddate)) { $$subs{$date} = format_date($$subs{$date}) if $date && $$subs{$date}; } $subs->{location} = GetKohaAuthorisedValueLib("LOC",$subs->{location}); @@ -109,15 +109,9 @@ $template->param(%{ $subs }); $template->param(biblionumber_for_new_subscription => $subs->{bibnum}); my @irregular_issues = split /,/, $subs->{irregularity}; -if (! $subs->{numberpattern}) { - $subs->{numberpattern} = q{}; -} -if (! $subs->{dow}) { - $subs->{dow} = q{}; -} -if (! $subs->{periodicity}) { - $subs->{periodicity} = '0'; -} +my $frequency = C4::Serials::Frequency::GetSubscriptionFrequency($subs->{periodicity}); +my $numberpattern = C4::Serials::Numberpattern::GetSubscriptionNumberpattern($subs->{numberpattern}); + my $default_bib_view = get_default_view(); $template->param( subscriptionid => $subscriptionid, @@ -131,9 +125,11 @@ $template->param( C4::Context->userenv->{flags} % 2 !=1 && C4::Context->userenv->{branch} && $subs->{branchcode} && (C4::Context->userenv->{branch} ne $subs->{branchcode})), - 'periodicity' . $subs->{periodicity} => 1, - 'arrival' . $subs->{dow} => 1, - 'numberpattern' . $subs->{numberpattern} => 1, + frequency => $frequency, + numberpattern => $numberpattern, + has_X => ($numberpattern->{'numberingmethod'} =~ /{X}/) ? 1 : 0, + has_Y => ($numberpattern->{'numberingmethod'} =~ /{Y}/) ? 1 : 0, + has_Z => ($numberpattern->{'numberingmethod'} =~ /{Z}/) ? 1 : 0, intranetstylesheet => C4::Context->preference('intranetstylesheet'), intranetcolorstylesheet => C4::Context->preference('intranetcolorstylesheet'), irregular_issues => scalar @irregular_issues, diff --git a/serials/subscription-frequencies.pl b/serials/subscription-frequencies.pl new file mode 100755 index 0000000..1997674 --- /dev/null +++ b/serials/subscription-frequencies.pl @@ -0,0 +1,104 @@ +#!/usr/bin/perl + +# Copyright 2011 BibLibre SARL +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +=head1 NAME + +subscription-frequencies.pl + +=head1 DESCRIPTION + +Manage subscription frequencies + +=cut + +use Modern::Perl; + +use CGI; + +use C4::Auth; +use C4::Output; +use C4::Serials; +use C4::Serials::Frequency; + +my $input = new CGI; +my ($template, $loggedinuser, $cookie, $flags) = get_template_and_user( { + template_name => 'serials/subscription-frequencies.tt', + query => $input, + type => 'intranet', + authnotrequired => 0, + flagsrequired => { 'parameters' => 1 }, + debug => 1, +} ); + +my $op = $input->param('op'); + +if($op && ($op eq 'new' || $op eq 'modify')) { + my @units_loop; + push @units_loop, {val => $_} for (qw/ day week month year /); + + if($op eq 'modify') { + my $frequencyid = $input->param('frequencyid'); + my $frequency = GetSubscriptionFrequency($frequencyid); + foreach (@units_loop) { + if($frequency->{unit} and $_->{val} eq $frequency->{unit}) { + $_->{selected} = 1; + last; + } + } + $template->param( %$frequency ); + } + + $template->param( + units_loop => \@units_loop, + $op => 1, + ); + output_html_with_http_headers $input, $cookie, $template->output; + exit; +} + +if($op && ($op eq 'savenew' || $op eq 'savemod')) { + my $frequency; + foreach (qw/ description unit issuesperunit unitsperissue displayorder /) { + $frequency->{$_} = $input->param($_); + } + $frequency->{unit} = undef if $frequency->{unit} eq ''; + foreach (qw/issuesperunit unitsperissue/) { + $frequency->{$_} = 1 if $frequency->{$_} !~ /\d+/; + } + $frequency->{issuesperunit} = 1 if $frequency->{issuesperunit} < 1; + $frequency->{unitsperissue} = 1 if $frequency->{issuesperunit} != 1; + + if($op eq 'savemod') { + $frequency->{id} = $input->param('id'); + ModSubscriptionFrequency($frequency); + } else { + AddSubscriptionFrequency($frequency); + } +} elsif($op && $op eq 'del') { + my $frequencyid = $input->param('frequencyid'); + + DelSubscriptionFrequency($frequencyid); +} + + +my @frequencies = GetSubscriptionFrequencies(); + +$template->param(frequencies_loop => \@frequencies); +$template->param($op => 1) if $op; + +output_html_with_http_headers $input, $cookie, $template->output; diff --git a/serials/subscription-frequency.pl b/serials/subscription-frequency.pl new file mode 100755 index 0000000..965b0ff --- /dev/null +++ b/serials/subscription-frequency.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl + +use CGI; +use C4::Context; +use C4::Serials::Frequency; +use C4::Auth qw/check_cookie_auth/; +use URI::Escape; +use strict; + +my $input=new CGI; +my $frqid=$input->param("frequency_id"); +my ($auth_status, $sessionID) = check_cookie_auth($input->cookie('CGISESSID'), { serials => '*' }); +if ($auth_status ne "ok") { + exit 0; +} +my $frequencyrecord=GetSubscriptionFrequency($frqid); +binmode STDOUT, ":utf8"; +print $input->header(-type => 'text/plain', -charset => 'UTF-8'); +print "{".join (",",map { "\"$_\":\"".uri_escape($frequencyrecord->{$_})."\"" }sort keys %$frequencyrecord)."}"; diff --git a/serials/subscription-history.pl b/serials/subscription-history.pl new file mode 100755 index 0000000..94791e6 --- /dev/null +++ b/serials/subscription-history.pl @@ -0,0 +1,88 @@ +#!/usr/bin/perl + +# Copyright 2011 BibLibre SARL +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +=head1 NAME + +subscription-history.pl + +=head1 DESCRIPTION + +Modify subscription history + +=cut + +use Modern::Perl; + +use CGI; +use C4::Auth; +use C4::Output; + +use C4::Biblio; +use C4::Dates qw(format_date_in_iso); +use C4::Serials; + +my $input = new CGI; +my ($template, $loggedinuser, $cookie, $flags) = get_template_and_user( { + template_name => 'serials/subscription-history.tt', + query => $input, + type => 'intranet', + authnotrequired => 0, + flagsrequired => { 'serials' => 'edit_subscription' }, + debug => 1, +} ); + +my $subscriptionid = $input->param('subscriptionid'); +my $op = $input->param('op'); + +if(!defined $subscriptionid || $subscriptionid eq '') { + print $input->redirect('/cgi-bin/koha/serials/serials-home.pl'); + exit; +} + +if($op && $op eq 'mod') { + my $histstartdate = $input->param('histstartdate'); + my $histenddate = $input->param('histenddate'); + my $receivedlist = $input->param('receivedlist'); + my $missinglist = $input->param('missinglist'); + my $opacnote = $input->param('opacnote'); + my $librariannote = $input->param('librariannote'); + + ModSubscriptionHistory( $subscriptionid, format_date_in_iso($histstartdate), + format_date_in_iso($histenddate), $receivedlist, $missinglist, $opacnote, + $librariannote ); + + print $input->redirect("/cgi-bin/koha/serials/subscription-detail.pl?subscriptionid=$subscriptionid"); + exit; +} else { + my $history = GetSubscriptionHistoryFromSubscriptionId($subscriptionid); + my (undef, $biblio) = GetBiblio($history->{'biblionumber'}); + + $template->param( + subscriptionid => $subscriptionid, + title => $biblio->{'title'}, + histstartdate => $history->{'histstartdate'}, + histenddate => $history->{'histenddate'}, + receivedlist => $history->{'recievedlist'}, + missinglist => $history->{'missinglist'}, + opacnote => $history->{'opacnote'}, + librariannote => $history->{'librariannote'}, + ); + + output_html_with_http_headers $input, $cookie, $template->output; +} + diff --git a/serials/subscription-numberpattern.pl b/serials/subscription-numberpattern.pl new file mode 100755 index 0000000..5da614e --- /dev/null +++ b/serials/subscription-numberpattern.pl @@ -0,0 +1,15 @@ +#!/usr/bin/perl + +use CGI; +use C4::Serials::Numberpattern; +use URI::Escape; +use strict; +use warnings; + +my $input=new CGI; +my $numpatternid=$input->param("numberpattern_id"); + +my $numberpatternrecord=GetSubscriptionNumberpattern($numpatternid); +binmode STDOUT, ":utf8"; +print $input->header(-type => 'text/plain', -charset => 'UTF-8'); +print "{",join (",",map {"\"$_\":\"".(uri_escape($numberpatternrecord->{$_}) // '')."\"" }sort keys %$numberpatternrecord),"}"; diff --git a/serials/subscription-numberpatterns.pl b/serials/subscription-numberpatterns.pl new file mode 100755 index 0000000..e7f6480 --- /dev/null +++ b/serials/subscription-numberpatterns.pl @@ -0,0 +1,130 @@ +#!/usr/bin/perl + +# Copyright 2011 BibLibre SARL +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +=head1 NAME + +subscription-numberpatterns.pl + +=head1 DESCRIPTION + +Manage numbering patterns + +=cut + +use Modern::Perl; +use CGI; + +use C4::Auth; +use C4::Output; +use C4::Serials::Numberpattern; +use C4::Serials::Frequency; + +my $input = new CGI; +my ($template, $loggedinuser, $cookie, $flags) = get_template_and_user( { + template_name => 'serials/subscription-numberpatterns.tt', + query => $input, + type => 'intranet', + authnotrequired => 0, + flagsrequired => { 'parameters' => 1 } +} ); + +my $op = $input->param('op'); + +if($op && $op eq 'savenew') { + my $label = $input->param('label'); + my $numberpattern; + foreach(qw/ label description numberingmethod displayorder + label1 label2 label3 add1 add2 add3 every1 every2 every3 + setto1 setto2 setto3 whenmorethan1 whenmorethan2 whenmorethan3 + numbering1 numbering2 numbering3 /) { + $numberpattern->{$_} = $input->param($_); + if($numberpattern->{$_} and $numberpattern->{$_} eq '') { + $numberpattern->{$_} = undef; + } + } + my $numberpattern2 = GetSubscriptionNumberpatternByName($label); + + if(!defined $numberpattern2) { + AddSubscriptionNumberpattern($numberpattern); + } else { + $op = 'new'; + $template->param(error_existing_numberpattern => 1); + $template->param(%$numberpattern); + } +} elsif ($op && $op eq 'savemod') { + my $id = $input->param('id'); + my $label = $input->param('label'); + my $numberpattern = GetSubscriptionNumberpattern($id); + my $mod_ok = 1; + if($numberpattern->{'label'} ne $label) { + my $numberpattern2 = GetSubscriptionNumberpatternByName($label); + if(defined $numberpattern2 && $id != $numberpattern2->{'id'}) { + $mod_ok = 0; + } + } + if($mod_ok) { + foreach(qw/ id label description numberingmethod displayorder + label1 label2 label3 add1 add2 add3 every1 every2 every3 + setto1 setto2 setto3 whenmorethan1 whenmorethan2 whenmorethan3 + numbering1 numbering2 numbering3 /) { + $numberpattern->{$_} = $input->param($_) || undef; + } + ModSubscriptionNumberpattern($numberpattern); + } else { + $op = 'modify'; + $template->param(error_existing_numberpattern => 1); + } +} + +if($op && ($op eq 'new' || $op eq 'modify')) { + if($op eq 'modify') { + my $id = $input->param('id'); + if(defined $id) { + my $numberpattern = GetSubscriptionNumberpattern($id); + $template->param(%$numberpattern); + } else { + $op = 'new'; + } + } + my @frequencies = GetSubscriptionFrequencies(); + my @subtypes; + push @subtypes, { value => $_ } for (qw/ issues weeks months /); + $template->param( + $op => 1, + frequencies_loop => \@frequencies, + subtypes_loop => \@subtypes, + DHTMLcalendar_dateformat => C4::Dates->DHTMLcalendar(), + ); + output_html_with_http_headers $input, $cookie, $template->output; + exit; +} + +if($op && $op eq 'del') { + my $id = $input->param('id'); + if(defined $id) { + DelSubscriptionNumberpattern($id); + } +} + +my @numberpatterns_loop = GetSubscriptionNumberpatterns(); + +$template->param( + numberpatterns_loop => \@numberpatterns_loop, +); + +output_html_with_http_headers $input, $cookie, $template->output; -- 1.7.7.3