3193a81ef4bafee14044d3779279647ff29d276a
[freeside.git] / FS / FS / part_event / Action / bill_sales_credit.pm
1 package FS::part_event::Action::bill_sales_credit;
2
3 # in this order:
4 # - pkg_sales_credit invokes NEXT, then appends the 'cust_main_sales' param
5 # - credit_bill contains the core _calc_credit logic, and also defines other
6 # params
7
8 use base qw( FS::part_event::Action::Mixin::pkg_sales_credit
9              FS::part_event::Action::Mixin::credit_bill
10              FS::part_event::Action );
11 use FS::Record qw(qsearch qsearchs);
12 use FS::Conf;
13 use Date::Format qw(time2str);
14
15 use strict;
16
17 sub description { 'Credit the sales person based on the billed amount'; }
18
19 sub eventtable_hashref {
20   { 'cust_bill' => 1 };
21 }
22
23 our $date_format;
24
25 sub do_action {
26   my( $self, $cust_bill, $cust_event ) = @_;
27
28   $date_format ||= FS::Conf->new->config('date_format') || '%x';
29
30   my $cust_main = $self->cust_main($cust_bill);
31
32   my %salesnum_sales; # salesnum => FS::sales object
33   my %salesnum_amount; # salesnum => credit amount
34   my %pkgnum_pkg; # pkgnum => FS::cust_pkg
35   my %salesnum_pkgnums; # salesnum => [ pkgnum, ... ]
36
37   my @items = qsearch('cust_bill_pkg', { invnum => $cust_bill->invnum,
38                                          pkgnum => { op => '>', value => '0' }
39                                        });
40
41   foreach my $cust_bill_pkg (@items) {
42     my $pkgnum = $cust_bill_pkg->pkgnum;
43     my $cust_pkg = $pkgnum_pkg{$pkgnum} ||= $cust_bill_pkg->cust_pkg;
44
45     my $salesnum = $cust_pkg->salesnum;
46     $salesnum ||= $cust_main->salesnum
47       if $self->option('cust_main_sales');
48     my $sales = $salesnum_sales{$salesnum}
49             ||= FS::sales->by_key($salesnum);
50
51     next if !$sales; #no sales person, no credit
52
53     my $amount = $self->_calc_credit($cust_bill_pkg, $sales);
54
55     if ($amount > 0) {
56       $salesnum_amount{$salesnum} ||= 0;
57       $salesnum_amount{$salesnum} += $amount;
58       push @{ $salesnum_pkgnums{$salesnum} ||= [] }, $pkgnum;
59     }
60   }
61
62   foreach my $salesnum (keys %salesnum_amount) {
63     my $amount = sprintf('%.2f', $salesnum_amount{$salesnum});
64     next if $amount < 0.005;
65
66     my $sales = $salesnum_sales{$salesnum};
67
68     my $sales_cust_main = $sales->sales_cust_main;
69     die "No customer record for sales person ". $sales->salesperson
70       unless $sales->sales_custnum;
71
72     my $reasonnum = $self->option('reasonnum');
73
74     my $desc = 'from invoice #'. $cust_bill->display_invnum .
75                ' ('. time2str($date_format, $cust_bill->_date) . ')';
76                # could also show custnum and pkgnums here?
77     my $error = $sales_cust_main->credit(
78       $amount, 
79       \$reasonnum,
80       'eventnum'            => $cust_event->eventnum,
81       'addlinfo'            => $desc,
82       'commission_salesnum' => $sales->salesnum,
83     );
84     die "Error crediting customer ". $sales_cust_main->custnum.
85         " for sales commission: $error"
86       if $error;
87   } # foreach $salesnum
88
89 }
90
91 1;