[freeside-commits] branch master updated. e9e0cf0989259b94d9758eceff448666a2e5a5cc

Ivan ivan at 420.am
Thu Mar 6 15:20:53 PST 2014


The branch, master has been updated
       via  e9e0cf0989259b94d9758eceff448666a2e5a5cc (commit)
       via  c7bc6770f2f0b4413b788f8fc9abde6ad5548da3 (commit)
       via  77b23be67a840dae149a9e82613248b5f048cedd (commit)
       via  0d991a8c986099180aaf2843a928e9396ff232db (commit)
       via  9ac90646828dd34b49fc2474c9666ba33c3508a4 (commit)
       via  aa302b14cbe21ca99b70d9d13d75dbd3fb72d038 (commit)
       via  43839f03bf937eb086c7f2a55c059a606571ab77 (commit)
       via  afe30fc7315196cc4ae6da7606995cb8388d1a32 (commit)
       via  daa3524d4f512f2bf671c6b07c606ba3eec1fefc (commit)
       via  73e20a91b38b27ad5be79306ba25bdfb5a1252e1 (commit)
       via  79981f908752492b00cb4bdce3dceb0636fb81dd (commit)
       via  128443531fae5fced8a8d2adbcaf6cb945218e3d (commit)
       via  23b5c810efb0975fb4a06142674aa27eabd5e689 (commit)
      from  d535b964454fbccc5ccf44a92a6cd8d8405cc549 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit e9e0cf0989259b94d9758eceff448666a2e5a5cc
Merge: d535b96 c7bc677
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Thu Mar 6 15:19:53 2014 -0800

    Merge branch 'master' of https://github.com/jgoodman/Freeside
    (github pull request #24 -- change refunds to proper refunds)


commit c7bc6770f2f0b4413b788f8fc9abde6ad5548da3
Author: Joshua Goodman <jgoodman1990 at gmail.com>
Date:   Thu Mar 6 23:02:59 2014 +0000

    Adding line 246 "edit global pockage definitions costs" back in

diff --git a/FS/FS/access_right.pm b/FS/FS/access_right.pm
index 9ec7ab9..d26db48 100644
--- a/FS/FS/access_right.pm
+++ b/FS/FS/access_right.pm
@@ -243,6 +243,7 @@ sub _upgrade_data { # class method
     'Configuration' => 'Alarm global configuration',
     'Services: Accounts' => 'Services: Conferencing',
     'Services: Accounts' => 'Services: Video',
+    'Edit global package definitions' => 'Edit package definition costs',
     'Add on-the-fly credit reason' => 'Add on-the-fly refund reason',
   );
 

commit 77b23be67a840dae149a9e82613248b5f048cedd
Author: Joshua Goodman <jgoodman1990 at gmail.com>
Date:   Thu Mar 6 22:48:43 2014 +0000

    removed activate, renewal, term change

diff --git a/FS/FS/reason_type.pm b/FS/FS/reason_type.pm
index d66f7b5..00ac9a8 100644
--- a/FS/FS/reason_type.pm
+++ b/FS/FS/reason_type.pm
@@ -10,9 +10,6 @@ our %class_name = (
   'C' => 'cancel',
   'R' => 'credit',
   'S' => 'suspend',
-  'U' => 'activate', #uncancel/unsuspend
-  'W' => 'renewal',
-  'T' => 'term change',
   'F' => 'refund',
 );
 
@@ -20,9 +17,6 @@ our %class_purpose = (
   'C' => 'explain why a customer package was cancelled',
   'R' => 'explain why a customer was credited',
   'S' => 'explain why a customer package was suspended',
-  'U' => 'explain why a customer package was unsuspended/uncanceled/activated',
-  'W' => 'explain why a customer package was renewed',
-  'T' => 'explain why a customer package term was changed',
   'F' => 'explain why a customer was refunded',
 );
 

commit 0d991a8c986099180aaf2843a928e9396ff232db
Author: Joshua Goodman <jgoodman1990 at gmail.com>
Date:   Thu Mar 6 22:45:53 2014 +0000

    modified _upgrade to grant "Add on-the-fly refund reason" to groups with "Add on-the-fly credit reason"

diff --git a/FS/FS/access_right.pm b/FS/FS/access_right.pm
index 0906c0c..9ec7ab9 100644
--- a/FS/FS/access_right.pm
+++ b/FS/FS/access_right.pm
@@ -243,7 +243,7 @@ sub _upgrade_data { # class method
     'Configuration' => 'Alarm global configuration',
     'Services: Accounts' => 'Services: Conferencing',
     'Services: Accounts' => 'Services: Video',
-    'Edit global package definitions' => 'Edit package definition costs',
+    'Add on-the-fly credit reason' => 'Add on-the-fly refund reason',
   );
 
 #  foreach my $old_acl ( keys %onetime ) {

commit 9ac90646828dd34b49fc2474c9666ba33c3508a4
Author: Joshua Goodman <jgoodman1990 at gmail.com>
Date:   Thu Mar 6 22:44:01 2014 +0000

    refactored reason and _upgrade method to inherit methods from reason_Mixin.pm

diff --git a/FS/FS/cust_credit.pm b/FS/FS/cust_credit.pm
index 7ae6c97..567be21 100644
--- a/FS/FS/cust_credit.pm
+++ b/FS/FS/cust_credit.pm
@@ -1,5 +1,6 @@
 package FS::cust_credit;
-use base qw( FS::otaker_Mixin FS::cust_main_Mixin FS::Record );
+use base qw( FS::otaker_Mixin FS::cust_main_Mixin FS::reason_Mixin
+             FS::Record );
 
 use strict;
 use vars qw( $conf $unsuspendauto $me $DEBUG
@@ -447,57 +448,8 @@ sub credited {
 
 Returns the customer (see L<FS::cust_main>) for this credit.
 
-=item reason
-
-Returns the text of the associated reason (see L<FS::reason>) for this credit.
-
 =cut
 
-sub reason {
-  my ($self, $value, %options) = @_;
-  my $dbh = dbh;
-  my $reason;
-  my $typenum = $options{'reason_type'};
-
-  my $oldAutoCommit = $FS::UID::AutoCommit;  # this should already be in
-  local $FS::UID::AutoCommit = 0;            # a transaction if it matters
-
-  if ( defined( $value ) ) {
-    my $hashref = { 'reason' => $value };
-    $hashref->{'reason_type'} = $typenum if $typenum;
-    my $addl_from = "LEFT JOIN reason_type ON ( reason_type = typenum ) ";
-    my $extra_sql = " AND reason_type.class='R'"; 
-
-    $reason = qsearchs( { 'table'     => 'reason',
-                          'hashref'   => $hashref,
-                          'addl_from' => $addl_from,
-                          'extra_sql' => $extra_sql,
-                       } );
-
-    if (!$reason && $typenum) {
-      $reason = new FS::reason( { 'reason_type' => $typenum,
-                                  'reason' => $value,
-                                  'disabled' => 'Y', 
-                              } );
-      my $error = $reason->insert;
-      if ( $error ) {
-        warn "error inserting reason: $error\n";
-        $reason = undef;
-      }
-    }
-
-    $self->reasonnum($reason ? $reason->reasonnum : '') ;
-    warn "$me reason used in set mode with non-existant reason -- clearing"
-      unless $reason;
-  }
-  $reason = qsearchs( 'reason', { 'reasonnum' => $self->reasonnum } );
-
-  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
-
-  ( $reason ? $reason->reason : '' ).
-  ( $self->addlinfo ? ' '.$self->addlinfo : '' );
-}
-
 # _upgrade_data
 #
 # Used by FS::Upgrade to migrate to a new database.
@@ -507,56 +459,9 @@ sub _upgrade_data {  # class method
 
   warn "$me upgrading $class\n" if $DEBUG;
 
-  if (defined dbdef->table($class->table)->column('reason')) {
-
-    warn "$me Checking for unmigrated reasons\n" if $DEBUG;
-
-    my @cust_credits = qsearch({ 'table'     => $class->table,
-                                 'hashref'   => {},
-                                 'extra_sql' => 'WHERE reason IS NOT NULL',
-                              });
-
-    if (scalar(grep { $_->getfield('reason') =~ /\S/ } @cust_credits)) {
-      warn "$me Found unmigrated reasons\n" if $DEBUG;
-      my $hashref = { 'class' => 'R', 'type' => 'Legacy' };
-      my $reason_type = qsearchs( 'reason_type', $hashref );
-      unless ($reason_type) {
-        $reason_type  = new FS::reason_type( $hashref );
-        my $error   = $reason_type->insert();
-        die "$class had error inserting FS::reason_type into database: $error\n"
-          if $error;
-      }
+  $class->_upgrade_reasonnum(%opts);
 
-      $hashref = { 'reason_type' => $reason_type->typenum,
-                   'reason' => '(none)'
-                 };
-      my $noreason = qsearchs( 'reason', $hashref );
-      unless ($noreason) {
-        $hashref->{'disabled'} = 'Y';
-        $noreason = new FS::reason( $hashref );
-        my $error  = $noreason->insert();
-        die "can't insert legacy reason '(none)' into database: $error\n"
-          if $error;
-      }
-
-      foreach my $cust_credit ( @cust_credits ) {
-        my $reason = $cust_credit->getfield('reason');
-        warn "Contemplating reason $reason\n" if $DEBUG > 1;
-        if ($reason =~ /\S/) {
-          $cust_credit->reason($reason, 'reason_type' => $reason_type->typenum)
-            or die "can't insert legacy reason $reason into database\n";
-        }else{
-          $cust_credit->reasonnum($noreason->reasonnum);
-        }
-
-        $cust_credit->setfield('reason', '');
-        my $error = $cust_credit->replace;
-
-        warn "*** WARNING: error replacing reason in $class ".
-             $cust_credit->crednum. ": $error ***\n"
-          if $error;
-      }
-    }
+  if (defined dbdef->table($class->table)->column('reason')) {
 
     warn "$me Ensuring existance of auto reasons\n" if $DEBUG;
 
diff --git a/FS/FS/cust_refund.pm b/FS/FS/cust_refund.pm
index 097ed2d..e3fc910 100644
--- a/FS/FS/cust_refund.pm
+++ b/FS/FS/cust_refund.pm
@@ -2,7 +2,7 @@ package FS::cust_refund;
 
 use strict;
 use base qw( FS::otaker_Mixin FS::payinfo_transaction_Mixin FS::cust_main_Mixin
-             FS::Record );
+             FS::reason_Mixin FS::Record );
 use vars qw( @encrypted_fields $me $DEBUG $ignore_empty_reasonnum );
 use Business::CreditCard;
 use FS::Record qw( qsearch qsearchs dbh dbdef );
@@ -406,114 +406,10 @@ sub unapplied_sql {
 
 }
 
-=item reason
-
-Returns the text of the associated reason (see L<FS::reason>) for this credit.
-
-=cut
-
-sub reason {
-  my ($self, $value, %options) = @_;
-  my $dbh = dbh;
-  my $reason;
-  my $typenum = $options{'reason_type'};
-
-  my $oldAutoCommit = $FS::UID::AutoCommit;  # this should already be in
-  local $FS::UID::AutoCommit = 0;            # a transaction if it matters
-
-  if ( defined( $value ) ) {
-    my $hashref = { 'reason' => $value };
-    $hashref->{'reason_type'} = $typenum if $typenum;
-    my $addl_from = "LEFT JOIN reason_type ON ( reason_type = typenum ) ";
-    my $extra_sql = " AND reason_type.class='F'";
-
-    $reason = qsearchs( { 'table'     => 'reason',
-                          'hashref'   => $hashref,
-                          'addl_from' => $addl_from,
-                          'extra_sql' => $extra_sql,
-                       } );
-
-    if (!$reason && $typenum) {
-      $reason = new FS::reason( { 'reason_type' => $typenum,
-                                  'reason' => $value,
-                                  'disabled' => 'Y',
-                              } );
-      my $error = $reason->insert;
-      if ( $error ) {
-        warn "error inserting reason: $error\n";
-        $reason = undef;
-      }
-    }
-
-    $self->reasonnum($reason ? $reason->reasonnum : '') ;
-    warn "$me reason used in set mode with non-existant reason -- clearing"
-      unless $reason;
-  }
-  $reason = qsearchs( 'reason', { 'reasonnum' => $self->reasonnum } );
-
-  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
-
-  ( $reason ? $reason->reason : '' ).
-  ( $self->addlinfo ? ' '.$self->addlinfo : '' );
-}
-
 # Used by FS::Upgrade to migrate to a new database.
 sub _upgrade_data {  # class method
   my ($class, %opts) = @_;
-
-  warn "$me upgrading $class\n" if $DEBUG;
-
-  if (defined dbdef->table($class->table)->column('reason')) {
-
-    warn "$me Checking for unmigrated reasons\n" if $DEBUG;
-
-    my @cust_refunds = qsearch({ 'table'     => $class->table,
-                                 'hashref'   => {},
-                                 'extra_sql' => 'WHERE reason IS NOT NULL',
-                              });
-
-    if (scalar(grep { $_->getfield('reason') =~ /\S/ } @cust_refunds)) {
-      warn "$me Found unmigrated reasons\n" if $DEBUG;
-      my $hashref = { 'class' => 'F', 'type' => 'Legacy' };
-      my $reason_type = qsearchs( 'reason_type', $hashref );
-      unless ($reason_type) {
-        $reason_type  = new FS::reason_type( $hashref );
-        my $error   = $reason_type->insert();
-        die "$class had error inserting FS::reason_type into database: $error\n"
-          if $error;
-      }
-
-      $hashref = { 'reason_type' => $reason_type->typenum,
-                   'reason' => '(none)'
-                 };
-      my $noreason = qsearchs( 'reason', $hashref );
-      unless ($noreason) {
-        $hashref->{'disabled'} = 'Y';
-        $noreason = new FS::reason( $hashref );
-        my $error  = $noreason->insert();
-        die "can't insert legacy reason '(none)' into database: $error\n"
-          if $error;
-      }
-
-      foreach my $cust_refund ( @cust_refunds ) {
-        my $reason = $cust_refund->getfield('reason');
-        warn "Contemplating reason $reason\n" if $DEBUG > 1;
-        if ($reason =~ /\S/) {
-          $cust_refund->reason($reason, 'reason_type' => $reason_type->typenum)
-            or die "can't insert legacy reason $reason into database\n";
-        }else{
-          $cust_refund->reasonnum($noreason->reasonnum);
-        }
-
-        $cust_refund->setfield('reason', '');
-        my $error = $cust_refund->replace;
-
-        warn "*** WARNING: error replacing reason in $class ".
-             $cust_refund->refundnum. ": $error ***\n"
-          if $error;
-      }
-    }
-  }
+  $class->_upgrade_reasonnum(%opts);
   $class->_upgrade_otaker(%opts);
 }
 

commit aa302b14cbe21ca99b70d9d13d75dbd3fb72d038
Author: Joshua Goodman <jgoodman1990 at gmail.com>
Date:   Thu Mar 6 22:42:55 2014 +0000

    Created reason_Mixin.pm module to refactor the reason method and code inside the _upgrade method in cust_credit.pm and cust_refund.pm

diff --git a/FS/FS/reason_Mixin.pm b/FS/FS/reason_Mixin.pm
new file mode 100644
index 0000000..fdf7962
--- /dev/null
+++ b/FS/FS/reason_Mixin.pm
@@ -0,0 +1,121 @@
+package FS::reason_Mixin;
+
+use strict;
+use Carp qw( croak ); #confess );
+use FS::Record qw( qsearch qsearchs dbdef );
+use FS::access_user;
+use FS::UID qw( dbh );
+
+our $DEBUG = 0;
+our $me = '[FS::reason_Mixin]';
+
+=item reason
+
+Returns the text of the associated reason (see L<FS::reason>) for this credit.
+
+=cut
+
+sub reason {
+  my ($self, $value, %options) = @_;
+  my $dbh = dbh;
+  my $reason;
+  my $typenum = $options{'reason_type'};
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;  # this should already be in
+  local $FS::UID::AutoCommit = 0;            # a transaction if it matters
+
+  if ( defined( $value ) ) {
+    my $hashref = { 'reason' => $value };
+    $hashref->{'reason_type'} = $typenum if $typenum;
+    my $addl_from = "LEFT JOIN reason_type ON ( reason_type = typenum ) ";
+    my $extra_sql = " AND reason_type.class='F'";
+
+    $reason = qsearchs( { 'table'     => 'reason',
+                          'hashref'   => $hashref,
+                          'addl_from' => $addl_from,
+                          'extra_sql' => $extra_sql,
+                       } );
+
+    if (!$reason && $typenum) {
+      $reason = new FS::reason( { 'reason_type' => $typenum,
+                                  'reason' => $value,
+                                  'disabled' => 'Y',
+                              } );
+      my $error = $reason->insert;
+      if ( $error ) {
+        warn "error inserting reason: $error\n";
+        $reason = undef;
+      }
+    }
+
+    $self->reasonnum($reason ? $reason->reasonnum : '') ;
+    warn "$me reason used in set mode with non-existant reason -- clearing"
+      unless $reason;
+  }
+  $reason = qsearchs( 'reason', { 'reasonnum' => $self->reasonnum } );
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+  ( $reason ? $reason->reason : '' ).
+  ( $self->addlinfo ? ' '.$self->addlinfo : '' );
+}
+
+# Used by FS::Upgrade to migrate reason text fields to reasonnum.
+sub _upgrade_reasonnum {  # class method
+  my $class = shift;
+  my $table = $class->table;
+
+  if (defined dbdef->table($table)->column('reason')) {
+
+    warn "$me Checking for unmigrated reasons\n" if $DEBUG;
+
+    my @cust_refunds = qsearch({ 'table'     => $table,
+                                 'hashref'   => {},
+                                 'extra_sql' => 'WHERE reason IS NOT NULL',
+                              });
+
+    if (scalar(grep { $_->getfield('reason') =~ /\S/ } @cust_refunds)) {
+      warn "$me Found unmigrated reasons\n" if $DEBUG;
+      my $hashref = { 'class' => 'F', 'type' => 'Legacy' };
+      my $reason_type = qsearchs( 'reason_type', $hashref );
+      unless ($reason_type) {
+        $reason_type  = new FS::reason_type( $hashref );
+        my $error   = $reason_type->insert();
+        die "$class had error inserting FS::reason_type into database: $error\n"
+          if $error;
+      }
+
+      $hashref = { 'reason_type' => $reason_type->typenum,
+                   'reason' => '(none)'
+                 };
+      my $noreason = qsearchs( 'reason', $hashref );
+      unless ($noreason) {
+        $hashref->{'disabled'} = 'Y';
+        $noreason = new FS::reason( $hashref );
+        my $error  = $noreason->insert();
+        die "can't insert legacy reason '(none)' into database: $error\n"
+          if $error;
+      }
+
+      foreach my $cust_refund ( @cust_refunds ) {
+        my $reason = $cust_refund->getfield('reason');
+        warn "Contemplating reason $reason\n" if $DEBUG > 1;
+        if ($reason =~ /\S/) {
+          $cust_refund->reason($reason, 'reason_type' => $reason_type->typenum)
+            or die "can't insert legacy reason $reason into database\n";
+        }else{
+          $cust_refund->reasonnum($noreason->reasonnum);
+        }
+
+        $cust_refund->setfield('reason', '');
+        my $error = $cust_refund->replace;
+
+        warn "*** WARNING: error replacing reason in $class ".
+             $cust_refund->refundnum. ": $error ***\n"
+          if $error;
+      }
+    }
+  }
+}
+
+1;

commit 43839f03bf937eb086c7f2a55c059a606571ab77
Author: Joshua Goodman <jgoodman1990 at gmail.com>
Date:   Tue Feb 25 05:45:23 2014 +0000

    added refund reason_type class

diff --git a/httemplate/elements/tr-select-reason.html b/httemplate/elements/tr-select-reason.html
index 9a670a2..b7a715b 100755
--- a/httemplate/elements/tr-select-reason.html
+++ b/httemplate/elements/tr-select-reason.html
@@ -6,8 +6,8 @@ Example:
 
     #required 
     'field'         => 'reasonnum',
-    'reason_class'  => 'C', # currently 'C', 'R',  or 'S'
-                           # for cancel, credit, or suspend
+    'reason_class'  => 'C', # currently 'C', 'R', 'F',  or 'S'
+                           # for cancel, credit, refund, or suspend
 
     #recommended
     'cgi' => $cgi, #easiest way for things to be properly "sticky" on errors
@@ -161,6 +161,8 @@ if ($class eq 'C') {
   $add_access_right = 'Add on-the-fly suspend reason';
 } elsif ($class eq 'R') {
   $add_access_right = 'Add on-the-fly credit reason';
+} elsif ($class eq 'F') {
+  $add_access_right = 'Add on-the-fly refund reason';
 } else {
   die "illegal class: $class";
 }

commit afe30fc7315196cc4ae6da7606995cb8388d1a32
Author: Joshua Goodman <jgoodman1990 at gmail.com>
Date:   Tue Feb 25 05:40:44 2014 +0000

    added refund reasons to main menu

diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html
index cd4fb39..4ba7b2f 100644
--- a/httemplate/elements/menu.html
+++ b/httemplate/elements/menu.html
@@ -656,6 +656,10 @@ if ( $curuser->access_right('Configuration') ) {
   $config_billing{'separator4'} = ''; #its a separator!
   $config_billing{'Credit reasons'}  = [ $fsurl.'browse/reason.html?class=R', 'Credit reasons explain why a credit was issued.' ];
   $config_billing{'Credit reason types'}  = [ $fsurl.'browse/reason_type.html?class=R', 'Credit reason types define groups of reasons.' ];
+  
+  $config_billing{'separator5'} = ''; #its a separator!
+  $config_billing{'Refund reasons'}  = [ $fsurl.'browse/reason.html?class=F', 'Refund reasons explain why a refund was issued.' ];
+  $config_billing{'Refund reason types'}  = [ $fsurl.'browse/reason_type.html?class=F', 'Refund reason types define groups of reasons.' ];
 }
 
 #XXX also to be unified

commit daa3524d4f512f2bf671c6b07c606ba3eec1fefc
Author: Joshua Goodman <jgoodman1990 at gmail.com>
Date:   Tue Feb 25 05:40:17 2014 +0000

    updated ui to use a dropdown of existing reason types instead of text box

diff --git a/httemplate/edit/cust_refund.cgi b/httemplate/edit/cust_refund.cgi
index df42e63..9f7ac8d 100755
--- a/httemplate/edit/cust_refund.cgi
+++ b/httemplate/edit/cust_refund.cgi
@@ -106,14 +106,17 @@
     <INPUT TYPE="hidden" NAME="payinfo" VALUE="">
 % }
 
-  <TR>
-    <TD ALIGN="right">Reason</TD>
-    <TD BGCOLOR="#ffffff"><INPUT TYPE="text" NAME="reason" VALUE="<% $reason %>"></TD>
-  </TR>
+<& /elements/tr-select-reason.html,
+              'field'          => 'reasonnum',
+              'reason_class'   => 'F',
+              'control_button' => "document.getElementById('confirm_refund_button')",
+              'cgi'            => $cgi,
+&>
+
 </TABLE>
 
 <BR>
-<INPUT TYPE="submit" NAME="submit" VALUE="Post refund">
+<INPUT TYPE="submit" ID="confirm_refund_button" VALUE="<% mt('Post refund') |h %>" DISABLED>
 
 </FORM>
 

commit 73e20a91b38b27ad5be79306ba25bdfb5a1252e1
Author: Joshua Goodman <jgoodman1990 at gmail.com>
Date:   Tue Feb 25 05:39:29 2014 +0000

    added activate, renewal, term change, and refund reason_type classes

diff --git a/FS/FS/reason_type.pm b/FS/FS/reason_type.pm
index a603809..d66f7b5 100644
--- a/FS/FS/reason_type.pm
+++ b/FS/FS/reason_type.pm
@@ -10,12 +10,20 @@ our %class_name = (
   'C' => 'cancel',
   'R' => 'credit',
   'S' => 'suspend',
+  'U' => 'activate', #uncancel/unsuspend
+  'W' => 'renewal',
+  'T' => 'term change',
+  'F' => 'refund',
 );
 
 our %class_purpose = (  
   'C' => 'explain why a customer package was cancelled',
   'R' => 'explain why a customer was credited',
   'S' => 'explain why a customer package was suspended',
+  'U' => 'explain why a customer package was unsuspended/uncanceled/activated',
+  'W' => 'explain why a customer package was renewed',
+  'T' => 'explain why a customer package term was changed',
+  'F' => 'explain why a customer was refunded',
 );
 
 =head1 NAME

commit 79981f908752492b00cb4bdce3dceb0636fb81dd
Author: Joshua Goodman <jgoodman1990 at gmail.com>
Date:   Tue Feb 25 05:37:31 2014 +0000

    added reason method, allowed reasonnum to be passed in, allowed reason to be null in check method, modified _upgrade_data to migrate reason col in cust_refund table to reasonnum col

diff --git a/FS/FS/cust_refund.pm b/FS/FS/cust_refund.pm
index d29db5c..097ed2d 100644
--- a/FS/FS/cust_refund.pm
+++ b/FS/FS/cust_refund.pm
@@ -3,14 +3,21 @@ package FS::cust_refund;
 use strict;
 use base qw( FS::otaker_Mixin FS::payinfo_transaction_Mixin FS::cust_main_Mixin
              FS::Record );
-use vars qw( @encrypted_fields );
+use vars qw( @encrypted_fields $me $DEBUG $ignore_empty_reasonnum );
 use Business::CreditCard;
-use FS::Record qw( qsearch qsearchs dbh );
+use FS::Record qw( qsearch qsearchs dbh dbdef );
 use FS::CurrentUser;
 use FS::cust_credit;
 use FS::cust_credit_refund;
 use FS::cust_pay_refund;
 use FS::cust_main;
+use FS::reason_type;
+use FS::reason;
+
+$me = '[ FS::cust_refund ]';
+$DEBUG = 0;
+
+$ignore_empty_reasonnum = 0;
 
 @encrypted_fields = ('payinfo');
 sub nohistory_fields { ('payinfo'); }
@@ -56,7 +63,11 @@ Amount of the refund
 
 =item reason
 
-Reason for the refund
+Text stating the reason for the refund ( deprecated )
+
+=item reasonnum
+
+Reason (see L<FS::reason>)
 
 =item _date
 
@@ -119,7 +130,7 @@ amount of the refund will be created.  In both cases, custnum is optional.
 =cut
 
 sub insert {
-  my $self = shift;
+  my ($self, %options) = @_;
 
   local $SIG{HUP} = 'IGNORE';
   local $SIG{INT} = 'IGNORE';
@@ -132,6 +143,20 @@ sub insert {
   local $FS::UID::AutoCommit = 0;
   my $dbh = dbh;
 
+  unless ($self->reasonnum) {
+    my $result = $self->reason( $self->getfield('reason'),
+                                exists($options{ 'reason_type' })
+                                  ? ('reason_type' => $options{ 'reason_type' })
+                                  : (),
+                              );
+    unless($result) {
+      $dbh->rollback if $oldAutoCommit;
+      return "failed to set reason for $me"; #: ". $dbh->errstr;
+    }
+  }
+
+  $self->setfield('reason', '');
+
   if ( $self->crednum ) {
     my $cust_credit = qsearchs('cust_credit', { 'crednum' => $self->crednum } )
       or do {
@@ -274,13 +299,17 @@ sub check {
     || $self->ut_numbern('custnum')
     || $self->ut_money('refund')
     || $self->ut_alphan('otaker')
-    || $self->ut_text('reason')
+    || $self->ut_textn('reason')
     || $self->ut_numbern('_date')
     || $self->ut_textn('paybatch')
     || $self->ut_enum('closed', [ '', 'Y' ])
   ;
   return $error if $error;
 
+  my $method = $ignore_empty_reasonnum ? 'ut_foreign_keyn' : 'ut_foreign_key';
+  $error = $self->$method('reasonnum', 'reason', 'reasonnum');
+  return $error if $error;
+
   return "refund must be > 0 " if $self->refund <= 0;
 
   $self->_date(time) unless $self->_date;
@@ -377,9 +406,114 @@ sub unapplied_sql {
 
 }
 
+=item reason
+
+Returns the text of the associated reason (see L<FS::reason>) for this credit.
+
+=cut
+
+sub reason {
+  my ($self, $value, %options) = @_;
+  my $dbh = dbh;
+  my $reason;
+  my $typenum = $options{'reason_type'};
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;  # this should already be in
+  local $FS::UID::AutoCommit = 0;            # a transaction if it matters
+
+  if ( defined( $value ) ) {
+    my $hashref = { 'reason' => $value };
+    $hashref->{'reason_type'} = $typenum if $typenum;
+    my $addl_from = "LEFT JOIN reason_type ON ( reason_type = typenum ) ";
+    my $extra_sql = " AND reason_type.class='F'";
+
+    $reason = qsearchs( { 'table'     => 'reason',
+                          'hashref'   => $hashref,
+                          'addl_from' => $addl_from,
+                          'extra_sql' => $extra_sql,
+                       } );
+
+    if (!$reason && $typenum) {
+      $reason = new FS::reason( { 'reason_type' => $typenum,
+                                  'reason' => $value,
+                                  'disabled' => 'Y',
+                              } );
+      my $error = $reason->insert;
+      if ( $error ) {
+        warn "error inserting reason: $error\n";
+        $reason = undef;
+      }
+    }
+
+    $self->reasonnum($reason ? $reason->reasonnum : '') ;
+    warn "$me reason used in set mode with non-existant reason -- clearing"
+      unless $reason;
+  }
+  $reason = qsearchs( 'reason', { 'reasonnum' => $self->reasonnum } );
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+  ( $reason ? $reason->reason : '' ).
+  ( $self->addlinfo ? ' '.$self->addlinfo : '' );
+}
+
 # Used by FS::Upgrade to migrate to a new database.
 sub _upgrade_data {  # class method
   my ($class, %opts) = @_;
+
+  warn "$me upgrading $class\n" if $DEBUG;
+
+  if (defined dbdef->table($class->table)->column('reason')) {
+
+    warn "$me Checking for unmigrated reasons\n" if $DEBUG;
+
+    my @cust_refunds = qsearch({ 'table'     => $class->table,
+                                 'hashref'   => {},
+                                 'extra_sql' => 'WHERE reason IS NOT NULL',
+                              });
+
+    if (scalar(grep { $_->getfield('reason') =~ /\S/ } @cust_refunds)) {
+      warn "$me Found unmigrated reasons\n" if $DEBUG;
+      my $hashref = { 'class' => 'F', 'type' => 'Legacy' };
+      my $reason_type = qsearchs( 'reason_type', $hashref );
+      unless ($reason_type) {
+        $reason_type  = new FS::reason_type( $hashref );
+        my $error   = $reason_type->insert();
+        die "$class had error inserting FS::reason_type into database: $error\n"
+          if $error;
+      }
+
+      $hashref = { 'reason_type' => $reason_type->typenum,
+                   'reason' => '(none)'
+                 };
+      my $noreason = qsearchs( 'reason', $hashref );
+      unless ($noreason) {
+        $hashref->{'disabled'} = 'Y';
+        $noreason = new FS::reason( $hashref );
+        my $error  = $noreason->insert();
+        die "can't insert legacy reason '(none)' into database: $error\n"
+          if $error;
+      }
+
+      foreach my $cust_refund ( @cust_refunds ) {
+        my $reason = $cust_refund->getfield('reason');
+        warn "Contemplating reason $reason\n" if $DEBUG > 1;
+        if ($reason =~ /\S/) {
+          $cust_refund->reason($reason, 'reason_type' => $reason_type->typenum)
+            or die "can't insert legacy reason $reason into database\n";
+        }else{
+          $cust_refund->reasonnum($noreason->reasonnum);
+        }
+
+        $cust_refund->setfield('reason', '');
+        my $error = $cust_refund->replace;
+
+        warn "*** WARNING: error replacing reason in $class ".
+             $cust_refund->refundnum. ": $error ***\n"
+          if $error;
+      }
+    }
+  }
   $class->_upgrade_otaker(%opts);
 }
 

commit 128443531fae5fced8a8d2adbcaf6cb945218e3d
Author: Joshua Goodman <jgoodman1990 at gmail.com>
Date:   Tue Feb 25 05:35:42 2014 +0000

    Added reasonnum col, allowed reason to be null, implemented key constraint with reasonnum col

diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index bf516b2..ec4a1b3 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -2847,7 +2847,8 @@ sub tables_hashref {
         'currency',       'char', 'NULL',       3, '', '',
         'otaker',       'varchar',   'NULL',   32, '', '', 
         'usernum',   'int', 'NULL', '', '', '',
-        'reason',       'varchar',   '',   $char_d, '', '', 
+        'reason',       'varchar',   'NULL',   $char_d, '', '', 
+        'reasonnum',   'int', 'NULL', '', '', '',
         'payby',        'char',   '',     4, '', '', # CARD/BILL/COMP, should
                                                      # be index into payby
                                                      # table eventually
@@ -2871,6 +2872,9 @@ sub tables_hashref {
                           { columns    => [ 'usernum' ],
                             table      => 'access_user',
                           },
+                          { columns    => [ 'reasonnum' ],
+                            table      => 'reason',
+                          },
                           { columns    => [ 'gatewaynum' ],
                             table      => 'payment_gateway',
                           },

commit 23b5c810efb0975fb4a06142674aa27eabd5e689
Author: Joshua Goodman <jgoodman1990 at gmail.com>
Date:   Tue Feb 25 05:31:27 2014 +0000

    Added perm relating to refund reasons

diff --git a/FS/FS/AccessRight.pm b/FS/FS/AccessRight.pm
index 4b165eb..4d9cff9 100644
--- a/FS/FS/AccessRight.pm
+++ b/FS/FS/AccessRight.pm
@@ -230,6 +230,7 @@ tie my %rights, 'Tie::IxHash',
     'Refund Echeck payment',
     'Delete refund', #NEW
     'Add on-the-fly credit reason', #NEW
+    'Add on-the-fly refund reason', #NEW
   ],
   
   ###

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/AccessRight.pm                      |    1 +
 FS/FS/Schema.pm                           |    6 +-
 FS/FS/access_right.pm                     |    1 +
 FS/FS/cust_credit.pm                      |  103 +-----------------------
 FS/FS/cust_refund.pm                      |   42 +++++++++--
 FS/FS/reason_Mixin.pm                     |  121 +++++++++++++++++++++++++++++
 FS/FS/reason_type.pm                      |    2 +
 httemplate/edit/cust_refund.cgi           |   13 ++-
 httemplate/elements/menu.html             |    4 +
 httemplate/elements/tr-select-reason.html |    6 +-
 10 files changed, 186 insertions(+), 113 deletions(-)
 create mode 100644 FS/FS/reason_Mixin.pm




More information about the freeside-commits mailing list