From 8b94c89f0bd73888d7f5146b0be1848cf2c25cbf Mon Sep 17 00:00:00 2001 From: Julian Maurice Date: Tue, 22 Jul 2014 14:43:16 +0200 Subject: [PATCH] Bug 12671: Guess next serial date when there are several issues per unit This guess uses the following algorithm 1/ Get the number of days remaining from first issue of this unit of time until the end of the unit of time (using 7 days for week, 28 for month and 365 for year) 2/ Divide it by the number of issues per unit 3/ Take the integer part of the result, this is the number of days to add to previous serial published date This patch also try to guess the date of the first issue of a unit of time. Before that, it was: - for week: monday of week - for month: 1st day of month - for year: 1st day of year Now it uses firstacquidate. Example: firstacquidate = 1970-01-07 (wednesday) unit = week issuesperunit = 2 (2 issues per week) From wednesday to sunday, there are 4 days so we add 2 days to get the next date. The next dates should be: - 1970-01-09 (+ 2 days) - 1970-01-14 (wednesday of next week) - 1970-01-16 (+ 2 days) - ... and so on Test plan: 1/ Go to numbering pattern creation page (Serials -> Manager numbering patterns -> New numbering pattern) 2/ In "Test prediction pattern" fieldset, set subscription length to 50 issues (this avoid to compute the next 1000 dates, which can take time) 3/ Fill first issue publication date 4/ Choose the frequency you want to test 5/ click on "Test pattern" button 6/ Check that the dates are correct 7/ Repeat steps 3-7 until you think you have tested enough cases Interesting frequencies to test: - 1/day - 1/week - 2/week - 6/week (firstacquidate should be monday or tuesday, or the generated dates will be the same for all the week) - 1/month - 2/month - 3/month - 1/year - 2/year - 3/year ---------------- Sign off report: ---------------- -Followed the test plan. Unit tests work. Also trying some more strange frequencies with our librarians: 5/year, 43/year, 10/year. -Received all serials for a subscription and found no errors. -Received some serials with frequency 2/month pre-patch, getting publication date as 1st of every month for each magazine. Having applied the patch, publication dates started working mid-subscription for new magazines. -Works well and fine! Signed-off-by: Olli-Antti Kivilahti Signed-off-by: Kyle M Hall Signed-off-by: Tomas Cohen Arazi --- C4/Serials.pm | 66 +++++++------ t/db_dependent/Serials/GetNextDate.t | 138 ++++++++++++++++++--------- 2 files changed, 129 insertions(+), 75 deletions(-) diff --git a/C4/Serials.pm b/C4/Serials.pm index 2863a84826..b203c32a4d 100644 --- a/C4/Serials.pm +++ b/C4/Serials.pm @@ -2395,11 +2395,11 @@ sub GetFictiveIssueNumber { sub _get_next_date_day { my ($subscription, $freqdata, $year, $month, $day) = @_; - if ($subscription->{'countissuesperunit'} + 1 > $freqdata->{'issuesperunit'}){ - ($year,$month,$day) = Add_Delta_Days($year,$month, $day , $freqdata->{'unitsperissue'} ); - $subscription->{'countissuesperunit'} = 1; + if ($subscription->{countissuesperunit} + 1 > $freqdata->{issuesperunit}){ + ($year,$month,$day) = Add_Delta_Days($year,$month, $day , $freqdata->{unitsperissue} ); + $subscription->{countissuesperunit} = 1; } else { - $subscription->{'countissuesperunit'}++; + $subscription->{countissuesperunit}++; } return ($year, $month, $day); @@ -2409,21 +2409,22 @@ sub _get_next_date_week { my ($subscription, $freqdata, $year, $month, $day) = @_; my ($wkno, $yr) = Week_of_Year($year, $month, $day); + my $fa_dow = Day_of_Week(split /-/, $subscription->{firstacquidate}); - if ($subscription->{'countissuesperunit'} + 1 > $freqdata->{'issuesperunit'}){ - $subscription->{'countissuesperunit'} = 1; - $wkno += $freqdata->{"unitsperissue"}; + 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); - } + ($year,$month,$day) = Add_Delta_Days($year, $month, $day, $fa_dow - 1); } else { - $subscription->{'countissuesperunit'}++; + # Try to guess the next day of week + my $delta_days = int((7 - ($fa_dow - 1)) / $freqdata->{issuesperunit}); + ($year,$month,$day) = Add_Delta_Days($year, $month, $day, $delta_days); + $subscription->{countissuesperunit}++; } return ($year, $month, $day); @@ -2432,14 +2433,20 @@ sub _get_next_date_week { sub _get_next_date_month { my ($subscription, $freqdata, $year, $month, $day) = @_; - 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 - } + my $fa_day; + (undef, undef, $fa_day) = split /-/, $subscription->{firstacquidate}; + + if ($subscription->{countissuesperunit} + 1 > $freqdata->{issuesperunit}){ + $subscription->{countissuesperunit} = 1; + ($year,$month,$day) = Add_Delta_YM($year,$month,$day, 0, + $freqdata->{unitsperissue}); + my $days_in_month = Days_in_Month($year, $month); + $day = $fa_day <= $days_in_month ? $fa_day : $days_in_month; } else { - $subscription->{'countissuesperunit'}++; + # Try to guess the next day in month + my $delta_days = int((28 - ($fa_day - 1)) / $freqdata->{issuesperunit}); + ($year,$month,$day) = Add_Delta_Days($year, $month, $day, $delta_days); + $subscription->{countissuesperunit}++; } return ($year, $month, $day); @@ -2448,16 +2455,19 @@ sub _get_next_date_month { sub _get_next_date_year { my ($subscription, $freqdata, $year, $month, $day) = @_; - 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; - } + my ($fa_year, $fa_month, $fa_day) = split /-/, $subscription->{firstacquidate}; + + if ($subscription->{countissuesperunit} + 1 > $freqdata->{issuesperunit}){ + $subscription->{countissuesperunit} = 1; + ($year) = Add_Delta_YM($year,$month,$day, $freqdata->{"unitsperissue"},0); + $month = $fa_month; + my $days_in_month = Days_in_Month($year, $month); + $day = $fa_day <= $days_in_month ? $fa_day : $days_in_month; } else { - $subscription->{'countissuesperunit'}++; + # Try to guess the next day in year + my $delta_days = int((365 - ($fa_day - 1)) / $freqdata->{issuesperunit}); + ($year,$month,$day) = Add_Delta_Days($year, $month, $day, $delta_days); + $subscription->{countissuesperunit}++; } return ($year, $month, $day); diff --git a/t/db_dependent/Serials/GetNextDate.t b/t/db_dependent/Serials/GetNextDate.t index 1572d0a78a..c9fe98c132 100644 --- a/t/db_dependent/Serials/GetNextDate.t +++ b/t/db_dependent/Serials/GetNextDate.t @@ -1,7 +1,7 @@ #!/usr/bin/perl use C4::Context; -use Test::More tests => 86; +use Test::More tests => 96; use Modern::Perl; my $dbh = C4::Context->dbh; @@ -11,7 +11,7 @@ $dbh->{AutoCommit} = 0; use C4::Serials::Frequency; use C4::Serials; -# TEST CASE 1 - 1 issue per day, no irregularities +# TEST CASE - 1 issue per day, no irregularities my $frequency = { description => "One issue per day", unit => 'day', @@ -35,7 +35,7 @@ is($publisheddate, '1970-01-03'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-01-04'); -# TEST CASE 2 - 1 issue per day, irregularities +# TEST CASE - 1 issue per day, irregularities $subscription = { periodicity => $id, firstacquidate => '1970-01-01', @@ -50,7 +50,7 @@ is($publisheddate, '1970-01-05'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-01-06'); -# TEST CASE 3 - 2 issues per day, no irregularity +# TEST CASE - 2 issues per day, no irregularity $id = AddSubscriptionFrequency({ description => "Two issues per day", unit => 'day', @@ -73,7 +73,7 @@ is($publisheddate, '1970-01-02'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-01-03'); -# TEST CASE 4 - 2 issues per day, irregularities +# TEST CASE - 2 issues per day, irregularities $subscription = { periodicity => $id, firstacquidate => '1970-01-01', @@ -92,7 +92,7 @@ is($publisheddate, '1970-01-04'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-01-05'); -# TEST CASE 5 - 1 issue every 2 days, no irregularity +# TEST CASE - 1 issue every 2 days, no irregularity $id = AddSubscriptionFrequency({ description => "one issue every two days", unit => 'day', @@ -111,7 +111,7 @@ is($publisheddate, '1970-01-03'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-01-05'); -# TEST CASE 6 - 1 issue every 2 days, irregularities +# TEST CASE - 1 issue every 2 days, irregularities $subscription = { periodicity => $id, firstacquidate => '1970-01-01', @@ -126,7 +126,7 @@ is($publisheddate, '1970-01-07'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-01-09'); -# TEST CASE 7 - 1 issue per week, no irregularity +# TEST CASE - 1 issue per week, no irregularity $id = AddSubscriptionFrequency({ description => "one issue per week", unit => 'week', @@ -145,7 +145,7 @@ is($publisheddate, '1970-01-08'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-01-15'); -# TEST CASE 8 - 1 issue per week, irregularities +# TEST CASE - 1 issue per week, irregularities $subscription = { periodicity => $id, firstacquidate => '1970-01-01', @@ -160,7 +160,7 @@ is($publisheddate, '1970-01-22'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-01-29'); -# TEST CASE 9 - 1 issue every 2 weeks, no irregularity +# TEST CASE - 1 issue every 2 weeks, no irregularity $id = AddSubscriptionFrequency({ description => "one issue every 2 weeks", unit => 'week', @@ -181,7 +181,7 @@ is($publisheddate, '1970-01-29'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-02-12'); -# TEST CASE 10 - 1 issue every 2 weeks, irregularities +# TEST CASE - 1 issue every 2 weeks, irregularities $subscription = { periodicity => $id, firstacquidate => '1970-01-01', @@ -196,7 +196,7 @@ is($publisheddate, '1970-02-12'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-02-26'); -# TEST CASE 11 - 2 issues per week, no irregularity +# TEST CASE - 2 issues per week, no irregularity $id = AddSubscriptionFrequency({ description => "two issues per week", unit => 'week', @@ -211,17 +211,17 @@ $subscription = { }; $publisheddate = $subscription->{firstacquidate}; $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1970-01-01'); -# when more than 1 issue per week, date is automatically set to monday -# because we can't guess the right day +is($publisheddate, '1970-01-03'); +# when more than 1 issue per week, date is automatically set to the same day of +# week as firstacquidate $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1970-01-05'); +is($publisheddate, '1970-01-08'); $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1970-01-05'); +is($publisheddate, '1970-01-10'); $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1970-01-12'); +is($publisheddate, '1970-01-15'); -# TEST CASE 12 - 2 issues per week, irregularities +# TEST CASE - 2 issues per week, irregularities $subscription = { periodicity => $id, firstacquidate => '1970-01-01', @@ -230,17 +230,61 @@ $subscription = { }; $publisheddate = $subscription->{firstacquidate}; $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1970-01-01'); +is($publisheddate, '1970-01-03'); $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1970-01-05'); +is($publisheddate, '1970-01-10'); +$publisheddate = GetNextDate($subscription, $publisheddate); +is($publisheddate, '1970-01-22'); +$publisheddate = GetNextDate($subscription, $publisheddate); +is($publisheddate, '1970-01-24'); +$publisheddate = GetNextDate($subscription, $publisheddate); +is($publisheddate, '1970-01-29'); + +# TEST CASE - 6 issues per week, no irregularity +$id = AddSubscriptionFrequency({ + description => "six issues per week", + unit => 'week', + issuesperunit => 6, + unitsperissue => 1, +}); +$subscription = { + periodicity => $id, + firstacquidate => '1970-01-06', + irregularity => '', + countissuesperunit => 1, +}; +$publisheddate = $subscription->{firstacquidate}; +$publisheddate = GetNextDate($subscription, $publisheddate); +is($publisheddate, '1970-01-07'); +$publisheddate = GetNextDate($subscription, $publisheddate); +is($publisheddate, '1970-01-08'); +$publisheddate = GetNextDate($subscription, $publisheddate); +is($publisheddate, '1970-01-09'); +$publisheddate = GetNextDate($subscription, $publisheddate); +is($publisheddate, '1970-01-10'); +$publisheddate = GetNextDate($subscription, $publisheddate); +is($publisheddate, '1970-01-11'); +$publisheddate = GetNextDate($subscription, $publisheddate); +is($publisheddate, '1970-01-13'); + +# TEST CASE - 6 issues per week, irregularities +$subscription = { + periodicity => $id, + firstacquidate => '1970-01-06', + irregularity => '3;5;6', + countissuesperunit => 1, +}; +$publisheddate = $subscription->{firstacquidate}; +$publisheddate = GetNextDate($subscription, $publisheddate); +is($publisheddate, '1970-01-07'); $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1970-01-19'); +is($publisheddate, '1970-01-09'); $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1970-01-19'); +is($publisheddate, '1970-01-13'); $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1970-01-26'); +is($publisheddate, '1970-01-14'); -# TEST CASE 13 - 1 issue per month, no irregularity +# TEST CASE - 1 issue per month, no irregularity $id = AddSubscriptionFrequency({ description => "1 issue per month", unit => 'month', @@ -261,7 +305,7 @@ is($publisheddate, '1970-03-01'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-04-01'); -# TEST CASE 14 - 1 issue per month, irregularities +# TEST CASE - 1 issue per month, irregularities $subscription = { periodicity => $id, firstacquidate => '1970-01-01', @@ -276,7 +320,7 @@ is($publisheddate, '1970-05-01'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-06-01'); -# TEST CASE 15 - 1 issue every 2 months, no irregularity +# TEST CASE - 1 issue every 2 months, no irregularity $id = AddSubscriptionFrequency({ description => "1 issue every 2 months", unit => 'month', @@ -297,7 +341,7 @@ is($publisheddate, '1970-05-01'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-07-01'); -# TEST CASE 16 - 1 issue every 2 months, irregularities +# TEST CASE - 1 issue every 2 months, irregularities $subscription = { periodicity => $id, firstacquidate => '1970-01-01', @@ -312,7 +356,7 @@ is($publisheddate, '1970-09-01'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-11-01'); -# TEST CASE 17 - 2 issues per month, no irregularity +# TEST CASE - 2 issues per month, no irregularity $id = AddSubscriptionFrequency({ description => "2 issues per month", unit => 'month', @@ -327,15 +371,15 @@ $subscription = { }; $publisheddate = $subscription->{firstacquidate}; $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1970-01-01'); +is($publisheddate, '1970-01-15'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-02-01'); $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1970-02-01'); +is($publisheddate, '1970-02-15'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-03-01'); -# TEST CASE 18 - 2 issues per month, irregularities +# TEST CASE - 2 issues per month, irregularities $subscription = { periodicity => $id, firstacquidate => '1970-01-01', @@ -344,17 +388,17 @@ $subscription = { }; $publisheddate = $subscription->{firstacquidate}; $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1970-01-01'); +is($publisheddate, '1970-01-15'); $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1970-02-01'); +is($publisheddate, '1970-02-15'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-04-01'); $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1970-04-01'); +is($publisheddate, '1970-04-15'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1970-05-01'); -# TEST CASE 19 - 1 issue per year, no irregularity +# TEST CASE - 1 issue per year, no irregularity $id = AddSubscriptionFrequency({ description => "1 issue per year", unit => 'year', @@ -375,7 +419,7 @@ is($publisheddate, '1972-01-01'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1973-01-01'); -# TEST CASE 20 - 1 issue per year, irregularities +# TEST CASE - 1 issue per year, irregularities $subscription = { periodicity => $id, firstacquidate => '1970-01-01', @@ -390,7 +434,7 @@ is($publisheddate, '1974-01-01'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1975-01-01'); -# TEST CASE 21 - 1 issue every 2 years, no irregularity +# TEST CASE - 1 issue every 2 years, no irregularity $id = AddSubscriptionFrequency({ description => "1 issue every 2 years", unit => 'year', @@ -411,7 +455,7 @@ is($publisheddate, '1974-01-01'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1976-01-01'); -# TEST CASE 22 - 1 issue every 2 years, irregularities +# TEST CASE - 1 issue every 2 years, irregularities $subscription = { periodicity => $id, firstacquidate => '1970-01-01', @@ -426,7 +470,7 @@ is($publisheddate, '1978-01-01'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1980-01-01'); -# TEST CASE 23 - 2 issues per year, no irregularity +# TEST CASE - 2 issues per year, no irregularity $id = AddSubscriptionFrequency({ description => "1 issue every 2 years", unit => 'year', @@ -441,15 +485,15 @@ $subscription = { }; $publisheddate = $subscription->{firstacquidate}; $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1970-01-01'); +is($publisheddate, '1970-07-02'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1971-01-01'); $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1971-01-01'); +is($publisheddate, '1971-07-02'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1972-01-01'); -# TEST CASE 24 - 2 issues per year, irregularities +# TEST CASE - 2 issues per year, irregularities $subscription = { periodicity => $id, firstacquidate => '1970-01-01', @@ -458,17 +502,17 @@ $subscription = { }; $publisheddate = $subscription->{firstacquidate}; $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1970-01-01'); +is($publisheddate, '1970-07-02'); $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1971-01-01'); +is($publisheddate, '1971-07-02'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1973-01-01'); $publisheddate = GetNextDate($subscription, $publisheddate); -is($publisheddate, '1973-01-01'); +is($publisheddate, '1973-07-02'); $publisheddate = GetNextDate($subscription, $publisheddate); is($publisheddate, '1974-01-01'); -# TEST CASE 25 - Irregular +# TEST CASE - Irregular $id = AddSubscriptionFrequency({ description => "Irregular", unit => undef, -- 2.39.5