From eb265def46e7010331161ad303de715c206eca16 Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Tue, 14 Jul 2015 13:18:49 -0700 Subject: [PATCH] allow non-integer ratios of supplemental package period, #37102 --- FS/FS/cust_main/Billing.pm | 34 +++++++++++++++++++++++++++------- FS/FS/part_pkg_link.pm | 10 ++++------ 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/FS/FS/cust_main/Billing.pm b/FS/FS/cust_main/Billing.pm index df7e17f81..0bc0fbd39 100644 --- a/FS/FS/cust_main/Billing.pm +++ b/FS/FS/cust_main/Billing.pm @@ -1133,19 +1133,39 @@ sub _make_lines { # its frequency my $main_pkg_freq = $main_pkg->part_pkg->freq; my $supp_pkg_freq = $part_pkg->freq; - my $ratio = $supp_pkg_freq / $main_pkg_freq; - if ( $ratio != int($ratio) ) { + if ( $supp_pkg_freq == 0 or $main_pkg_freq == 0 ) { # the UI should prevent setting up packages like this, but just # in case - return "supplemental package period is not an integer multiple of main package period"; + return "unable to calculate supplemental package period ratio"; } - $next_bill = $sdate; - for (1..$ratio) { - $next_bill = $part_pkg->add_freq( $next_bill, $main_pkg_freq ); + my $ratio = $supp_pkg_freq / $main_pkg_freq; + if ( $ratio == int($ratio) ) { + # simple case: main package is X months, supp package is X*A months, + # advance supp package to where the main package will be in A cycles. + $next_bill = $sdate; + for (1..$ratio) { + $next_bill = $part_pkg->add_freq( $next_bill, $main_pkg_freq ); + } + } else { + # harder case: main package is X months, supp package is Y months. + # advance supp package by Y months. then if they're within half a + # month of each other, resync them. this may result in the period + # not being exactly Y months. + $next_bill = $part_pkg->add_freq( $sdate, $supp_pkg_freq ); + my $main_next_bill = $main_pkg->bill; + if ( $main_pkg->bill <= $time ) { + # then the main package has not yet been billed on this cycle; + # predict what its bill date will be. + $main_next_bill = + $part_pkg->add_freq( $main_next_bill, $main_pkg_freq ); + } + if ( abs($main_next_bill - $next_bill) < 86400*15 ) { + $next_bill = $main_next_bill; + } } } else { - # the normal case + # the normal case, not a supplemental package $next_bill = $part_pkg->add_freq($sdate, $options{freq_override} || 0); return "unparsable frequency: ". $part_pkg->freq if $next_bill == -1; diff --git a/FS/FS/part_pkg_link.pm b/FS/FS/part_pkg_link.pm index ce071ef17..5fe6f2f01 100644 --- a/FS/FS/part_pkg_link.pm +++ b/FS/FS/part_pkg_link.pm @@ -250,12 +250,10 @@ sub check { my $dst_pkg = $self->dst_pkg; if ( $src_pkg->freq eq '0' and $dst_pkg->freq ne '0' ) { return "One-time charges can't have supplemental packages." - } elsif ( $dst_pkg->freq ne '0' ) { - my $ratio = $dst_pkg->freq / $src_pkg->freq; - if ($ratio != int($ratio)) { - return "Supplemental package period (pkgpart ".$dst_pkg->pkgpart. - ") must be an integer multiple of main package period."; - } + } elsif ( $dst_pkg->freq == 0 ) { + return "The billing period of a supplemental package must be a whole number of months."; + } elsif ( $src_pkg->freq == 0 ) { + return "To have supplemental packages, the billing period of a package must be a whole number of months."; } } -- 2.11.0