summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FS/FS/Cron/bill.pm2
-rw-r--r--FS/FS/Mason.pm1
-rw-r--r--FS/FS/cust_statement.pm37
-rw-r--r--FS/FS/part_event/Action/cust_statement.pm5
-rw-r--r--FS/FS/part_event/Action/cust_statement_send.pm2
-rw-r--r--FS/FS/part_event/Condition/has_pkg_class.pm40
-rw-r--r--FS/FS/part_event/Condition/has_pkgpart.pm41
-rw-r--r--FS/FS/part_event/Condition/hasnt_pkgpart.pm40
-rwxr-xr-xhttemplate/misc/email-statement.cgi19
-rwxr-xr-xhttemplate/view/cust_statement-pdf.cgi28
-rwxr-xr-xhttemplate/view/cust_statement.html13
11 files changed, 211 insertions, 17 deletions
diff --git a/FS/FS/Cron/bill.pm b/FS/FS/Cron/bill.pm
index 2bdb120..d727d92 100644
--- a/FS/FS/Cron/bill.pm
+++ b/FS/FS/Cron/bill.pm
@@ -194,7 +194,7 @@ END
my $where = FS::part_event_condition->where_conditions_sql( $eventtable,
'time'=>$time,
);
- my $where = "AND $where" if $where;
+ $where = $where ? "AND $where" : '';
my $are_part_event =
"EXISTS ( SELECT 1 FROM part_event $join
diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm
index d73d381..f71db20 100644
--- a/FS/FS/Mason.pm
+++ b/FS/FS/Mason.pm
@@ -197,6 +197,7 @@ Initializes the Mason environment, loads all Freeside and RT libraries, etc.
use FS::h_svc_phone;
#use FS::h_phone_device;
use FS::h_svc_www;
+ use FS::cust_statement;
# Sammath Naur
if ( %%%RT_ENABLED%%% ) {
diff --git a/FS/FS/cust_statement.pm b/FS/FS/cust_statement.pm
index cd3e7ce..83dd5c1 100644
--- a/FS/FS/cust_statement.pm
+++ b/FS/FS/cust_statement.pm
@@ -180,6 +180,18 @@ sub _aggregate {
@agg;
}
+sub _total {
+ my( $self, $method ) = ( shift, shift );
+
+ my $total = 0;
+
+ foreach my $cust_bill ( $self->cust_bill ) {
+ $total += $cust_bill->$method( @_ );
+ }
+
+ $total;
+}
+
=item cust_bill_pkg
Returns the line items (see L<FS::cust_bill_pkg>) for all associated invoices.
@@ -221,20 +233,29 @@ sub cust_bill_pkg_pkgnum { shift->_aggregate('cust_bill_pkg_pkgnum', @_); }
=item tax
-Returns the tax amount (see L<FS::cust_bill_pkg>) for this invoice.
+Returns the total tax amount for all assoicated invoices.0
=cut
-sub tax {
- my $self = shift;
+=item charged
- my $total = 0;
+Returns the total amount charged for all associated invoices.
- foreach my $cust_bill ( $self->cust_bill ) {
- $total += $cust_bill->tax;
- }
+=cut
- $total;
+=item owed
+
+Returns the total amount owed for all associated invoices.
+
+=cut
+
+sub tax { shift->_total('tax', @_); }
+sub charged { shift->_total('charged', @_); }
+sub owed { shift->_total('owed', @_); }
+
+#don't show previous info
+sub previous {
+ ( 0 ); # 0, empty list
}
=back
diff --git a/FS/FS/part_event/Action/cust_statement.pm b/FS/FS/part_event/Action/cust_statement.pm
index 8d8f127..2d9e877 100644
--- a/FS/FS/part_event/Action/cust_statement.pm
+++ b/FS/FS/part_event/Action/cust_statement.pm
@@ -11,8 +11,9 @@ sub description {
}
sub eventtable_hashref {
- { 'cust_main' => 1, };
- { 'cust_pkg' => 1, };
+ { 'cust_main' => 1,
+ 'cust_pkg' => 1,
+ };
}
sub default_weight {
diff --git a/FS/FS/part_event/Action/cust_statement_send.pm b/FS/FS/part_event/Action/cust_statement_send.pm
index 34f023e..74cc48c 100644
--- a/FS/FS/part_event/Action/cust_statement_send.pm
+++ b/FS/FS/part_event/Action/cust_statement_send.pm
@@ -19,7 +19,7 @@ sub default_weight {
sub do_action {
my( $self, $cust_statement ) = @_;
- $cust_statement->send;
+ $cust_statement->send( 'statement' ); #XXX configure
}
diff --git a/FS/FS/part_event/Condition/has_pkg_class.pm b/FS/FS/part_event/Condition/has_pkg_class.pm
new file mode 100644
index 0000000..59a3675
--- /dev/null
+++ b/FS/FS/part_event/Condition/has_pkg_class.pm
@@ -0,0 +1,40 @@
+package FS::part_event::Condition::has_pkg_class;
+
+use strict;
+
+use base qw( FS::part_event::Condition );
+use FS::Record qw( qsearch );
+use FS::pkg_class;
+
+sub description {
+ 'Customer has uncancelled package with class';
+}
+
+sub eventtable_hashref {
+ { 'cust_main' => 1,
+ 'cust_bill' => 1,
+ 'cust_pkg' => 1,
+ };
+}
+
+#something like this
+sub option_fields {
+ (
+ 'pkgclass' => { 'label' => 'Package Class',
+ 'type' => 'select-pkg_class',
+ 'multiple' => 1,
+ },
+ );
+}
+
+sub condition {
+ my( $self, $object ) = @_;
+
+ my $cust_main = $self->cust_main($object);
+
+ #XXX test
+ my $hashref = $self->option('pkgclass') || {};
+ grep $hashref->{ $_->part_pkg->classnum }, $cust_main->ncancelled_pkgs;
+}
+
+1;
diff --git a/FS/FS/part_event/Condition/has_pkgpart.pm b/FS/FS/part_event/Condition/has_pkgpart.pm
new file mode 100644
index 0000000..c54b7e2
--- /dev/null
+++ b/FS/FS/part_event/Condition/has_pkgpart.pm
@@ -0,0 +1,41 @@
+package FS::part_event::Condition::has_pkgpart;
+
+use strict;
+
+use base qw( FS::part_event::Condition );
+
+sub description { 'Customer has uncancelled package of specified definitions'; }
+
+sub eventtable_hashref {
+ { 'cust_main' => 1,
+ 'cust_bill' => 1,
+ 'cust_pkg' => 1,
+ };
+}
+
+sub option_fields {
+ (
+ 'if_pkgpart' => { 'label' => 'Only packages: ',
+ 'type' => 'select-part_pkg',
+ 'multiple' => 1,
+ },
+ );
+}
+
+sub condition {
+ my( $self, $object) = @_;
+
+ my $cust_main = $self->cust_main($object);
+
+ #XXX test
+ my $if_pkgpart = $self->option('if_pkgpart') || {};
+ grep $if_pkgpart->{ $_->pkgpart }, $cust_main->ncancelled_pkgs;
+
+}
+
+#XXX
+#sub condition_sql {
+#
+#}
+
+1;
diff --git a/FS/FS/part_event/Condition/hasnt_pkgpart.pm b/FS/FS/part_event/Condition/hasnt_pkgpart.pm
new file mode 100644
index 0000000..421d023
--- /dev/null
+++ b/FS/FS/part_event/Condition/hasnt_pkgpart.pm
@@ -0,0 +1,40 @@
+package FS::part_event::Condition::hasnt_pkgpart;
+
+use strict;
+
+use base qw( FS::part_event::Condition );
+
+sub description { 'Customer does not have uncancelled package of specified definitions'; }
+
+sub eventtable_hashref {
+ { 'cust_main' => 1,
+ 'cust_bill' => 1,
+ 'cust_pkg' => 1,
+ };
+}
+
+sub option_fields {
+ (
+ 'unless_pkgpart' => { 'label' => 'Packages: ',
+ 'type' => 'select-part_pkg',
+ 'multiple' => 1,
+ },
+ );
+}
+
+sub condition {
+ my( $self, $object ) = @_;
+
+ my $cust_main = $self->cust_main($object);
+
+ #XXX test
+ my $unless_pkgpart = $self->option('unless_pkgpart') || {};
+ ! grep $unless_pkgpart->{ $_->pkgpart }, $cust_main->ncancelled_pkgs;
+}
+
+#XXX
+#sub condition_sql {
+#
+#}
+
+1;
diff --git a/httemplate/misc/email-statement.cgi b/httemplate/misc/email-statement.cgi
new file mode 100755
index 0000000..67f654d
--- /dev/null
+++ b/httemplate/misc/email-statement.cgi
@@ -0,0 +1,19 @@
+<% $cgi->redirect("${p}view/cust_main.cgi?$custnum") %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+#untaint statementnum
+my($query) = $cgi->keywords;
+$query =~ /^((.+)-)?(\d+)$/;
+my $template = $2 || 'statement'; #XXX configure... via event?? eh..
+my $statementnum = $3;
+my $cust_statement = qsearchs('cust_statement',{'statementnum'=>$statementnum});
+die "Can't find statement!\n" unless $cust_statement;
+
+$cust_statement->email($template);
+
+my $custnum = $cust_statement->getfield('custnum');
+
+</%init>
diff --git a/httemplate/view/cust_statement-pdf.cgi b/httemplate/view/cust_statement-pdf.cgi
new file mode 100755
index 0000000..a1739e0
--- /dev/null
+++ b/httemplate/view/cust_statement-pdf.cgi
@@ -0,0 +1,28 @@
+<% $pdf %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View invoices');
+
+#untaint statementnum
+my($query) = $cgi->keywords;
+$query =~ /^((.+)-)?(\d+)(.pdf)?$/;
+my $templatename = $2 || 'statement'; #XXX configure... via event?? eh..
+my $statementnum = $3;
+
+my $cust_statement = qsearchs({
+ 'select' => 'cust_statement.*',
+ 'table' => 'cust_statement',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'statementnum' => $statementnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+die "Statement #$statementnum not found!" unless $cust_statement;
+
+my $pdf = $cust_statement->print_pdf( '', $templatename);
+
+http_header('Content-Type' => 'application/pdf' );
+http_header('Content-Length' => length($pdf) );
+http_header('Cache-control' => 'max-age=60' );
+
+</%init>
diff --git a/httemplate/view/cust_statement.html b/httemplate/view/cust_statement.html
index ec4ee9e..b078c9d 100755
--- a/httemplate/view/cust_statement.html
+++ b/httemplate/view/cust_statement.html
@@ -4,13 +4,15 @@
% if ( $FS::CurrentUser::CurrentUser->access_right('Resend invoices') ) {
- <A HREF="<% $p %>misc/print-invoice.cgi?<% $link %>">Re-print this statement</A>
+%# <A HREF="<% $p %>misc/print-invoice.cgi?<% $link %>">Re-print this statement</A>
% if ( grep { $_ ne 'POST' } $cust_statement->cust_main->invoicing_list ) {
- | <A HREF="<% $p %>misc/email-invoice.cgi?<% $link %>">Re-email this statement</A>
+%# |
+ <A HREF="<% $p %>misc/email-invoice.cgi?<% $link %>">Re-email this statement</A>
% }
-% if ( $conf->exists('hylafax') && length($cust_statement->cust_main->fax) ) {
+% if ( 0 ) {
+% #if ( $conf->exists('hylafax') && length($cust_statement->cust_main->fax) ) {
| <A HREF="<% $p %>misc/fax-invoice.cgi?<% $link %>">Re-fax this statement</A>
% }
@@ -19,7 +21,8 @@
% }
-% if ( $conf->exists('invoice_latex') ) {
+% #if ( $conf->exists('invoice_latex') ) {
+% if ( 0 ) { #broken???
<A HREF="<% $p %>view/cust_statement-pdf.cgi?<% $link %>.pdf">View typeset statement</A>
<BR><BR>
@@ -47,7 +50,7 @@ die "access denied"
#untaint statement
my($query) = $cgi->keywords;
$query =~ /^((.+)-)?(\d+)$/;
-my $templatename = $2;
+my $templatename = $2 || 'statement'; #XXX configure... via event?? eh..
my $statementnum = $3;
my $conf = new FS::Conf;