summaryrefslogtreecommitdiff
path: root/FS/FS/part_event/Action/pkg_discount.pm
blob: bae3c342a6df2d9c4249056bac5368bf29e1dcb5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package FS::part_event::Action::pkg_discount;

use strict;
use base qw( FS::part_event::Action );

sub description { "Discount unsuspended package(s) (monthly recurring only)"; }

sub eventtable_hashref {
  { 'cust_main' => 1,
    'cust_pkg'  => 1,
  };
}

sub event_stage { 'pre-bill'; }

sub option_fields {
  (
    'if_pkgpart'  => { 'label'    => 'Only packages',
                       'type'     => 'select-table',
                       'table'    => 'part_pkg',
                       'name_col' => 'pkg',
                       #can tweak after fixing discount bug with non-monthly recurring pkgs 
                       '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,
                     },
    '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
                       'hashref'  => { 'disabled' => '',
                                       'months'   => { op=>'!=', value=>'0' },
                                     },
                       'disable_empty' => 1,
                     },
  );
}

#lots of false laziness with referral_pkg_discount
#but also lots of doing it differently...and better???
sub do_action {
  my( $self, $object, $cust_event ) = @_;

  my $cust_main = $self->cust_main($object);
  my %if_pkgpart = map { $_=>1 } split(/\s*,\s*/, $self->option('if_pkgpart') );
  my $allpkgs = (keys %if_pkgpart) ? 0 : 1;

  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 frequency not monthly or a multiple'
      if $object->part_pkg->freq !~ /^\d+$/;

    @cust_pkg = ( $object );

  } else {

    @cust_pkg = grep { ( $allpkgs || $if_pkgpart{ $_->pkgpart } ) 
                         && $_->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) {

    my @cust_pkg_discount = $cust_pkg->cust_pkg_discount_active;

    #our logic here only makes sense insomuch as you can't have multiple discounts
    die "Unexpected multiple discounts, contact developers"
      if scalar(@cust_pkg_discount) > 1;

    my @my_cust_pkg_discount =
      grep { $_->discountnum == $self->option('discountnum') } @cust_pkg_discount;

    if ( @my_cust_pkg_discount ) { #reset the existing one instead

      $gotit = 1;

      #it's already got this discount and discount never expires--great, move on
      next unless $cust_pkg_discount[0]->discount->months;
	
      #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;

    } elsif ( @cust_pkg_discount ) {

      #can't currently discount an already discounted package,
      #but maybe we can discount a different package
      next;

    } else { #normal case, create a new one

      $gotit = 1;
      my $cust_pkg_discount = new FS::cust_pkg_discount {
        'pkgnum'      => $cust_pkg->pkgnum,
        'discountnum' => $self->option('discountnum'),
        'months_used' => 0
      };
      my $error = $cust_pkg_discount->insert;
      die "Error discounting package: $error\n" if $error;

    }
  }

  return $gotit ? '' : 'Discount not applied due to existing discounts';

}

1;