From 9e992baf49d7ac4372fd9dab88f41731f04e53b8 Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 29 Oct 2008 08:03:08 +0000 Subject: [PATCH] prepaid cdr pickup & bill daemon, RT#4184 --- FS/FS/cust_main.pm | 76 +++++++++++++++++------------- FS/FS/part_pkg/voip_cdr.pm | 6 ++- FS/bin/freeside-cdrd | 112 +++++++++++++++++++++++++++++++++++++++++++++ init.d/freeside-init | 8 ++++ 4 files changed, 168 insertions(+), 34 deletions(-) create mode 100644 FS/bin/freeside-cdrd diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index aa97d2233..db70dacc6 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -2399,9 +2399,13 @@ sub _make_lines { my $recur = 0; my $unitrecur = 0; my $sdate; - if ( $part_pkg->getfield('freq') ne '0' && - ! $cust_pkg->getfield('susp') && - ( $cust_pkg->getfield('bill') || 0 ) <= $time + if ( ! $cust_pkg->getfield('susp') and + ( $part_pkg->getfield('freq') ne '0' && + ( $cust_pkg->getfield('bill') || 0 ) <= $time + ) + || ( $part_pkg->plan eq 'voip_cdr' + && $part_pkg->option('bill_every_call') + ) ) { # XXX should this be a package event? probably. events are called @@ -2418,42 +2422,50 @@ sub _make_lines { $sdate = $cust_pkg->bill || $cust_pkg->setup || $time; #over two params! lets at least switch to a hashref for the rest... - my %param = ( 'precommit_hooks' => $precommit_hooks, ); + my $increment_next_bill = ( $part_pkg->freq ne '0' + && ( $cust_pkg->getfield('bill') || 0 ) <= $time + ); + my %param = ( 'precommit_hooks' => $precommit_hooks, + 'increment_next_bill' => $increment_next_bill, + ); $recur = eval { $cust_pkg->calc_recur( \$sdate, \@details, \%param ) }; return "$@ running calc_recur for $cust_pkg\n" if ( $@ ); + if ( $increment_next_bill ) { - #change this bit to use Date::Manip? CAREFUL with timezones (see - # mailing list archive) - my ($sec,$min,$hour,$mday,$mon,$year) = - (localtime($sdate) )[0,1,2,3,4,5]; - - #pro-rating magic - if $recur_prog fiddles $sdate, want to use that - # only for figuring next bill date, nothing else, so, reset $sdate again - # here - $sdate = $cust_pkg->bill || $cust_pkg->setup || $time; - #no need, its in $hash{last_bill}# my $last_bill = $cust_pkg->last_bill; - $cust_pkg->last_bill($sdate); - - if ( $part_pkg->freq =~ /^\d+$/ ) { - $mon += $part_pkg->freq; - until ( $mon < 12 ) { $mon -= 12; $year++; } - } elsif ( $part_pkg->freq =~ /^(\d+)w$/ ) { - my $weeks = $1; - $mday += $weeks * 7; - } elsif ( $part_pkg->freq =~ /^(\d+)d$/ ) { - my $days = $1; - $mday += $days; - } elsif ( $part_pkg->freq =~ /^(\d+)h$/ ) { - my $hours = $1; - $hour += $hours; - } else { - return "unparsable frequency: ". $part_pkg->freq; + #change this bit to use Date::Manip? CAREFUL with timezones (see + # mailing list archive) + my ($sec,$min,$hour,$mday,$mon,$year) = + (localtime($sdate) )[0,1,2,3,4,5]; + + #pro-rating magic - if $recur_prog fiddles $sdate, want to use that + # only for figuring next bill date, nothing else, so, reset $sdate again + # here + $sdate = $cust_pkg->bill || $cust_pkg->setup || $time; + #no need, its in $hash{last_bill}# my $last_bill = $cust_pkg->last_bill; + $cust_pkg->last_bill($sdate); + + if ( $part_pkg->freq =~ /^\d+$/ ) { + $mon += $part_pkg->freq; + until ( $mon < 12 ) { $mon -= 12; $year++; } + } elsif ( $part_pkg->freq =~ /^(\d+)w$/ ) { + my $weeks = $1; + $mday += $weeks * 7; + } elsif ( $part_pkg->freq =~ /^(\d+)d$/ ) { + my $days = $1; + $mday += $days; + } elsif ( $part_pkg->freq =~ /^(\d+)h$/ ) { + my $hours = $1; + $hour += $hours; + } else { + return "unparsable frequency: ". $part_pkg->freq; + } + $cust_pkg->setfield('bill', + timelocal_nocheck($sec,$min,$hour,$mday,$mon,$year)); + } - $cust_pkg->setfield('bill', - timelocal_nocheck($sec,$min,$hour,$mday,$mon,$year)); } diff --git a/FS/FS/part_pkg/voip_cdr.pm b/FS/FS/part_pkg/voip_cdr.pm index 1b565f2c4..a3b54ee84 100644 --- a/FS/FS/part_pkg/voip_cdr.pm +++ b/FS/FS/part_pkg/voip_cdr.pm @@ -395,7 +395,7 @@ sub calc_recur { # don't add it to invoice, don't set its status to NULL, # don't call downstream_csv or something on it... # but DO emit a warning... - #if ( ! $rate_detail && ! scalar(@call_details) ) { + #if ( ! $rate_detail && ! scalar(@call_details) ) {} if ( ! $rate_detail && $charge eq '' ) { warn "no rate_detail found for CDR.acctid: ". $cdr->acctid. @@ -509,8 +509,10 @@ sub calc_recur { } #if ( $spool_cdr && length($downstream_cdr) ) - $self->option('recur_fee') + $charges; + $charges += $self->option('recur_fee') + if $param->{'increment_next_bill'}; + $charges; } sub is_free { diff --git a/FS/bin/freeside-cdrd b/FS/bin/freeside-cdrd new file mode 100644 index 000000000..ef420b53b --- /dev/null +++ b/FS/bin/freeside-cdrd @@ -0,0 +1,112 @@ +#!/usr/bin/perl -w + +use strict; +use FS::Daemon qw(daemonize1 drop_root logfile daemonize2 sigint sigterm); +use FS::UID qw(adminsuidsetup); +use FS::Record qw(qsearch ); #qsearchs); +#use FS::cdr; +use FS::cust_pkg; + +my $user = shift or die &usage; + +#daemonize1('freeside-sprepaidd', $user); #keep unique pid files w/multi installs +daemonize1('freeside-cdrd'); + +drop_root(); + +adminsuidsetup($user); + +logfile( "%%%FREESIDE_LOG%%%/cdrd-log.". $FS::UID::datasrc ); + +daemonize2(); + +#-- + +my $addl_from = + 'LEFT JOIN part_pkg USING ( pkgpart ) '. + "LEFT JOIN part_pkg_option + ON ( cust_pkg.pkgpart = part_pkg_option.pkgpart + AND part_pkg_option.optionname = 'bill_every_call' )"; + +#XXX should pay attention to disable_src for efficiency + +my $extra_sql = + "WHERE plan = 'voip_cdr' ". + " AND optionvalue = '1' ". + " AND ( susp IS NULL OR susp = 0)". + " AND ( cancel IS NULL OR cancel = 0)". + " AND 0 < ( + SELECT COUNT(*) FROM svc_phone LEFT JOIN cust_svc USING (svcnum) + WHERE cust_pkg.pkgnum = cust_svc.pkgnum + AND 0 < ( SELECT COUNT(*) FROM cdr + WHERE ( freesidestatus IS NULL OR freesidestatus = '' ) + AND ( charged_party = svc_phone.phonenum + OR charged_party = svc_phone.countrycode + || svc_phone.phonenum + OR src = svc_phone.phonenum + OR src = svc_phone.countrycode + || svc_phone.phonenum + ) + ) + ) + "; + +while (1) { + + my $found = 0; + foreach my $cust_pkg ( + qsearch( { + 'select' => 'cust_pkg.*, part_pkg.plan', + 'table' => 'cust_pkg', + 'addl_from' => $addl_from, + 'hashref' => {}, + 'extra_sql' => $extra_sql, + } ) + ) { + + $found = 1; + + my $work_cust_pkg = $cust_pkg; + + my $cust_main = $cust_pkg->cust_main; + + my $time = time; + $cust_main->bill_and_collect( + 'time' => $time, + 'invoice_time' => $time, + 'actual_time' => $time, + 'check_freq' => '1d', #well + #'debug' => 1, + ); + + } + + die "exiting" if sigterm() || sigint(); + sleep 5; # unless $found; + +} + +#-- + +sub usage { + die "Usage:\n\n freeside-prepaidd user\n"; +} + +=head1 NAME + +freeside-prepaidd - Real-time daemon for prepaid packages + +=head1 SYNOPSIS + + freeside-prepaidd + +=head1 DESCRIPTION + +Runs continuously and suspends or cancels any prepaid customer packages which +have passed their renewal date (next bill date). + +=head1 SEE ALSO + +=cut + +1; diff --git a/init.d/freeside-init b/init.d/freeside-init index ddee5d2d7..1f3ce2bc5 100644 --- a/init.d/freeside-init +++ b/init.d/freeside-init @@ -29,6 +29,10 @@ case "$1" in freeside-prepaidd $QUEUED_USER echo "done." + echo -n "Starting freeside-cdrd: " + freeside-cdrd $QUEUED_USER + echo "done." + for MACHINE in $SELFSERVICE_MACHINES; do echo -n "Starting freeside-selfservice-server to $MACHINE: " freeside-selfservice-server $SELFSERVICE_USER $MACHINE @@ -53,6 +57,10 @@ case "$1" in kill `cat /var/run/freeside-prepaidd.pid` echo "done." + echo -n "Stopping freeside-cdrd: " + kill `cat /var/run/freeside-cdrd.pid` + echo "done." + if [ -e /var/run/freeside-selfservice-server.$SELFSERVICE_USER.pid ] then echo -n "Stopping (old) freeside-selfservice-server: " -- 2.11.0