RT#25563 [documentation]
[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 setup_cost recur_cost setup_margin recur_margin_permonth )],
28       'labels'  => {
29         'setuprecur'        => 'Amount charged on this invoice',
30         'setup'             => 'Setup fee charged on this invoice',
31         'recur'             => 'Recurring fee charged on this invoice',
32         'setup_cost'        => 'Setup cost',
33         'recur_cost'        => 'Recurring cost',
34         'setup_margin'      => 'Package setup fee minus setup cost',
35         'recur_margin_permonth' => 'Monthly recurring fee minus recurring cost',
36       },
37     },
38   );
39   if ($class->can('_calc_credit_percent')) {
40     splice @fields, 2, 2; #remove the percentage option
41   }
42   @fields;
43     
44 }
45
46 our %part_pkg_cache;
47
48 # arguments:
49 # 1. the line item
50 # 2. the recipient of the commission; may be FS::sales, FS::agent, 
51 # FS::access_user, etc. Here we don't use it, but it will be passed through
52 # to _calc_credit_percent.
53 # 3. optional scalar reference for recording a warning message
54
55 sub _calc_credit {
56   my $self = shift;
57   my $cust_bill_pkg = shift;
58   my $who = shift;
59   my $warnref = shift;
60   my $warning = '';
61
62   my $what = $self->option('what');
63   my $cost = ($what =~ /_cost/ ? 1 : 0);
64   my $margin = ($what =~ /_margin/ ? 1 : 0);
65
66   my $pkgnum = $cust_bill_pkg->pkgnum;
67   my $cust_pkg = $cust_bill_pkg->cust_pkg;
68
69   my $percent;
70   if ( $self->can('_calc_credit_percent') ) {
71     $percent = $self->_calc_credit_percent($cust_pkg, $who);
72     $warning = 'Percent calculated to zero ' unless $percent+0;
73   } else {
74     $percent = $self->option('percent') || 0;
75     $warning = 'Percent set to zero ' unless $percent+0;
76   }
77
78   my $charge = 0;
79   if ( $margin or $cost ) {
80     # look up package costs only if we need them
81     my $pkgpart = $cust_bill_pkg->pkgpart_override || $cust_pkg->pkgpart;
82     my $part_pkg   = $part_pkg_cache{$pkgpart}
83                  ||= FS::part_pkg->by_key($pkgpart);
84
85     if ( $cost ) {
86       $charge = $part_pkg->get($what);
87     } else { # $margin
88       $charge = $part_pkg->$what($cust_pkg);
89     }
90
91     $charge = ($charge || 0) * ($cust_pkg->quantity || 1);
92     $warning .= 'Charge calculated to zero ' unless $charge+0;
93
94   } else { # setup, recur, or setuprecur
95
96     if ( $what eq 'setup' ) {
97       $charge = $cust_bill_pkg->get('setup');
98       $warning .= 'Setup is zero ' unless $charge+0;
99     } elsif ( $what eq 'recur' ) {
100       $charge = $cust_bill_pkg->get('recur');
101       $warning .= 'Recur is zero ' unless $charge+0;
102     } elsif ( $what eq 'setuprecur' ) {
103       $charge = $cust_bill_pkg->get('setup') + $cust_bill_pkg->get('recur');
104       $warning .= 'Setup and recur are zero ' unless $charge+0;
105     }
106
107     # don't multiply by quantity here; it's already included
108   }
109
110   $$warnref .= $warning if ref($warnref);
111
112   $charge = 0 if $charge < 0; # e.g. prorate
113   return ($percent * $charge / 100);
114 }
115
116 1;