default to a session cookie instead of setting an explicit timeout, weird timezone...
[freeside.git] / FS / FS / msg_template.pm
index 4c2ac4b..33e150a 100644 (file)
@@ -11,6 +11,7 @@ use FS::cust_msg;
 use FS::template_content;
 
 use Date::Format qw(time2str);
+use PDF::WebKit;
 
 FS::UID->install_callback( sub { $conf = new FS::Conf; } );
 
@@ -66,7 +67,9 @@ global template.
 
 =item bcc_addr - Bcc all mail to this address.
 
-=item disabled - disabled ('Y' or NULL).
+=item disabled - disabled (NULL for not-disabled and selectable, 'D' for a
+draft of a one-time message, 'C' for a completed one-time message, 'Y' for a
+normal template disabled by user action).
 
 =back
 
@@ -91,9 +94,11 @@ sub extension_table { ''; } # subclasses don't HAVE to have extensions
 
 sub _rebless {
   my $self = shift;
+  return '' unless $self->msgclass;
   my $class = 'FS::msg_template::' . $self->msgclass;
   eval "use $class;";
   bless($self, $class) unless $@;
+  warn "Error loading msg_template msgclass: " . $@ if $@; #or die?
 
   # merge in the extension fields (but let fields in $self override them)
   # except don't ever override the extension's primary key, it's immutable
@@ -246,7 +251,7 @@ sub check {
     || $self->ut_text('msgname')
     || $self->ut_foreign_keyn('agentnum', 'agent', 'agentnum')
     || $self->ut_textn('mime_type')
-    || $self->ut_enum('disabled', [ '', 'Y' ] )
+    || $self->ut_enum('disabled', [ '', 'Y', 'D', 'S' ] )
     || $self->ut_textn('from_addr')
     || $self->ut_textn('bcc_addr')
     # fine for now, but change this to some kind of dynamic check if we
@@ -271,7 +276,7 @@ Options are passed as a list of name/value pairs:
 
 =item cust_main
 
-Customer object (required).
+Customer object
 
 =item object
 
@@ -321,7 +326,7 @@ sub prepare_substitutions {
   my( $self, %opt ) = @_;
 
   my $cust_main = $opt{'cust_main'}; # or die 'cust_main required';
-  my $object = $opt{'object'} or die 'object required';
+  my $object = $opt{'object'}; # or die 'object required';
 
   warn "preparing substitutions for '".$self->msgname."'\n"
     if $DEBUG;
@@ -407,8 +412,6 @@ Options are as for 'prepare', but 'from' and 'to' are meaningless.
 
 sub render {
   my $self = shift;
-  eval "use PDF::WebKit";
-  die $@ if $@;
   my %opt = @_;
   my %hash = $self->prepare(%opt);
   my $html = $hash{'html_body'};
@@ -459,6 +462,17 @@ my $usage_warning = sub {
 # If you add anything, be sure to add a description in 
 # httemplate/edit/msg_template.html.
 sub substitutions {
+  my $payinfo_sub = sub { 
+    my $obj = shift;
+    ($obj->payby eq 'CARD' || $obj->payby eq 'CHEK')
+    ? $obj->paymask 
+    : $obj->decrypt($obj->payinfo)
+  };
+  my $payinfo_end = sub {
+    my $obj = shift;
+    my $payinfo = &$payinfo_sub($obj);
+    substr($payinfo, -4);
+  };
   { 'cust_main' => [qw(
       display_custnum agentnum agent_name
 
@@ -605,11 +619,17 @@ sub substitutions {
       # overrides the one in cust_main in cases where a cust_pay is passed
       [ payby             => sub { FS::payby->shortname(shift->payby) } ],
       [ date              => sub { time2str("%a %B %o, %Y", shift->_date) } ],
-      [ payinfo           => sub { 
-          my $cust_pay = shift;
-          ($cust_pay->payby eq 'CARD' || $cust_pay->payby eq 'CHEK') ?
-            $cust_pay->paymask : $cust_pay->decrypt($cust_pay->payinfo)
-        } ],
+      [ 'payinfo' => $payinfo_sub ],
+      [ 'payinfo_end' => $payinfo_end ],
+    ],
+    # for refund receipts
+    'cust_refund' => [
+      'refundnum',
+      [ refund            => sub { sprintf("%.2f", shift->refund) } ],
+      [ payby             => sub { FS::payby->shortname(shift->payby) } ],
+      [ date              => sub { time2str("%a %B %o, %Y", shift->_date) } ],
+      [ 'payinfo' => $payinfo_sub ],
+      [ 'payinfo_end' => $payinfo_end ],
     ],
     # for payment decline messages
     # try to support all cust_pay fields
@@ -621,11 +641,8 @@ sub substitutions {
       [ paid              => sub { sprintf("%.2f", shift->paid) } ],
       [ payby             => sub { FS::payby->shortname(shift->payby) } ],
       [ date              => sub { time2str("%a %B %o, %Y", shift->_date) } ],
-      [ payinfo           => sub {
-          my $pending = shift;
-          ($pending->payby eq 'CARD' || $pending->payby eq 'CHEK') ?
-            $pending->paymask : $pending->decrypt($pending->payinfo)
-        } ],
+      [ 'payinfo' => $payinfo_sub ],
+      [ 'payinfo_end' => $payinfo_end ],
     ],
   };
 }
@@ -657,20 +674,22 @@ sub _upgrade_data {
     [ 'decline_msgnum',  'declinetemplate',    '',               '', '' ],
     [ 'impending_recur_msgnum', 'impending_recur_template', '',  '', 'impending_recur_bcc' ],
     [ 'payment_receipt_msgnum', 'payment_receipt_email', '',     '', '' ],
-    [ 'welcome_msgnum',  'welcome_email',      'welcome_email-subject', 'welcome_email-from', '' ],
-    [ 'warning_msgnum',  'warning_email',      'warning_email-subject', 'warning_email-from', '' ],
+    [ 'welcome_msgnum',  'welcome_email',      'welcome_email-subject', 'welcome_email-from', '', 'welcome_email-mimetype' ],
+    [ 'threshold_warning_msgnum',  'warning_email',      'warning_email-subject', 'warning_email-from', 'warning_email-cc', 'warning_email-mimetype' ],
   );
  
   my @agentnums = ('', map {$_->agentnum} qsearch('agent', {}));
   foreach my $agentnum (@agentnums) {
     foreach (@fixes) {
-      my ($newname, $oldname, $subject, $from, $bcc) = @$_;
+      my ($newname, $oldname, $subject, $from, $bcc, $mimetype) = @$_;
+      
       if ($conf->exists($oldname, $agentnum)) {
         my $new = new FS::msg_template({
+          'msgclass'  => 'email',
           'msgname'   => $oldname,
           'agentnum'  => $agentnum,
           'from_addr' => ($from && $conf->config($from, $agentnum)) || '',
-          'bcc_addr'  => ($bcc && $conf->config($from, $agentnum)) || '',
+          'bcc_addr'  => ($bcc && $conf->config($bcc, $agentnum)) || '',
           'subject'   => ($subject && $conf->config($subject, $agentnum)) || '',
           'mime_type' => 'text/html',
           'body'      => join('<BR>',$conf->config($oldname, $agentnum)),
@@ -681,6 +700,8 @@ sub _upgrade_data {
         $conf->delete($oldname, $agentnum);
         $conf->delete($from, $agentnum) if $from;
         $conf->delete($subject, $agentnum) if $subject;
+        $conf->delete($bcc, $agentnum) if $bcc;
+        $conf->delete($mimetype, $agentnum) if $mimetype;
       }
     }
 
@@ -782,6 +803,78 @@ sub _upgrade_data {
   ###
   $self->_populate_initial_data;
 
+  ###
+  # Move welcome_msgnum to an export
+  ###
+
+  #upgrade_journal loaded by _populate_initial_data
+  unless (FS::upgrade_journal->is_done('msg_template__welcome_export')) {
+    if (my $msgnum = $conf->config('welcome_msgnum')) {
+      eval "use FS::part_export;";
+      die $@ if $@;
+      eval "use FS::part_svc;";
+      die $@ if $@;
+      eval "use FS::export_svc;";
+      die $@ if $@;
+      #create the export
+      my $part_export = new FS::part_export {
+        'exportname' => 'Welcome Email',
+        'exporttype' => 'send_email'
+      };
+      my $error = $part_export->insert({
+        'to_customer' => 1,
+        'insert_template' => $msgnum,
+        # replicate blank options that would be generated by UI,
+        # to avoid unexpected results from not having them exist
+        'to_address'  => '',
+        'replace_template' => 0,
+        'suspend_template' => 0,
+        'unsuspend_template' => 0,
+        'delete_template' => 0,
+      });
+      die $error if $error;
+      #attach it to part_svcs
+      my @welcome_exclude_svcparts = $conf->config('svc_acct_welcome_exclude');
+      foreach my $part_svc (
+        qsearch('part_svc',{ 'svcdb' => 'svc_acct', 'disabled' => '' })
+      ) {
+        next if grep { $_ eq $part_svc->svcpart } @welcome_exclude_svcparts;
+        my $export_svc = new FS::export_svc {
+          'exportnum' => $part_export->exportnum,
+          'svcpart'   => $part_svc->svcpart,
+        };
+        $error = $export_svc->insert;
+        die $error if $error;
+      }
+      #remove the old confs
+      $error = $conf->delete('welcome_msgnum');
+      die $error if $error;
+      $error = $conf->delete('svc_acct_welcome_exclude');
+      die $error if $error;
+    }
+    FS::upgrade_journal->set_done('msg_template__welcome_export');
+  }
+
+
+  ### Fix dump-email_to (needs to happen after _populate_initial_data)
+  if ($conf->config('dump-email_to')) {
+    # anyone who still uses dump-email_to should have just had this created
+    my ($msg_template) = qsearch('msg_template',{ msgname => 'System log' });
+    if ($msg_template) {
+      eval "use FS::log_email;";
+      die $@ if $@;
+      my $log_email = new FS::log_email {
+        'context' => 'Cron::backup',
+        'min_level' => 1,
+        'msgnum' => $msg_template->msgnum,
+        'to_addr' => $conf->config('dump-email_to'),
+      };
+      my $error = $log_email->insert;
+      die $error if $error;
+      $conf->delete('dump-email_to');
+    }
+  }
+
 }
 
 sub _populate_initial_data { #class method
@@ -790,18 +883,22 @@ sub _populate_initial_data { #class method
 
   eval "use FS::msg_template::InitialData;";
   die $@ if $@;
+  eval "use FS::upgrade_journal;";
+  die $@ if $@;
 
   my $initial_data = FS::msg_template::InitialData->_initial_data;
 
   foreach my $hash ( @$initial_data ) {
 
     next if $hash->{_conf} && $conf->config( $hash->{_conf} );
+    next if $hash->{_upgrade_journal} && FS::upgrade_journal->is_done( $hash->{_upgrade_journal} );
 
     my $msg_template = new FS::msg_template($hash);
     my $error = $msg_template->insert( @{ $hash->{_insert_args} || [] } );
     die $error if $error;
 
     $conf->set( $hash->{_conf}, $msg_template->msgnum ) if $hash->{_conf};
+    FS::upgrade_journal->set_done( $hash->{_upgrade_journal} ) if $hash->{_upgrade_journal};
   
   }