credit on suspend, #16066
authormark <mark>
Thu, 26 Jan 2012 21:18:21 +0000 (21:18 +0000)
committermark <mark>
Thu, 26 Jan 2012 21:18:21 +0000 (21:18 +0000)
FS/FS/Conf.pm
FS/FS/cust_pkg.pm
FS/FS/part_pkg/global_Mixin.pm

index 8266d07..2899de3 100644 (file)
@@ -632,6 +632,21 @@ my %payment_gateway_options = (
   },
 );
 
+# takes the reason class (C, R, S) as an argument
+sub reason_type_options {
+  my $reason_class = shift;
+
+  'type'        => 'select-sub',
+  'options_sub' => sub {
+    map { $_->typenum => $_->type } 
+      qsearch('reason_type', { class => $reason_class });
+  },
+  'option_sub'  => sub {
+    my $type = FS::reason_type->by_key(shift);
+    $type ? $type->type : '';
+  }
+}
+
 #Billing (81 items)
 #Invoicing (50 items)
 #UI (69 items)
@@ -3586,77 +3601,35 @@ and customer address. Include units.',
     'key'         => 'cancel_credit_type',
     'section'     => 'billing',
     'description' => 'The group to use for new, automatically generated credit reasons resulting from cancellation.',
-    'type'        => 'select-sub',
-    'options_sub' => sub { require FS::Record;
-                           require FS::reason_type;
-                          map { $_->typenum => $_->type }
-                               FS::Record::qsearch('reason_type', { class=>'R' } );
-                        },
-    'option_sub'  => sub { require FS::Record;
-                           require FS::reason_type;
-                          my $reason_type = FS::Record::qsearchs(
-                            'reason_type', { 'typenum' => shift }
-                          );
-                           $reason_type ? $reason_type->type : '';
-                        },
+    reason_type_options('R'),
+  },
+
+  {
+    'key'         => 'suspend_credit_type',
+    'section'     => 'billing',
+    'description' => 'The group to use for new, automatically generated credit reasons resulting from package suspension.',
+    reason_type_options('R'),
   },
 
   {
     'key'         => 'referral_credit_type',
     'section'     => 'deprecated',
     'description' => 'Used to be the group to use for new, automatically generated credit reasons resulting from referrals.  Now set in a package billing event for the referral.',
-    'type'        => 'select-sub',
-    'options_sub' => sub { require FS::Record;
-                           require FS::reason_type;
-                          map { $_->typenum => $_->type }
-                               FS::Record::qsearch('reason_type', { class=>'R' } );
-                        },
-    'option_sub'  => sub { require FS::Record;
-                           require FS::reason_type;
-                          my $reason_type = FS::Record::qsearchs(
-                            'reason_type', { 'typenum' => shift }
-                          );
-                           $reason_type ? $reason_type->type : '';
-                        },
+    reason_type_options('R'),
   },
 
   {
     'key'         => 'signup_credit_type',
     'section'     => 'billing', #self-service?
     'description' => 'The group to use for new, automatically generated credit reasons resulting from signup and self-service declines.',
-    'type'        => 'select-sub',
-    'options_sub' => sub { require FS::Record;
-                           require FS::reason_type;
-                          map { $_->typenum => $_->type }
-                               FS::Record::qsearch('reason_type', { class=>'R' } );
-                        },
-    'option_sub'  => sub { require FS::Record;
-                           require FS::reason_type;
-                          my $reason_type = FS::Record::qsearchs(
-                            'reason_type', { 'typenum' => shift }
-                          );
-                           $reason_type ? $reason_type->type : '';
-                        },
+    reason_type_options('R'),
   },
 
   {
     'key'         => 'prepayment_discounts-credit_type',
     'section'     => 'billing',
     'description' => 'Enables the offering of prepayment discounts and establishes the credit reason type.',
-    'type'        => 'select-sub',
-    'options_sub' => sub { require FS::Record;
-                           require FS::reason_type;
-                           map { $_->typenum => $_->type }
-                               FS::Record::qsearch('reason_type', { class=>'R' } );
-                         },
-    'option_sub'  => sub { require FS::Record;
-                           require FS::reason_type;
-                           my $reason_type = FS::Record::qsearchs(
-                             'reason_type', { 'typenum' => shift }
-                           );
-                           $reason_type ? $reason_type->type : '';
-                         },
-
+    reason_type_options('R'),
   },
 
   {
index 5458634..c41f04b 100644 (file)
@@ -810,7 +810,7 @@ sub cancel {
       $do_credit = $self->part_pkg->option('unused_credit_cancel', 1);
     }
     if ( $do_credit ) {
-      my $error = $self->credit_remaining($cancel_time);
+      my $error = $self->credit_remaining('cancel', $cancel_time);
       if ($error) {
         $dbh->rollback if $oldAutoCommit;
         return $error;
@@ -1029,7 +1029,7 @@ sub suspend {
   unless ( $date ) {
     # credit remaining time if appropriate
     if ( $self->part_pkg->option('unused_credit_suspend', 1) ) {
-      my $error = $self->credit_remaining($suspend_time);
+      my $error = $self->credit_remaining('suspend', $suspend_time);
       if ($error) {
         $dbh->rollback if $oldAutoCommit;
         return $error;
@@ -1094,11 +1094,25 @@ sub suspend {
   ''; #no errors
 }
 
+=item credit_remaining MODE TIME
+
+Generate a credit for this package for the time remaining in the current 
+billing period.  MODE is either "suspend" or "cancel" (determines the 
+credit type).  TIME is the time of suspension/cancellation.  Both options
+are mandatory.
+
+=cut
+
 sub credit_remaining {
   # Add a credit for remaining service
-  my $self = shift;
-  my $time = shift or die 'no suspend/cancel time';
+  my ($self, $mode, $time) = @_;
+  die 'credit_remaining requires suspend or cancel' 
+    unless $mode eq 'suspend' or $mode eq 'cancel';
+  die 'no suspend/cancel time' unless $time > 0;
+
   my $conf = FS::Conf->new;
+  my $reason_type = $conf->config($mode.'_credit_type');
+
   my $last_bill = $self->getfield('last_bill') || 0;
   my $next_bill = $self->getfield('bill') || 0;
   if ( $last_bill > 0         # the package has been billed
@@ -1112,8 +1126,8 @@ sub credit_remaining {
       my $error = $self->cust_main->credit(
         $remaining_value,
         'Credit for unused time on '. $self->part_pkg->pkg,
-        'reason_type' => $conf->config('cancel_credit_type'),
-      ); # need 'suspend_credit_type'?
+        'reason_type' => $reason_type,
+      );
       return "Error crediting customer \$$remaining_value for unused time".
         " on ". $self->part_pkg->pkg. ": $error"
         if $error;
index ec2eb4e..137db1c 100644 (file)
@@ -19,6 +19,11 @@ use vars qw(%info);
                  'cancellation',
       'type' => 'checkbox',
     },
+    'unused_credit_suspend' => {
+      'name' => 'Credit the customer for the unused portion of service when '.
+                'suspending',
+      'type' => 'checkbox',
+    },
     'unused_credit_change' => {
       'name' => 'Credit the customer for the unused portion of service when '.
                 'changing packages',
@@ -29,6 +34,7 @@ use vars qw(%info);
     setup_fee
     recur_fee
     unused_credit_cancel
+    unused_credit_suspend
     unused_credit_change
   )],
 );