diff options
| -rw-r--r-- | FS/FS/cust_pkg.pm | 34 | ||||
| -rw-r--r-- | FS/FS/part_pkg/flat.pm | 49 | ||||
| -rw-r--r-- | FS/FS/part_pkg/flat_comission.pm | 42 | ||||
| -rw-r--r-- | FS/FS/part_pkg/flat_comission_cust.pm | 42 | ||||
| -rw-r--r-- | FS/FS/part_pkg/flat_comission_pkg.pm | 58 | ||||
| -rw-r--r-- | FS/FS/part_pkg/flat_delayed.pm | 38 | ||||
| -rw-r--r-- | FS/FS/part_pkg/prorate.pm | 32 | ||||
| -rw-r--r-- | FS/FS/part_pkg/sesmon_hour.pm | 42 | ||||
| -rw-r--r-- | FS/FS/part_pkg/sesmon_minute.pm | 40 | ||||
| -rw-r--r-- | FS/FS/part_pkg/sql_external.pm | 46 | ||||
| -rw-r--r-- | FS/FS/part_pkg/sql_generic.pm | 62 | ||||
| -rw-r--r-- | FS/FS/part_pkg/sqlradacct_hour.pm | 74 | ||||
| -rw-r--r-- | FS/FS/part_pkg/subscription.pm | 28 | ||||
| -rw-r--r-- | FS/FS/part_pkg/voip_sqlradacct.pm | 46 | 
14 files changed, 373 insertions, 260 deletions
diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index 5705ac2c6..56da5c77d 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -376,6 +376,16 @@ sub cancel {      }    } +  # Add a credit for remaining service +  my $remaining_value= $self->calc_remain(); +  if ($remaining_value > 0) { +    my $error = $self->credit($remaining_value, 'Credit for service remaining'); +    if ($error) { +      $dbh->rollback if $oldAutoCommit; +      return "Error crediting customer for service remaining: $error"; +    }                                                                           +  }                                                                             +    unless ( $self->getfield('cancel') ) {      my %hash = $self->hash;      $hash{'cancel'} = time; @@ -592,6 +602,30 @@ sub calc_recur {    $self->part_pkg->calc_recur($self, @_);  } +=item calc_remain + +Calls the I<calc_remain> of the FS::part_pkg object associated with this +billing item. + +=cut + +sub calc_recur { +  my $self = shift; +  $self->part_pkg->calc_remain($self, @_); +} + +=item calc_cancel + +Calls the I<calc_cancel> of the FS::part_pkg object associated with this +billing item. + +=cut + +sub calc_cancel { +  my $self = shift; +  $self->part_pkg->calc_cancel($self, @_); +} +  =item cust_svc [ SVCPART ]  Returns the services for this package, as FS::cust_svc objects (see diff --git a/FS/FS/part_pkg/flat.pm b/FS/FS/part_pkg/flat.pm index 5721eddd1..131f850e9 100644 --- a/FS/FS/part_pkg/flat.pm +++ b/FS/FS/part_pkg/flat.pm @@ -10,14 +10,18 @@ use FS::part_pkg;  %info = (    'name' => 'Flat rate (anniversary billing)',    'fields' => { -    'setup_fee' => { 'name' => 'Setup fee for this package', -                     'default' => 0, -                   }, -    'recur_fee' => { 'name' => 'Recurring fee for this package', -                     'default' => 0, -                    }, +    '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', +                       },    }, -  'fieldorder' => [ 'setup_fee', 'recur_fee' ], +  'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit' ],    #'setup' => 'what.setup_fee.value',    #'recur' => 'what.recur_fee.value',    'weight' => 10, @@ -38,6 +42,37 @@ sub base_recur {    $self->option('recur_fee');  } +sub calc_remain { +  my ($self, $cust_pkg) = @_; +  my $time = time; +  my $next_bill = $cust_pkg->getfield('bill') || 0; +  my $last_bill = $cust_pkg->last_bill || 0; +  return 0 if    ! $self->base_recur +              || ! $self->option('unused_credit') +              || ! $last_bill +              || ! $next_bill; + +  my $now_date = ParseDate("epoch $time"); +  my $last_date = ParseDate("epoch $last_bill"); +  my $next_date = ParseDate("epoch $next_bill"); +  my $err; +  my $delta = DateCalc($now_date,$next_date,\$err, 0); +  my $days_remaining = Delta_Format($delta, 4, "%dh"); + +  my $frequency = $self->freq; + +  # TODO: Remove this after the frequencies are Data::Manip friendly. +  $frequency .= "m" unless $frequency =~ /[wd]$/; + +  my $freq_delta = ParseDateDelta($frequency); +  my $days = Delta_Format($freq_delta,4,"%dh"); + +  my $recurring= $self->base_recur; +  my $daily =  $recurring/$days; + +  sprintf("%.2f",($daily * $days_remaining)); +} +  sub is_free_options {    qw( setup_fee recur_fee );  } diff --git a/FS/FS/part_pkg/flat_comission.pm b/FS/FS/part_pkg/flat_comission.pm index 9b288c3a3..21c03c294 100644 --- a/FS/FS/part_pkg/flat_comission.pm +++ b/FS/FS/part_pkg/flat_comission.pm @@ -8,25 +8,29 @@ use FS::part_pkg;  @ISA = qw(FS::part_pkg::flat);  %info = ( -    'name' => 'Flat rate with recurring commission per (any) active package', -    'fields' => { -      'setup_fee' => { 'name' => 'Setup fee for this package', -                       'default' => 0, -                     }, -      'recur_fee' => { 'name' => 'Recurring fee for this package', -                       'default' => 0, -                     }, -      'comission_amount' => { 'name' => 'Commission amount per month (per active package)', -                              'default' => 0, -                            }, -      'comission_depth'  => { 'name' => 'Number of layers', -                              'default' => 1, -                            }, -    }, -    'fieldorder' => [ 'setup_fee', 'recur_fee', 'comission_depth', 'comission_amount' ], -    #'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, +  'name' => 'Flat rate with recurring commission per (any) active package', +  '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, +                          }, +    'comission_depth'  => { 'name' => 'Number of layers', +                            'default' => 1, +                          }, +  }, +  'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', 'comission_depth', 'comission_amount' ], +  #'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,  );  sub calc_recur { diff --git a/FS/FS/part_pkg/flat_comission_cust.pm b/FS/FS/part_pkg/flat_comission_cust.pm index 8aa993ca6..27a93ff79 100644 --- a/FS/FS/part_pkg/flat_comission_cust.pm +++ b/FS/FS/part_pkg/flat_comission_cust.pm @@ -8,25 +8,29 @@ use FS::part_pkg;  @ISA = qw(FS::part_pkg::flat);  %info = ( -    'name' => 'Flat rate with recurring 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, -                     }, -      'comission_amount' => { 'name' => 'Commission amount per month (per active customer)', -                              'default' => 0, -                            }, -      'comission_depth'  => { 'name' => 'Number of layers', -                              'default' => 1, -                            }, -    }, -    'fieldorder' => [ 'setup_fee', 'recur_fee', 'comission_depth', 'comission_amount' ], -    #'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', +  'name' => 'Flat rate with recurring 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, +                          }, +  }, +  'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', 'comission_depth', 'comission_amount' ], +  #'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',  );  sub calc_recur { diff --git a/FS/FS/part_pkg/flat_comission_pkg.pm b/FS/FS/part_pkg/flat_comission_pkg.pm index befa77e23..20d235c40 100644 --- a/FS/FS/part_pkg/flat_comission_pkg.pm +++ b/FS/FS/part_pkg/flat_comission_pkg.pm @@ -8,33 +8,37 @@ use FS::part_pkg;  @ISA = qw(FS::part_pkg::flat);  %info = ( -    'name' => 'Flat rate with recurring commission per (selected) active package', -    'fields' => { -      'setup_fee' => { 'name' => 'Setup fee for this package', -                       'default' => 0, -                     }, -      'recur_fee' => { 'name' => 'Recurring fee for this package', -                       'default' => 0, -                     }, -      '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<BR><FONT SIZE="-1">(hold <b>ctrl</b> to select multiple packages)</FONT>', -                               'type' => 'select_multiple', -                               'select_table' => 'part_pkg', -                               'select_hash'  => { 'disabled' => '' } , -                               'select_key'   => 'pkgpart', -                               'select_label' => 'pkg', -                             }, -    }, -    'fieldorder' => [ 'setup_fee', 'recur_fee', 'comission_depth', 'comission_amount', 'comission_pkgpart' ], -    #'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, -    'weight' => '64', +  'name' => 'Flat rate with recurring commission per (selected) active package', +  '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<BR><FONT SIZE="-1">(hold <b>ctrl</b> to select multiple packages)</FONT>', +                             'type' => 'select_multiple', +                             'select_table' => 'part_pkg', +                             'select_hash'  => { 'disabled' => '' } , +                             'select_key'   => 'pkgpart', +                             'select_label' => 'pkg', +                           }, +  }, +  'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', 'comission_depth', 'comission_amount', 'comission_pkgpart' ], +  #'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, +  'weight' => '64',  );  # XXX this needs to be fixed!!! diff --git a/FS/FS/part_pkg/flat_delayed.pm b/FS/FS/part_pkg/flat_delayed.pm index f39783fd6..4a04583d6 100644 --- a/FS/FS/part_pkg/flat_delayed.pm +++ b/FS/FS/part_pkg/flat_delayed.pm @@ -8,23 +8,27 @@ use FS::part_pkg;  @ISA = qw(FS::part_pkg::flat);  %info = ( -    'name' => 'Free (or setup fee) for X days, then flat rate'. -              ' (anniversary billing)', -    '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, -                      }, -    }, -    'fieldorder' => [ 'free_days', 'setup_fee', 'recur_fee' ], -    #'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' => 50, +  'name' => 'Free (or setup fee) for X days, then flat rate'. +            ' (anniversary billing)', +  '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, +                    }, +    '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' ], +  #'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' => 50,  );  sub calc_setup { diff --git a/FS/FS/part_pkg/prorate.pm b/FS/FS/part_pkg/prorate.pm index d27adbda7..f8a482645 100644 --- a/FS/FS/part_pkg/prorate.pm +++ b/FS/FS/part_pkg/prorate.pm @@ -9,20 +9,24 @@ use FS::part_pkg;  @ISA = qw(FS::part_pkg::flat);  %info = ( -    'name' => 'First partial month pro-rated, then flat-rate (1st of month billing)', -    'fields' =>  { -      'setup_fee' => { 'name' => 'Setup fee for this package', -                       'default' => 0, -                     }, -      'recur_fee' => { 'name' => 'Recurring fee for this package', -                       'default' => 0, -                      }, -    }, -    'fieldorder' => [ 'setup_fee', 'recur_fee' ], -    #'setup' => 'what.setup_fee.value', -    #'recur' => '\'my $mnow = $sdate; my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($sdate) )[0,1,2,3,4,5]; my $mstart = timelocal(0,0,0,1,$mon,$year); my $mend = timelocal(0,0,0,1, $mon == 11 ? 0 : $mon+1, $year+($mon==11)); $sdate = $mstart; ( $part_pkg->freq - 1 ) * \' + what.recur_fee.value + \' / $part_pkg->freq + \' + what.recur_fee.value + \' / $part_pkg->freq * ($mend-$mnow) / ($mend-$mstart) ; \'', -    'freq' => 'm', -    'weight' => 20, +  'name' => 'First partial month pro-rated, then flat-rate (1st of month billing)', +  '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', +                       }, +  }, +  'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit' ], +  #'setup' => 'what.setup_fee.value', +  #'recur' => '\'my $mnow = $sdate; my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($sdate) )[0,1,2,3,4,5]; my $mstart = timelocal(0,0,0,1,$mon,$year); my $mend = timelocal(0,0,0,1, $mon == 11 ? 0 : $mon+1, $year+($mon==11)); $sdate = $mstart; ( $part_pkg->freq - 1 ) * \' + what.recur_fee.value + \' / $part_pkg->freq + \' + what.recur_fee.value + \' / $part_pkg->freq * ($mend-$mnow) / ($mend-$mstart) ; \'', +  'freq' => 'm', +  'weight' => 20,  );  sub calc_recur { diff --git a/FS/FS/part_pkg/sesmon_hour.pm b/FS/FS/part_pkg/sesmon_hour.pm index 1f62631ef..41c7f25c3 100644 --- a/FS/FS/part_pkg/sesmon_hour.pm +++ b/FS/FS/part_pkg/sesmon_hour.pm @@ -8,25 +8,29 @@ use FS::part_pkg;  @ISA = qw(FS::part_pkg::flat);  %info = ( -    'name' => 'Base charge plus charge per-hour from the session monitor', -    'fields' => { -      'setup_fee' => { 'name' => 'Setup fee for this package', -                       'default' => 0, -                     }, -      'recur_flat' => { 'name' => 'Base monthly charge for this package', -                        'default' => 0, -                      }, -      'recur_included_hours' => { 'name' => 'Hours included', -                                  'default' => 0, -                                }, -      'recur_hourly_charge' => { 'name' => 'Additional charge per hour', -                                 'default' => 0, -                               }, -    }, -    'fieldorder' => [ 'setup_fee', 'recur_flat', '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_flat.value + \' + \' + what.recur_hourly_charge.value + \' * $hours;\'', -    'weight' => 80, +  'name' => 'Base charge plus charge per-hour from the session monitor', +  'fields' => { +    'setup_fee' => { 'name' => 'Setup fee for this package', +                     'default' => 0, +                   }, +    'recur_flat' => { 'name' => 'Base monthly charge 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, +                              }, +    'recur_hourly_charge' => { 'name' => 'Additional charge per hour', +                               'default' => 0, +                             }, +  }, +  'fieldorder' => [ 'setup_fee', 'recur_flat', 'unused_credit', '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_flat.value + \' + \' + what.recur_hourly_charge.value + \' * $hours;\'', +  'weight' => 80,  );  sub calc_recur { diff --git a/FS/FS/part_pkg/sesmon_minute.pm b/FS/FS/part_pkg/sesmon_minute.pm index 86affa70c..fd90235d1 100644 --- a/FS/FS/part_pkg/sesmon_minute.pm +++ b/FS/FS/part_pkg/sesmon_minute.pm @@ -8,25 +8,29 @@ use FS::part_pkg;  @ISA = qw(FS::part_pkg::flat);  %info = ( -    'name' => 'Base charge plus charge per-minute from the session monitor', -    'fields' => { -      'setup_fee' => { 'name' => 'Setup fee for this package', -                       'default' => 0, -                     }, -      'recur_flat' => { 'name' => 'Base monthly charge for this package', -                        'default' => 0, -                      }, -      'recur_included_min' => { 'name' => 'Minutes included', -                                'default' => 0, -                                }, -      'recur_minly_charge' => { 'name' => 'Additional charge per minute', -                                'default' => 0, +  'name' => 'Base charge plus charge per-minute from the session monitor', +  'fields' => { +    'setup_fee' => { 'name' => 'Setup fee for this package', +                     'default' => 0, +                   }, +    'recur_flat' => { 'name' => 'Base monthly charge 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,                                }, -    }, -    'fieldorder' => [ 'setup_fee', 'recur_flat', '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_flat.value + \' + \' + what.recur_minly_charge.value + \' * $min;\'', -    'weight' => 80, +    'recur_minly_charge' => { 'name' => 'Additional charge per minute', +                              'default' => 0, +                            }, +  }, +  'fieldorder' => [ 'setup_fee', 'recur_flat', 'unused_credit', '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_flat.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 96071fa4f..28a489767 100644 --- a/FS/FS/part_pkg/sql_external.pm +++ b/FS/FS/part_pkg/sql_external.pm @@ -9,31 +9,35 @@ use FS::part_pkg;  @ISA = qw(FS::part_pkg::flat);  %info = ( -    'name' => 'Base charge plus additional fees for external services from a configurable SQL query', -    'fields' => { -      'setup_fee' => { 'name' => 'Setup fee for this package', -                       'default' => 0, -                     }, -      'recur_flat' => { 'name' => 'Base monthly charge for this package', -                        'default' => 0, -                      }, -      'datasrc' => { 'name' => 'DBI data source', -                     'default' => '', +  'name' => 'Base charge plus additional fees for external services from a configurable SQL query', +  'fields' => { +    'setup_fee' => { 'name' => 'Setup fee for this package', +                     'default' => 0,                     }, -      'db_username' => { 'name' => 'Database username', -                         'default' => '', -                       }, -      'db_password' => { 'name' => 'Database password', -                         'default' => '', +    'recur_flat' => { 'name' => 'Base monthly charge for this package', +                      'default' => 0, +                    }, +    'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. +                                   ' of service at cancellation', +                         'type' => 'checkbox',                         }, -      'query' => { 'name' => 'SQL query', +    'datasrc' => { 'name' => 'DBI data source',                     'default' => '',                   }, -    }, -    'fieldorder' => [qw( setup_fee recur_flat datasrc db_username db_password query )], -    #'setup' => 'what.setup_fee.value', -    #'recur' => q!'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 $price = ' + what.recur_flat.value + '; foreach my $cust_svc ( grep { $_->part_svc->svcdb eq "svc_external" } $cust_pkg->cust_svc ){ my $id = $cust_svc->svc_x->id; $sth->execute($id) or die $sth->errstr; $price += $sth->fetchrow_arrayref->[0]; } $price;'!, -    'weight' => '72', +    'db_username' => { 'name' => 'Database username', +                       'default' => '', +                     }, +    'db_password' => { 'name' => 'Database password', +                       'default' => '', +                     }, +    'query' => { 'name' => 'SQL query', +                 'default' => '', +               }, +  }, +  'fieldorder' => [qw( setup_fee recur_flat unused_credit datasrc db_username db_password query )], +  #'setup' => 'what.setup_fee.value', +  #'recur' => q!'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 $price = ' + what.recur_flat.value + '; foreach my $cust_svc ( grep { $_->part_svc->svcdb eq "svc_external" } $cust_pkg->cust_svc ){ my $id = $cust_svc->svc_x->id; $sth->execute($id) or die $sth->errstr; $price += $sth->fetchrow_arrayref->[0]; } $price;'!, +  'weight' => '72',  );  sub calc_recur { diff --git a/FS/FS/part_pkg/sql_generic.pm b/FS/FS/part_pkg/sql_generic.pm index d1233e939..646957c9c 100644 --- a/FS/FS/part_pkg/sql_generic.pm +++ b/FS/FS/part_pkg/sql_generic.pm @@ -9,39 +9,43 @@ use FS::part_pkg;  @ISA = qw(FS::part_pkg::flat);  %info = ( -    'name' => 'Base charge plus a per-domain metered rate from a configurable SQL query', -    'fields' => { -      'setup_fee' => { 'name' => 'Setup fee for this package', -                       'default' => 0, -                     }, -      'recur_flat' => { 'name' => 'Base monthly charge for this package', -                        'default' => 0, -                      }, -      'recur_included' => { 'name' => 'Units included', -                            'default' => 0, -                          }, -      'recur_unit_charge' => { 'name' => 'Additional charge per unit', -                               'default' => 0, -                             }, -      'datasrc' => { 'name' => 'DBI data source', -                     'default' => '', +  'name' => 'Base charge plus a per-domain metered rate from a configurable SQL query', +  'fields' => { +    'setup_fee' => { 'name' => 'Setup fee for this package', +                     'default' => 0,                     }, -      'db_username' => { 'name' => 'Database username', -                         'default' => '', -                       }, -      'db_password' => { 'name' => 'Database username', -                         'default' => '', +    'recur_flat' => { 'name' => 'Base monthly charge for this package', +                      'default' => 0, +                    }, +    'unused_credit' => { 'name' => 'Credit the customer for the unused portion'. +                                   ' of service at cancellation', +                         'type' => 'checkbox',                         }, -      'query' => { 'name' => 'SQL query', +    'recur_included' => { 'name' => 'Units included', +                          'default' => 0, +                        }, +    'recur_unit_charge' => { 'name' => 'Additional charge per unit', +                             'default' => 0, +                           }, +    'datasrc' => { 'name' => 'DBI data source',                     'default' => '',                   }, -    }, -    'fieldorder' => [qw( setup_fee recur_flat 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_flat.value + \' + $units * \' + what.recur_unit_charge.value + \';\'', -    #'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_flat.value + \' + $units * \' + what.recur_unit_charge + \';\'', -    'weight' => '70', +    'db_username' => { 'name' => 'Database username', +                       'default' => '', +                     }, +    'db_password' => { 'name' => 'Database username', +                       'default' => '', +                     }, +    'query' => { 'name' => 'SQL query', +                 'default' => '', +               }, +  }, +  'fieldorder' => [qw( setup_fee recur_flat unused_credit 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_flat.value + \' + $units * \' + what.recur_unit_charge.value + \';\'', +  #'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_flat.value + \' + $units * \' + what.recur_unit_charge + \';\'', +  'weight' => '70',  );  sub calc_recur { diff --git a/FS/FS/part_pkg/sqlradacct_hour.pm b/FS/FS/part_pkg/sqlradacct_hour.pm index 76533d59d..7ecb97026 100644 --- a/FS/FS/part_pkg/sqlradacct_hour.pm +++ b/FS/FS/part_pkg/sqlradacct_hour.pm @@ -8,47 +8,51 @@ use FS::part_pkg;  @ISA = qw(FS::part_pkg::flat);  %info = ( -    'name' => 'Base charge plus per-hour (and for data) from an SQL RADIUS radacct table', -    'fields' => { -      'setup_fee' => { 'name' => 'Setup fee for this package', -                       'default' => 0, -                     }, -      'recur_flat' => { 'name' => 'Base monthly charge for this package', -                        'default' => 0, -                      }, -      'recur_included_hours' => { 'name' => 'Hours included', -                                  'default' => 0, -                                }, -      'recur_hourly_charge' => { 'name' => 'Additional charge per hour', -                                 'default' => 0, -                               }, -      'recur_included_input' => { 'name' => 'Upload megabytes included', -                                  'default' => 0, -                                }, -      'recur_input_charge' => { 'name' => -                                        'Additional charge per megabyte upload', +  'name' => 'Base charge plus per-hour (and for data) from an SQL RADIUS radacct table', +  'fields' => { +    'setup_fee' => { 'name' => 'Setup fee for this package', +                     'default' => 0, +                   }, +    'recur_flat' => { 'name' => 'Base monthly charge 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,                                }, -      'recur_included_output' => { 'name' => 'Download megabytes included', -                                   'default' => 0, -                                }, -      'recur_output_charge' => { 'name' => -                                       'Additional charge per megabyte download', +    'recur_hourly_charge' => { 'name' => 'Additional charge per hour', +                               'default' => 0, +                             }, +    'recur_included_input' => { 'name' => 'Upload megabytes included',                                  'default' => 0,                                }, -      'recur_included_total' => { 'name' => -                                       'Total megabytes included', -                                  'default' => 0, -                                }, -      'recur_total_charge' => { 'name' => -                                 'Additional charge per megabyte total', +    'recur_input_charge' => { 'name' => +                                      'Additional charge per megabyte upload', +                              'default' => 0, +                            }, +    'recur_included_output' => { 'name' => 'Download megabytes included', +                                 'default' => 0, +                              }, +    'recur_output_charge' => { 'name' => +                                     'Additional charge per megabyte download', +                              'default' => 0, +                            }, +    'recur_included_total' => { 'name' => +                                     'Total megabytes included',                                  'default' => 0,                                }, -    }, -    'fieldorder' => [qw( setup_fee recur_flat recur_included_hours recur_hourly_charge recur_included_input recur_input_charge recur_included_output recur_output_charge recur_included_total recur_total_charge )], -    #'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_flat.value + \' + $hourscharge + $inputcharge + $outputcharge + $totalcharge ;\'', -    'weight' => 40, +    'recur_total_charge' => { 'name' => +                               'Additional charge per megabyte total', +                              'default' => 0, +                            }, +  }, +  'fieldorder' => [qw( setup_fee recur_flat unused_credit recur_included_hours recur_hourly_charge recur_included_input recur_input_charge recur_included_output recur_output_charge recur_included_total recur_total_charge )], +  #'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_flat.value + \' + $hourscharge + $inputcharge + $outputcharge + $totalcharge ;\'', +  'weight' => 40,  );  sub calc_recur { diff --git a/FS/FS/part_pkg/subscription.pm b/FS/FS/part_pkg/subscription.pm index d057b6b34..e03573b7b 100644 --- a/FS/FS/part_pkg/subscription.pm +++ b/FS/FS/part_pkg/subscription.pm @@ -9,20 +9,20 @@ use FS::part_pkg;  @ISA = qw(FS::part_pkg::flat);  %info = ( -    'name' => 'First partial month full charge, then flat-rate (1st of month billing)', -    'fields' => { -      'setup_fee' => { 'name' => 'Setup fee for this package', -                       'default' => 0, -                     }, -      'recur_fee' => { 'name' => 'Recurring fee for this package', -                       'default' => 0, -                      }, -    }, -    'fieldorder' => [ 'setup_fee', 'recur_fee' ], -    #'setup' => 'what.setup_fee.value', -    #'recur' => '\'my $mnow = $sdate; my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($sdate) )[0,1,2,3,4,5]; $sdate = timelocal(0,0,0,1,$mon,$year); \' + what.recur_fee.value', -    'freq' => 'm', -    'weight' => 30, +  'name' => 'First partial month full charge, then flat-rate (1st of month billing)', +  'fields' => { +    'setup_fee' => { 'name' => 'Setup fee for this package', +                     'default' => 0, +                   }, +    'recur_fee' => { 'name' => 'Recurring fee for this package', +                     'default' => 0, +                   }, +  }, +  'fieldorder' => [ 'setup_fee', 'recur_fee' ], +  #'setup' => 'what.setup_fee.value', +  #'recur' => '\'my $mnow = $sdate; my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($sdate) )[0,1,2,3,4,5]; $sdate = timelocal(0,0,0,1,$mon,$year); \' + what.recur_fee.value', +  'freq' => 'm', +  'weight' => 30,  );  sub calc_recur { diff --git a/FS/FS/part_pkg/voip_sqlradacct.pm b/FS/FS/part_pkg/voip_sqlradacct.pm index b9db39f16..a6a3a3857 100644 --- a/FS/FS/part_pkg/voip_sqlradacct.pm +++ b/FS/FS/part_pkg/voip_sqlradacct.pm @@ -7,31 +7,35 @@ use FS::part_pkg;  #use FS::rate;  use FS::rate_prefix; -@ISA = qw(FS::part_pkg); +@ISA = qw(FS::part_pkg::flat);  $DEBUG = 1;  %info = ( -    'name' => 'VoIP rating by plan of CDR records in an SQL RADIUS radacct table', -    'fields' => { -      'setup_fee' => { 'name' => 'Setup fee for this package', -                       'default' => 0, -                     }, -      'recur_flat' => { 'name' => 'Base monthly charge for this package', -                        'default' => 0, -                      }, -      'ratenum'   => { 'name' => 'Rate plan', -                       'type' => 'select', -                       'select_table' => 'rate', -                       'select_key'   => 'ratenum', -                       'select_label' => 'ratename', -                     }, -      'ignore_unrateable' => { 'name' => 'Ignore calls for which not rate prefix can be found (otherwise they are fatal)', -                               'type' => 'checkbox', -                             }, -    }, -    'fieldorder' => [qw( setup_fee recur_flat ratenum ignore_unrateable )], -    'weight' => 40, +  'name' => 'VoIP rating by plan of CDR records in an SQL RADIUS radacct table', +  'fields' => { +    'setup_fee'     => { 'name' => 'Setup fee for this package', +                         'default' => 0, +                       }, +    'recur_flat'     => { 'name' => 'Base monthly charge 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', +                     'select_key'   => 'ratenum', +                     'select_label' => 'ratename', +                   }, +    'ignore_unrateable' => { 'name' => 'Ignore calls for which not rate prefix can be found (otherwise they are fatal)', +                             'type' => 'checkbox', +                           }, +  }, +  'fieldorder' => [qw( setup_fee recur_flat unused_credit ratenum ignore_unrateable )], +  'weight' => 40,  );  sub calc_setup {  | 
