add per-agent invoice templates, add per-package suspend invoice events, fix automati...
authorivan <ivan>
Fri, 14 May 2004 12:25:45 +0000 (12:25 +0000)
committerivan <ivan>
Fri, 14 May 2004 12:25:45 +0000 (12:25 +0000)
FS/FS/Conf.pm
FS/FS/cust_bill.pm
FS/FS/cust_main.pm
FS/FS/part_bill_event.pm
httemplate/edit/part_bill_event.cgi
httemplate/edit/process/part_bill_event.cgi

index 3cddc20..e69a156 100644 (file)
@@ -108,6 +108,22 @@ sub exists {
   -e "$dir/$file";
 }
 
+=item config_orbase KEY SUFFIX
+
+Returns the configuration value or values (depending on context) for 
+KEY_SUFFIX, if it exists, otherwise for KEY
+
+=cut
+
+sub config_orbase {
+  my( $self, $file, $suffix ) = @_;
+  if ( $self->exists("${file}_$suffix") ) {
+    $self->config("${file}_$suffix");
+  } else {
+    $self->config($file);
+  }
+}
+
 =item touch KEY
 
 Creates the specified configuration key if it does not exist.
@@ -197,6 +213,18 @@ sub config_items {
                            'type'        => 'textarea',
                          }
       } glob($self->dir. '/invoice_latex_*')
+  ),
+  ( map { 
+        my $basename = basename($_);
+        $basename =~ /^(.*)$/;
+        $basename = $1;
+        new FS::ConfItem {
+                           'key'         => $basename,
+                           'section'     => 'billing',
+                           'description' => 'Alternate Notes section for LaTeX typeset PostScript invoices.  See the <a href="../docs/billing.html">billing documentation</a> for details.',
+                           'type'        => 'textarea',
+                         }
+      } glob($self->dir. '/invoice_latexnotes_*')
   );
 }
 
index 7e2c8fb..367e1bc 100644 (file)
@@ -316,15 +316,23 @@ sub owed {
   $balance;
 }
 
-=item send
+=item send [ TEMPLATENAME [ , AGENTNUM ] ]
 
 Sends this invoice to the destinations configured for this customer: send
 emails or print.  See L<FS::cust_main_invoice>.
 
+TEMPLATENAME, if specified, is the name of a suffix for alternate invoices.
+
+AGENTNUM, if specified, means that this invoice will only be sent for customers
+of the specified agent.
+
 =cut
 
 sub send {
-  my($self,$template) = @_;
+  my $self = shift;
+  my $template = scalar(@_) ? shift : '';
+  return '' if scalar(@_) && $_[0] && $self->cust_main->agentnum ne shift;
+
   my @print_text = $self->print_text('', $template);
   my @invoicing_list = $self->cust_main->invoicing_list;
 
@@ -654,6 +662,31 @@ sub batch_card {
   '';
 }
 
+sub _agent_template {
+  my $self = shift;
+
+  my $cust_bill_event = qsearchs( 'part_bill_event',
+    {
+      'payby'     => $self->cust_main->payby,
+      'plan'      => 'send_agent',
+      'eventcode' => { 'op'    => 'LIKE',
+                       'value' => '_%, '. $self->cust_main->agentnum. ');' },
+    },
+    '',
+    'ORDER BY seconds LIMIT 1'
+  );
+
+  return '' unless $cust_bill_event;
+
+  if ( $cust_bill_event->eventcode =~ /\(\s*'(.*)'\s*,\s*(\d+)\s*\)\;$/ ) {
+    return $1;
+  } else {
+    warn "can't parse eventcode for agent-specific invoice template";
+    return '';
+  }
+
+}
+
 =item print_text [ TIME [ , TEMPLATE ] ]
 
 Returns an text invoice, as a list of lines.
@@ -798,10 +831,11 @@ sub print_text {
     sprintf("%10.2f", $balance_due ) ];
 
   #create the template
+  $template ||= $self->_agent_template;
   my $templatefile = 'invoice_template';
-  $templatefile .= "_$template" if $template;
+  $templatefile .= "_$template" if length($template);
   my @invoice_template = $conf->config($templatefile)
-  or die "cannot load config file $templatefile";
+    or die "cannot load config file $templatefile";
   $invoice_lines = 0;
   my $wasfunc = 0;
   foreach ( grep /invoice_lines\(\d*\)/, @invoice_template ) { #kludgy
@@ -923,8 +957,10 @@ sub print_latex {
   @buf = ();
 
   #create the template
+  $template ||= $self->_agent_template;
   my $templatefile = 'invoice_latex';
-  $templatefile .= "_$template" if $template;
+  my $suffix = length($template) ? "_$template" : '';
+  $templatefile .= $suffix;
   my @invoice_template = $conf->config($templatefile)
     or die "cannot load config file $templatefile";
 
@@ -954,7 +990,7 @@ sub print_latex {
   $invoice_data{'notes'} =
     join("\n",
       map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b }
-        $conf->config('invoice_latexnotes')
+        $conf->config_orbase('invoice_latexnotes', $suffix)
     );
 
   $invoice_data{'footer'} =~ s/\n+$//;
@@ -1396,9 +1432,6 @@ The delete method.
 print_text formatting (and some logic :/) is in source, but needs to be
 slurped in from a file.  Also number of lines ($=).
 
-missing print_ps for a nice postscript copy (maybe HylaFAX-cover-page-style
-or something similar so the look can be completely customized?)
-
 =head1 SEE ALSO
 
 L<FS::Record>, L<FS::cust_main>, L<FS::cust_bill_pay>, L<FS::cust_pay>,
index f275d10..fbd4618 100644 (file)
@@ -1028,6 +1028,38 @@ sub suspend {
   grep { $_->suspend } $self->unsuspended_pkgs;
 }
 
+=item suspend_if_pkgpart PKGPART [ , PKGPART ... ]
+
+Suspends all unsuspended packages (see L<FS::cust_pkg>) matching the listed
+PKGPARTs (see L<FS::part_pkg>).  Always returns a list: an empty list on
+success or a list of errors.
+
+=cut
+
+sub suspend_if_pkgpart {
+  my $self = shift;
+  my @pkgparts = @_;
+  grep { $_->suspend }
+    grep { my $pkgpart = $_->pkgpart; grep { $pkgpart eq $_ } @pkgparts }
+      $self->unsuspended_pkgs;
+}
+
+=item suspend_unless_pkgpart PKGPART [ , PKGPART ... ]
+
+Suspends all unsuspended packages (see L<FS::cust_pkg>) unless they match the
+listed PKGPARTs (see L<FS::part_pkg>).  Always returns a list: an empty list
+on success or a list of errors.
+
+=cut
+
+sub suspend_unless_pkgpart {
+  my $self = shift;
+  my @pkgparts = @_;
+  grep { $_->suspend }
+    grep { my $pkgpart = $_->pkgpart; ! grep { $pkgpart eq $_ } @pkgparts }
+      $self->unsuspended_pkgs;
+}
+
 =item cancel [ OPTION => VALUE ... ]
 
 Cancels all uncancelled packages (see L<FS::cust_pkg>) for this customer.
index 86f9294..4774b8d 100644 (file)
@@ -149,22 +149,20 @@ sub check {
     || $self->ut_textn('plan')
     || $self->ut_anything('plandata')
   ;
+    #|| $self->ut_snumber('seconds')
   return $error if $error;
 
   #quelle kludge
-  if ( $self->plandata =~ /^templatename\s+(.*)$/ ) {
-    my $name= $1;
-    unless ( $conf->exists("invoice_template_$name") ) {
-      $conf->set(
-        "invoice_template_$name" =>
-          join("\n", $conf->config('invoice_template') )
-      );
-    }
-    unless ( $conf->exists("invoice_latex_$name") ) {
-      $conf->set(
-        "invoice_latex_$name" =>
-          join("\n", $conf->config('invoice_latex') )
-      );
+  if ( $self->plandata =~ /^(agent_)?templatename\s+(.*)$/m ) {
+    my $name= $2;
+
+    foreach my $file (qw( template latex latexnotes )) {
+      unless ( $conf->exists("invoice_${file}_$name") ) {
+        $conf->set(
+          "invoice_${file}_$name" =>
+            join("\n", $conf->config("invoice_$file") )
+        );
+      }
     }
   }
 
index 48ed791..d0fa973 100755 (executable)
@@ -68,6 +68,31 @@ print '<TR><TD ALIGN="right">Action</TD><TD>';
 
 #print ntable();
 
+sub select_pkgpart {
+  my $label = shift;
+  my $plandata = shift;
+  my %selected = map { $_=>1 } split(/,\s*/, $plandata->{$label});
+  qq(<SELECT NAME="$label" MULTIPLE>).
+  join("\n", map {
+    '<OPTION VALUE="'. $_->pkgpart. '"'.
+    ( $selected{$_->pkgpart} ? ' SELECTED' : '' ).
+    '>'. $_->pkg. ' - '. $_->comment
+  } qsearch('part_pkg', { 'disabled' => '' } ) ).
+  '</SELECT>';
+}
+
+sub select_agentnum {
+  my $plandata = shift;
+  my $agentnum = $plandata->{'agentnum'};
+  '<SELECT NAME="agentnum">'.
+  join("\n", map {
+    '<OPTION VALUE="'. $_->agentnum. '"'.
+    ( $_->agentnum == $agentnum ? ' SELECTED' : '' ).
+    '>'. $_->agent
+  } qsearch('agent', { 'disabled' => '' } ) ).
+  '</SELECT>';
+}
+
 #this is pretty kludgy right here.
 tie my %events, 'Tie::IxHash',
 
@@ -84,6 +109,18 @@ tie my %events, 'Tie::IxHash',
     'code'   => '$cust_main->suspend();',
     'weight' => 10,
   },
+  'suspend-if-pkgpart' => {
+    'name'   => 'Suspend packages',
+    'code'   => '$cust_main->suspend_if_pkgpart(%%%if_pkgpart%%%);',
+    'html'   => sub { &select_pkgpart('if_pkgpart', @_) },
+    'weight' => 10,
+  },
+  'suspend-unless-pkgpart' => {
+    'name'   => 'Suspend packages except',
+    'code'   => '$cust_main->suspend_unless_pkgpart(%%%unless_pkgpart%%%);',
+    'html'   => sub { &select_pkgpart('unless_pkgpart', @_) },
+    'weight' => 10,
+  },
   'cancel' => {
     'name'   => 'Cancel',
     'code'   => '$cust_main->cancel();',
@@ -140,6 +177,26 @@ tie my %events, 'Tie::IxHash',
     'weight' => 50,
   },
 
+  'send_agent' => {
+    'name' => 'Send invoice (email/print) ',
+    'code' => '$cust_bill->send(\'%%%agent_templatename%%%\', %%%agentnum%%%);',
+    'html' => sub {
+        '<TABLE BORDER=0>
+          <TR>
+            <TD ALIGN="right">only for agent </TD>
+            <TD>'. &select_agentnum(@_). '</TD>
+          </TR>
+          <TR>
+            <TD ALIGN="right">with template </TD>
+            <TD>
+              <INPUT TYPE="text" NAME="agent_templatename" VALUE="%%%agent_templatename%%%">
+            </TD>
+          </TR>
+        </TABLE>';
+    },
+    'weight' => 50,
+  },
+
   'send_csv_ftp' => {
     'name' => 'Upload CSV invoice data to an FTP server',
     'code' => '$cust_bill->send_csv( protocol => \'ftp\',
@@ -188,6 +245,9 @@ foreach my $event ( keys %events ) {
   my %plandata = map { /^(\w+) (.*)$/; ($1, $2); }
                    split(/\n/, $part_bill_event->plandata);
   my $html = $events{$event}{html};
+  if ( ref($html) eq 'CODE' ) {
+    $html = &{$html}(\%plandata);
+  }
   while ( $html =~ /%%%(\w+)%%%/ ) {
     my $field = $1;
     $html =~ s/%%%$field%%%/$plandata{$field}/;
index e224bf6..77dcd24 100755 (executable)
@@ -5,7 +5,7 @@ my $eventpart = $cgi->param('eventpart');
 my $old = qsearchs('part_bill_event',{'eventpart'=>$eventpart}) if $eventpart;
 
 #s/days/seconds/
-$cgi->param('seconds', $cgi->param('days') * 86400 );
+$cgi->param('seconds', int( $cgi->param('days') * 86400 ) );
 
 my $error;
 if ( ! $cgi->param('plan_weight_eventcode') ) {
@@ -21,7 +21,8 @@ if ( ! $cgi->param('plan_weight_eventcode') ) {
   my $plandata = '';
   while ( $eventcode =~ /%%%(\w+)%%%/ ) {
     my $field = $1;
-    my $value = $cgi->param($field);
+    my $value = join(', ', $cgi->param($field) );
+    $cgi->param($field, $value); #in case it errors out
     $eventcode =~ s/%%%$field%%%/$value/;
     $plandata .= "$field $value\n";
   }