RT# 33362 - fixed discount_mixin to not throw perl error when trying to discount...
[freeside.git] / FS / FS / part_event / Action / pkg_discount.pm
index 592e044..d245ef4 100644 (file)
@@ -3,10 +3,12 @@ package FS::part_event::Action::pkg_discount;
 use strict;
 use base qw( FS::part_event::Action );
 
-sub description { "Discount unsuspended customer packages (monthly recurring only)"; }
+sub description { "Discount unsuspended package(s) (monthly recurring only)"; }
 
 sub eventtable_hashref {
-  { 'cust_main' => 1 };
+  { 'cust_main' => 1,
+    'cust_pkg'  => 1,
+  };
 }
 
 sub event_stage { 'pre-bill'; }
@@ -21,16 +23,27 @@ sub option_fields {
                        'extra_sql' => q(AND freq NOT LIKE '0%' AND freq NOT LIKE '%d' AND freq NOT LIKE '%h' AND freq NOT LIKE '%w'), 
                        'multiple' => 1,
                      },
+    'if_pkg_class' => { 'label'    => 'Only package class',
+                        'type'     => 'select-pkg_class',
+                        'multiple' => 1,
+                      },
     'discountnum' => { 'label'    => 'Discount',
                        'type'     => 'select-table', #we don't handle the select-discount create a discount case
                        'table'    => 'discount',
-                       'name_col' => 'description', #well, method
-                       'order_by' => 'ORDER BY discountnum', #requied because name_col is a method
+                       #(well, since 2013 it winds up calling select-discount
+                       # anyway (but not tr-select-discount)
+                       #'name_col' => 'description', #well, method
+                       #'order_by' => 'ORDER BY discountnum', #requied because name_col is a method
+                       'disable_empty' => 1,
                        'hashref'  => { 'disabled' => '',
                                        'months'   => { op=>'!=', value=>'0' },
                                      },
-                       'disable_empty' => 1,
+                       'disable_custom_discount' => 1,
                      },
+    'once_percust' => { 'label' => 'Only discount one package per customer',
+                        'type'  => 'checkbox',
+                        'value' => 'Y',
+                      },
   );
 }
 
@@ -41,13 +54,38 @@ sub do_action {
 
   my $cust_main = $self->cust_main($object);
   my %if_pkgpart = map { $_=>1 } split(/\s*,\s*/, $self->option('if_pkgpart') );
+  my %if_pkg_class = map { $_=>1 } split(/\s*,\s*/, $self->option('if_pkg_class') );
+
   my $allpkgs = (keys %if_pkgpart) ? 0 : 1;
-  my @cust_pkg = grep { ( $allpkgs || $if_pkgpart{ $_->pkgpart } ) 
-                          && $_->part_pkg->freq
-                          #can remove after fixing discount bug with non-monthly pkgs
-                          && ( $_->part_pkg->freq =~ /^\d+$/) } 
-                      $cust_main->unsuspended_pkgs;
-  return 'No qualifying packages' unless @cust_pkg;
+
+  my @cust_pkg = ();
+  if ( $object->table eq 'cust_pkg' ) {
+
+    return 'Package is suspended' if $object->susp;
+    return 'Package not selected'
+      if ! $allpkgs && ! $if_pkgpart{ $object->pkgpart };
+    return 'Package not of selected class'
+      if keys %if_pkg_class
+      && ! $if_pkg_class{ $object->part_pkg->classnum };
+    return 'Package frequency not monthly or a multiple'
+      if $object->part_pkg->freq !~ /^\d+$/;
+
+    @cust_pkg = ( $object );
+
+  } else {
+
+    @cust_pkg = grep {
+         ( $allpkgs || $if_pkgpart{ $_->pkgpart } ) 
+      && ( ! keys %if_pkg_class || $if_pkg_class{ $_->part_pkg->classnum } )
+      && $_->part_pkg->freq
+      #remove after fixing discount bug with non-monthly pkgs
+      && ( $_->part_pkg->freq =~ /^\d+$/)
+    }
+      $cust_main->unsuspended_pkgs;
+
+    return 'No qualifying packages' unless @cust_pkg;
+
+  }
 
   my $gotit = 0;
   foreach my $cust_pkg (@cust_pkg) {
@@ -66,12 +104,20 @@ sub do_action {
       $gotit = 1;
 
       #it's already got this discount and discount never expires--great, move on
-      next unless $cust_pkg_discount[0]->discount->months;
+      unless ( $cust_pkg_discount[0]->discount->months ) {
+        if ( $self->option('once_percust') ) {
+          last;
+        } else {
+          next;
+        }
+      };
        
       #reset the discount
       my $error = $cust_pkg_discount[0]->decrement_months_used( $cust_pkg_discount[0]->months_used );
       die "Error extending discount: $error\n" if $error;
 
+      last if $self->option('once_percust');
+
     } elsif ( @cust_pkg_discount ) {
 
       #can't currently discount an already discounted package,
@@ -89,6 +135,8 @@ sub do_action {
       my $error = $cust_pkg_discount->insert;
       die "Error discounting package: $error\n" if $error;
 
+      last if $self->option('once_percust');
+
     }
   }