sales commission events on invoices, #25847
[freeside.git] / FS / FS / part_event / Action / Mixin / credit_bill.pm
1 package FS::part_event::Action::Mixin::credit_bill;
2
3 use strict;
4
5 # credit_bill: calculates a credit amount that is some percentage of each 
6 # line item of an invoice
7
8 sub eventtable_hashref {
9   { 'cust_bill' => 1 };
10 }
11
12 sub option_fields {
13   my $class = shift;
14   my @fields = (
15     'reasonnum' => { 'label'        => 'Credit reason',
16                      'type'         => 'select-reason',
17                      'reason_class' => 'R',
18                    },
19     'percent'   => { 'label'   => 'Percent',
20                      'type'    => 'input-percentage',
21                      'default' => '100',
22                    },
23     'what' => {
24       'label'   => 'Of',
25       'type'    => 'select',
26       #add additional ways to specify in the package def
27       'options' => [qw( setuprecur setup recur setuprecur_margin setup_margin recur_margin )],
28       'labels'  => {
29         'setuprecur'        => 'Amount charged',
30         'setup'             => 'Setup fee',
31         'recur'             => 'Recurring fee',
32         'setuprecur_margin' => 'Amount charged minus total cost',
33         'setup_margin'      => 'Setup fee minus setup cost',
34         'recur_margin'      => 'Recurring fee minus recurring cost',
35       },
36     },
37   );
38   if ($class->can('_calc_credit_percent')) {
39     splice @fields, 2, 2; #remove the percentage option
40   }
41   @fields;
42     
43 }
44
45 our %part_pkg_cache;
46
47 # arguments:
48 # 1. the line item
49 # 2. the recipient of the commission; may be FS::sales, FS::agent, 
50 # FS::access_user, etc. Here we don't use it, but it will be passed through
51 # to _calc_credit_percent.
52
53 sub _calc_credit {
54   my $self = shift;
55   my $cust_bill_pkg = shift;
56
57   my $what = $self->option('what');
58   my $margin = 1 if $what =~ s/_margin$//;
59
60   my $pkgnum = $cust_bill_pkg->pkgnum;
61   my $cust_pkg = $cust_bill_pkg->cust_pkg;
62
63   my $percent;
64   if ( $self->can('_calc_credit_percent') ) {
65     $percent = $self->_calc_credit_percent($cust_pkg, @_);
66   } else {
67     $percent = $self->option('percent') || 0;
68   }
69
70   my $charge = 0;
71   if ( $what eq 'setup' ) {
72     $charge = $cust_bill_pkg->get('setup');
73   } elsif ( $what eq 'recur' ) {
74     $charge = $cust_bill_pkg->get('recur');
75   } elsif ( $what eq 'setuprecur' ) {
76     $charge = $cust_bill_pkg->get('setup') + $cust_bill_pkg->get('recur');
77   }
78   if ( $margin ) {
79     my $pkgpart = $cust_bill_pkg->pkgpart_override || $cust_pkg->pkgpart;
80     my $part_pkg   = $part_pkg_cache{$pkgpart}
81                  ||= FS::part_pkg->by_key($pkgpart);
82     if ( $what eq 'setup' ) {
83       $charge -= $part_pkg->get('setup_cost');
84     } elsif ( $what eq 'recur' ) {
85       $charge -= $part_pkg->get('recur_cost');
86     } elsif ( $what eq 'setuprecur' ) {
87       $charge -= $part_pkg->get('setup_cost') + $part_pkg->get('recur_cost');
88     }
89   }
90
91   $charge = 0 if $charge < 0; # e.g. prorate
92   return ($percent * $charge / 100);
93 }
94
95 1;