summaryrefslogtreecommitdiff
path: root/httemplate
diff options
context:
space:
mode:
authorIvan Kohler <ivan@freeside.biz>2016-08-03 17:52:34 -0700
committerIvan Kohler <ivan@freeside.biz>2016-08-03 17:52:34 -0700
commitcf54023e010df76e0c39ac70902877d7c4c94c6e (patch)
tree8109fa975ae8ecb4435172f9a990435a734c67b6 /httemplate
parentd7759b49c2ff3b220ab328767645bfed85d18f31 (diff)
parentecf1c9cc0a20be6e489657e005ea771977b9f69c (diff)
Merge branch 'master' of git.freeside.biz:/home/git/freeside
Diffstat (limited to 'httemplate')
-rw-r--r--httemplate/browse/commission_schedule.html70
-rw-r--r--httemplate/browse/log_email.html2
-rw-r--r--httemplate/edit/commission_schedule.html53
-rwxr-xr-xhttemplate/edit/cust_main.cgi11
-rw-r--r--httemplate/edit/cust_pay_pending.html19
-rw-r--r--httemplate/edit/elements/edit.html2
-rw-r--r--httemplate/edit/log_email.html4
-rw-r--r--httemplate/edit/part_event.html4
-rw-r--r--httemplate/edit/process/bulk-cust_main_county.html2
-rw-r--r--httemplate/edit/process/bulk-cust_svc-pkgnum.html2
-rw-r--r--httemplate/edit/process/cgp_rule-simplified.html2
-rw-r--r--httemplate/edit/process/change-cust_pkg.html2
-rw-r--r--httemplate/edit/process/commission_schedule.html36
-rw-r--r--httemplate/edit/process/credit-cust_bill_pkg.html2
-rwxr-xr-xhttemplate/edit/process/cust_credit-pkgnum.html2
-rwxr-xr-xhttemplate/edit/process/cust_credit.cgi2
-rw-r--r--httemplate/edit/process/cust_location-censustract.html2
-rw-r--r--httemplate/edit/process/cust_location.cgi2
-rwxr-xr-xhttemplate/edit/process/cust_main.cgi10
-rw-r--r--httemplate/edit/process/cust_main_attach.cgi2
-rwxr-xr-xhttemplate/edit/process/cust_main_county-add.cgi2
-rwxr-xr-xhttemplate/edit/process/cust_main_county-expand.cgi2
-rwxr-xr-xhttemplate/edit/process/cust_main_note.cgi2
-rw-r--r--httemplate/edit/process/cust_pay-no_auto_apply.cgi2
-rwxr-xr-xhttemplate/edit/process/cust_pay-pkgnum.html2
-rwxr-xr-xhttemplate/edit/process/cust_pay.cgi2
-rw-r--r--httemplate/edit/process/cust_pay_pending.html11
-rw-r--r--httemplate/edit/process/cust_pkg_detail.html2
-rw-r--r--httemplate/edit/process/cust_pkg_discount.html2
-rw-r--r--httemplate/edit/process/cust_pkg_quantity.html2
-rw-r--r--httemplate/edit/process/cust_pkg_salesnum.html2
-rwxr-xr-xhttemplate/edit/process/cust_refund.cgi2
-rw-r--r--httemplate/edit/process/cust_tax_adjustment.html2
-rw-r--r--httemplate/edit/process/detach-cust_pkg.html2
-rwxr-xr-xhttemplate/edit/process/domain_record.cgi2
-rw-r--r--httemplate/edit/process/elements/ApplicationCommon.html2
-rw-r--r--httemplate/edit/process/elements/process.html2
-rw-r--r--httemplate/edit/process/quick-charge.cgi9
-rw-r--r--httemplate/edit/process/quotation_pkg_detail.html2
-rw-r--r--httemplate/elements/commission_rate.html68
-rw-r--r--httemplate/elements/header-full.html2
-rw-r--r--httemplate/elements/header-popup.html1
-rw-r--r--httemplate/elements/menu.html5
-rw-r--r--httemplate/elements/selectlayersx.html248
-rw-r--r--httemplate/elements/topreload.js5
-rwxr-xr-xhttemplate/elements/tr-select-reason.html3
-rw-r--r--httemplate/elements/tr-selectlayersx.html25
-rwxr-xr-xhttemplate/misc/change_pkg_date.html (renamed from httemplate/misc/change_pkg_start.html)33
-rwxr-xr-xhttemplate/misc/cust_main-cancel.cgi2
-rwxr-xr-xhttemplate/misc/cust_main-suspend.cgi2
-rwxr-xr-xhttemplate/misc/cust_main-unsuspend.cgi2
-rw-r--r--httemplate/misc/delete-addr_range.html2
-rwxr-xr-xhttemplate/misc/delete-rate_detail.html2
-rw-r--r--httemplate/misc/did_order_confirmed.html2
-rwxr-xr-xhttemplate/misc/disable-cust_location.cgi2
-rw-r--r--httemplate/misc/disable-msg_template.cgi2
-rwxr-xr-xhttemplate/misc/process/bulk_pkg_increment_bill.cgi2
-rwxr-xr-xhttemplate/misc/process/cancel_pkg.html2
-rw-r--r--httemplate/misc/process/change_pkg_contact.html2
-rwxr-xr-xhttemplate/misc/process/change_pkg_date.html (renamed from httemplate/misc/process/change_pkg_start.html)32
-rw-r--r--httemplate/misc/process/cust_bill-promised_date.html2
-rwxr-xr-xhttemplate/misc/process/delay_susp_pkg.html2
-rwxr-xr-xhttemplate/misc/process/enable_or_disable_tax.html2
-rw-r--r--httemplate/misc/process/nms-add_iface.html2
-rw-r--r--httemplate/misc/process/nms-add_router.html2
-rwxr-xr-xhttemplate/misc/process/recharge_svc.html2
-rwxr-xr-xhttemplate/misc/process/unhold_pkg.html2
-rwxr-xr-xhttemplate/misc/process/void-cust_bill.html2
-rw-r--r--httemplate/misc/reason-merge.html2
-rwxr-xr-xhttemplate/misc/void-cust_credit.html2
-rw-r--r--httemplate/search/cust_bill_pay_pkg.html30
-rwxr-xr-xhttemplate/search/cust_pay.html1
-rwxr-xr-xhttemplate/search/cust_pay_pending.html2
-rwxr-xr-xhttemplate/search/elements/cust_pay_or_refund.html77
-rw-r--r--httemplate/search/elements/report_cust_pay_or_refund.html6
-rw-r--r--httemplate/search/elements/search.html13
-rw-r--r--httemplate/search/log.html31
-rw-r--r--httemplate/search/report_cust_bill_pay_pkg.html7
-rw-r--r--httemplate/search/report_sqlradius_usage-custnum.html71
-rw-r--r--httemplate/search/report_sqlradius_usage.html1
-rw-r--r--httemplate/search/sqlradius_usage.html93
-rw-r--r--httemplate/view/cust_main/menu.html9
-rw-r--r--httemplate/view/cust_main/packages/status.html59
-rw-r--r--httemplate/view/cust_main/payment_history/pending_payment.html1
84 files changed, 972 insertions, 178 deletions
diff --git a/httemplate/browse/commission_schedule.html b/httemplate/browse/commission_schedule.html
new file mode 100644
index 000000000..5a4f9840e
--- /dev/null
+++ b/httemplate/browse/commission_schedule.html
@@ -0,0 +1,70 @@
+<& elements/browse.html,
+ 'title' => "Commission schedules",
+ 'name' => "commission schedules",
+ 'menubar' => [ 'Add a new schedule' =>
+ $p.'edit/commission_schedule.html'
+ ],
+ 'query' => { 'table' => 'commission_schedule', },
+ 'count_query' => 'SELECT COUNT(*) FROM commission_schedule',
+ 'header' => [ '#',
+ 'Name',
+ 'Rates',
+ ],
+ 'fields' => [ 'schedulenum',
+ 'schedulename',
+ $rates_sub,
+ ],
+ 'links' => [ $link,
+ $link,
+ '',
+ ],
+ 'disable_total' => 1,
+&>
+<%init>
+
+my $money_char = FS::Conf->new->config('money_char') || '$';
+
+my $ordinal_sub = sub {
+ # correct from 1 to 12...
+ my $num = shift;
+ $num == 1 ? '1st' :
+ $num == 2 ? '2nd' :
+ $num == 3 ? '3rd' :
+ $num . 'th'
+};
+
+my $rates_sub = sub {
+ my $schedule = shift;
+ my @rates = sort { $a->cycle <=> $b->cycle } $schedule->commission_rate;
+ my @data;
+ my $basis = emt(lc( $FS::commission_schedule::basis_options{$schedule->basis} ));
+ foreach my $rate (@rates) {
+ my $desc = '';
+ if ( $rate->amount > 0 ) {
+ $desc = $money_char . sprintf('%.2f', $rate->amount);
+ }
+ if ( $rate->percent > 0 ) {
+ $desc .= ' + ' if $desc;
+ $desc .= $rate->percent . '% ' . emt('of') . ' ' . $basis;
+ }
+ next if !$desc;
+ $desc = &$ordinal_sub($rate->cycle) . ' ' . emt('invoice') .
+ ':&nbsp;' . $desc;
+
+ push @data,
+ [
+ {
+ 'data' => $desc,
+ 'align' => 'right',
+ }
+ ];
+ }
+ \@data;
+};
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $link = [ $p.'edit/commission_schedule.html?', 'schedulenum' ];
+
+</%init>
diff --git a/httemplate/browse/log_email.html b/httemplate/browse/log_email.html
index 0f64dd454..007ea6f74 100644
--- a/httemplate/browse/log_email.html
+++ b/httemplate/browse/log_email.html
@@ -21,7 +21,7 @@
],
'fields' => [ 'logemailnum',
sub { $_[0]->context || '(all)' },
- sub { $FS::Log::LEVELS[$_[0]->min_level] },
+ sub { $FS::Log::LEVELS{$_[0]->min_level} },
'msgname',
'to_addr',
$actions,
diff --git a/httemplate/edit/commission_schedule.html b/httemplate/edit/commission_schedule.html
new file mode 100644
index 000000000..c76a3618e
--- /dev/null
+++ b/httemplate/edit/commission_schedule.html
@@ -0,0 +1,53 @@
+<& elements/edit.html,
+ name_singular => 'schedule',
+ table => 'commission_schedule',
+ viewall_dir => 'browse',
+ fields => [ 'schedulename',
+ { field => 'reasonnum',
+ type => 'select-reason',
+ reason_class => 'R',
+ },
+ { field => 'basis',
+ type => 'select',
+ options => [ keys %FS::commission_schedule::basis_options ],
+ labels => { %FS::commission_schedule::basis_options },
+ },
+ { type => 'tablebreak-tr-title', value => 'Billing cycles' },
+ { field => 'commissionratenum',
+ type => 'commission_rate',
+ o2m_table => 'commission_rate',
+ m2_label => ' ',
+ m2_error_callback => $m2_error_callback,
+ colspan => 2,
+ },
+ ],
+ labels => { 'schedulenum' => '',
+ 'schedulename' => 'Name',
+ 'basis' => 'Based on',
+ 'commissionratenum' => '',
+ },
+&>
+<%init>
+
+my $m2_error_callback = sub {
+ my ($cgi, $object) = @_;
+
+ my @rates;
+ foreach my $k ( grep /^commissionratenum\d+/, $cgi->param ) {
+ my $num = $cgi->param($k);
+ my $cycle = $cgi->param($k.'_cycle');
+ my $amount = $cgi->param($k.'_amount');
+ my $percent = $cgi->param($k.'_percent');
+ if ($cycle > 0) {
+ push @rates, FS::commission_rate->new({
+ 'commissionratenum' => $num,
+ 'cycle' => $cycle,
+ 'amount' => $amount,
+ 'percent' => $percent,
+ });
+ }
+ }
+ @rates;
+};
+
+</%init>
diff --git a/httemplate/edit/cust_main.cgi b/httemplate/edit/cust_main.cgi
index 39cddc021..b314d2d6e 100755
--- a/httemplate/edit/cust_main.cgi
+++ b/httemplate/edit/cust_main.cgi
@@ -203,12 +203,19 @@ if ( $cgi->param('error') ) {
my %locations;
for my $pre (qw(bill ship)) {
my %hash;
- foreach ( FS::cust_main->location_fields ) {
- $hash{$_} = scalar($cgi->param($pre.'_'.$_));
+ foreach my $locfield ( FS::cust_main->location_fields ) {
+ # don't search on lat/long, string values can cause qsearchs to die
+ next if grep {$_ eq $locfield} qw(latitude longitude);
+ $hash{$locfield} = scalar($cgi->param($pre.'_'.$locfield));
}
$hash{'custnum'} = $cgi->param('custnum');
$locations{$pre} = qsearchs('cust_location', \%hash)
|| FS::cust_location->new( \%hash );
+ # now set lat/long, for redisplay of entered values
+ foreach my $locfield ( qw(latitude longitude) ) {
+ my $locvalue = scalar($cgi->param($pre.'_'.$locfield));
+ $locations{$pre}->set($locfield,$locvalue);
+ }
}
if ( $same ) {
$locations{ship} = $locations{bill};
diff --git a/httemplate/edit/cust_pay_pending.html b/httemplate/edit/cust_pay_pending.html
index 0056bb925..7d480f319 100644
--- a/httemplate/edit/cust_pay_pending.html
+++ b/httemplate/edit/cust_pay_pending.html
@@ -4,6 +4,10 @@
<CENTER><FONT SIZE="+1"><B>Are you sure you want to delete this pending payment?</B></FONT></CENTER>
+% } elsif (( $action eq 'complete' ) and $authorized) {
+
+ <CENTER><FONT SIZE="+1"><B>Payment was authorized but not captured. Contact <% $cust_pay_pending->processor || 'the payment gateway' %> to establish the final disposition of this transaction.</B></FONT></CENTER>
+
% } elsif ( $action eq 'complete' ) {
<CENTER><FONT SIZE="+1"><B>No response was received from <% $cust_pay_pending->processor || 'the payment gateway' %> for this transaction. Check <% $cust_pay_pending->processor || 'the payment gateway' %>'s reporting and determine if this transaction completed successfully.</B></FONT></CENTER>
@@ -97,8 +101,6 @@
% } else {
-%# if ( $action eq 'complete' ) {
-
<INPUT TYPE="hidden" NAME="action" VALUE="">
<TR>
@@ -106,18 +108,25 @@
<BUTTON TYPE="button" onClick="document.pendingform.action.value = 'insert_cust_pay'; document.pendingform.submit();"><!--IMG SRC="<%$p%>images/tick.png" ALT=""-->Yes, transaction completed sucessfully.</BUTTON>
</TD>
-% if ( $action eq 'complete' ) {
+% if ( $action eq 'complete' ) {
<TD>&nbsp;&nbsp;&nbsp;</TD>
+% if ($authorized) {
+ <TD ALIGN="center">
+ <BUTTON TYPE="button" onClick="document.pendingform.action.value = 'reverse'; document.pendingform.submit();"><!--IMG SRC="<%$p%>images/cross.png" ALT=""-->No, transaction was reversed</BUTTON>
+ </TD>
+% } else {
<TD ALIGN="center">
<BUTTON TYPE="button" onClick="document.pendingform.action.value = 'decline'; document.pendingform.submit();"><!--IMG SRC="<%$p%>images/cross.png" ALT=""-->No, transaction was declined</BUTTON>
</TD>
+% }
<TD>&nbsp;&nbsp;&nbsp;</TD>
<TD ALIGN="center">
<BUTTON TYPE="button" onClick="document.pendingform.action.value = 'delete'; document.pendingform.submit();"><!--IMG SRC="<%$p%>images/cross.png" ALT=""-->No, transaction was not received</BUTTON>
</TD>
- </TR>
% }
+ </TR>
+
<TR><TD COLSPAN=5></TD></TR>
<TR>
@@ -156,6 +165,8 @@ my $cust_pay_pending =
})
or die 'unknown paypendingnum';
+my $authorized = ($cust_pay_pending->status eq 'authorized') ? 1 : 0;
+
my $conf = new FS::Conf;
my $money_char = $conf->config('money_char') || '$';
diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html
index bbc9797dc..8dd15dcfb 100644
--- a/httemplate/edit/elements/edit.html
+++ b/httemplate/edit/elements/edit.html
@@ -650,7 +650,7 @@ Example:
var newrow = <% include(@layer_opt, html_only=>1) |js_string %>;
% #until the rest have html/js_only
-% if ( $type eq 'selectlayers' || $type =~ /^select-cgp_rule_/ ) {
+% if ( ($type eq 'selectlayers') || ($type eq 'selectlayersx') || ($type =~ /^select-cgp_rule_/) ) {
var newfunc = <% include(@layer_opt, js_only=>1) |js_string %>;
% } else {
var newfunc = '';
diff --git a/httemplate/edit/log_email.html b/httemplate/edit/log_email.html
index 0c98046d3..b79aba986 100644
--- a/httemplate/edit/log_email.html
+++ b/httemplate/edit/log_email.html
@@ -16,8 +16,8 @@
},
{ 'field' => 'min_level',
'type' => 'select',
- 'options' => [ 0..7 ],
- 'labels' => { map {$_ => $FS::Log::LEVELS[$_]} 0..7 },
+ 'options' => [ &FS::Log::levelnums ],
+ 'labels' => { &FS::Log::levelmap },
'curr_value' => scalar($cgi->param('min_level')),
},
'to_addr',
diff --git a/httemplate/edit/part_event.html b/httemplate/edit/part_event.html
index 47b8c1ac8..c8072e9f9 100644
--- a/httemplate/edit/part_event.html
+++ b/httemplate/edit/part_event.html
@@ -31,7 +31,7 @@
value => 'Event Conditions',
},
{ field => 'conditionname',
- type => 'selectlayers',
+ type => 'selectlayersx',
options => [ keys %all_conditions ],
labels => \%condition_labels,
onchange => 'condition_changed(what);',
@@ -51,7 +51,7 @@
value => 'Event Action',
},
{ field => 'action',
- type => 'selectlayers',
+ type => 'selectlayersx',
options => [ keys %all_actions ],
labels => \%action_labels,
onchange => 'action_changed(what);',
diff --git a/httemplate/edit/process/bulk-cust_main_county.html b/httemplate/edit/process/bulk-cust_main_county.html
index b7ff40fa7..b5a0258b1 100644
--- a/httemplate/edit/process/bulk-cust_main_county.html
+++ b/httemplate/edit/process/bulk-cust_main_county.html
@@ -12,7 +12,7 @@
<% include('/elements/header-popup.html', "Taxes ${action}ed") %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
diff --git a/httemplate/edit/process/bulk-cust_svc-pkgnum.html b/httemplate/edit/process/bulk-cust_svc-pkgnum.html
index f5cf7dd07..3c273069a 100644
--- a/httemplate/edit/process/bulk-cust_svc-pkgnum.html
+++ b/httemplate/edit/process/bulk-cust_svc-pkgnum.html
@@ -7,7 +7,7 @@
<% header(emt("Services moved")) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/edit/process/cgp_rule-simplified.html b/httemplate/edit/process/cgp_rule-simplified.html
index 60769d4e6..24515d551 100644
--- a/httemplate/edit/process/cgp_rule-simplified.html
+++ b/httemplate/edit/process/cgp_rule-simplified.html
@@ -4,7 +4,7 @@
% } else { #success XXX better msg talking about vacation vs. redirect all
<% include('/elements/header-popup.html', 'Rule updated') %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
diff --git a/httemplate/edit/process/change-cust_pkg.html b/httemplate/edit/process/change-cust_pkg.html
index 308ea8ffd..54cafbf18 100644
--- a/httemplate/edit/process/change-cust_pkg.html
+++ b/httemplate/edit/process/change-cust_pkg.html
@@ -5,7 +5,7 @@
<% header(emt("Package changed")) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/edit/process/commission_schedule.html b/httemplate/edit/process/commission_schedule.html
new file mode 100644
index 000000000..50e0371da
--- /dev/null
+++ b/httemplate/edit/process/commission_schedule.html
@@ -0,0 +1,36 @@
+<& elements/process.html,
+ 'table' => 'commission_schedule',
+ 'viewall_dir' => 'browse',
+ 'process_o2m' => {
+ 'table' => 'commission_rate',
+ 'fields' => [qw( cycle amount percent )],
+ },
+ 'precheck_callback' => $precheck,
+ 'debug' => 1,
+&>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $precheck = sub {
+ my $cgi = shift;
+ $cgi->param('reasonnum') =~ /^(-?\d+)$/ or die "Illegal reasonnum";
+
+ my ($reasonnum, $error) = $m->comp('/misc/process/elements/reason');
+ if (!$reasonnum) {
+ $error ||= 'Reason required'
+ }
+ $cgi->param('reasonnum', $reasonnum) unless $error;
+
+ # remove rate entries with no cycle selected
+ foreach my $k (grep /^commissionratenum\d+$/, $cgi->param) {
+ if (! $cgi->param($k.'_cycle') ) {
+ $cgi->delete($k);
+ }
+ }
+
+ $error;
+};
+
+</%init>
diff --git a/httemplate/edit/process/credit-cust_bill_pkg.html b/httemplate/edit/process/credit-cust_bill_pkg.html
index 75900bde5..12b68c0f5 100644
--- a/httemplate/edit/process/credit-cust_bill_pkg.html
+++ b/httemplate/edit/process/credit-cust_bill_pkg.html
@@ -3,7 +3,7 @@
%} else {
<& /elements/header-popup.html, 'Credit successful' &>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
% }
diff --git a/httemplate/edit/process/cust_credit-pkgnum.html b/httemplate/edit/process/cust_credit-pkgnum.html
index 8941cbc73..56f7989a4 100755
--- a/httemplate/edit/process/cust_credit-pkgnum.html
+++ b/httemplate/edit/process/cust_credit-pkgnum.html
@@ -4,7 +4,7 @@
%} else {
<% header(emt('Credit package changed')) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
diff --git a/httemplate/edit/process/cust_credit.cgi b/httemplate/edit/process/cust_credit.cgi
index 39c6f1997..5d3028777 100755
--- a/httemplate/edit/process/cust_credit.cgi
+++ b/httemplate/edit/process/cust_credit.cgi
@@ -16,7 +16,7 @@
%
<% header(emt('Credit successful')) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
diff --git a/httemplate/edit/process/cust_location-censustract.html b/httemplate/edit/process/cust_location-censustract.html
index bc9cd4f31..6edaca3fd 100644
--- a/httemplate/edit/process/cust_location-censustract.html
+++ b/httemplate/edit/process/cust_location-censustract.html
@@ -5,7 +5,7 @@
<% header("Census tract changed") %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/edit/process/cust_location.cgi b/httemplate/edit/process/cust_location.cgi
index fd1b8740e..3a2388111 100644
--- a/httemplate/edit/process/cust_location.cgi
+++ b/httemplate/edit/process/cust_location.cgi
@@ -5,7 +5,7 @@
<% header("Location changed") %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/edit/process/cust_main.cgi b/httemplate/edit/process/cust_main.cgi
index 04516e984..74f8f2382 100755
--- a/httemplate/edit/process/cust_main.cgi
+++ b/httemplate/edit/process/cust_main.cgi
@@ -1,5 +1,15 @@
% if ( $error ) {
% $cgi->param('error', $error);
+% # workaround for create_uri_query's mangling of unicode characters,
+% # false laziness with FS::Record::ut_coord
+% use charnames ':full';
+% for my $pre (qw(bill ship)) {
+% foreach (qw( latitude longitude)) {
+% my $coord = $cgi->param($pre.'_'.$_);
+% $coord =~ s/\N{DEGREE SIGN}\s*$//;
+% $cgi->param($pre.'_'.$_, $coord);
+% }
+% }
% my $query = $m->scomp('/elements/create_uri_query', 'secure'=>1);
<% $cgi->redirect(popurl(2). "cust_main.cgi?$query" ) %>
%
diff --git a/httemplate/edit/process/cust_main_attach.cgi b/httemplate/edit/process/cust_main_attach.cgi
index 09c18adcb..569500246 100644
--- a/httemplate/edit/process/cust_main_attach.cgi
+++ b/httemplate/edit/process/cust_main_attach.cgi
@@ -9,7 +9,7 @@
% $act = 'deleted' if($attachnum and $delete);
<% header('Attachment ' . $act ) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
% }
diff --git a/httemplate/edit/process/cust_main_county-add.cgi b/httemplate/edit/process/cust_main_county-add.cgi
index fc8956b0c..fcc138f49 100755
--- a/httemplate/edit/process/cust_main_county-add.cgi
+++ b/httemplate/edit/process/cust_main_county-add.cgi
@@ -1,7 +1,7 @@
<% include('/elements/header-popup.html', 'Addition successful' ) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
diff --git a/httemplate/edit/process/cust_main_county-expand.cgi b/httemplate/edit/process/cust_main_county-expand.cgi
index a10827621..42e46734a 100755
--- a/httemplate/edit/process/cust_main_county-expand.cgi
+++ b/httemplate/edit/process/cust_main_county-expand.cgi
@@ -1,7 +1,7 @@
<% include('/elements/header-popup.html', 'Addition successful' ) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
diff --git a/httemplate/edit/process/cust_main_note.cgi b/httemplate/edit/process/cust_main_note.cgi
index 53e616a43..bb52db8f3 100755
--- a/httemplate/edit/process/cust_main_note.cgi
+++ b/httemplate/edit/process/cust_main_note.cgi
@@ -4,7 +4,7 @@
%} else {
<% header('Note ' . ($notenum ? 'updated' : 'added') ) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
% }
diff --git a/httemplate/edit/process/cust_pay-no_auto_apply.cgi b/httemplate/edit/process/cust_pay-no_auto_apply.cgi
index ccbd2d7b5..4a5ee841a 100644
--- a/httemplate/edit/process/cust_pay-no_auto_apply.cgi
+++ b/httemplate/edit/process/cust_pay-no_auto_apply.cgi
@@ -15,7 +15,7 @@ Requires 'Apply payment' acl.
<P STYLE="font-weight: bold;"><% emt($message) %></P>
<P><% emt('Please wait while the page reloads.') %></P>
<SCRIPT TYPE="text/javascript">
-window.top.location.reload();
+topreload();
</SCRIPT>
% }
diff --git a/httemplate/edit/process/cust_pay-pkgnum.html b/httemplate/edit/process/cust_pay-pkgnum.html
index d9a92a1de..cefe970fe 100755
--- a/httemplate/edit/process/cust_pay-pkgnum.html
+++ b/httemplate/edit/process/cust_pay-pkgnum.html
@@ -4,7 +4,7 @@
%} else {
<% header(emt('Payment package changed')) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
diff --git a/httemplate/edit/process/cust_pay.cgi b/httemplate/edit/process/cust_pay.cgi
index 9e5f3d3f7..15b26f9c6 100755
--- a/httemplate/edit/process/cust_pay.cgi
+++ b/httemplate/edit/process/cust_pay.cgi
@@ -14,7 +14,7 @@
%
<% header(emt('Payment entered')) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
diff --git a/httemplate/edit/process/cust_pay_pending.html b/httemplate/edit/process/cust_pay_pending.html
index 1bad6cffe..80bd14aaf 100644
--- a/httemplate/edit/process/cust_pay_pending.html
+++ b/httemplate/edit/process/cust_pay_pending.html
@@ -3,7 +3,7 @@
<FONT SIZE="+1" COLOR="#ff0000">Error: <% $error |h %></FONT>
% } else {
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
% }
</BODY>
@@ -59,6 +59,15 @@ if ( $action eq 'delete' ) {
$title = 'Pending payment completed (decline)';
}
+} elsif ( $action eq 'reverse' ) {
+
+ $error = $cust_pay_pending->reverse;
+ if ( $error ) {
+ $title = 'Error reversing pending payment';
+ } else {
+ $title = 'Pending payment completed (reverse)';
+ }
+
} else {
die "unknown action $action";
diff --git a/httemplate/edit/process/cust_pkg_detail.html b/httemplate/edit/process/cust_pkg_detail.html
index 132ff63c5..25fabd930 100644
--- a/httemplate/edit/process/cust_pkg_detail.html
+++ b/httemplate/edit/process/cust_pkg_detail.html
@@ -6,7 +6,7 @@
% } else {
<% header($action) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
% }
diff --git a/httemplate/edit/process/cust_pkg_discount.html b/httemplate/edit/process/cust_pkg_discount.html
index 143611ef9..963546363 100644
--- a/httemplate/edit/process/cust_pkg_discount.html
+++ b/httemplate/edit/process/cust_pkg_discount.html
@@ -5,7 +5,7 @@
<% header("Discount applied") %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/edit/process/cust_pkg_quantity.html b/httemplate/edit/process/cust_pkg_quantity.html
index fb2657252..b60595583 100644
--- a/httemplate/edit/process/cust_pkg_quantity.html
+++ b/httemplate/edit/process/cust_pkg_quantity.html
@@ -5,7 +5,7 @@
<& /elements/header-popup.html, "Quantity changed" &>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/edit/process/cust_pkg_salesnum.html b/httemplate/edit/process/cust_pkg_salesnum.html
index aab37416a..c1cb26813 100644
--- a/httemplate/edit/process/cust_pkg_salesnum.html
+++ b/httemplate/edit/process/cust_pkg_salesnum.html
@@ -5,7 +5,7 @@
<& /elements/header-popup.html, "Sales Person changed" &>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/edit/process/cust_refund.cgi b/httemplate/edit/process/cust_refund.cgi
index 8977ced20..d4236bcdf 100755
--- a/httemplate/edit/process/cust_refund.cgi
+++ b/httemplate/edit/process/cust_refund.cgi
@@ -7,7 +7,7 @@
%
<% header('Refund entered') %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
diff --git a/httemplate/edit/process/cust_tax_adjustment.html b/httemplate/edit/process/cust_tax_adjustment.html
index 204b5b9f7..fe232757f 100644
--- a/httemplate/edit/process/cust_tax_adjustment.html
+++ b/httemplate/edit/process/cust_tax_adjustment.html
@@ -4,7 +4,7 @@
% } else {
<% header("Tax adjustment added") %>
<SCRIPT TYPE="text/javascript">
- //window.top.location.reload();
+ //topreload();
parent.cClick();
</SCRIPT>
</BODY></HTML>
diff --git a/httemplate/edit/process/detach-cust_pkg.html b/httemplate/edit/process/detach-cust_pkg.html
index 782ffa5e0..34c580560 100644
--- a/httemplate/edit/process/detach-cust_pkg.html
+++ b/httemplate/edit/process/detach-cust_pkg.html
@@ -5,7 +5,7 @@
<% header(emt("Package detached")) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/edit/process/domain_record.cgi b/httemplate/edit/process/domain_record.cgi
index 8369f7114..9d869d547 100755
--- a/httemplate/edit/process/domain_record.cgi
+++ b/httemplate/edit/process/domain_record.cgi
@@ -3,7 +3,7 @@
%} elsif ( $recnum ) { #editing
<% header('Nameservice record changed') %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
%} else { #adding
diff --git a/httemplate/edit/process/elements/ApplicationCommon.html b/httemplate/edit/process/elements/ApplicationCommon.html
index a73b1bccd..67fa89196 100644
--- a/httemplate/edit/process/elements/ApplicationCommon.html
+++ b/httemplate/edit/process/elements/ApplicationCommon.html
@@ -26,7 +26,7 @@ Examples:
%} else {
<% header("$src_thing application$to sucessful") %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html
index 60aaf749a..76722c960 100644
--- a/httemplate/edit/process/elements/process.html
+++ b/httemplate/edit/process/elements/process.html
@@ -188,7 +188,7 @@ process();
<% include('/elements/header-popup.html', $opt{'popup_reload'} ) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
diff --git a/httemplate/edit/process/quick-charge.cgi b/httemplate/edit/process/quick-charge.cgi
index d1b8e1086..00d17c8b1 100644
--- a/httemplate/edit/process/quick-charge.cgi
+++ b/httemplate/edit/process/quick-charge.cgi
@@ -1,4 +1,13 @@
+% if ( $error ) {
+% $cgi->param('error', $error );
<% $cgi->redirect($redirect) %>
+% } else {
+<% header(emt($message)) %>
+ <SCRIPT TYPE="text/javascript">
+ topreload();
+ </SCRIPT>
+ </BODY></HTML>
+% }
<%init>
my $curuser = $FS::CurrentUser::CurrentUser;
diff --git a/httemplate/edit/process/quotation_pkg_detail.html b/httemplate/edit/process/quotation_pkg_detail.html
index b836baebc..5728832b2 100644
--- a/httemplate/edit/process/quotation_pkg_detail.html
+++ b/httemplate/edit/process/quotation_pkg_detail.html
@@ -6,7 +6,7 @@
% } else {
<% header($action) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
% }
diff --git a/httemplate/elements/commission_rate.html b/httemplate/elements/commission_rate.html
new file mode 100644
index 000000000..071ebb1e3
--- /dev/null
+++ b/httemplate/elements/commission_rate.html
@@ -0,0 +1,68 @@
+% unless ( $opt{'js_only'} ) {
+
+ <INPUT TYPE="hidden" NAME="<%$name%>" ID="<%$id%>" VALUE="<% $curr_value %>">
+
+ <& select.html,
+ field => "${name}_cycle",
+ options => [ '', 1 .. 12 ],
+ option_labels => {
+ '' => '',
+ 1 => '1st',
+ 2 => '2nd',
+ 3 => '3rd',
+ map { $_ => $_.'th' } 4 .. 12
+ },
+ onchange => $onchange,
+ curr_value => $commission_rate->get("cycle"),
+ &>
+ <B><% $money_char %></B>
+ <& input-text.html,
+ field => "${name}_amount",
+ size => 8,
+ curr_value => $commission_rate->get("amount")
+ || '0.00',
+ 'text-align' => 'right'
+ &>
+ <B> + </B>
+ <& input-text.html,
+ field => "${name}_percent",
+ size => 8,
+ curr_value => $commission_rate->get("percent")
+ || '0',
+ 'text-align' => 'right'
+ &><B>%</B>
+% }
+<%init>
+
+my( %opt ) = @_;
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+my $name = $opt{'field'} || 'commissionratenum';
+my $id = $opt{'id'} || 'commissionratenum';
+
+my $curr_value = $opt{'curr_value'} || $opt{'value'};
+
+my $onchange = '';
+if ( $opt{'onchange'} ) {
+ $onchange = $opt{'onchange'};
+ $onchange .= '(this)' unless $onchange =~ /\(\w*\);?$/;
+ $onchange =~ s/\(what\);/\(this\);/g; #ugh, terrible hack. all onchange
+ #callbacks should act the same
+ $onchange = 'onChange="'. $onchange. '"';
+}
+
+my $commission_rate;
+if ( $curr_value ) {
+ $commission_rate = qsearchs('commission_rate', { 'commissionratenum' => $curr_value } );
+} else {
+ $commission_rate = new FS::commission_rate {};
+}
+
+foreach my $field (qw( amount percent cycle)) {
+ my $value = $cgi->param("${name}_${field}");
+ $commission_rate->set($field, $value) if $value;
+}
+
+</%init>
diff --git a/httemplate/elements/header-full.html b/httemplate/elements/header-full.html
index 07595a539..850eaed8c 100644
--- a/httemplate/elements/header-full.html
+++ b/httemplate/elements/header-full.html
@@ -53,7 +53,7 @@ Example:
% }
<% include('init_overlib.html') |n %>
<% include('rs_init_object.html') |n %>
-
+ <script type="text/javascript" src="<% $fsurl %>elements/topreload.js"></script>
<% $head |n %>
%# announce our base path, and the Mason comp path of this page
diff --git a/httemplate/elements/header-popup.html b/httemplate/elements/header-popup.html
index 6c0f80b37..839a63676 100644
--- a/httemplate/elements/header-popup.html
+++ b/httemplate/elements/header-popup.html
@@ -34,6 +34,7 @@ Example:
<SCRIPT SRC="<% $fsurl %>elements/printtofit.js"></SCRIPT>
% }
% }
+ <SCRIPT SRC="<% $fsurl %>elements/topreload.js"></SCRIPT>
<% $head |n %>
</HEAD>
<BODY <% $etc |n %>>
diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html
index 0f98bc960..88c1df3c8 100644
--- a/httemplate/elements/menu.html
+++ b/httemplate/elements/menu.html
@@ -672,7 +672,10 @@ $config_cust{'Note classes'} = [ $fsurl.'browse/cust_note_class.html', 'Note cla
tie my %config_agent, 'Tie::IxHash',
'Agent types' => [ $fsurl.'browse/agent_type.cgi', 'Agent types define groups of package definitions that you can then assign to particular agents' ],
'Agents' => [ $fsurl.'browse/agent.cgi', 'Agents are resellers of your service. Agents may be limited to a subset of your full offerings (via their type)' ],
- 'Agent payment gateways' => [ $fsurl.'browse/payment_gateway.html', 'Credit card and electronic check processors for agent overrides' ];
+ 'Agent payment gateways' => [ $fsurl.'browse/payment_gateway.html', 'Credit card and electronic check processors for agent overrides' ],
+ 'separator' => '',
+ 'Commission schedules' => [ $fsurl.'browse/commission_schedule.html',
+ 'Commission schedules for consecutive billing periods' ],
;
tie my %config_sales, 'Tie::IxHash',
diff --git a/httemplate/elements/selectlayersx.html b/httemplate/elements/selectlayersx.html
new file mode 100644
index 000000000..41f3cb0b7
--- /dev/null
+++ b/httemplate/elements/selectlayersx.html
@@ -0,0 +1,248 @@
+<%doc>
+
+Example:
+
+ include( '/elements/selectlayers.html',
+ 'field' => $key, # SELECT element NAME (passed as form field)
+ # also used as ID and a unique key for layers and
+ # functions
+ 'curr_value' => $selected_layer,
+ 'options' => [ 'option1', 'option2' ],
+ 'labels' => { 'option1' => 'Option 1 Label',
+ 'option2' => 'Option 2 Label',
+ },
+
+ #XXX put this handling it its own selectlayers-fields.html element?
+ 'layer_prefix' => 'prefix_', #optional prefix for fieldnames
+ 'layer_fields' => { 'layer' => [ 'fieldname',
+ { label => 'fieldname2',
+ type => 'text', #implemented:
+ # text, money, fixed,
+ # hidden, checkbox,
+ # checkbox-multiple,
+ # select, select-agent,
+ # select-pkg_class,
+ # select-part_referral,
+ # select-taxclass,
+ # select-table,
+ #XXX tbd:
+ # more?
+ },
+ ...
+ ],
+ 'layer2' => [ 'l2fieldname',
+ ...
+ ],
+ },
+
+ #current values for layer fields above
+ 'layer_values' => { 'layer' => { 'fieldname' => 'current_value',
+ 'fieldname2' => 'field2value',
+ ...
+ },
+ 'layer2' => { 'l2fieldname' => 'l2value',
+ ...
+ },
+ ...
+ },
+
+ #or manual control, instead of layer_fields and layer_values above
+ #called with args: my( $layer, $layer_fields, $layer_values, $layer_prefix )
+ 'layer_callback' =>
+
+ 'html_between => '', #optional HTML displayed between the SELECT and the
+ #layers, scalar or coderef ('field' passed as a param)
+ 'onchange' => '', #javascript code run when the SELECT changes
+ # ("what" is the element)
+ 'js_only' => 0, #set true to return only the JS portions
+ 'html_only' => 0, #set true to return only the HTML portions
+ 'select_only' => 0, #set true to return only the <SELECT> HTML
+ 'layers_only' => 0, #set true to return only the layers <DIV> HTML
+ )
+
+</%doc>
+% unless ( grep $opt{$_}, qw(html_only js_only select_only layers_only) ) {
+<SCRIPT TYPE="text/javascript">
+% }
+% unless ( grep $opt{$_}, qw(html_only select_only layers_only) ) {
+
+% unless ($selectlayersx_init) {
+
+var selectlayerx_info = {};
+
+function selectlayersx_changed (field) {
+
+ var what = document.getElementById(field);
+ selectlayerx_info[field]['onchange'](what);
+
+ var selectedlayer = what.options[what.selectedIndex].value;
+ for (i=0; i < selectlayerx_info[field]['layers'].length; i++) {
+ var iterlayer = selectlayerx_info[field]['layers'][i];
+ var iterobj = document.getElementById(field+'d'+iterlayer);
+ if (selectedlayer == iterlayer) {
+ iterobj.style.display = "";
+ iterobj.style.zIndex = 1;
+ } else {
+ iterobj.style.display = "none";
+ iterobj.style.zIndex = 0;
+ }
+ }
+
+}
+
+% $selectlayersx_init = 1;
+% } #selectlayersx_init
+
+selectlayerx_info['<% $key %>'] = {};
+selectlayerx_info['<% $key %>']['onchange'] = function (what) { <% $opt{'onchange'} %> };
+selectlayerx_info['<% $key %>']['layers'] = <% encode_json(\@layers) %>;
+
+
+% } #unless html_only/select_only/layers_only
+% unless ( grep $opt{$_}, qw(html_only js_only select_only layers_only) ) {
+</SCRIPT>
+% }
+%
+% unless ( grep $opt{$_}, qw(js_only layers_only) ) {
+
+ <SELECT NAME = "<% $key %>"
+ ID = "<% $key %>"
+ previousValue = "<% $selected %>"
+ previousText = "<% $options{$selected} %>"
+ onChange="selectlayersx_changed('<% $key %>')"
+ >
+
+% foreach my $option ( keys %$options ) {
+
+ <OPTION VALUE="<% $option %>"
+ <% $option eq $selected ? ' SELECTED' : '' %>
+ ><% $options->{$option} |h %></OPTION>
+
+% }
+
+ </SELECT>
+
+% }
+% unless ( grep $opt{$_}, qw(js_only select_only layers_only) ) {
+
+<% ref($between) ? &{$between}($key) : $between %>
+
+% }
+%
+% unless ( grep $opt{$_}, qw(js_only select_only) ) {
+
+% foreach my $layer ( @layers ) {
+% my $selected_layer;
+% $selected_layer = $selected;
+
+ <DIV ID="<% $key %>d<% $layer %>"
+ STYLE="<% $selected_layer eq $layer
+ ? 'display: block; z-index: 1'
+ : 'display: none; z-index: 0'
+ %>"
+ >
+
+ <% &{$layer_callback}($layer, $layer_fields, $layer_values, $layer_prefix) %>
+
+ </DIV>
+
+% }
+
+% }
+<%once>
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+my $date_noinit = 0;
+
+</%once>
+<%shared>
+
+my $selectlayersx_init = 0;
+
+</%shared>
+<%init>
+
+my %opt = @_;
+
+#use Data::Dumper;
+#warn Dumper(%opt);
+
+my $key = $opt{field}; # || 'generate_one' #?
+
+tie my %options, 'Tie::IxHash',
+ map { $_ => $opt{'labels'}->{$_} }
+ @{ $opt{'options'} }; #just arrayref for now
+
+my $between = exists($opt{html_between}) ? $opt{html_between} : '';
+my $options = \%options;
+
+my @layers = ();
+@layers = keys %options;
+
+my $selected = exists($opt{curr_value}) ? $opt{curr_value} : '';
+
+#XXX eek. also eek $layer_fields in the layer_callback() call...
+my $layer_fields = $opt{layer_fields};
+my $layer_values = $opt{layer_values};
+my $layer_prefix = $opt{layer_prefix};
+
+my $layer_callback = $opt{layer_callback} || \&layer_callback;
+
+sub layer_callback {
+ my( $layer, $layer_fields, $layer_values, $layer_prefix ) = @_;
+
+ return '' unless $layer && exists $layer_fields->{$layer};
+ tie my %fields, 'Tie::IxHash', @{ $layer_fields->{$layer} };
+
+ #XXX this should become an element itself... (false laziness w/edit.html)
+ # but at least all the elements inside are the shared mason elements now
+
+ return '' unless keys %fields;
+ my $html = "<TABLE>";
+
+ foreach my $field ( keys %fields ) {
+
+ my $lf = ref($fields{$field})
+ ? $fields{$field}
+ : { 'label'=>$fields{$field} };
+
+ my $value = $layer_values->{$layer}{$field};
+
+ my $type = $lf->{type} || 'text';
+
+ my $include = $type;
+
+ if ( $include eq 'date' ) {
+ # several important differences from other tr-*
+ $html .= include( '/elements/tr-input-date-field.html',
+ {
+ 'name' => "$layer_prefix$field",
+ 'value' => $value,
+ 'label' => $lf->{label},
+ 'format'=> $lf->{format},
+ 'noinit'=> $date_noinit,
+ }
+ );
+ $date_noinit = 1;
+ }
+ else {
+ $include = "input-$include" if $include =~ /^(text|money|percentage)$/;
+ $include = "tr-$include" unless $include eq 'hidden';
+ $html .= include( "/elements/$include.html",
+ %$lf,
+ 'field' => "$layer_prefix$field",
+ 'id' => "$layer_prefix$field", #separate?
+ #don't want field0_label0...?
+ 'label_id' => $layer_prefix.$field."_label",
+
+ 'value' => ( $lf->{'value'} || $value ), #hmm.
+ 'curr_value' => $value,
+ );
+ }
+ } #foreach $field
+ $html .= '</TABLE>';
+ return $html;
+}
+
+</%init>
diff --git a/httemplate/elements/topreload.js b/httemplate/elements/topreload.js
new file mode 100644
index 000000000..a66703b29
--- /dev/null
+++ b/httemplate/elements/topreload.js
@@ -0,0 +1,5 @@
+window.topreload = function() {
+ if (window != window.top) {
+ window.top.location.reload();
+ }
+}
diff --git a/httemplate/elements/tr-select-reason.html b/httemplate/elements/tr-select-reason.html
index 97466f175..9a430222c 100755
--- a/httemplate/elements/tr-select-reason.html
+++ b/httemplate/elements/tr-select-reason.html
@@ -188,9 +188,8 @@ my $class = $opt{'reason_class'};
my $init_reason;
if ( $opt{'cgi'} ) {
$init_reason = $opt{'cgi'}->param($name);
-} else {
- $init_reason = $opt{'curr_value'};
}
+$init_reason ||= $opt{'curr_value'};
my $id = $opt{'id'} || $name;
$id =~ s/\./_/g; # for edit/part_event
diff --git a/httemplate/elements/tr-selectlayersx.html b/httemplate/elements/tr-selectlayersx.html
new file mode 100644
index 000000000..ca7a36079
--- /dev/null
+++ b/httemplate/elements/tr-selectlayersx.html
@@ -0,0 +1,25 @@
+% unless ( $opt{js_only} ) {
+
+ <% include('tr-td-label.html', @_ ) %>
+
+ <TD <% $style %>>
+
+% }
+
+ <% include('selectlayersx.html', @_ ) %>
+
+% unless ( $opt{js_only} ) {
+
+ </TD>
+
+ </TR>
+
+% }
+
+<%init>
+
+my %opt = @_;
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+</%init>
diff --git a/httemplate/misc/change_pkg_start.html b/httemplate/misc/change_pkg_date.html
index 5a890c86e..642a5b89e 100755
--- a/httemplate/misc/change_pkg_start.html
+++ b/httemplate/misc/change_pkg_date.html
@@ -3,11 +3,12 @@
<& /elements/error.html &>
% # only slightly different from unhold_pkg.
-<FORM NAME="MyForm" ACTION="process/change_pkg_start.html" METHOD=POST>
+<FORM NAME="MyForm" ACTION="process/change_pkg_date.html" METHOD=POST>
<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
+<INPUT TYPE="hidden" NAME="field" VALUE="<% $field %>">
<BR>
-<% emt('Start billing [_1]', $part_pkg->pkg_comment(cust_pkg => $cust_pkg)) %>
+<% emt(($isstart ? 'Start billing' : 'Set contract end for').' [_1]', $part_pkg->pkg_comment(cust_pkg => $cust_pkg)) %>
<UL STYLE="padding-left: 3ex; list-style: none; background-color: #cccccc">
<LI>
<& /elements/radio.html,
@@ -16,7 +17,7 @@
value => 'now',
curr_value => $when,
&>
- <label for="when_now"><% emt('Immediately') %></label>
+ <label for="when_now"><% emt($isstart ? 'Now' : 'Never') %></label>
</LI>
% if ( $next_bill_date ) {
<LI>
@@ -41,13 +42,13 @@
&>
<label for="when_date"> <% emt('On this date:') %> </label>
<& /elements/input-date-field.html,
- { name => 'start_date',
- value => $cgi->param('start_date') || $cust_pkg->start_date,
+ { name => 'date_value',
+ value => $cgi->param('date_value') || $cust_pkg->get($field),
}
&>
</LI>
</UL>
-<INPUT TYPE="submit" NAME="submit" VALUE="<% emt('Set start date') %>">
+<INPUT TYPE="submit" NAME="submit" VALUE="<% emt('Set '.($isstart ? 'start date' : 'contract end')) %>">
</FORM>
</BODY>
@@ -55,9 +56,21 @@
<%init>
+my $field = $cgi->param('field');
+
+my ($acl, $isstart);
+if ($field eq 'start_date') {
+ $acl = 'Change package start date';
+ $isstart = 1;
+} elsif ($field eq 'contract_end') {
+ $acl = 'Change package contract end date';
+} else {
+ die "Unknown date field";
+}
+
my $curuser = $FS::CurrentUser::CurrentUser;
die "access denied"
- unless $curuser->access_right('Change package start date');
+ unless $curuser->access_right($acl);
my $pkgnum;
if ( $cgi->param('pkgnum') =~ /^(\d+)$/ ) {
@@ -69,7 +82,7 @@ if ( $cgi->param('pkgnum') =~ /^(\d+)$/ ) {
my $conf = new FS::Conf;
my $date_format = $conf->config('date_format') || '%m/%d/%Y';
-my $title = 'Start billing package';
+my $title = $isstart ? 'Start billing package' : 'Change contract end';
my $cust_pkg = qsearchs({
table => 'cust_pkg',
@@ -83,12 +96,12 @@ my $next_bill_date = $cust_pkg->cust_main->next_bill_date;
my $part_pkg = $cust_pkg->part_pkg;
# defaults:
-# sticky on error, then the existing start date if any, then the customer's
+# sticky on error, then the existing date if any, then the customer's
# next bill date, and if none of those, default to now
my $when = $cgi->param('when');
if (!$when) {
- if ($cust_pkg->start_date) {
+ if ($cust_pkg->get($field)) {
$when = 'date';
} elsif ($next_bill_date) {
$when = 'next_bill_date';
diff --git a/httemplate/misc/cust_main-cancel.cgi b/httemplate/misc/cust_main-cancel.cgi
index f6fd1e915..73c4deb7a 100755
--- a/httemplate/misc/cust_main-cancel.cgi
+++ b/httemplate/misc/cust_main-cancel.cgi
@@ -1,6 +1,6 @@
<& /elements/header-popup.html, mt("Customer cancelled") &>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/misc/cust_main-suspend.cgi b/httemplate/misc/cust_main-suspend.cgi
index 7a501d61a..e81e2b490 100755
--- a/httemplate/misc/cust_main-suspend.cgi
+++ b/httemplate/misc/cust_main-suspend.cgi
@@ -1,6 +1,6 @@
<& /elements/header-popup.html, mt("Customer suspended") &>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/misc/cust_main-unsuspend.cgi b/httemplate/misc/cust_main-unsuspend.cgi
index e8ac8d31e..99ec70a23 100755
--- a/httemplate/misc/cust_main-unsuspend.cgi
+++ b/httemplate/misc/cust_main-unsuspend.cgi
@@ -1,6 +1,6 @@
<& /elements/header-popup.html, mt("Customer unsuspended") &>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/misc/delete-addr_range.html b/httemplate/misc/delete-addr_range.html
index c6310e9b1..239332d23 100644
--- a/httemplate/misc/delete-addr_range.html
+++ b/httemplate/misc/delete-addr_range.html
@@ -3,7 +3,7 @@
% } else {
<& /elements/header-popup.html, "Address range deleted" &>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/misc/delete-rate_detail.html b/httemplate/misc/delete-rate_detail.html
index 30856a73a..b4d31b379 100755
--- a/httemplate/misc/delete-rate_detail.html
+++ b/httemplate/misc/delete-rate_detail.html
@@ -3,7 +3,7 @@
% } else {
<% header('Rate deleted') %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
% }
diff --git a/httemplate/misc/did_order_confirmed.html b/httemplate/misc/did_order_confirmed.html
index 53dbb2f3a..3cc121c6f 100644
--- a/httemplate/misc/did_order_confirmed.html
+++ b/httemplate/misc/did_order_confirmed.html
@@ -14,7 +14,7 @@ die "access denied"
my $action = $1;
my $header = '';
my $popup = '';
-my $js = 'window.top.location.reload();';
+my $js = 'topreload();';
$cgi->param('ordernum') =~ /^(\d+)$/ or die 'illegal ordernum';
my $ordernum = $1;
diff --git a/httemplate/misc/disable-cust_location.cgi b/httemplate/misc/disable-cust_location.cgi
index ee7ba1dbc..677f0b891 100755
--- a/httemplate/misc/disable-cust_location.cgi
+++ b/httemplate/misc/disable-cust_location.cgi
@@ -1,6 +1,6 @@
<% header("Location disabled") %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/misc/disable-msg_template.cgi b/httemplate/misc/disable-msg_template.cgi
index 1eb4d25e5..565eb2cee 100644
--- a/httemplate/misc/disable-msg_template.cgi
+++ b/httemplate/misc/disable-msg_template.cgi
@@ -3,7 +3,7 @@
% } else {
<& /elements/header-popup.html, "Template ${actioned}" &>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/misc/process/bulk_pkg_increment_bill.cgi b/httemplate/misc/process/bulk_pkg_increment_bill.cgi
index 0d8417b26..8da849508 100755
--- a/httemplate/misc/process/bulk_pkg_increment_bill.cgi
+++ b/httemplate/misc/process/bulk_pkg_increment_bill.cgi
@@ -4,7 +4,7 @@
%} else {
<% header('Packages Adjusted') %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
% }
diff --git a/httemplate/misc/process/cancel_pkg.html b/httemplate/misc/process/cancel_pkg.html
index eb3b2efe6..46ba06a6d 100755
--- a/httemplate/misc/process/cancel_pkg.html
+++ b/httemplate/misc/process/cancel_pkg.html
@@ -1,6 +1,6 @@
<% header(emt("Package $past_method")) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/misc/process/change_pkg_contact.html b/httemplate/misc/process/change_pkg_contact.html
index 2795c1197..5bf896200 100644
--- a/httemplate/misc/process/change_pkg_contact.html
+++ b/httemplate/misc/process/change_pkg_contact.html
@@ -1,6 +1,6 @@
<% header(emt("Package contact $past_method")) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/misc/process/change_pkg_start.html b/httemplate/misc/process/change_pkg_date.html
index 17a8518f9..3084ec538 100755
--- a/httemplate/misc/process/change_pkg_start.html
+++ b/httemplate/misc/process/change_pkg_date.html
@@ -6,9 +6,21 @@
</HTML>
<%init>
+my $field = $cgi->param('field');
+
+my ($acl, $isstart);
+if ($field eq 'start_date') {
+ $acl = 'Change package start date';
+ $isstart = 1;
+} elsif ($field eq 'contract_end') {
+ $acl = 'Change package contract end date';
+} else {
+ die "Unknown date field";
+}
+
my $curuser = $FS::CurrentUser::CurrentUser;
die "access denied"
- unless $curuser->access_right('Change package start date');
+ unless $curuser->access_right($acl);
$cgi->param('pkgnum') =~ /^(\d+)$/
or die "illegal pkgnum";
@@ -24,23 +36,25 @@ my $cust_pkg = qsearchs({
my $cust_main = $cust_pkg->cust_main;
my $error;
-my $start_date;
+my $date_value;
if ( $cgi->param('when') eq 'now' ) {
- # start it the next time billing runs
- $start_date = '';
+ # blank start means start it the next time billing runs ("Now")
+ # blank contract end means it never ends ("Never")
+ $date_value = '';
} elsif ( $cgi->param('when') eq 'next_bill_date' ) {
- $start_date = $cust_main->next_bill_date;
+ $date_value = $cust_main->next_bill_date;
} elsif ( $cgi->param('when') eq 'date' ) {
- $start_date = parse_datetime($cgi->param('start_date'));
+ $date_value = parse_datetime($cgi->param('date_value'));
}
-if ( $cust_pkg->setup ) {
+if ( $isstart && $cust_pkg->setup ) {
# shouldn't happen
$error = 'This package has already started billing.';
} else {
local $FS::UID::AutoCommit = 0;
foreach my $pkg ($cust_pkg, $cust_pkg->supplemental_pkgs) {
- $pkg->set('start_date', $start_date);
+ last if $error;
+ $pkg->set($field, $date_value);
$error ||= $pkg->replace;
}
$error ? dbh->rollback : dbh->commit;
@@ -48,6 +62,6 @@ if ( $cust_pkg->setup ) {
if ( $error ) {
$cgi->param('error', $error);
- print $cgi->redirect($fsurl.'misc/change_pkg_start.html?', $cgi->query_string);
+ print $cgi->redirect($fsurl.'misc/change_pkg_date.html?', $cgi->query_string);
}
</%init>
diff --git a/httemplate/misc/process/cust_bill-promised_date.html b/httemplate/misc/process/cust_bill-promised_date.html
index 721a763eb..f390609c7 100644
--- a/httemplate/misc/process/cust_bill-promised_date.html
+++ b/httemplate/misc/process/cust_bill-promised_date.html
@@ -1,4 +1,4 @@
-<SCRIPT TYPE="text/javascript">window.top.location.reload()</SCRIPT>
+<SCRIPT TYPE="text/javascript">topreload()</SCRIPT>
<%init>
# XXX ACL?
die "access denied"
diff --git a/httemplate/misc/process/delay_susp_pkg.html b/httemplate/misc/process/delay_susp_pkg.html
index 675da0496..15a3c963c 100755
--- a/httemplate/misc/process/delay_susp_pkg.html
+++ b/httemplate/misc/process/delay_susp_pkg.html
@@ -1,6 +1,6 @@
<% header($msg) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/misc/process/enable_or_disable_tax.html b/httemplate/misc/process/enable_or_disable_tax.html
index 9b7324b0d..8a7a559a0 100755
--- a/httemplate/misc/process/enable_or_disable_tax.html
+++ b/httemplate/misc/process/enable_or_disable_tax.html
@@ -4,7 +4,7 @@
<% include('/elements/header-popup.html', $title) %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
diff --git a/httemplate/misc/process/nms-add_iface.html b/httemplate/misc/process/nms-add_iface.html
index 79e685686..cbd0fc048 100644
--- a/httemplate/misc/process/nms-add_iface.html
+++ b/httemplate/misc/process/nms-add_iface.html
@@ -1,6 +1,6 @@
<& /elements/header-popup.html, 'Interface added' &>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
<%init>
diff --git a/httemplate/misc/process/nms-add_router.html b/httemplate/misc/process/nms-add_router.html
index c3b42a8d3..a4c3423da 100644
--- a/httemplate/misc/process/nms-add_router.html
+++ b/httemplate/misc/process/nms-add_router.html
@@ -1,6 +1,6 @@
<& /elements/header-popup.html, 'Router added' &>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
<%init>
diff --git a/httemplate/misc/process/recharge_svc.html b/httemplate/misc/process/recharge_svc.html
index 2d49f6b06..88a1f7f36 100755
--- a/httemplate/misc/process/recharge_svc.html
+++ b/httemplate/misc/process/recharge_svc.html
@@ -4,7 +4,7 @@
%} else {
<% header("Package recharged") %>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
%}
diff --git a/httemplate/misc/process/unhold_pkg.html b/httemplate/misc/process/unhold_pkg.html
index 694048023..7e54262c6 100755
--- a/httemplate/misc/process/unhold_pkg.html
+++ b/httemplate/misc/process/unhold_pkg.html
@@ -1,6 +1,6 @@
<& /elements/header-popup.html &>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/misc/process/void-cust_bill.html b/httemplate/misc/process/void-cust_bill.html
index 7773b0ba9..32a2fc591 100755
--- a/httemplate/misc/process/void-cust_bill.html
+++ b/httemplate/misc/process/void-cust_bill.html
@@ -4,7 +4,7 @@
%} else {
<& /elements/header-popup.html, 'Invoice voided' &>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY></HTML>
%}
diff --git a/httemplate/misc/reason-merge.html b/httemplate/misc/reason-merge.html
index 14f5ebb84..b7e4df454 100644
--- a/httemplate/misc/reason-merge.html
+++ b/httemplate/misc/reason-merge.html
@@ -1,7 +1,7 @@
% if ($success) {
<% include('/elements/header-popup.html', 'Reason Merge Success') %>
<SCRIPT>
-window.top.location.reload()
+topreload()
</SCRIPT>
% } else {
<% include('/elements/header-popup.html', 'Merge Reasons') %>
diff --git a/httemplate/misc/void-cust_credit.html b/httemplate/misc/void-cust_credit.html
index 1e71f0030..81ba31d54 100755
--- a/httemplate/misc/void-cust_credit.html
+++ b/httemplate/misc/void-cust_credit.html
@@ -1,7 +1,7 @@
%if ( $success ) {
<& /elements/header-popup.html, mt("Credit voided") &>
<SCRIPT TYPE="text/javascript">
- window.top.location.reload();
+ topreload();
</SCRIPT>
</BODY>
</HTML>
diff --git a/httemplate/search/cust_bill_pay_pkg.html b/httemplate/search/cust_bill_pay_pkg.html
index 7c231a65d..e2ffd1258 100644
--- a/httemplate/search/cust_bill_pay_pkg.html
+++ b/httemplate/search/cust_bill_pay_pkg.html
@@ -14,7 +14,7 @@
#payment
'Date',
- 'Order Number',
+ @on_header,
'By',
#application
@@ -44,7 +44,7 @@
? cardtype($cust_pay->paymask) : '';
},
sub { time2str('%b %d %Y', shift->get('cust_pay_date') ) },
- sub { shift->cust_bill_pay->cust_pay->order_number },
+ @on_field,
sub { shift->cust_bill_pay->cust_pay->otaker },
sub { sprintf($money_char.'%.2f', shift->amount ) },
@@ -66,7 +66,7 @@
'', #payinfo/paymask
'', #cardtype
'cust_pay_date',
- '', #order_number
+ @on_null, #order_number
'', #'otaker',
'', #amount
'', #line item description
@@ -83,7 +83,7 @@
'',
'',
'',
- '',
+ @on_null,
'',
'',
'',
@@ -96,10 +96,9 @@
FS::UI::Web::cust_header()
),
],
- 'align' => 'rcrlrrlrlll',
-#original value before cardtype & package were added
-#why are there 13 cols?
-#'rcrrlrlllrrcl'.
+ 'align' => 'rcrlr'.
+ $on_align.
+ 'lrlll'.
$post_desc_align.
'rr'.
FS::UI::Web::cust_aligns(),
@@ -109,7 +108,7 @@
'',
'',
'',
- '',
+ @on_null,
'',
'',
'',
@@ -126,7 +125,7 @@
'',
'',
'',
- '',
+ @on_null,
'',
'',
'',
@@ -148,6 +147,17 @@
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+my @on_header = ();
+my @on_field = ();
+my @on_null = ();
+my $on_align = '';
+if ($cgi->param('show_order_number')) {
+ @on_header = ('Order Number');
+ @on_field = (sub { shift->cust_bill_pay->cust_pay->order_number });
+ @on_null = ('');
+ $on_align = 'r';
+}
+
my $conf = new FS::Conf;
my %payby = FS::payby->payby2shortname;
diff --git a/httemplate/search/cust_pay.html b/httemplate/search/cust_pay.html
index 536ab291f..e466f6afa 100755
--- a/httemplate/search/cust_pay.html
+++ b/httemplate/search/cust_pay.html
@@ -4,5 +4,4 @@
'name_singular' => emt('payment'),
'name_verb' => emt('paid'),
'show_card_type' => 1,
- 'show_order_number' => 1,
&>
diff --git a/httemplate/search/cust_pay_pending.html b/httemplate/search/cust_pay_pending.html
index 8662d1989..697bdbbf0 100755
--- a/httemplate/search/cust_pay_pending.html
+++ b/httemplate/search/cust_pay_pending.html
@@ -17,7 +17,7 @@
my %statusaction = (
'new' => 'delete',
'pending' => 'complete',
- #'authorized' => '',
+ 'authorized' => 'complete',
'captured' => 'capture',
#'declined' => '',
#wouldn't need to take action on a done state#'done'
diff --git a/httemplate/search/elements/cust_pay_or_refund.html b/httemplate/search/elements/cust_pay_or_refund.html
index 03aaedd36..1b1be5f36 100755
--- a/httemplate/search/elements/cust_pay_or_refund.html
+++ b/httemplate/search/elements/cust_pay_or_refund.html
@@ -74,6 +74,7 @@ my %cardtype_of = (
'Amex' => q['American Express card'],
'Discover' => q['Discover card'],
'Maestro' => q['Switch', 'Solo', 'Laser'],
+ 'Tokenized' => q['Tokenized'],
);
</%shared>
<%init>
@@ -100,29 +101,30 @@ my $title = '';
$title = 'Unapplied ' if $unapplied;
$title .= "\u$name_singular Search Results";
-my $link = '';
-if ( ( $curuser->access_right('View invoices') #remove in 2.5 (2.7?)
- || ($curuser->access_right('View payments') && $table =~ /^cust_pay/)
- || ($curuser->access_right('View refunds') && $table eq 'cust_refund')
- )
- && ! $opt{'disable_link'}
- )
-{
-
- my $key;
- my $q = '';
- if ( $table eq 'cust_pay_void' ) {
- $key = 'paynum';
- $q .= 'void=1;';
- } elsif ( $table eq /^cust_(\w+)$/ ) {
- $key = $1.'num';
- }
-
- if ( $key ) {
- $q .= "$key=";
- $link = [ "${p}view/$table.html?$q", $key ]
- }
-}
+###NOT USED???
+#my $link = '';
+#if ( ( $curuser->access_right('View invoices') #remove in 2.5 (2.7?)
+# || ($curuser->access_right('View payments') && $table =~ /^cust_pay/)
+# || ($curuser->access_right('View refunds') && $table eq 'cust_refund')
+# )
+# && ! $opt{'disable_link'}
+# )
+#{
+#
+# my $key;
+# my $q = '';
+# if ( $table eq 'cust_pay_void' ) {
+# $key = 'paynum';
+# $q .= 'void=1;';
+# } elsif ( $table eq /^cust_(\w+)$/ ) {
+# $key = $1.'num';
+# }
+#
+# if ( $key ) {
+# $q .= "$key=";
+# $link = [ "${p}view/$table.html?$q", $key ]
+# }
+#}
my $cust_link = sub {
my $cust_thing = shift;
@@ -175,12 +177,18 @@ if ( $opt{'pre_header'} ) {
push @sort_fields, @{ $opt{'pre_fields'} };
}
-my $sub_receipt = sub {
+my $sub_receipt = $opt{'disable_link'} ? '' : sub {
my $obj = shift;
my $objnum = $obj->primary_key . '=' . $obj->get($obj->primary_key);
+ my $table = $obj->table;
+ my $void = '';
+ if ($table eq 'cust_pay_void') {
+ $table = 'cust_pay';
+ $void = ';void=1';
+ }
include('/elements/popup_link_onclick.html',
- 'action' => $p.'view/cust_pay.html?link=popup;'.$objnum,
+ 'action' => $p.'view/'.$table.'.html?link=popup;'.$objnum.$void,
'actionlabel' => emt('Payment Receipt'),
);
};
@@ -218,7 +226,7 @@ push @links, '';
push @fields, sub { time2str('%b %d %Y', shift->_date ) };
push @sort_fields, '_date';
-if ($opt{'show_order_number'}) {
+if ($cgi->param('show_order_number')) {
push @header, emt('Order Number');
$align .= 'r';
push @links, '';
@@ -326,18 +334,9 @@ if ( $cgi->param('magic') ) {
if ( $subtype ) {
- if ( $subtype eq 'Tokenized' ) {
-
- $payby_search .= " AND substring($table.payinfo from 1 for 2 ) = '99' ";
- # XXX should store the cardtype as 'Tokenized' in this case?
-
- } else {
-
- my $in_cardtype = $cardtype_of{$subtype}
- or die "unknown card type $subtype";
- $payby_search .= " AND $table.paycardtype IN($in_cardtype)";
-
- }
+ my $in_cardtype = $cardtype_of{$subtype}
+ or die "unknown card type $subtype";
+ $payby_search .= " AND $table.paycardtype IN($in_cardtype)";
}
@@ -499,8 +498,6 @@ if ( $cgi->param('magic') ) {
'addl_from' => $addl_from,
};
-warn Dumper \$sql_query;
-
} else {
#hmm... is this still used?
diff --git a/httemplate/search/elements/report_cust_pay_or_refund.html b/httemplate/search/elements/report_cust_pay_or_refund.html
index 730db68e8..806746a23 100644
--- a/httemplate/search/elements/report_cust_pay_or_refund.html
+++ b/httemplate/search/elements/report_cust_pay_or_refund.html
@@ -151,6 +151,12 @@ Examples:
'value' => 1,
&>
+ <& /elements/tr-checkbox.html,
+ 'label' => emt('Include order number'),
+ 'field' => 'show_order_number',
+ 'value' => 1,
+ &>
+
</TABLE>
% }
diff --git a/httemplate/search/elements/search.html b/httemplate/search/elements/search.html
index a279f5327..b6ee7b373 100644
--- a/httemplate/search/elements/search.html
+++ b/httemplate/search/elements/search.html
@@ -135,8 +135,11 @@ Example:
# sort, link & display properties for fields
- 'sort_fields' => [], #optional list of field names or SQL expressions for
- # sorts
+ 'sort_fields' => [], #optional list of field names or SQL expressions for sorts
+
+ 'order_by_sql' => { #to keep complex SQL expressions out of cgi order_by value,
+ 'fieldname' => 'sql snippet', # maps fields/sort_fields values to sql snippets
+ }
#listref - each item is the empty string,
# or a listref of link and method name to append,
@@ -406,6 +409,12 @@ $order_by = $cgi->param('order_by') if $cgi->param('order_by');
my $header = [ map { ref($_) ? $_->{'label'} : $_ } @{$opt{header}} ];
my $rows;
+my ($order_by_key,$order_by_desc) = ($order_by =~ /^\s*(.*?)(\s+DESC)?\s*$/i);
+$opt{'order_by_sql'} ||= {};
+$order_by_desc ||= '';
+$order_by = $opt{'order_by_sql'}{$order_by_key} . $order_by_desc
+ if $opt{'order_by_sql'}{$order_by_key};
+
if ( ref $query ) {
my @query;
if (ref($query) eq 'HASH') {
diff --git a/httemplate/search/log.html b/httemplate/search/log.html
index 111200f55..5b330f899 100644
--- a/httemplate/search/log.html
+++ b/httemplate/search/log.html
@@ -81,15 +81,15 @@ a:visited {text-decoration: none}
<TD>Level
<& /elements/select.html,
field => 'min_level',
- options => [ 0..7 ],
- labels => { map {$_ => $FS::Log::LEVELS[$_]} 0..7 },
+ options => [ &FS::Log::levelnums ],
+ labels => { &FS::Log::levelmap },
curr_value => $cgi->param('min_level'),
&>
to
<& /elements/select.html,
field => 'max_level',
- options => [ 0..7 ],
- labels => { map {$_ => $FS::Log::LEVELS[$_]} 0..7 },
+ options => [ &FS::Log::levelnums ],
+ labels => { &FS::Log::levelmap },
curr_value => $cgi->param('max_level'),
&>
</TD>
@@ -128,7 +128,7 @@ a:visited {text-decoration: none}
<%once>
my $date_sub = sub { time2str('%Y-%m-%d %T', $_[0]->_date) };
-my $level_sub = sub { $FS::Log::LEVELS[$_[0]->level] };
+my $level_sub = sub { $FS::Log::LEVELS{$_[0]->level} };
my $context_sub = sub {
my $log = shift;
@@ -191,18 +191,15 @@ my $object_link_sub = sub {
}
};
-my @colors = (
- '404040', #debug
- '0000aa', #info
- '00aa00', #notice
- 'aa0066', #warning
- '000000', #error
- 'aa0000', #critical
- 'ff0000', #alert
- 'ff0000', #emergency
+my %colors = (
+ 0 => '404040', #debug, gray
+ 1 => '000000', #info, black
+ 3 => '0000aa', #warning, blue
+ 4 => 'aa0066', #error, purple
+ 5 => 'ff0000', #critical, red
);
-my $color_sub = sub { $colors[ $_[0]->level ]; };
+my $color_sub = sub { $colors{ $_[0]->level }; };
my @contexts = ('', sort FS::log_context->contexts);
</%once>
@@ -212,10 +209,10 @@ die "access denied"
unless $curuser->access_right([ 'View system logs', 'Configuration' ]);
my @menubar = ();
-push @menubar, qq(<A HREF="${fsurl}browse/log_email.html" STYLE="text-decoration: underline;">Configure conditions for sending email when logging</A>),
+push @menubar, qq(<A HREF="${fsurl}browse/log_email.html" STYLE="text-decoration: underline;">Configure conditions for sending email when logging</A>);
$cgi->param('min_level', 0) unless defined($cgi->param('min_level'));
-$cgi->param('max_level', 7) unless defined($cgi->param('max_level'));
+$cgi->param('max_level', 5) unless defined($cgi->param('max_level'));
my %search = ();
$search{'date'} = [ FS::UI::Web::parse_beginning_ending($cgi) ];
diff --git a/httemplate/search/report_cust_bill_pay_pkg.html b/httemplate/search/report_cust_bill_pay_pkg.html
index 2347bab6d..bdcd1549e 100644
--- a/httemplate/search/report_cust_bill_pay_pkg.html
+++ b/httemplate/search/report_cust_bill_pay_pkg.html
@@ -41,6 +41,13 @@
field => 'paid',
&>
+ <& /elements/tr-checkbox.html,
+ 'label' => emt('Display order number'),
+ 'field' => 'show_order_number',
+ 'value' => 1,
+ 'cell_style' => 'font-weight: normal', #for consistency
+ &>
+
<!--
<TR>
<TD ALIGN="right"><INPUT TYPE="checkbox" NAME="nottax" VALUE="Y" onClick="nottax_changed(this)" onChange="nottax_change(thid)"></TD>
diff --git a/httemplate/search/report_sqlradius_usage-custnum.html b/httemplate/search/report_sqlradius_usage-custnum.html
new file mode 100644
index 000000000..a71012dd4
--- /dev/null
+++ b/httemplate/search/report_sqlradius_usage-custnum.html
@@ -0,0 +1,71 @@
+<& /elements/header-popup.html, mt($title) &>
+
+<FORM ACTION="sqlradius_usage.html" METHOD="GET" TARGET="_top">
+
+<& /elements/hidden.html,
+ 'field' => 'custnum',
+ 'value' => $custnum,
+&>
+<TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+
+% if ( scalar(@exports) == 1 ) {
+<tr><td>
+<& /elements/hidden.html,
+ 'field' => 'exportnum',
+ 'value' => $exports[0]->exportnum,
+&>
+</td></tr>
+% } else {
+<& /elements/tr-select-table.html,
+ 'label' => 'Export', # kind of non-indicative...
+ 'table' => 'part_export',
+ 'name_col' => 'label',
+ 'value_col' => 'exportnum',
+ 'records' => \@exports,
+ 'disable_empty' => 1,
+&>
+% }
+<& /elements/tr-input-beginning_ending.html &>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="<% mt('Get Report') |h %>">
+
+</FORM>
+
+<& /elements/footer.html &>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+die "access denied"
+ unless $curuser->access_right('Usage: RADIUS sessions');
+ # yes?
+
+my $title = 'Data Usage Report';
+my $custnum;
+if ($cgi->keywords) {
+ ($custnum) = $cgi->keywords;
+} else {
+ $custnum = $cgi->param('custnum');
+}
+$custnum =~ /^(\d+)$/
+ or die "illegal custnum $custnum";
+my $cust_main = qsearchs( {
+ 'table' => 'cust_main',
+ 'hashref' => { 'custnum' => $custnum },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
+});
+# get all exports that apply to this customer's services--should be fast, as
+# everything here is indexed
+my @exports = qsearch({
+ 'table' => 'part_export',
+ 'select' => 'DISTINCT part_export.*',
+ 'addl_from' => ' JOIN export_svc USING (exportnum)
+ JOIN cust_svc USING (svcpart)
+ JOIN cust_pkg USING (pkgnum) ',
+ 'extra_sql' => ' WHERE cust_pkg.custnum = '.$custnum,
+});
+@exports = grep { $_->can('usage_sessions') } @exports;
+
+</%init>
diff --git a/httemplate/search/report_sqlradius_usage.html b/httemplate/search/report_sqlradius_usage.html
index e818fb57d..89b60847b 100644
--- a/httemplate/search/report_sqlradius_usage.html
+++ b/httemplate/search/report_sqlradius_usage.html
@@ -1,3 +1,4 @@
+%# some overlap with report_sqlradius_usage_custnum.html
<& /elements/header.html, mt($title) &>
<FORM ACTION="sqlradius_usage.html" METHOD="GET">
diff --git a/httemplate/search/sqlradius_usage.html b/httemplate/search/sqlradius_usage.html
index 29ef4c0e8..08f9b6ba1 100644
--- a/httemplate/search/sqlradius_usage.html
+++ b/httemplate/search/sqlradius_usage.html
@@ -39,6 +39,7 @@
@svc_fields,
@svc_usage,
],
+ 'order_by_sql' => $order_by_sql,
'links' => [ #( map { $_ ne 'Cust. Status' ? $link_cust : '' }
# FS::UI::Web::cust_header() ),
$link_cust,
@@ -59,8 +60,8 @@
my %opt = @_;
-die "access denied" unless
- $FS::CurrentUser::CurrentUser->access_right('List services');
+my $curuser = $FS::CurrentUser::CurrentUser;
+die "access denied" unless $curuser->access_right('List services');
my $title = 'Data Usage Report - ';
my $agentnum;
@@ -92,6 +93,40 @@ if ( $ending == 4294967295 ) {
$title .= time2str('%h %o %Y', $ending);
}
+# can also show a specific customer / service. the main query will handle
+# agent restrictions, but we need a list of the services to ask the export
+# for usage data.
+my ($cust_main, @svc_x);
+if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
+ $cust_main = qsearchs( {
+ 'table' => 'cust_main',
+ 'hashref' => { 'custnum' => $1 },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
+ });
+ die "Customer not found!" unless $cust_main;
+ # then only report on this agent
+ $agentnum = $cust_main->agentnum;
+ @include_agents = ();
+ # and announce that we're doing it
+ $title .= ' - ' . $cust_main->name_short;
+
+ # yes, we'll query the database once for each service the customer has,
+ # even non-radacct'd services. probably less bad than a single query that
+ # pulls records for every service for every customer.
+ foreach my $cust_pkg ($cust_main->all_pkgs) {
+ foreach my $cust_svc ($cust_pkg->cust_svc) {
+ push @svc_x, $cust_svc->svc_x;
+ }
+ }
+}
+foreach ($cgi->param('svcnum')) {
+ if (/^(\d+)$/) {
+ my $cust_svc = FS::cust_svc->by_key($1)
+ or die "service #$1 not found."; # or continue?
+ push @svc_x, $cust_svc->svc_x;
+ }
+}
+
my $export;
my %usage_by_username;
if ( exists($opt{usage_by_username}) ) {
@@ -109,16 +144,28 @@ if ( exists($opt{usage_by_username}) ) {
or die "exportnum ".$export->exportnum." is type ".$export->exporttype.
", not sqlradius";
- my $usage = $export->usage_sessions( {
+ my %usage_param = (
stoptime_start => $beginning,
stoptime_end => $ending,
summarize => 1
- } );
- # arrayref of hashrefs of
+ );
+ # usage_sessions() returns an arrayref of hashrefs of
# (username, acctsessiontime, acctinputoctets, acctoutputoctets)
# (XXX needs to include 'realm' for sqlradius_withdomain)
- # rearrange to be indexed by username.
+ my $usage;
+ if ( @svc_x ) {
+ # then query once per service
+ $usage = [];
+ foreach my $svc ( @svc_x ) {
+ $usage_param{'svc'} = $svc;
+ push @$usage, @{ $export->usage_sessions(\%usage_param) };
+ }
+ } else {
+ # one query, get everyone's data
+ my $usage = $export->usage_sessions(\%usage_param);
+ }
+ # rearrange to be indexed by username.
foreach (@$usage) {
my $username = $_->{'username'};
my @row = (
@@ -171,10 +218,22 @@ my @svc_fields = @{ $svc_fields{$svcdb} };
my %search_hash = ( 'agentnum' => $agentnum,
'exportnum' => $export->exportnum );
+if ($cust_main) {
+ $search_hash{'custnum'} = $cust_main->custnum;
+}
+if (@svc_x) {
+ $search_hash{'svcnum'} = [ map { $_->get('svcnum') } @svc_x ];
+}
+
my $sql_query = $class->search(\%search_hash);
$sql_query->{'select'} .= ', part_pkg.pkg';
$sql_query->{'addl_from'} .= ' LEFT JOIN part_pkg USING (pkgpart)';
+if ( @svc_x ) {
+ my $svcnums = join(',', map { $_->get('svcnum') } @svc_x);
+ $sql_query->{'extra_sql'} .= ' AND svcnum IN('.$svcnums.')';
+}
+
my $link_svc = [ $p.'view/cust_svc.cgi?', 'svcnum' ];
my $link_cust = [ $p.'view/cust_main.cgi?', 'custnum' ];
@@ -182,9 +241,10 @@ my $link_cust = [ $p.'view/cust_main.cgi?', 'custnum' ];
# columns between the customer name and the usage fields
my $skip_cols = 1 + scalar(@svc_header);
+my $num_rows = FS::Record->scalar_sql($sql_query->{count_query});
my @footer = (
'',
- FS::Record->scalar_sql($sql_query->{count_query}) . ' services',
+ emt('[quant,_1,service]', $num_rows),
('') x $skip_cols,
map {
my $i = $_;
@@ -198,4 +258,23 @@ sub bytes_to_gb {
$_[0] ? sprintf('%.3f', $_[0] / (1024*1024*1024.0)) : '';
}
+my $conf = new FS::Conf;
+my $order_by_sql = {
+ 'name' => "CASE WHEN cust_main.company IS NOT NULL
+ AND cust_main.company != ''
+ THEN CONCAT(cust_main.company,' (',cust_main.last,', ',cust_main.first,')')
+ ELSE CONCAT(cust_main.last,', ',cust_main.first)
+ END",
+ 'display_custnum' => $conf->exists('cust_main-default_agent_custid')
+ ? "CASE WHEN cust_main.agent_custid IS NOT NULL
+ AND cust_main.agent_custid != ''
+ AND cust_main.agent_custid ". regexp_sql. " '^[0-9]+\$'
+ THEN CAST(cust_main.agent_custid AS BIGINT)
+ ELSE cust_main.custnum
+ END"
+ : "custnum",
+};
+
+#warn Dumper \%usage_by_username;
+
</%init>
diff --git a/httemplate/view/cust_main/menu.html b/httemplate/view/cust_main/menu.html
index 9e194f42d..7c7303bc9 100644
--- a/httemplate/view/cust_main/menu.html
+++ b/httemplate/view/cust_main/menu.html
@@ -391,8 +391,17 @@ my @menu = (
url => "search/report_svc_acct.html?custnum=$custnum",
},
{
+ label => 'View data usage',
+ popup => "search/report_sqlradius_usage-custnum.html?$custnum",
+ acl => 'Usage: RADIUS sessions',
+ actionlabel => 'Data usage report',
+ width => 480,
+ height => 245,
+ },
+ {
label => 'View CDRs',
url => "search/report_cdr.html?custnum=$custnum",
+ # XXX should have a condition that the customer has any CDR packages
},
],
[
diff --git a/httemplate/view/cust_main/packages/status.html b/httemplate/view/cust_main/packages/status.html
index 97011c3b7..3f629e12f 100644
--- a/httemplate/view/cust_main/packages/status.html
+++ b/httemplate/view/cust_main/packages/status.html
@@ -104,6 +104,14 @@
<TR>
<TD COLSPAN=<%$opt{colspan}%>>
<FONT SIZE=-1>
+% if ( !$cust_pkg->change_to_pkgnum # because on a technical level, change won't propagate,
+% # and there's not really a use case worth making that work
+% and $part_pkg->freq # technically possible to have contract_end w/o freq, but nonsensical
+% and $curuser->access_right('Change package contract end date')
+% ) {
+ (&nbsp;<% pkg_change_contract_end_link($cust_pkg) %>&nbsp;)
+ <BR>
+% }
% if ( $cust_pkg->change_to_pkgnum ) {
% # then you can modify the package change
% if ( $curuser->access_right('Change customer package') ) {
@@ -188,21 +196,6 @@
<% pkg_status_row_if($cust_pkg, emt('Start billing'), 'start_date', %opt) %>
<% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
-% if ( !$opt{no_links}
-% and !$change_from
-% and !$supplemental # can be changed from its main package
-% and $curuser->access_right('Change package start date') )
-% {
-
- <TR>
- <TD COLSPAN=<%$opt{colspan}%>>
- <FONT SIZE=-1>
- (&nbsp;<% pkg_change_start_link($cust_pkg) %>&nbsp;)
- </FONT>
- </TD>
- </TR>
-% }
-
% }
%
% } else { #setup
@@ -286,6 +279,28 @@
<TR>
<TD COLSPAN=<%$opt{colspan}%>>
<FONT SIZE=-1>
+
+% #change date links
+% if ( !$change_from and !$supplemental ) {
+% my $has_date_links = 0;
+% if ( !$cust_pkg->get('setup')
+% and $curuser->access_right('Change package start date')
+% ) {
+ (&nbsp;<% pkg_change_start_link($cust_pkg) %>&nbsp;)
+% $has_date_links = 1;
+% }
+% if ( !$cust_pkg->change_to_pkgnum # because on a technical level, change won't propagate,
+% # and there's not really a use case worth making that work
+% and $curuser->access_right('Change package contract end date')
+% ) {
+ (&nbsp;<% pkg_change_contract_end_link($cust_pkg) %>&nbsp;)
+% $has_date_links = 1;
+% }
+% if ($has_date_links) {
+ <BR>
+% }
+% }
+
% # action links
% if ( $change_from ) {
% # nothing
@@ -745,7 +760,7 @@ sub pkg_change_later_link {
sub pkg_change_start_link {
my $cust_pkg = shift;
include( '/elements/popup_link-cust_pkg.html',
- 'action' => $p . 'misc/change_pkg_start.html',
+ 'action' => $p . 'misc/change_pkg_date.html?field=start_date',
'label' => emt('Set start date'),
'actionlabel' => emt('Set start of billing for'),
'cust_pkg' => $cust_pkg,
@@ -754,6 +769,18 @@ sub pkg_change_start_link {
)
}
+sub pkg_change_contract_end_link {
+ my $cust_pkg = shift;
+ include( '/elements/popup_link-cust_pkg.html',
+ 'action' => $p . 'misc/change_pkg_date.html?field=contract_end',
+ 'label' => emt('Set contract end'),
+ 'actionlabel' => emt('Set contract end for'),
+ 'cust_pkg' => $cust_pkg,
+ 'width' => 510,
+ 'height' => 310,
+ )
+}
+
sub svc_recharge_link {
include( '/elements/popup_link-cust_svc.html',
'action' => $p. 'misc/recharge_svc.html',
diff --git a/httemplate/view/cust_main/payment_history/pending_payment.html b/httemplate/view/cust_main/payment_history/pending_payment.html
index 31149231b..cf7ef7c08 100644
--- a/httemplate/view/cust_main/payment_history/pending_payment.html
+++ b/httemplate/view/cust_main/payment_history/pending_payment.html
@@ -12,6 +12,7 @@ my %statusaction = (
'new' => 'delete',
'thirdparty' => 'delete',
'pending' => 'complete',
+ 'authorized' => 'complete',
'captured' => 'capture',
);