From d3ce5efd1ec0e1a715a154696e2b0aa86e51c27b Mon Sep 17 00:00:00 2001 From: mark Date: Fri, 24 Dec 2010 09:49:32 +0000 Subject: [PATCH] part_pkg option inheritance, part 1 --- FS/FS/part_pkg.pm | 39 +++++++++++-- FS/FS/part_pkg/agent.pm | 13 +---- FS/FS/part_pkg/base_delayed.pm | 14 +---- FS/FS/part_pkg/base_rate.pm | 25 ++------- FS/FS/part_pkg/bulk.pm | 15 +---- FS/FS/part_pkg/cdr_termination.pm | 17 +----- FS/FS/part_pkg/flat.pm | 101 ++-------------------------------- FS/FS/part_pkg/flat_comission.pm | 13 +---- FS/FS/part_pkg/flat_comission_cust.pm | 29 +--------- FS/FS/part_pkg/flat_comission_pkg.pm | 26 +-------- FS/FS/part_pkg/flat_delayed.pm | 21 +------ FS/FS/part_pkg/flat_introrate.pm | 28 +++++----- FS/FS/part_pkg/global_Mixin.pm | 38 +++++++++++++ FS/FS/part_pkg/prepaid.pm | 17 +++--- FS/FS/part_pkg/prorate.pm | 80 ++------------------------- FS/FS/part_pkg/prorate_delayed.pm | 22 ++------ FS/FS/part_pkg/rt_time.pm | 5 +- FS/FS/part_pkg/sesmon_hour.pm | 13 +---- FS/FS/part_pkg/sesmon_minute.pm | 13 +---- FS/FS/part_pkg/sql_external.pm | 13 +---- FS/FS/part_pkg/sql_generic.pm | 13 +---- FS/FS/part_pkg/sqlradacct_hour.pm | 14 +---- FS/FS/part_pkg/subscription.pm | 9 +-- FS/FS/part_pkg/usage_Mixin.pm | 77 ++++++++++++++++++++++++++ FS/FS/part_pkg/voip_cdr.pm | 15 +---- FS/FS/part_pkg/voip_inbound.pm | 16 +----- FS/FS/part_pkg/voip_sqlradacct.pm | 13 +---- 27 files changed, 230 insertions(+), 469 deletions(-) create mode 100644 FS/FS/part_pkg/global_Mixin.pm create mode 100644 FS/FS/part_pkg/usage_Mixin.pm diff --git a/FS/FS/part_pkg.pm b/FS/FS/part_pkg.pm index 5c67ed96a..58f70716d 100644 --- a/FS/FS/part_pkg.pm +++ b/FS/FS/part_pkg.pm @@ -1545,19 +1545,48 @@ foreach my $INC ( @INC ) { next; } warn "got plan info from FS::part_pkg::$mod: $info\n" if $DEBUG; - if ( exists($info->{'disabled'}) && $info->{'disabled'} ) { - warn "skipping disabled plan FS::part_pkg::$mod" if $DEBUG; - next; - } + #if ( exists($info->{'disabled'}) && $info->{'disabled'} ) { + # warn "skipping disabled plan FS::part_pkg::$mod" if $DEBUG; + # next; + #} $info{$mod} = $info; + $info->{'weight'} ||= 0; # quiet warnings } } +# copy one level deep to allow replacement of fields and fieldorder tie %plans, 'Tie::IxHash', - map { $_ => $info{$_} } + map { my %infohash = %{ $info{$_} }; + $_ => \%infohash } sort { $info{$a}->{'weight'} <=> $info{$b}->{'weight'} } keys %info; +# inheritance of plan options +foreach my $name (keys(%info)) { + if (exists($info{$name}->{'disabled'}) and $info{$name}->{'disabled'}) { + warn "skipping disabled plan FS::part_pkg::$name" if $DEBUG; + delete $plans{$name}; + next; + } + my $parents = $info{$name}->{'inherit_fields'} || []; + my (%fields, %field_exists, @fieldorder); + foreach my $parent ($name, @$parents) { + %fields = ( # avoid replacing existing fields + %{ $info{$parent}->{'fields'} || {} }, + %fields + ); + foreach (@{ $info{$parent}->{'fieldorder'} || [] }) { + # avoid duplicates + next if $field_exists{$_}; + $field_exists{$_} = 1; + # allow inheritors to remove inherited fields from the fieldorder + push @fieldorder, $_ if !exists($fields{$_}->{'disabled'}); + } + } + $plans{$name}->{'fields'} = \%fields; + $plans{$name}->{'fieldorder'} = \@fieldorder; +} + sub plan_info { \%plans; } diff --git a/FS/FS/part_pkg/agent.pm b/FS/FS/part_pkg/agent.pm index 69ecf77ca..6ab21d64f 100644 --- a/FS/FS/part_pkg/agent.pm +++ b/FS/FS/part_pkg/agent.pm @@ -19,16 +19,8 @@ $me = '[FS::part_pkg::agent]'; %info = ( 'name' => 'Wholesale bulk billing, for master customers of an agent.', 'shortname' => 'Wholesale bulk billing for agent.', - + 'inherit_fields' => [qw( prorate global_Mixin)], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Base recurring fee for this package', - 'default' => 0, - }, - - #'recur_method' => { 'name' => 'Recurring fee method', # #'type' => 'radio', # #'options' => \%recur_method, @@ -49,8 +41,7 @@ $me = '[FS::part_pkg::agent]'; }, - #'fieldorder' => [qw( setup_fee recur_fee recur_method cutoff_day ) ], - 'fieldorder' => [qw( setup_fee recur_fee cutoff_day add_full_period no_pkg_prorate ) ], + 'fieldorder' => [qw( cutoff_day add_full_period no_pkg_prorate ) ], 'weight' => 51, diff --git a/FS/FS/part_pkg/base_delayed.pm b/FS/FS/part_pkg/base_delayed.pm index df503760e..c6864a692 100644 --- a/FS/FS/part_pkg/base_delayed.pm +++ b/FS/FS/part_pkg/base_delayed.pm @@ -11,28 +11,18 @@ use FS::part_pkg::base_rate; 'name' => 'Free (or setup fee) for X days, then base rate'. ' (anniversary billing)', 'shortname' => 'Bulk (manual from "units" option), w/intro period', + 'inherit_fields' => [ 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, 'free_days' => { 'name' => 'Initial free days', 'default' => 0, }, - 'recur_fee' => { 'name' => 'Recurring base fee for this package', - 'default' => 0, - }, 'recur_notify' => { 'name' => 'Number of days before recurring billing'. ' commences to notify customer. (0 means'. ' no warning)', 'default' => 0, }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, }, - 'fieldorder' => [ 'free_days', 'setup_fee', 'recur_fee', 'recur_notify', - 'unused_credit' + 'fieldorder' => [ 'free_days', 'recur_notify', ], #'setup' => '\'my $d = $cust_pkg->bill || $time; $d += 86400 * \' + what.free_days.value + \'; $cust_pkg->bill($d); $cust_pkg_mod_flag=1; \' + what.setup_fee.value', #'recur' => 'what.recur_fee.value', diff --git a/FS/FS/part_pkg/base_rate.pm b/FS/FS/part_pkg/base_rate.pm index 440e98518..678197799 100644 --- a/FS/FS/part_pkg/base_rate.pm +++ b/FS/FS/part_pkg/base_rate.pm @@ -12,23 +12,13 @@ use FS::part_pkg; # XXX it multiplies recurring fee by cust_pkg option "units", how to # express that 'shortname' => 'Bulk (manual from "units" option)', + 'inherit_fields' => [ 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Recurring Base fee for this package', - 'default' => 0, - }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, - 'externalid' => { 'name' => 'Optional External ID', + 'externalid' => { 'name' => 'Optional External ID', 'default' => '', }, }, - 'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', - 'externalid' ], + 'fieldorder' => [ qw( externalid ) ], 'weight' => 52, ); @@ -59,13 +49,10 @@ sub base_recur { } sub calc_remain { - my ($self, $cust_pkg) = @_; - my $time = time; #should be able to pass this in for credit calculation + my ($self, $cust_pkg, %options) = @_; + my $time = $options{'time'} || time; my $next_bill = $cust_pkg->getfield('bill') || 0; - my $last_bill = $cust_pkg->last_bill || 0; - return 0 if ! $self->base_recur($cust_pkg) - || ! $self->option('unused_credit', 1) - || ! $last_bill + return 0 if ! $self->base_recur($cust_pkg) || ! $next_bill || $next_bill < $time; diff --git a/FS/FS/part_pkg/bulk.pm b/FS/FS/part_pkg/bulk.pm index b28fd3046..0df929edf 100644 --- a/FS/FS/part_pkg/bulk.pm +++ b/FS/FS/part_pkg/bulk.pm @@ -12,23 +12,14 @@ $me = '[FS::part_pkg::bulk]'; %info = ( 'name' => 'Bulk billing based on number of active services', + 'inherit_fields' => [ 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for the entire bulk package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Recurring fee for the entire bulk package', - 'default' => 0, - }, 'svc_setup_fee' => { 'name' => 'Setup fee for each new service', 'default' => 0, }, 'svc_recur_fee' => { 'name' => 'Recurring fee for each service', 'default' => 0, }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, 'summarize_svcs'=> { 'name' => 'Show a count of services on the invoice, '. 'instead of a detailed list', 'type' => 'checkbox', @@ -38,8 +29,8 @@ $me = '[FS::part_pkg::bulk]'; 'type' => 'checkbox', }, }, - 'fieldorder' => [ 'setup_fee', 'recur_fee', 'svc_setup_fee', 'svc_recur_fee', - 'unused_credit', 'summarize_svcs', 'no_prorate' ], + 'fieldorder' => [ 'svc_setup_fee', 'svc_recur_fee', + 'summarize_svcs', 'no_prorate' ], 'weight' => 50, ); diff --git a/FS/FS/part_pkg/cdr_termination.pm b/FS/FS/part_pkg/cdr_termination.pm index 0666d7939..840da8224 100644 --- a/FS/FS/part_pkg/cdr_termination.pm +++ b/FS/FS/part_pkg/cdr_termination.pm @@ -16,15 +16,8 @@ tie my %temporalities, 'Tie::IxHash', %info = ( 'name' => 'VoIP rating of CDR records for termination partners.', 'shortname' => 'VoIP/telco CDR termination', + 'inherit_fields' => [ 'global_Mixin' ], 'fields' => { - - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Base recurring fee for this package', - 'default' => 0, - }, - #'cdr_column' => { 'name' => 'Column from CDR records', # 'type' => 'select', # 'select_enum' => [qw( @@ -49,11 +42,6 @@ tie my %temporalities, 'Tie::IxHash', 'select_options' => \%temporalities, }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, - 'cutoff_day' => { 'name' => 'Billing Day (1 - 28) for prorating or '. 'subscription', 'default' => '1', @@ -92,8 +80,7 @@ tie my %temporalities, 'Tie::IxHash', }, #cdr_column 'fieldorder' => [qw( - setup_fee recur_fee - recur_temporality unused_credit recur_method cutoff_day + recur_temporality recur_method cutoff_day add_full_period output_format usage_section summarize_usage usage_mandate ) diff --git a/FS/FS/part_pkg/flat.pm b/FS/FS/part_pkg/flat.pm index e8f54d124..b5e0fa023 100644 --- a/FS/FS/part_pkg/flat.pm +++ b/FS/FS/part_pkg/flat.pm @@ -2,8 +2,7 @@ package FS::part_pkg::flat; use strict; use vars qw( @ISA %info - %usage_fields %usage_recharge_fields - @usage_fieldorder @usage_recharge_fieldorder + %usage_recharge_fields @usage_recharge_fieldorder ); use Tie::IxHash; use List::Util qw(min); # max); @@ -26,97 +25,16 @@ tie my %contract_years, 'Tie::IxHash', ( map { $_*12 => $_ } (1..5), ); -%usage_fields = ( - - 'seconds' => { 'name' => 'Time limit for this package', - 'default' => '', - 'check' => sub { shift =~ /^\d*$/ }, - }, - 'upbytes' => { 'name' => 'Upload limit for this package', - 'default' => '', - 'check' => sub { shift =~ /^\d*$/ }, - 'format' => \&FS::UI::bytecount::display_bytecount, - 'parse' => \&FS::UI::bytecount::parse_bytecount, - }, - 'downbytes' => { 'name' => 'Download limit for this package', - 'default' => '', - 'check' => sub { shift =~ /^\d*$/ }, - 'format' => \&FS::UI::bytecount::display_bytecount, - 'parse' => \&FS::UI::bytecount::parse_bytecount, - }, - 'totalbytes' => { 'name' => 'Transfer limit for this package', - 'default' => '', - 'check' => sub { shift =~ /^\d*$/ }, - 'format' => \&FS::UI::bytecount::display_bytecount, - 'parse' => \&FS::UI::bytecount::parse_bytecount, - }, -); - -%usage_recharge_fields = ( - - 'recharge_amount' => { 'name' => 'Cost of recharge for this package', - 'default' => '', - 'check' => sub { shift =~ /^\d*(\.\d{2})?$/ }, - }, - 'recharge_seconds' => { 'name' => 'Recharge time for this package', - 'default' => '', - 'check' => sub { shift =~ /^\d*$/ }, - }, - 'recharge_upbytes' => { 'name' => 'Recharge upload for this package', - 'default' => '', - 'check' => sub { shift =~ /^\d*$/ }, - 'format' => \&FS::UI::bytecount::display_bytecount, - 'parse' => \&FS::UI::bytecount::parse_bytecount, - }, - 'recharge_downbytes' => { 'name' => 'Recharge download for this package', - 'default' => '', - 'check' => sub { shift =~ /^\d*$/ }, - 'format' => \&FS::UI::bytecount::display_bytecount, - 'parse' => \&FS::UI::bytecount::parse_bytecount, - }, - 'recharge_totalbytes' => { 'name' => 'Recharge transfer for this package', - 'default' => '', - 'check' => sub { shift =~ /^\d*$/ }, - 'format' => \&FS::UI::bytecount::display_bytecount, - 'parse' => \&FS::UI::bytecount::parse_bytecount, - }, - 'usage_rollover' => { 'name' => 'Allow usage from previous period to roll '. - ' over into current period', - 'type' => 'checkbox', - }, - 'recharge_reset' => { 'name' => 'Reset usage to these values on manual '. - 'package recharge', - 'type' => 'checkbox', - }, -); - -@usage_fieldorder = qw( seconds upbytes downbytes totalbytes ); -@usage_recharge_fieldorder = qw( - recharge_amount recharge_seconds recharge_upbytes - recharge_downbytes recharge_totalbytes - usage_rollover recharge_reset -); - %info = ( 'name' => 'Flat rate (anniversary billing)', 'shortname' => 'Anniversary', + 'inherit_fields' => [ 'usage_Mixin', 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Recurring fee for this package', - 'default' => 0, - }, - #false laziness w/voip_cdr.pm 'recur_temporality' => { 'name' => 'Charge recurring fee for period', 'type' => 'select', 'select_options' => \%temporalities, }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, #used in cust_pkg.pm so could add to any price plan 'expire_months' => { 'name' => 'Auto-add an expiration date this number of months out', @@ -145,22 +63,16 @@ tie my %contract_years, 'Tie::IxHash', ( 'type' => 'checkbox', }, - %usage_fields, - %usage_recharge_fields, - 'externalid' => { 'name' => 'Optional External ID', 'default' => '', }, }, - 'fieldorder' => [ qw( setup_fee recur_fee - recur_temporality unused_credit + 'fieldorder' => [ qw( recur_temporality expire_months adjourn_months contract_end_months start_1st sync_bill_date suspend_bill unsuspend_adjust_bill - ), - @usage_fieldorder, @usage_recharge_fieldorder, - qw( externalid ), + externalid ), ], 'weight' => 10, ); @@ -239,12 +151,7 @@ sub calc_remain { my $next_bill = $cust_pkg->getfield('bill') || 0; - #my $last_bill = $cust_pkg->last_bill || 0; - my $last_bill = $cust_pkg->get('last_bill') || 0; #->last_bill falls back to setup - return 0 if ! $self->base_recur($cust_pkg) - || ! $self->option('unused_credit', 1) - || ! $last_bill || ! $next_bill || $next_bill < $time; diff --git a/FS/FS/part_pkg/flat_comission.pm b/FS/FS/part_pkg/flat_comission.pm index c05e45586..ec8c8ebbc 100644 --- a/FS/FS/part_pkg/flat_comission.pm +++ b/FS/FS/part_pkg/flat_comission.pm @@ -10,17 +10,8 @@ use FS::part_pkg::flat; %info = ( 'name' => 'Flat rate with recurring commission per (any) active package', 'shortname' => 'Commission per (any) active package', + 'inherit_fields' => [ 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Recurring fee for this package', - 'default' => 0, - }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, 'comission_amount' => { 'name' => 'Commission amount per month (per active package)', 'default' => 0, }, @@ -35,7 +26,7 @@ use FS::part_pkg::flat; 'select_label' => 'type', }, }, - 'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', 'comission_depth', 'comission_amount', 'reason_type' ], + 'fieldorder' => [ 'comission_depth', 'comission_amount', 'reason_type' ], #'setup' => 'what.setup_fee.value', #'recur' => '\'my $error = $cust_pkg->cust_main->credit( \' + what.comission_amount.value + \' * scalar($cust_pkg->cust_main->referral_cust_pkg(\' + what.comission_depth.value+ \')), "commission" ); die $error if $error; \' + what.recur_fee.value + \';\'', 'weight' => 62, diff --git a/FS/FS/part_pkg/flat_comission_cust.pm b/FS/FS/part_pkg/flat_comission_cust.pm index 5db46585e..5acf73d7a 100644 --- a/FS/FS/part_pkg/flat_comission_cust.pm +++ b/FS/FS/part_pkg/flat_comission_cust.pm @@ -10,32 +10,9 @@ use FS::part_pkg::flat; %info = ( 'name' => 'Flat rate with recurring commission per active customer', 'shortname' => 'Commission per active customer', - 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Recurring fee for this package', - 'default' => 0, - }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, - 'comission_amount' => { 'name' => 'Commission amount per month (per active customer)', - 'default' => 0, - }, - 'comission_depth' => { 'name' => 'Number of layers', - 'default' => 1, - }, - 'reason_type' => { 'name' => 'Reason type for commission credits', - 'type' => 'select_table', - 'select_table' => 'reason_type', - 'select_hash' => { 'class' => 'R' }, - 'select_key' => 'typenum', - 'select_label' => 'type', - }, - }, - 'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', 'comission_depth', 'comission_amount', 'reason_type' ], + 'inherit_fields' => [ 'flat_comission', 'global_Mixin' ], + 'fields' => { }, + 'fieldorder' => [ ], #'setup' => 'what.setup_fee.value', #'recur' => '\'my $error = $cust_pkg->cust_main->credit( \' + what.comission_amount.value + \' * scalar($cust_pkg->cust_main->referral_cust_main_ncancelled(\' + what.comission_depth.value+ \')), "commission" ); die $error if $error; \' + what.recur_fee.value + \';\'', 'weight' => '60', diff --git a/FS/FS/part_pkg/flat_comission_pkg.pm b/FS/FS/part_pkg/flat_comission_pkg.pm index 6f5ee692c..26dd4d2fc 100644 --- a/FS/FS/part_pkg/flat_comission_pkg.pm +++ b/FS/FS/part_pkg/flat_comission_pkg.pm @@ -10,23 +10,8 @@ use FS::part_pkg::flat; %info = ( 'name' => 'Flat rate with recurring commission per (selected) active package', 'shortname' => 'Commission per (selected) active package', + 'inherit_fields' => [ 'flat_comission', 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Recurring fee for this package', - 'default' => 0, - }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, - 'comission_amount' => { 'name' => 'Commission amount per month (per uncancelled package)', - 'default' => 0, - }, - 'comission_depth' => { 'name' => 'Number of layers', - 'default' => 1, - }, 'comission_pkgpart' => { 'name' => 'Applicable packages
(hold ctrl to select multiple packages)', 'type' => 'select_multiple', 'select_table' => 'part_pkg', @@ -34,15 +19,8 @@ use FS::part_pkg::flat; 'select_key' => 'pkgpart', 'select_label' => 'pkg', }, - 'reason_type' => { 'name' => 'Reason type for commission credits', - 'type' => 'select', - 'select_table' => 'reason_type', - 'select_hash' => { 'class' => 'R' } , - 'select_key' => 'typenum', - 'select_label' => 'type', - }, }, - 'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', 'comission_depth', 'comission_amount', 'comission_pkgpart', 'reason_type' ], + 'fieldorder' => [ 'comission_depth', 'comission_amount', 'comission_pkgpart', 'reason_type' ], #'setup' => 'what.setup_fee.value', #'recur' => '""; var pkgparts = ""; for ( var c=0; c < document.flat_comission_pkg.comission_pkgpart.options.length; c++ ) { if (document.flat_comission_pkg.comission_pkgpart.options[c].selected) { pkgparts = pkgparts + document.flat_comission_pkg.comission_pkgpart.options[c].value + \', \'; } } what.recur.value = \'my $error = $cust_pkg->cust_main->credit( \' + what.comission_amount.value + \' * scalar( grep { my $pkgpart = $_->pkgpart; grep { $_ == $pkgpart } ( \' + pkgparts + \' ) } $cust_pkg->cust_main->referral_cust_pkg(\' + what.comission_depth.value+ \')), "commission" ); die $error if $error; \' + what.recur_fee.value + \';\'', #'disabled' => 1, diff --git a/FS/FS/part_pkg/flat_delayed.pm b/FS/FS/part_pkg/flat_delayed.pm index 33f9dd80e..b4be72bec 100644 --- a/FS/FS/part_pkg/flat_delayed.pm +++ b/FS/FS/part_pkg/flat_delayed.pm @@ -11,28 +11,18 @@ use FS::part_pkg::flat; 'name' => 'Free (or setup fee) for X days, then flat rate'. ' (anniversary billing)', 'shortname' => 'Anniversary, with intro period', + 'inherit_fields' => [ 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, 'free_days' => { 'name' => 'Initial free days', 'default' => 0, }, - 'recur_fee' => { 'name' => 'Recurring fee for this package', - 'default' => 0, - }, 'recur_notify' => { 'name' => 'Number of days before recurring billing'. ' commences to notify customer. (0 means'. ' no warning)', 'default' => 0, }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, - }, - 'fieldorder' => [ 'free_days', 'setup_fee', 'recur_fee', 'recur_notify', - 'unused_credit' + }, + 'fieldorder' => [ 'free_days', 'recur_notify', ], #'setup' => '\'my $d = $cust_pkg->bill || $time; $d += 86400 * \' + what.free_days.value + \'; $cust_pkg->bill($d); $cust_pkg_mod_flag=1; \' + what.setup_fee.value', #'recur' => 'what.recur_fee.value', @@ -58,11 +48,6 @@ sub calc_remain { return 0 if $last_bill + (86400 * $free_days) == $next_bill && $last_bill == $cust_pkg->setup; - return 0 if ! $self->base_recur($cust_pkg) - || ! $self->option('unused_credit', 1) - || ! $last_bill - || ! $next_bill; - return $self->SUPER::calc_remain($cust_pkg, %options); } diff --git a/FS/FS/part_pkg/flat_introrate.pm b/FS/FS/part_pkg/flat_introrate.pm index 2d551f10f..1447730e7 100644 --- a/FS/FS/part_pkg/flat_introrate.pm +++ b/FS/FS/part_pkg/flat_introrate.pm @@ -2,7 +2,6 @@ package FS::part_pkg::flat_introrate; use strict; use vars qw(@ISA %info $DEBUG $me); -#use FS::Record qw(qsearch qsearchs); use FS::part_pkg::flat; use Date::Manip qw(DateCalc UnixDate ParseDate); @@ -11,22 +10,23 @@ use Date::Manip qw(DateCalc UnixDate ParseDate); $me = '[' . __PACKAGE__ . ']'; $DEBUG = 0; -(%info) = (%FS::part_pkg::flat::info); -$info{name} = 'Introductory price for X months, then flat rate,'. - 'relative to setup date (anniversary billing)'; -$info{shortname} = 'Anniversary, with intro price'; -$info{fields} = { %{$info{fields}} }; -$info{fields}{intro_fee} = - { 'name' => 'Introductory recurring fee for this package', +%info = ( + 'name' => 'Introductory price for X months, then flat rate,'. + 'relative to setup date (anniversary billing)', + 'shortname' => 'Anniversary, with intro price', + 'inherit_fields' => [ 'flat', 'usage_Mixin', 'global_Mixin' ], + 'fields' => { + 'intro_fee' => { 'name' => 'Introductory recurring fee for this package', 'default' => 0, - }; -$info{fields}{intro_duration} = + }, + 'intro_duration' => { 'name' => 'Duration of the introductory period, in number of months', 'default' => 0, - }; -$info{fieldorder} = [ @{ $info{fieldorder} } ]; -splice @{$info{fieldorder}}, 1, 0, qw( intro_duration intro_fee ); -$info{weight} = 14; + }, + }, + 'fieldorder' => [ qw(intro_duration intro_fee) ], + 'weight' => 14, +); sub base_recur { my($self, $cust_pkg, $time ) = @_; diff --git a/FS/FS/part_pkg/global_Mixin.pm b/FS/FS/part_pkg/global_Mixin.pm new file mode 100644 index 000000000..56f160247 --- /dev/null +++ b/FS/FS/part_pkg/global_Mixin.pm @@ -0,0 +1,38 @@ +package FS::part_pkg::global_Mixin; + +use strict; +use vars qw(@ISA %info); +use FS::part_pkg; +@ISA = qw(FS::part_pkg); + +%info = ( + 'disabled' => 1, + 'fields' => { + 'setup_fee' => { + 'name' => 'Setup fee for this package', + 'default' => 0, + }, + 'recur_fee' => { + 'name' => 'Recurring fee for this package', + 'default' => 0, + }, + 'unused_credit_cancel' => { + 'name' => 'Credit the customer for the unused portion of service at '. + 'cancellation', + 'type' => 'checkbox', + }, + 'unused_credit_change' => { + 'name' => 'Credit the customer for the unused portion of service when '. + 'changing packages', + 'type' => 'checkbox', + }, + }, + 'fieldorder' => [ qw( + setup_fee + recur_fee + unused_credit_cancel + unused_credit_change + )], +); + +1; diff --git a/FS/FS/part_pkg/prepaid.pm b/FS/FS/part_pkg/prepaid.pm index cff165a5d..407343bc8 100644 --- a/FS/FS/part_pkg/prepaid.pm +++ b/FS/FS/part_pkg/prepaid.pm @@ -21,28 +21,25 @@ tie my %overlimit_action, 'Tie::IxHash', 'name' => 'Prepaid, flat rate', #'name' => 'Prepaid (no automatic recurring)', #maybe use it here too 'shortname' => 'Prepaid, no automatic cycle', + 'inherit_fields' => [ 'usage_Mixin', 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'One-time setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Initial and recharge fee for this package', - 'default' => 0, - }, 'recur_action' => { 'name' => 'Action to take upon reaching end of prepaid preiod', 'type' => 'select', 'select_options' => \%recur_action, }, - %FS::part_pkg::flat::usage_fields, 'overlimit_action' => { 'name' => 'Action to take upon reaching a usage limit.', 'type' => 'select', 'select_options' => \%overlimit_action, }, #XXX if you set overlimit_action to 'cancel', should also have the ability # to select a reason + + # do we need to disable these? + map { $_ => { 'disabled' => 1 } } ( + qw(recharge_amount recharge_seconds recharge_upbytes recharge_downbytes + recharge_totalbytes usage_rollover recharge_reset) ), }, - 'fieldorder' => [ qw( setup_fee recur_fee recur_action ), - @FS::part_pkg::flat::usage_fieldorder, 'overlimit_action', - ], + 'fieldorder' => [ qw( recur_action overlimit_action ) ], 'weight' => 25, ); diff --git a/FS/FS/part_pkg/prorate.pm b/FS/FS/part_pkg/prorate.pm index 4abdb8d83..367f15275 100644 --- a/FS/FS/part_pkg/prorate.pm +++ b/FS/FS/part_pkg/prorate.pm @@ -11,74 +11,14 @@ use FS::part_pkg::flat; %info = ( 'name' => 'First partial month pro-rated, then flat-rate (selectable billing day)', 'shortname' => 'Prorate (Nth of month billing)', + 'inherit_fields' => [ 'flat', 'usage_Mixin', 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Recurring fee for this package', - 'default' => 0, - }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, + 'recur_temporality' => {'disabled' => 1}, + 'sync_bill_date' => {'disabled' => 1}, 'cutoff_day' => { 'name' => 'Billing Day (1 - 28)', 'default' => 1, }, - 'seconds' => { 'name' => 'Time limit for this package', - 'default' => '', - 'check' => sub { shift =~ /^\d*$/ }, - }, - 'upbytes' => { 'name' => 'Upload limit for this package', - 'default' => '', - 'check' => sub { shift =~ /^\d*$/ }, - 'format' => \&FS::UI::bytecount::display_bytecount, - 'parse' => \&FS::UI::bytecount::parse_bytecount, - }, - 'downbytes' => { 'name' => 'Download limit for this package', - 'default' => '', - 'check' => sub { shift =~ /^\d*$/ }, - 'format' => \&FS::UI::bytecount::display_bytecount, - 'parse' => \&FS::UI::bytecount::parse_bytecount, - }, - 'totalbytes' => { 'name' => 'Transfer limit for this package', - 'default' => '', - 'check' => sub { shift =~ /^\d*$/ }, - 'format' => \&FS::UI::bytecount::display_bytecount, - 'parse' => \&FS::UI::bytecount::parse_bytecount, - }, - 'recharge_amount' => { 'name' => 'Cost of recharge for this package', - 'default' => '', - 'check' => sub { shift =~ /^\d*(\.\d{2})?$/ }, - }, - 'recharge_seconds' => { 'name' => 'Recharge time for this package', - 'default' => '', - 'check' => sub { shift =~ /^\d*$/ }, - }, - 'recharge_upbytes' => { 'name' => 'Recharge upload for this package', - 'default' => '', - 'check' => sub { shift =~ /^\d*$/ }, - 'format' => \&FS::UI::bytecount::display_bytecount, - 'parse' => \&FS::UI::bytecount::parse_bytecount, - }, - 'recharge_downbytes' => { 'name' => 'Recharge download for this package', 'default' => '', - 'check' => sub { shift =~ /^\d*$/ }, - 'format' => \&FS::UI::bytecount::display_bytecount, - 'parse' => \&FS::UI::bytecount::parse_bytecount, - }, - 'recharge_totalbytes' => { 'name' => 'Recharge transfer for this package', 'default' => '', - 'check' => sub { shift =~ /^\d*$/ }, - 'format' => \&FS::UI::bytecount::display_bytecount, - 'parse' => \&FS::UI::bytecount::parse_bytecount, - }, - 'usage_rollover' => { 'name' => 'Allow usage from previous period to roll '. - 'over into current period', - 'type' => 'checkbox', - }, - 'recharge_reset' => { 'name' => 'Reset usage to these values on manual '. - 'package recharge', - 'type' => 'checkbox', - }, + 'add_full_period'=> { 'name' => 'When prorating first month, also bill '. 'for one full period after that', 'type' => 'checkbox', @@ -88,18 +28,8 @@ use FS::part_pkg::flat; 'the nearest full day', 'type' => 'checkbox', }, - - #it would be better if this had to be turned on, its confusing - 'externalid' => { 'name' => 'Optional External ID', - 'default' => '', - }, }, - 'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', 'cutoff_day', - 'seconds', 'upbytes', 'downbytes', 'totalbytes', - 'recharge_amount', 'recharge_seconds', 'recharge_upbytes', - 'recharge_downbytes', 'recharge_totalbytes', - 'usage_rollover', 'recharge_reset', 'add_full_period', - 'prorate_round_day', 'externalid', ], + 'fieldorder' => [ 'cutoff_day', 'add_full_period', 'prorate_round_day' ], 'freq' => 'm', 'weight' => 20, ); diff --git a/FS/FS/part_pkg/prorate_delayed.pm b/FS/FS/part_pkg/prorate_delayed.pm index 0073493ed..dd1b81600 100644 --- a/FS/FS/part_pkg/prorate_delayed.pm +++ b/FS/FS/part_pkg/prorate_delayed.pm @@ -11,27 +11,18 @@ use FS::part_pkg; 'name' => 'Free (or setup fee) for X days, then prorate, then flat-rate ' . '(1st of month billing)', 'shortname' => 'Prorate (Nth of month billing), with intro period', #?? + 'inherit_fields' => [ 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, 'free_days' => { 'name' => 'Initial free days', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Recurring fee for this package', - 'default' => 0, + 'default' => 0, }, 'recur_notify' => { 'name' => 'Number of days before recurring billing'. ' commences to notify customer. (0 means'. ' no warning)', 'default' => 0, }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, }, - 'fieldorder' => [ 'free_days', 'setup_fee', 'recur_fee', 'unused_credit' ], + 'fieldorder' => [ 'free_days', 'recur_notify' ], #'setup' => '\'my $d = $cust_pkg->bill || $time; $d += 86400 * \' + what.free_days.value + \'; $cust_pkg->bill($d); $cust_pkg_mod_flag=1; \' + what.setup_fee.value', #'recur' => 'what.recur_fee.value', 'weight' => 22, @@ -49,18 +40,13 @@ sub calc_setup { sub calc_remain { my ($self, $cust_pkg, %options) = @_; - my $next_bill = $cust_pkg->getfield('bill') || 0; my $last_bill = $cust_pkg->last_bill || 0; + my $next_bill = $cust_pkg->getfield('bill') || 0; my $free_days = $self->option('free_days'); return 0 if $last_bill + (86400 * $free_days) == $next_bill && $last_bill == $cust_pkg->setup; - return 0 if ! $self->base_recur($cust_pkg) - || ! $self->option('unused_credit', 1) - || ! $last_bill - || ! $next_bill; - return $self->SUPER::calc_remain($cust_pkg, %options); } diff --git a/FS/FS/part_pkg/rt_time.pm b/FS/FS/part_pkg/rt_time.pm index 9452d4402..03ed1cde7 100644 --- a/FS/FS/part_pkg/rt_time.pm +++ b/FS/FS/part_pkg/rt_time.pm @@ -14,11 +14,14 @@ our %info = ( 'name' => 'Bill from Time Worked on tickets in RT', 'shortname' => 'Project Billing (RT)', 'weight' => 55, + 'inherit_fields' => [ 'global_Mixin' ], 'fields' => { 'base_rate' => { 'name' => 'Rate (per minute)', 'default' => 0, }, - } + 'recur_fee' => {'disabled' => 1}, + }, + 'fieldorder' => [ 'base_rate' ], ); sub calc_setup { diff --git a/FS/FS/part_pkg/sesmon_hour.pm b/FS/FS/part_pkg/sesmon_hour.pm index e608d5510..97274d094 100644 --- a/FS/FS/part_pkg/sesmon_hour.pm +++ b/FS/FS/part_pkg/sesmon_hour.pm @@ -10,17 +10,8 @@ use FS::part_pkg::flat; %info = ( 'name' => 'Base charge plus charge per-hour from the session monitor', 'shortname' => 'Session monitor (per-hour)', + 'inherit_fields' => [ 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Base recurring fee for this package', - 'default' => 0, - }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, 'recur_included_hours' => { 'name' => 'Hours included', 'default' => 0, }, @@ -28,7 +19,7 @@ use FS::part_pkg::flat; 'default' => 0, }, }, - 'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', 'recur_included_hours', 'recur_hourly_charge' ], + 'fieldorder' => [ 'recur_included_hours', 'recur_hourly_charge' ], #'setup' => 'what.setup_fee.value', #'recur' => '\'my $hours = $cust_pkg->seconds_since($cust_pkg->bill || 0) / 3600 - \' + what.recur_included_hours.value + \'; $hours = 0 if $hours < 0; \' + what.recur_fee.value + \' + \' + what.recur_hourly_charge.value + \' * $hours;\'', 'weight' => 80, diff --git a/FS/FS/part_pkg/sesmon_minute.pm b/FS/FS/part_pkg/sesmon_minute.pm index 654fdf596..9c8dfd1b7 100644 --- a/FS/FS/part_pkg/sesmon_minute.pm +++ b/FS/FS/part_pkg/sesmon_minute.pm @@ -10,17 +10,8 @@ use FS::part_pkg::flat; %info = ( 'name' => 'Base charge plus charge per-minute from the session monitor', 'shortname' => 'Session monitor (per-minute)', + 'inherit_fields' => [ 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Base recurring fee for this package', - 'default' => 0, - }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, 'recur_included_min' => { 'name' => 'Minutes included', 'default' => 0, }, @@ -28,7 +19,7 @@ use FS::part_pkg::flat; 'default' => 0, }, }, - 'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', 'recur_included_min', 'recur_minly_charge' ], + 'fieldorder' => [ 'recur_included_min', 'recur_minly_charge' ], #'setup' => 'what.setup_fee.value', #'recur' => '\'my $min = $cust_pkg->seconds_since($cust_pkg->bill || 0) / 60 - \' + what.recur_included_min.value + \'; $min = 0 if $min < 0; \' + what.recur_fee.value + \' + \' + what.recur_minly_charge.value + \' * $min;\'', 'weight' => 80, diff --git a/FS/FS/part_pkg/sql_external.pm b/FS/FS/part_pkg/sql_external.pm index 8e803f967..8d4308676 100644 --- a/FS/FS/part_pkg/sql_external.pm +++ b/FS/FS/part_pkg/sql_external.pm @@ -9,17 +9,8 @@ use DBI; %info = ( 'name' => 'Base charge plus additional fees for external services from a configurable SQL query', 'shortname' => 'External SQL query', + 'inherit_fields' => [ 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Base recurring fee for this package', - 'default' => 0, - }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, 'cutoff_day' => { 'name' => 'Billing Day (1 - 28) for prorating or '. 'subscription', 'default' => '1', @@ -48,7 +39,7 @@ use DBI; 'default' => '', }, }, - 'fieldorder' => [qw( setup_fee recur_fee unused_credit recur_method cutoff_day + 'fieldorder' => [qw( recur_method cutoff_day add_full_period datasrc db_username db_password query )], 'weight' => '58', diff --git a/FS/FS/part_pkg/sql_generic.pm b/FS/FS/part_pkg/sql_generic.pm index eb8004476..cf38257fa 100644 --- a/FS/FS/part_pkg/sql_generic.pm +++ b/FS/FS/part_pkg/sql_generic.pm @@ -11,17 +11,8 @@ use FS::part_pkg::flat; %info = ( 'name' => 'Base charge plus a per-domain metered rate from a configurable SQL query', 'shortname' => 'Bulk (per-domain from SQL query)', + 'inherit_fields' => [ 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Base recurring fee for this package', - 'default' => 0, - }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, 'recur_included' => { 'name' => 'Units included', 'default' => 0, }, @@ -41,7 +32,7 @@ use FS::part_pkg::flat; 'default' => '', }, }, - 'fieldorder' => [qw( setup_fee recur_fee unused_credit recur_included recur_unit_charge datasrc db_username db_password query )], + 'fieldorder' => [qw( recur_included recur_unit_charge datasrc db_username db_password query )], # 'setup' => 'what.setup_fee.value', # 'recur' => '\'my $dbh = DBI->connect(\"\' + what.datasrc.value + \'\", \"\' + what.db_username.value + \'\") or die $DBI::errstr; \'', #'recur' => '\'my $dbh = DBI->connect(\"\' + what.datasrc.value + \'\", \"\' + what.db_username.value + \'\", \"\' + what.db_password.value + \'\" ) or die $DBI::errstr; my $sth = $dbh->prepare(\"\' + what.query.value + \'\") or die $dbh->errstr; my $units = 0; foreach my $cust_svc ( grep { $_->part_svc->svcdb eq \"svc_domain\" } $cust_pkg->cust_svc ) { my $domain = $cust_svc->svc_x->domain; $sth->execute($domain) or die $sth->errstr; $units += $sth->fetchrow_arrayref->[0]; } $units -= \' + what.recur_included.value + \'; $units = 0 if $units < 0; \' + what.recur_fee.value + \' + $units * \' + what.recur_unit_charge.value + \';\'', diff --git a/FS/FS/part_pkg/sqlradacct_hour.pm b/FS/FS/part_pkg/sqlradacct_hour.pm index 15f678f0e..3cc46acc4 100644 --- a/FS/FS/part_pkg/sqlradacct_hour.pm +++ b/FS/FS/part_pkg/sqlradacct_hour.pm @@ -10,18 +10,8 @@ use FS::part_pkg::flat; %info = ( 'name' => 'Base charge plus per-hour (and for data) from an SQL RADIUS radacct table', 'shortname' => 'Usage charges from RADIUS', + 'inherit_fields' => [ 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Base recurring fee for this package', - 'default' => 0, - }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, - 'recur_included_hours' => { 'name' => 'Hours included', 'default' => 0, }, @@ -77,7 +67,7 @@ use FS::part_pkg::flat; }, }, - 'fieldorder' => [qw( setup_fee recur_fee unused_credit recur_included_hours recur_hourly_charge recur_hourly_cap recur_included_input recur_input_charge recur_input_cap recur_included_output recur_output_charge recur_output_cap recur_included_total recur_total_charge recur_total_cap global_cap )], + 'fieldorder' => [qw( recur_included_hours recur_hourly_charge recur_hourly_cap recur_included_input recur_input_charge recur_input_cap recur_included_output recur_output_charge recur_output_cap recur_included_total recur_total_charge recur_total_cap global_cap )], #'setup' => 'what.setup_fee.value', #'recur' => '\'my $last_bill = $cust_pkg->last_bill; my $hours = $cust_pkg->seconds_since_sqlradacct($last_bill, $sdate ) / 3600 - \' + what.recur_included_hours.value + \'; $hours = 0 if $hours < 0; my $input = $cust_pkg->attribute_since_sqlradacct($last_bill, $sdate, \"AcctInputOctets\" ) / 1048576; my $output = $cust_pkg->attribute_since_sqlradacct($last_bill, $sdate, \"AcctOutputOctets\" ) / 1048576; my $total = $input + $output - \' + what.recur_included_total.value + \'; $total = 0 if $total < 0; my $input = $input - \' + what.recur_included_input.value + \'; $input = 0 if $input < 0; my $output = $output - \' + what.recur_included_output.value + \'; $output = 0 if $output < 0; my $totalcharge = sprintf(\"%.2f\", \' + what.recur_total_charge.value + \' * $total); my $inputcharge = sprintf(\"%.2f\", \' + what.recur_input_charge.value + \' * $input); my $outputcharge = sprintf(\"%.2f\", \' + what.recur_output_charge.value + \' * $output); my $hourscharge = sprintf(\"%.2f\", \' + what.recur_hourly_charge.value + \' * $hours); if ( \' + what.recur_total_charge.value + \' > 0 ) { push @details, \"Last month\\\'s data \". sprintf(\"%.1f\", $total). \" megs: \\\$$totalcharge\" } if ( \' + what.recur_input_charge.value + \' > 0 ) { push @details, \"Last month\\\'s download \". sprintf(\"%.1f\", $input). \" megs: \\\$$inputcharge\" } if ( \' + what.recur_output_charge.value + \' > 0 ) { push @details, \"Last month\\\'s upload \". sprintf(\"%.1f\", $output). \" megs: \\\$$outputcharge\" } if ( \' + what.recur_hourly_charge.value + \' > 0 ) { push @details, \"Last month\\\'s time \". sprintf(\"%.1f\", $hours). \" hours: \\\$$hourscharge\"; } \' + what.recur_fee.value + \' + $hourscharge + $inputcharge + $outputcharge + $totalcharge ;\'', 'weight' => 40, diff --git a/FS/FS/part_pkg/subscription.pm b/FS/FS/part_pkg/subscription.pm index 5495e3ad3..3c5f96b89 100644 --- a/FS/FS/part_pkg/subscription.pm +++ b/FS/FS/part_pkg/subscription.pm @@ -11,13 +11,8 @@ use FS::part_pkg::flat; %info = ( 'name' => 'First partial month full charge, then flat-rate (selectable billing day)', 'shortname' => 'Subscription (Nth of month, full charge for first)', + 'inherit_fields' => [ 'usage_Mixin', 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Recurring fee for this package', - 'default' => 0, - }, 'cutoff_day' => { 'name' => 'Billing day', 'default' => 1, }, @@ -81,7 +76,7 @@ use FS::part_pkg::flat; 'default' => '', }, }, - 'fieldorder' => [ 'setup_fee', 'recur_fee', 'cutoff_day', 'seconds', + 'fieldorder' => [ 'cutoff_day', 'seconds', 'upbytes', 'downbytes', 'totalbytes', 'recharge_amount', 'recharge_seconds', 'recharge_upbytes', 'recharge_downbytes', 'recharge_totalbytes', diff --git a/FS/FS/part_pkg/usage_Mixin.pm b/FS/FS/part_pkg/usage_Mixin.pm new file mode 100644 index 000000000..028fce7b9 --- /dev/null +++ b/FS/FS/part_pkg/usage_Mixin.pm @@ -0,0 +1,77 @@ +package FS::part_pkg::usage_Mixin; + +use strict; +use vars qw( @ISA %info ); +use FS::part_pkg; +use FS::UI::bytecount; +@ISA = qw(FS::part_pkg); + +# Field definitions for time and data usage, other than CDRs. + +%info = ( + 'disabled' => 1, + 'fields' => { + 'seconds' => { 'name' => 'Time limit for this package', + 'default' => '', + 'check' => sub { shift =~ /^\d*$/ }, + }, + 'upbytes' => { 'name' => 'Upload limit for this package', + 'default' => '', + 'check' => sub { shift =~ /^\d*$/ }, + 'format' => \&FS::UI::bytecount::display_bytecount, + 'parse' => \&FS::UI::bytecount::parse_bytecount, + }, + 'downbytes' => { 'name' => 'Download limit for this package', + 'default' => '', + 'check' => sub { shift =~ /^\d*$/ }, + 'format' => \&FS::UI::bytecount::display_bytecount, + 'parse' => \&FS::UI::bytecount::parse_bytecount, + }, + 'totalbytes' => { 'name' => 'Transfer limit for this package', + 'default' => '', + 'check' => sub { shift =~ /^\d*$/ }, + 'format' => \&FS::UI::bytecount::display_bytecount, + 'parse' => \&FS::UI::bytecount::parse_bytecount, + }, + 'recharge_amount' => { 'name' => 'Cost of recharge for this package', + 'default' => '', + 'check' => sub { shift =~ /^\d*(\.\d{2})?$/ }, + }, + 'recharge_seconds' => { 'name' => 'Recharge time for this package', + 'default' => '', + 'check' => sub { shift =~ /^\d*$/ }, + }, + 'recharge_upbytes' => { 'name' => 'Recharge upload for this package', + 'default' => '', + 'check' => sub { shift =~ /^\d*$/ }, + 'format' => \&FS::UI::bytecount::display_bytecount, + 'parse' => \&FS::UI::bytecount::parse_bytecount, + }, + 'recharge_downbytes' => { 'name' => 'Recharge download for this package', + 'default' => '', + 'check' => sub { shift =~ /^\d*$/ }, + 'format' => \&FS::UI::bytecount::display_bytecount, + 'parse' => \&FS::UI::bytecount::parse_bytecount, + }, + 'recharge_totalbytes' => { 'name' => 'Recharge transfer for this package', + 'default' => '', + 'check' => sub { shift =~ /^\d*$/ }, + 'format' => \&FS::UI::bytecount::display_bytecount, + 'parse' => \&FS::UI::bytecount::parse_bytecount, + }, + 'usage_rollover' => { 'name' => 'Allow usage from previous period to roll '. + ' over into current period', + 'type' => 'checkbox', + }, + 'recharge_reset' => { 'name' => 'Reset usage to these values on manual '. + 'package recharge', + 'type' => 'checkbox', + }, + }, + 'fieldorder' => [ qw( seconds upbytes downbytes totalbytes + recharge_amount recharge_seconds recharge_upbytes + recharge_downbytes recharge_totalbytes + usage_rollover recharge_reset ) ], +); + +1; diff --git a/FS/FS/part_pkg/voip_cdr.pm b/FS/FS/part_pkg/voip_cdr.pm index 768f89487..5dbd115ad 100644 --- a/FS/FS/part_pkg/voip_cdr.pm +++ b/FS/FS/part_pkg/voip_cdr.pm @@ -48,25 +48,14 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities(); %info = ( 'name' => 'VoIP rating by plan of CDR records in an internal (or external) SQL table', 'shortname' => 'VoIP/telco CDR rating (standard)', + 'inherit_fields' => [ 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Base recurring fee for this package', - 'default' => 0, - }, - #false laziness w/flat.pm 'recur_temporality' => { 'name' => 'Charge recurring fee for period', 'type' => 'select', 'select_options' => \%temporalities, }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, - 'cutoff_day' => { 'name' => 'Billing Day (1 - 28) for prorating or '. 'subscription', 'default' => '1', @@ -259,7 +248,7 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities(); }, 'fieldorder' => [qw( - setup_fee recur_fee recur_temporality unused_credit + recur_temporality recur_method cutoff_day add_full_period cdr_svc_method diff --git a/FS/FS/part_pkg/voip_inbound.pm b/FS/FS/part_pkg/voip_inbound.pm index 8b1844ad9..1b91575d4 100644 --- a/FS/FS/part_pkg/voip_inbound.pm +++ b/FS/FS/part_pkg/voip_inbound.pm @@ -24,25 +24,13 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities(); %info = ( 'name' => 'VoIP flat rate pricing of CDRs for inbound calls', 'shortname' => 'VoIP/telco CDR rating (inbound)', + 'inherit_fields' => [ 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Base recurring fee for this package', - 'default' => 0, - }, - #false laziness w/flat.pm 'recur_temporality' => { 'name' => 'Charge recurring fee for period', 'type' => 'select', 'select_options' => \%temporalities, }, - - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, - 'cutoff_day' => { 'name' => 'Billing Day (1 - 28) for prorating or '. 'subscription', 'default' => '1', @@ -155,7 +143,7 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities(); }, 'fieldorder' => [qw( - setup_fee recur_fee recur_temporality unused_credit + recur_temporality recur_method cutoff_day add_full_period min_charge sec_granularity default_prefix diff --git a/FS/FS/part_pkg/voip_sqlradacct.pm b/FS/FS/part_pkg/voip_sqlradacct.pm index 441df587b..538876712 100644 --- a/FS/FS/part_pkg/voip_sqlradacct.pm +++ b/FS/FS/part_pkg/voip_sqlradacct.pm @@ -16,17 +16,8 @@ $DEBUG = 1; 'disabled' => 1, #they're sucked into our CDR table now instead 'name' => 'VoIP rating by plan of CDR records in an SQL RADIUS radacct table', 'shortname' => 'VoIP/telco CDR rating (external RADIUS)', + 'inherit_fields' => [ 'global_Mixin' ], 'fields' => { - 'setup_fee' => { 'name' => 'Setup fee for this package', - 'default' => 0, - }, - 'recur_fee' => { 'name' => 'Base recurring fee for this package', - 'default' => 0, - }, - 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. - ' of service at cancellation', - 'type' => 'checkbox', - }, 'ratenum' => { 'name' => 'Rate plan', 'type' => 'select', 'select_table' => 'rate', @@ -34,7 +25,7 @@ $DEBUG = 1; 'select_label' => 'ratename', }, }, - 'fieldorder' => [qw( setup_fee recur_fee unused_credit ratenum ignore_unrateable )], + 'fieldorder' => [qw( ratenum ignore_unrateable )], 'weight' => 40, ); -- 2.11.0