summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wells <mark@freeside.biz>2015-09-18 10:18:43 -0700
committerMark Wells <mark@freeside.biz>2015-09-18 10:19:08 -0700
commit77a4ccff7384368888fe88379f01f9ddc34244d8 (patch)
treedf949604ac1bbd5bb17b647fa37b7c0fb42dee1d
parent8cbf995cfbc851821242f4ab5e03713b3de8ef69 (diff)
send commission reports by email, #33101
-rw-r--r--FS/FS/AccessRight.pm1
-rw-r--r--FS/FS/Mason.pm4
-rw-r--r--FS/FS/Schema.pm31
-rw-r--r--FS/FS/cust_bill_pkg.pm10
-rw-r--r--FS/FS/cust_msg.pm1
-rw-r--r--FS/FS/msg_template/email.pm12
-rw-r--r--FS/FS/msg_template/http.pm4
-rw-r--r--FS/FS/report_batch.pm321
-rw-r--r--FS/MANIFEST8
-rw-r--r--FS/t/report_batch.t5
-rw-r--r--httemplate/elements/popup_link-send_report_batch.html28
-rw-r--r--httemplate/misc/process/send-report.html7
-rw-r--r--httemplate/misc/send-report.html166
-rw-r--r--httemplate/search/cust_msg.html3
-rw-r--r--httemplate/search/report_sales_commission_pkg.html10
-rw-r--r--httemplate/search/sales_commission_pkg.html7
16 files changed, 615 insertions, 3 deletions
diff --git a/FS/FS/AccessRight.pm b/FS/FS/AccessRight.pm
index 0493edd..c26cc2c 100644
--- a/FS/FS/AccessRight.pm
+++ b/FS/FS/AccessRight.pm
@@ -289,6 +289,7 @@ tie my %rights, 'Tie::IxHash',
'Billing event reports',
'Receivables report',
'Financial reports',
+ { rightname=>'Send reports to customers', global=>1 },
{ rightname=> 'List inventory', global=>1 },
{ rightname=>'View email logs', global=>1 },
{ rightname=>'View system logs' },
diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm
index ae4f07c..98a75c8 100644
--- a/FS/FS/Mason.pm
+++ b/FS/FS/Mason.pm
@@ -405,6 +405,10 @@ if ( -e $addl_handler_use_file ) {
use FS::cust_pkg_reason_fee;
use FS::part_svc_link;
use FS::access_user_log;
+ use FS::report_batch;
+ use FS::report_batch;
+ use FS::report_batch;
+ use FS::report_batch;
# Sammath Naur
if ( $FS::Mason::addl_handler_use ) {
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index 12211d1..85fbbeb 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -7124,6 +7124,37 @@ sub tables_hashref {
],
},
+ 'report_batch' => {
+ 'columns' => [
+ 'reportbatchnum', 'serial', '', '', '', '',
+ 'reportname', 'varchar', '', 255, '', '',
+ 'agentnum', 'int', 'NULL', '', '', '',
+ 'send_date', @date_type, '', '',
+ 'sdate', @date_type, '', '',
+ 'edate', @date_type, '', '',
+ 'usernum', 'int', 'NULL', '', '', '',
+ 'msgnum', 'int', 'NULL', '', '', '',
+ # add report params here as necessary
+ ],
+ 'primary_key' => 'reportbatchnum',
+ 'unique' => [],
+ 'index' => [],
+ 'foreign_keys' => [
+ { columns => [ 'agentnum' ],
+ table => 'agent',
+ references => [ 'agentnum' ],
+ },
+ { columns => [ 'usernum' ],
+ table => 'access_user',
+ references => [ 'usernum' ],
+ },
+ { columns => [ 'msgnum' ],
+ table => 'msg_template',
+ references => [ 'msgnum' ],
+ },
+ ],
+ },
+
# name type nullability length default local
#'new_table' => {
diff --git a/FS/FS/cust_bill_pkg.pm b/FS/FS/cust_bill_pkg.pm
index 8233ce0..1780426 100644
--- a/FS/FS/cust_bill_pkg.pm
+++ b/FS/FS/cust_bill_pkg.pm
@@ -1124,7 +1124,10 @@ sub tax_locationnum {
if ( $self->pkgnum ) { # normal sales
return $self->cust_pkg->tax_locationnum;
} elsif ( $self->feepart ) { # fees
- return $self->cust_bill->cust_main->ship_locationnum;
+ my $custnum = $self->fee_origin->custnum;
+ if ( $custnum ) {
+ return FS::cust_main->by_key($custnum)->ship_locationnum;
+ }
} else { # taxes
return '';
}
@@ -1135,7 +1138,10 @@ sub tax_location {
if ( $self->pkgnum ) { # normal sales
return $self->cust_pkg->tax_location;
} elsif ( $self->feepart ) { # fees
- return $self->cust_bill->cust_main->ship_location;
+ my $custnum = $self->fee_origin->custnum;
+ if ( $custnum ) {
+ return FS::cust_main->by_key($custnum)->ship_location;
+ }
} else { # taxes
return;
}
diff --git a/FS/FS/cust_msg.pm b/FS/FS/cust_msg.pm
index db02680..27272b8 100644
--- a/FS/FS/cust_msg.pm
+++ b/FS/FS/cust_msg.pm
@@ -148,6 +148,7 @@ sub check {
'invoice',
'receipt',
'admin',
+ 'report',
])
;
return $error if $error;
diff --git a/FS/FS/msg_template/email.pm b/FS/FS/msg_template/email.pm
index e69183f..5f27370 100644
--- a/FS/FS/msg_template/email.pm
+++ b/FS/FS/msg_template/email.pm
@@ -200,6 +200,12 @@ A hash reference of additional substitutions
A string identifying the kind of message this is. Currently can be "invoice",
"receipt", "admin", or null. Expand this list as necessary.
+=item override_content
+
+A string to use as the HTML body; if specified, replaces the entire
+body of the message. This should be used ONLY by L<FS::report_batch> and may
+go away in the future.
+
=back
=cut
@@ -265,6 +271,12 @@ sub prepare {
warn "$me filling in body template\n" if $DEBUG;
$body = $body_tmpl->fill_in( HASH => $hashref );
+ # override $body if requested
+ if ( $opt{'override_content'} ) {
+ warn "$me overriding template body with requested content" if $DEBUG;
+ $body = $opt{'override_content'};
+ }
+
###
# and email
###
diff --git a/FS/FS/msg_template/http.pm b/FS/FS/msg_template/http.pm
index 51dfcff..a2b0986 100644
--- a/FS/FS/msg_template/http.pm
+++ b/FS/FS/msg_template/http.pm
@@ -59,6 +59,10 @@ sub prepare {
%$document,
%$hashref
};
+ # put override content _somewhere_ so it can be used
+ if ( $opt{'override_content'} ) {
+ $document{'content'} = $opt{'override_content'};
+ }
my $request_content = $json->encode($document);
warn "$me ".$self->prepare_url."\n" if $DEBUG;
diff --git a/FS/FS/report_batch.pm b/FS/FS/report_batch.pm
new file mode 100644
index 0000000..64412df
--- /dev/null
+++ b/FS/FS/report_batch.pm
@@ -0,0 +1,321 @@
+package FS::report_batch;
+use base qw( FS::Record );
+
+use strict;
+use FS::Record qw( qsearch qsearchs dbdef );
+use FS::msg_template;
+use FS::cust_main;
+use FS::Misc::DateTime qw(parse_datetime);
+use FS::Mason qw(mason_interps);
+use URI::Escape;
+use HTML::Defang;
+
+our $DEBUG = 0;
+
+=head1 NAME
+
+FS::report_batch - Object methods for report_batch records
+
+=head1 SYNOPSIS
+
+ use FS::report_batch;
+
+ $record = new FS::report_batch \%hash;
+ $record = new FS::report_batch { 'column' => 'value' };
+
+ $error = $record->insert;
+
+ $error = $new_record->replace($old_record);
+
+ $error = $record->delete;
+
+ $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::report_batch object represents an order to send a batch of reports to
+their respective customers or other contacts. FS::report_batch inherits from
+FS::Record. The following fields are currently supported:
+
+=over 4
+
+=item reportbatchnum
+
+primary key
+
+=item reportname
+
+The name of the report, which will be the same as the file name (minus any
+directory names). There's an enumerated set of these; you can't use just any
+report.
+
+=item send_date
+
+The date the report was sent.
+
+=item agentnum
+
+The agentnum to limit the report to, if any.
+
+=item sdate
+
+The start date of the report period.
+
+=item edate
+
+The end date of the report period.
+
+=item usernum
+
+The user who ordered the report.
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new report batch. To add the record to the database, see L<"insert">.
+
+=cut
+
+sub table { 'report_batch'; }
+
+=item insert
+
+Adds this record to the database. If there is an error, returns the error,
+otherwise returns false.
+
+=item delete
+
+Deletes this record from the database.
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database. If there is an error,
+returns the error, otherwise returns false.
+
+=item check
+
+Checks all fields to make sure this is a valid record. If there is
+an error, returns the error, otherwise returns false. Called by the insert
+and replace methods.
+
+=cut
+
+sub check {
+ my $self = shift;
+
+ my $error =
+ $self->ut_numbern('reportbatchnum')
+ || $self->ut_text('reportname')
+ || $self->ut_numbern('agentnum')
+ || $self->ut_numbern('sdate')
+ || $self->ut_numbern('edate')
+ || $self->ut_numbern('usernum')
+ ;
+ return $error if $error;
+
+ $self->set('send_date', time);
+
+ $self->SUPER::check;
+}
+
+=back
+
+=head1 SUBROUTINES
+
+=over 4
+
+=item process_send_report JOB, PARAMS
+
+Takes a hash of PARAMS, determines all contacts who need to receive a report,
+and sends it to them. On completion, creates and stores a report_batch record.
+JOB is a queue job to receive status messages.
+
+PARAMS can include:
+
+- reportname: the name of the report (listed in the C<%sendable_reports> hash).
+Required.
+- msgnum: the L<FS::msg_template> to use for this report. Currently the
+content of the template is ignored, but the subject line and From/Bcc addresses
+are still used. Required.
+- agentnum: the agent to limit the report to.
+- beginning, ending: the date range to run the report, as human-readable
+dates (I<not> unix timestamps).
+
+=cut
+
+# trying to keep this data-driven, with parameters that tell how the report is
+# to be handled rather than callbacks.
+# - path: where under the document root the report is located
+# - domain: which table to query for objects on which the report is run.
+# Each record in that table produces one report.
+# - cust_main: the method on that object that returns its linked customer (to
+# which the report will be sent). If the table has a 'custnum' field, this
+# can be omitted.
+our %sendable_reports = (
+ 'sales_commission_pkg' => {
+ 'name' => 'Sales commission per package',
+ 'path' => '/search/sales_commission_pkg.html',
+ 'domain' => 'sales',
+ 'cust_main' => 'sales_cust_main',
+ },
+);
+
+sub process_send_report {
+ my $job = shift;
+ my $param = shift;
+
+ my $msgnum = $param->{'msgnum'};
+ my $template = FS::msg_template->by_key($msgnum)
+ or die "msg_template $msgnum not found\n";
+
+ my $reportname = $param->{'reportname'};
+ my $info = $sendable_reports{$reportname}
+ or die "don't know how to send report '$reportname'\n";
+
+ # the most important thing: which report is it?
+ my $path = $info->{'path'};
+
+ # find all targets for the report:
+ # - those matching the agentnum if there is one.
+ # - those that aren't disabled.
+ my $domain = $info->{domain};
+ my $dbt = dbdef->table($domain);
+ my $hashref = {};
+ if ( $param->{'agentnum'} and $dbt->column('agentnum') ) {
+ $hashref->{'agentnum'} = $param->{'agentnum'};
+ }
+ if ( $dbt->column('disabled') ) {
+ $hashref->{'disabled'} = '';
+ }
+ my @records = qsearch($domain, $hashref);
+ my $num_targets = scalar(@records);
+ return if $num_targets == 0;
+ my $sent = 0;
+
+ my $outbuf;
+ my ($fs_interp) = mason_interps('standalone', 'outbuf' => \$outbuf);
+ # if generating the report fails, we want to capture the error and exit,
+ # not send it.
+ $fs_interp->error_mode('fatal');
+ $fs_interp->error_format('brief');
+
+ # we have to at least have an RT::Handle
+ require RT;
+ RT::LoadConfig();
+ RT::Init();
+
+ # hold onto all the reports until we're sure they generated correctly.
+ my %cust_main;
+ my %report_content;
+
+ # grab the stylesheet
+ ### note: if we need the ability to support different stylesheets, this
+ ### is the place to put it in
+ eval { $fs_interp->exec('/elements/freeside.css') };
+ die "couldn't load stylesheet via Mason: $@\n" if $@;
+ my $stylesheet = $outbuf;
+
+ my $pkey = $dbt->primary_key;
+ foreach my $rec (@records) {
+
+ $job->update_statustext(int( 100 * $sent / $num_targets ));
+ my $pkey_val = $rec->get($pkey); # e.g. sales.salesnum
+
+ # find the customer we're sending to, and their email
+ my $cust_main;
+ if ( $info->{'cust_main'} ) {
+ my $cust_method = $info->{'cust_main'};
+ $cust_main = $rec->$cust_method;
+ } elsif ( $rec->custnum ) {
+ $cust_main = FS::cust_main->by_key($rec->custnum);
+ } else {
+ warn "$pkey = $pkey_val has no custnum; not sending report\n";
+ next;
+ }
+ my @email = $cust_main->invoicing_list_emailonly;
+ if (!@email) {
+ warn "$pkey = $pkey_val has no email destinations\n" if $DEBUG;
+ next;
+ }
+
+ # params to send to the report (as if from the user's browser)
+ my @report_param = ( # maybe list these in $info
+ agentnum => $param->{'agentnum'},
+ beginning => $param->{'beginning'},
+ ending => $param->{'ending'},
+ $pkey => $pkey_val,
+ _type => 'html-print',
+ );
+
+ # build a query string
+ my $query_string = '';
+ while (@report_param) {
+ $query_string .= uri_escape(shift @report_param)
+ . '='
+ . uri_escape(shift @report_param);
+ $query_string .= ';' if @report_param;
+ }
+ warn "$path?$query_string\n\n" if $DEBUG;
+
+ # run the report!
+ $FS::Mason::Request::QUERY_STRING = $query_string;
+ $FS::Mason::Request::FSURL = '';
+ $outbuf = '';
+ eval { $fs_interp->exec($path) };
+ die "creating report for $pkey = $pkey_val: $@" if $@;
+
+ # make some adjustments to the report
+ my $html_defang;
+ $html_defang = HTML::Defang->new(
+ url_callback => sub { 1 }, # strip all URLs (they're not accessible)
+ tags_to_callback => [ 'body' ], # and after the BODY tag...
+ tags_callback => sub {
+ my $isEndTag = $_[4];
+ $html_defang->add_to_output("\n<style>\n$stylesheet\n</style>\n")
+ unless $isEndTag;
+ },
+ );
+ $outbuf = $html_defang->defang($outbuf);
+
+ $cust_main{ $cust_main->custnum } = $cust_main;
+ $report_content{ $cust_main->custnum } = $outbuf;
+ } # foreach $rec
+
+ $job->update_statustext('Sending reports...');
+ foreach my $custnum (keys %cust_main) {
+ # create an email message with the report as body
+ # change this when backporting to 3.x
+ $template->send(
+ cust_main => $cust_main{$custnum},
+ object => $cust_main{$custnum},
+ msgtype => 'report',
+ override_content => $report_content{$custnum},
+ );
+ }
+
+ my $self = FS::report_batch->new({
+ reportname => $param->{'reportname'},
+ agentnum => $param->{'agentnum'},
+ sdate => parse_datetime($param->{'beginning'}),
+ edate => parse_datetime($param->{'ending'}),
+ usernum => $job->usernum,
+ msgnum => $param->{'msgnum'},
+ });
+ my $error = $self->insert;
+ warn "error recording completion of report: $error\n" if $error;
+
+}
+
+=head1 SEE ALSO
+
+L<FS::Record>
+
+=cut
+
+1;
+
diff --git a/FS/MANIFEST b/FS/MANIFEST
index 5b73b72..5041ccd 100644
--- a/FS/MANIFEST
+++ b/FS/MANIFEST
@@ -850,3 +850,11 @@ FS/part_svc_link.pm
t/part_svc_link.t
FS/access_user_log.pm
t/access_user_log.t
+FS/report_batch.pm
+t/report_batch.t
+FS/report_batch.pm
+t/report_batch.t
+FS/report_batch.pm
+t/report_batch.t
+FS/report_batch.pm
+t/report_batch.t
diff --git a/FS/t/report_batch.t b/FS/t/report_batch.t
new file mode 100644
index 0000000..42fc893
--- /dev/null
+++ b/FS/t/report_batch.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::report_batch;
+$loaded=1;
+print "ok 1\n";
diff --git a/httemplate/elements/popup_link-send_report_batch.html b/httemplate/elements/popup_link-send_report_batch.html
new file mode 100644
index 0000000..5f44710
--- /dev/null
+++ b/httemplate/elements/popup_link-send_report_batch.html
@@ -0,0 +1,28 @@
+<%doc>
+
+Example:
+
+<& /elements/popup_link-send_report_batch.html,
+ reportname => 'sales_commission_pkg',
+ label => 'Click here to send reports by email',
+&>
+</%doc>
+<& /elements/popup_link.html, $params &>\
+<%init>
+
+my $params = { 'closetext' => emt('Close') };
+
+if (ref($_[0]) eq 'HASH') {
+ $params = { %$params, %{ $_[0] } };
+} else {
+ $params = { %$params, @_ };
+}
+
+$params->{'label'} ||= emt('Send reports by email');
+$params->{'actionlabel'} ||= emt('Send reports');
+#$params->{'width'} ||= 350;
+$params->{'height'} ||= 650;
+
+$params->{'action'} = $fsurl. 'misc/send-report.html?reportname='. $params->{'reportname'};
+
+</%init>
diff --git a/httemplate/misc/process/send-report.html b/httemplate/misc/process/send-report.html
new file mode 100644
index 0000000..3bceebc
--- /dev/null
+++ b/httemplate/misc/process/send-report.html
@@ -0,0 +1,7 @@
+<%init>
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Send reports to customers');
+
+my $server = FS::UI::Web::JSRPC->new('FS::report_batch::process_send_report', $cgi);
+</%init>
+<% $server->process %>
diff --git a/httemplate/misc/send-report.html b/httemplate/misc/send-report.html
new file mode 100644
index 0000000..557767a
--- /dev/null
+++ b/httemplate/misc/send-report.html
@@ -0,0 +1,166 @@
+<%doc>
+
+Parameters:
+
+- reportname: the report name (per FS::report_batch)
+
+</%doc>
+<& /elements/header-popup.html, { title => $report_info->{name} } &>
+<script type="text/javascript">
+
+$().ready(function() {
+ var agent_info = <% encode_json(\%agent) %>;
+
+ $('#agentnum').on('change', function() {
+ var agentnum = this.value;
+ if ( agent_info[agentnum] ) {
+ $('#msgnum').prop('value', agent_info[agentnum]['msgnum']);
+ $('#beginning_text').prop('value', agent_info[agentnum]['beginning']);
+ $('#ending_text').prop('value', agent_info[agentnum]['ending']);
+ } else {
+ $('#msgnum').prop('value', '');
+ $('#beginning_text').prop('value', '');
+ $('#ending_text').prop('value', '');
+ }
+ });
+
+ $('#agentnum').trigger('change');
+
+});
+
+</script>
+<FORM NAME="OneTrueForm" ACTION="process/send-report.html" METHOD="POST">
+
+<table class="inv">
+ <input type="hidden" name="reportname" value="<% $cgi->param('reportname') |h %>">
+
+ <& /elements/tr-select-agent.html &>
+
+ <& /elements/tr-td-label.html, label => emt('Message template') &>
+ <TD>
+ <& /elements/select-msg_template.html, field => 'msgnum' &>
+ </TD>
+ </TR>
+
+ <& /elements/tr-input-beginning_ending.html &>
+
+ <& /elements/progress-init.html,
+ 'OneTrueForm',
+ [ qw( reportname msgnum agentnum beginning ending ) ],
+ $p.'misc/process/send-report.html',
+ { message => 'Reports sent',
+ url => $cgi->referer }
+ &>
+
+</table>
+
+<INPUT TYPE="button" onclick="process()" VALUE="<% emt('Send reports') %>" />
+</FORM>
+
+<style>
+table.grid {
+ border-collapse: collapse;
+ margin-top: 1ex;
+ margin-left: auto;
+ margin-right: auto;
+}
+.grid caption {
+ font-weight: bold;
+ margin-bottom: 0.5ex;
+}
+.grid th,td {
+ padding-left: 3px;
+ padding-right: 3px;
+ padding-bottom: 2px;
+ border: none;
+ empty-cells: show;
+}
+.grid th {
+ border-bottom: 1px solid #999999;
+ font-size: 90%;
+ vertical-align: bottom;
+}
+</style>
+
+% if ( @report_history ) {
+<hr>
+<table class="grid">
+<caption><% emt('Report history') %></caption>
+<thead>
+ <th>Agent</th>
+ <th>Sent on</th>
+ <th colspan=2>Date range</th>
+ <th>User</th>
+</thead>
+<tbody>
+% my $row = 0;
+% foreach my $report (@report_history) {
+% my $agent = ($report->agentnum ?
+% $report->agent->agent : 'All agents');
+ <tr class="row<% $row % 2 %>">
+ <td><% $agent %></td>
+ <td><% time2str($date_format, $report->send_date) %></td>
+ <td><% time2str($date_format, $report->sdate) %></td>
+ <td><% time2str($date_format, $report->edate) %></td>
+ <td><% $report->access_user->username %></td>
+ </tr>
+% $row++;
+% }
+</tbody>
+</table>
+% }
+
+<& /elements/footer.html &>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Send reports to customers');
+
+$cgi->param('reportname') =~ /^(\w+)$/
+ or die "bad reportname";
+my $reportname = $1;
+my $report_info = $FS::report_batch::sendable_reports{$reportname}
+ or die "bad reportname";
+
+my $date_format = FS::Conf->new->config('date_format') || '%x';
+
+my @report_history = qsearch({
+ table => 'report_batch',
+ hashref => { reportname => $reportname },
+ order_by => ' ORDER BY send_date DESC',
+});
+
+# defaults per agent that could be selected for the report
+my %agent;
+
+foreach my $report ( @report_history ) {
+ my $agentnum = $report->agentnum;
+ next if $agent{$agentnum};
+
+ # estimate the width of the report period, in months
+ my $last_sdate = DateTime->from_epoch( epoch => $report->sdate );
+ my $last_edate = DateTime->from_epoch( epoch => $report->edate );
+
+ my $days = $last_sdate->delta_days( $last_edate )->delta_days;
+ my $months = sprintf('%.0f', $days / 6) / 5;
+
+ my $next_sdate = $last_edate->clone->add(days => 1);
+ my $next_edate = $next_sdate->clone;
+ if ( $months >= 1 ) { # then treat as an interval in months
+ $next_edate->add( months => sprintf('%.0f', $months) );
+ $next_edate->subtract(days => 1);
+ } else { # treat as a number of days
+ $next_edate->add( days => $days );
+ }
+
+ my $name = $agentnum ? FS::agent->by_key($agentnum)->agent : 'All agents';
+ $agent{$agentnum} = {
+ name => $name,
+ beginning => $next_sdate->strftime($date_format),
+ ending => $next_edate->strftime($date_format),
+ msgnum => $report->msgnum,
+ };
+}
+
+</%init>
diff --git a/httemplate/search/cust_msg.html b/httemplate/search/cust_msg.html
index 401f52e..e9aece2 100644
--- a/httemplate/search/cust_msg.html
+++ b/httemplate/search/cust_msg.html
@@ -144,11 +144,12 @@ include('/elements/select.html',
include('/elements/select.html',
'field' => 'msgtype',
'curr_value' => $cgi->param('msgtype') || '',
- 'options' => [ '', 'invoice', 'receipt', 'admin' ],
+ 'options' => [ '', 'invoice', 'receipt', 'admin', 'report' ],
'labels' => { '' => '(any)',
'invoice' => 'Invoices',
'receipt' => 'Receipts',
'admin' => 'Admin notices',
+ 'report' => 'Reports',
},
) .
'</TD>
diff --git a/httemplate/search/report_sales_commission_pkg.html b/httemplate/search/report_sales_commission_pkg.html
index 6adf090..27906e0 100644
--- a/httemplate/search/report_sales_commission_pkg.html
+++ b/httemplate/search/report_sales_commission_pkg.html
@@ -1,5 +1,15 @@
<& /elements/header.html, 'Sales commission report per package' &>
+% if ($FS::CurrentUser::CurrentUser->access_right('Send reports to customers'))
+% {
+<P>
+<& /elements/popup_link-send_report_batch.html,
+ reportname => 'sales_commission_pkg',
+ label => emt('Send these reports by email'),
+&>
+</P>
+% }
+
<FORM ACTION="sales_commission_pkg.html">
<TABLE BGCOLOR="#cccccc" CELLSPACING=0>
diff --git a/httemplate/search/sales_commission_pkg.html b/httemplate/search/sales_commission_pkg.html
index 2b5f2bb..9fbe22e 100644
--- a/httemplate/search/sales_commission_pkg.html
+++ b/httemplate/search/sales_commission_pkg.html
@@ -1,12 +1,17 @@
%# still not a good way to do rows grouped by some field in a search.html
%# report
+%# (there is now, but we're not yet sponsored to switch this over to it)
% if ( $type eq 'xls' ) {
<% $data %>\
% } else {
+% if ( $type eq 'html-print' ) {
+<& /elements/header-popup.html, $title &>
+% } else {
<& /elements/header.html, $title &>
<P ALIGN="right" CLASS="noprint">
Download full results<BR>
as <A HREF="<% $cgi->self_url %>;_type=xls">Excel spreadsheet</A></P>
+% }
<BR>
<STYLE TYPE="text/css">
td.cust_head {
@@ -22,12 +27,14 @@ td.money:before { content: '<% $money_char %>'; }
.row1 { background-color: #ffffff; }
</STYLE>
<& /elements/table-grid.html &>
+<THEAD>
<TR STYLE="background-color: #cccccc">
<TH CLASS="grid">Package</TH>
<TH CLASS="grid">Sales</TH>
<TH CLASS="grid">Percentage</TH>
<TH CLASS="grid">Commission</TH>
</TR>
+</THEAD>
% my ($custnum, $sales, $commission, $row, $bgcolor) = (0, 0, 0, 0);
% foreach my $cust_pkg ( @cust_pkg ) {
% if ( $custnum ne $cust_pkg->custnum ) {