email statements, RT#4860
authorivan <ivan>
Thu, 20 Aug 2009 09:47:05 +0000 (09:47 +0000)
committerivan <ivan>
Thu, 20 Aug 2009 09:47:05 +0000 (09:47 +0000)
FS/FS/Cron/bill.pm
FS/FS/Mason.pm
FS/FS/cust_statement.pm
FS/FS/part_event/Action/cust_statement.pm
FS/FS/part_event/Action/cust_statement_send.pm
FS/FS/part_event/Condition/has_pkg_class.pm [new file with mode: 0644]
FS/FS/part_event/Condition/has_pkgpart.pm [new file with mode: 0644]
FS/FS/part_event/Condition/hasnt_pkgpart.pm [new file with mode: 0644]
httemplate/misc/email-statement.cgi [new file with mode: 0755]
httemplate/view/cust_statement-pdf.cgi [new file with mode: 0755]
httemplate/view/cust_statement.html

index 2bdb120..d727d92 100644 (file)
@@ -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
index d73d381..f71db20 100644 (file)
@@ -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%%% ) {
index cd3e7ce..83dd5c1 100644 (file)
@@ -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
index 8d8f127..2d9e877 100644 (file)
@@ -11,8 +11,9 @@ sub description {
 }
 
 sub eventtable_hashref {
-    { 'cust_main' => 1, };
-    { 'cust_pkg'  => 1, };
+  { 'cust_main' => 1,
+    'cust_pkg'  => 1,
+  };
 }
 
 sub default_weight {
index 34f023e..74cc48c 100644 (file)
@@ -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 (file)
index 0000000..59a3675
--- /dev/null
@@ -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 (file)
index 0000000..c54b7e2
--- /dev/null
@@ -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 (file)
index 0000000..421d023
--- /dev/null
@@ -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 (executable)
index 0000000..67f654d
--- /dev/null
@@ -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 (executable)
index 0000000..a1739e0
--- /dev/null
@@ -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>
index ec4ee9e..b078c9d 100755 (executable)
@@ -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;