#21564: user interface for REST client
[freeside.git] / FS / FS / msg_template.pm
index 180e9de..4c2ac4b 100644 (file)
@@ -5,11 +5,13 @@ use strict;
 use vars qw( $DEBUG $conf );
 
 use FS::Conf;
-use FS::Record qw( qsearch qsearchs );
+use FS::Record qw( qsearch qsearchs dbh );
 
 use FS::cust_msg;
 use FS::template_content;
 
+use Date::Format qw(time2str);
+
 FS::UID->install_callback( sub { $conf = new FS::Conf; } );
 
 $DEBUG=0;
@@ -33,6 +35,12 @@ FS::msg_template - Object methods for msg_template records
 
   $error = $record->check;
 
+=head1 NOTE
+
+This uses a table-per-subclass ORM strategy, which is a somewhat cleaner
+version of what we do elsewhere with _option tables. We could easily extract 
+that functionality into a base class, or even into FS::Record itself.
+
 =head1 DESCRIPTION
 
 An FS::msg_template object represents a customer message template.
@@ -79,20 +87,71 @@ points to.  You can ask the object for a copy with the I<hash> method.
 
 sub table { 'msg_template'; }
 
+sub extension_table { ''; } # subclasses don't HAVE to have extensions
+
 sub _rebless {
   my $self = shift;
   my $class = 'FS::msg_template::' . $self->msgclass;
   eval "use $class;";
   bless($self, $class) unless $@;
+
+  # 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
+  if ( $self->msgnum and $self->extension_table ) {
+    my $extension = $self->_extension;
+    if ( $extension ) {
+      my $ext_key = $extension->get($extension->primary_key);
+      $self->{Hash} = { $extension->hash,
+                        $self->hash,
+                        $extension->primary_key => $ext_key
+                      };
+    }
+  }
+
   $self;
 }
 
+# Returns the subclass-specific extension record for this object. For internal
+# use only; everyone else is supposed to think of this as a single record.
+
+sub _extension {
+  my $self = shift;
+  if ( $self->extension_table and $self->msgnum ) {
+    local $FS::Record::nowarn_classload = 1;
+    return qsearchs($self->extension_table, { msgnum => $self->msgnum });
+  }
+  return;
+}
+
 =item insert [ CONTENT ]
 
 Adds this record to the database.  If there is an error, returns the error,
 otherwise returns false.
 
-# inherited
+=cut
+
+sub insert {
+  my $self = shift;
+  $self->_rebless;
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+
+  my $error = $self->SUPER::insert;
+  # calling _extension at this point makes it copy the msgnum, so links work
+  if ( $self->extension_table ) {
+    local $FS::Record::nowarn_classload = 1;
+    my $extension = FS::Record->new($self->extension_table, { $self->hash });
+    $error ||= $extension->insert;
+  }
+
+  if ( $error ) {
+    dbh->rollback if $oldAutoCommit;
+  } else {
+    dbh->commit if $oldAutoCommit;
+  }
+  $error;
+}
 
 =item delete
 
@@ -100,16 +159,58 @@ Delete this record from the database.
 
 =cut
 
-# inherited
+sub delete {
+  my $self = shift;
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+
+  my $error;
+  my $extension = $self->_extension;
+  if ( $extension ) {
+    $error = $extension->delete;
+  }
+
+  $error ||= $self->SUPER::delete;
+
+  if ( $error ) {
+    dbh->rollback if $oldAutoCommit;
+  } else {
+    dbh->commit if $oldAutoCommit;
+  }
+  $error;
+}
 
-=item replace [ OLD_RECORD ] [ CONTENT ]
+=item replace [ OLD_RECORD ]
 
 Replaces the OLD_RECORD with this one in the database.  If there is an error,
 returns the error, otherwise returns false.
 
 =cut
 
-# inherited
+sub replace {
+  my $new = shift;
+  my $old = shift || $new->replace_old;
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+
+  my $error = $new->SUPER::replace($old, @_);
+
+  my $extension = $new->_extension;
+  if ( $extension ) {
+    # merge changes into the extension record and replace it
+    $extension->{Hash} = { $extension->hash, $new->hash };
+    $error ||= $extension->replace;
+  }
+
+  if ( $error ) {
+    dbh->rollback if $oldAutoCommit;
+  } else {
+    dbh->commit if $oldAutoCommit;
+  }
+  $error;
+}
 
 sub replace_check {
   my $self = shift;
@@ -118,7 +219,7 @@ sub replace_check {
   if ( $old->msgclass ) {
     if ( !$self->msgclass ) {
       $self->set('msgclass', $old->msgclass);
-    } else {
+    } elsif ( $old->msgclass ne $self->msgclass ) {
       return "Can't change message template class from ".$old->msgclass.
              " to ".$self->msgclass.".";
     }