[freeside-commits] branch master updated. 3cda3a85eb0daa5b8b9f4d30cd0896da6ccf4a9b

Mark Wells mark at 420.am
Tue Nov 25 19:39:30 PST 2014


The branch, master has been updated
       via  3cda3a85eb0daa5b8b9f4d30cd0896da6ccf4a9b (commit)
      from  77be6115a8972c8e7917fc9f80e30a6ba571a552 (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 3cda3a85eb0daa5b8b9f4d30cd0896da6ccf4a9b
Author: Mark Wells <mark at freeside.biz>
Date:   Tue Nov 25 19:39:23 2014 -0800

    option to credit unused time on suspension as part of suspend reason, #31702

diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index 396c866..715a603 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -5881,6 +5881,7 @@ sub tables_hashref {
         'disabled',      'char',    'NULL', 1, '', '', 
         'unsuspend_pkgpart', 'int',  'NULL', '', '', '',
         'unsuspend_hold','char',    'NULL', 1, '', '',
+        'unused_credit', 'char',    'NULL', 1, '', '',
       ],
       'primary_key'  => 'reasonnum',
       'unique'       => [],
diff --git a/FS/FS/cust_credit.pm b/FS/FS/cust_credit.pm
index 156ba5f..212be7a 100644
--- a/FS/FS/cust_credit.pm
+++ b/FS/FS/cust_credit.pm
@@ -679,11 +679,9 @@ Example:
     'apply'             => 1, #0 leaves the credit unapplied
 
     #the credit
-    'newreasonnum'      => scalar($cgi->param('newreasonnum')),
-    'newreasonnum_type' => scalar($cgi->param('newreasonnumT')),
     map { $_ => scalar($cgi->param($_)) }
       #fields('cust_credit')  
-      qw( custnum _date amount reason reasonnum addlinfo ), #pkgnum eventnum
+      qw( custnum _date amount reasonnum addlinfo ), #pkgnum eventnum
 
   );
 
@@ -725,26 +723,11 @@ sub credit_lineitems {
   #});
 
   my $error = '';
-  if ($arg{reasonnum} == -1) {
-
-    $error = 'Enter a new reason (or select an existing one)'
-      unless $arg{newreasonnum} !~ /^\s*$/;
-    my $reason = new FS::reason {
-                   'reason'      => $arg{newreasonnum},
-                   'reason_type' => $arg{newreasonnum_type},
-                 };
-    $error ||= $reason->insert;
-    if ( $error ) {
-      $dbh->rollback if $oldAutoCommit;
-      return "Error inserting reason: $error";
-    }
-    $arg{reasonnum} = $reason->reasonnum;
-  }
 
   my $cust_credit = new FS::cust_credit ( {
     map { $_ => $arg{$_} }
       #fields('cust_credit')
-      qw( custnum _date amount reason reasonnum addlinfo ), #pkgnum eventnum
+      qw( custnum _date amount reasonnum addlinfo ), #pkgnum eventnum
   } );
   $error = $cust_credit->insert;
   if ( $error ) {
diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm
index e8e202e..a810f5a 100644
--- a/FS/FS/cust_pkg.pm
+++ b/FS/FS/cust_pkg.pm
@@ -1207,7 +1207,7 @@ Available options are:
 
 =over 4
 
-=item reason - can be set to a cancellation reason (see L<FS:reason>), 
+=item reason - can be set to a cancellation reason (see L<FS:reason>),
 either a reasonnum of an existing reason, or passing a hashref will create 
 a new reason.  The hashref should have the following keys: 
 - typenum - Reason type (see L<FS::reason_type>
@@ -1297,6 +1297,16 @@ sub suspend {
     }
   }
 
+  # if a reasonnum was passed, get the actual reason object so we can check
+  # unused_credit
+  # (passing a reason hashref is still allowed, but it can't be used with
+  # the fancy behavioral options.)
+
+  my $reason;
+  if ($options{'reason'} =~ /^\d+$/) {
+    $reason = FS::reason->by_key($options{'reason'});
+  }
+
   my %hash = $self->hash;
   if ( $date ) {
     $hash{'adjourn'} = $date;
@@ -1321,9 +1331,15 @@ sub suspend {
     return $error;
   }
 
-  unless ( $date ) {
+  unless ( $date ) { # then we are suspending now
+
     # credit remaining time if appropriate
-    if ( $self->part_pkg->option('unused_credit_suspend', 1) ) {
+    # (if required by the package def, or the suspend reason)
+    my $unused_credit = $self->part_pkg->option('unused_credit_suspend',1)
+                        || ( defined($reason) && $reason->unused_credit );
+
+    if ( $unused_credit ) {
+      warn "crediting unused time on pkg#".$self->pkgnum."\n" if $DEBUG;
       my $error = $self->credit_remaining('suspend', $suspend_time);
       if ($error) {
         $dbh->rollback if $oldAutoCommit;
@@ -3872,7 +3888,7 @@ sub insert_reason {
     $reasonnum = $reason->reasonnum;
 
   } else {
-    return "Unparsable reason: ". $options{'reason'};
+    return "Unparseable reason: ". $options{'reason'};
   }
 
   my $cust_pkg_reason =
diff --git a/FS/FS/reason.pm b/FS/FS/reason.pm
index e6b20db..f28989a 100644
--- a/FS/FS/reason.pm
+++ b/FS/FS/reason.pm
@@ -56,6 +56,10 @@ suspensions but not others.
 whether to bill the unsuspend package immediately ('') or to wait until 
 the customer's next invoice ('Y').
 
+=item unused_credit - 'Y' or ''. For suspension reasons only (for now).
+If enabled, the customer will be credited for their remaining time on 
+suspension.
+
 =back
 
 =head1 METHODS
@@ -109,7 +113,6 @@ sub check {
     || $self->ut_number('reason_type')
     || $self->ut_foreign_key('reason_type', 'reason_type', 'typenum')
     || $self->ut_text('reason')
-    || $self->ut_flag('disabled')
   ;
   return $error if $error;
 
@@ -117,11 +120,13 @@ sub check {
     $error = $self->ut_numbern('unsuspend_pkgpart')
           || $self->ut_foreign_keyn('unsuspend_pkgpart', 'part_pkg', 'pkgpart')
           || $self->ut_flag('unsuspend_hold')
+          || $self->ut_flag('unused_credit')
     ;
     return $error if $error;
   } else {
-    $self->set('unsuspend_pkgpart' => '');
-    $self->set('unsuspend_hold'    => '');
+    foreach (qw(unsuspend_pkgpart unsuspend_hold unused_credit)) {
+      $self->set($_ => '');
+    }
   }
 
   $self->SUPER::check;
@@ -178,8 +183,6 @@ sub new_or_existing {
 
 =head1 BUGS
 
-Here by termintes.  Don't use on wooden computers.
-
 =head1 SEE ALSO
 
 L<FS::Record>, schema.html from the base documentation.
diff --git a/httemplate/edit/credit-cust_bill_pkg.html b/httemplate/edit/credit-cust_bill_pkg.html
index 40faddc..85f7943 100644
--- a/httemplate/edit/credit-cust_bill_pkg.html
+++ b/httemplate/edit/credit-cust_bill_pkg.html
@@ -80,9 +80,9 @@
 <& /elements/tr-select-reason.html,
               'field'          => 'reasonnum',
               'reason_class'   => 'R',
-              #XXX reconcile both this and show_taxes wanteding to enable this
+              #XXX reconcile both this and show_taxes wanting to enable this
               'id'             => 'select_reason',
-              'control_button' => "document.getElementById('credit_button')",
+              'control_button' => 'credit_button',
               'cgi'            => $cgi,
 &>
 
diff --git a/httemplate/edit/cust_credit.cgi b/httemplate/edit/cust_credit.cgi
index a3565f1..29801ef 100755
--- a/httemplate/edit/cust_credit.cgi
+++ b/httemplate/edit/cust_credit.cgi
@@ -24,7 +24,7 @@
 <& /elements/tr-select-reason.html,
               'field'          => 'reasonnum',
               'reason_class'   => 'R',
-              'control_button' => "document.getElementById('confirm_credit_button')",
+              'control_button' => 'confirm_credit_button',
               'cgi'            => $cgi,
 &>
 
diff --git a/httemplate/edit/process/credit-cust_bill_pkg.html b/httemplate/edit/process/credit-cust_bill_pkg.html
index 8e66368..75900bd 100644
--- a/httemplate/edit/process/credit-cust_bill_pkg.html
+++ b/httemplate/edit/process/credit-cust_bill_pkg.html
@@ -27,19 +27,35 @@ foreach my $billpkgnum_setuprecur (@billpkgnum_setuprecurs) {
   push @amounts,     $amount;
 }
 
-my $error = FS::cust_credit->credit_lineitems(
+my $reasonnum = $cgi->param('reasonnum');
+$reasonnum =~ /^(-?\d+)$/ or die "Illegal reasonnum";
+$reasonnum = $1;
+
+my $error;
+if ($reasonnum == -1) {
+  my $new_reason = FS::reason->new({
+    map { $_ => scalar( $cgi->param("select_reason_new_$_") ) }
+    qw( reason_type reason )
+  });
+  $error = $new_reason->insert;
+  $reasonnum = $new_reason->reasonnum;
+}
+
+if ( !$reasonnum ) {
+  $error ||= 'Reason required'
+}
+
+$error ||= FS::cust_credit->credit_lineitems(
   #the lineitems to credit
   'billpkgnums'       => \@billpkgnums,
   'setuprecurs'       => \@setuprecurs,
   'amounts'           => \@amounts,
   'apply'             => ( $cgi->param('apply') eq 'yes' ),
+  'reasonnum'         => $reasonnum,
 
-  #the credit
-  'newreasonnum'      => scalar($cgi->param('newreasonnum')),
-  'newreasonnum_type' => scalar($cgi->param('newreasonnumT')),
   map { $_ => scalar($cgi->param($_)) }
     #fields('cust_credit')  
-    qw( custnum _date amount reason reasonnum addlinfo ), #pkgnum eventnum
+    qw( custnum _date amount addlinfo ), #pkgnum eventnum
 );
 
 </%init>
diff --git a/httemplate/edit/process/cust_credit.cgi b/httemplate/edit/process/cust_credit.cgi
index 245f31a..e442d7f 100755
--- a/httemplate/edit/process/cust_credit.cgi
+++ b/httemplate/edit/process/cust_credit.cgi
@@ -1,5 +1,4 @@
 %if ( $error ) {
-%  $cgi->param('reasonnum', $reasonnum);
 %  $cgi->param('error', $error);
 %  $dbh->rollback if $oldAutoCommit;
 %  
@@ -37,19 +36,11 @@ my $oldAutoCommit = $FS::UID::AutoCommit;
 local $FS::UID::AutoCommit = 0;
 my $dbh = dbh;
 
-my $error = '';
-if ($reasonnum == -1) {
-
-  $error = 'Enter a new reason (or select an existing one)'
-    unless $cgi->param('newreasonnum') !~ /^\s*$/;
-  my $reason = new FS::reason {
-                 'reason_type' => scalar($cgi->param('newreasonnumT')),
-                 'reason'      => scalar($cgi->param('newreasonnum')),
-               };
-  $error ||= $reason->insert;
-  $cgi->param('reasonnum', $reason->reasonnum)
-    unless $error;
+my ($reasonnum, $error) = $m->comp('/misc/process/elements/reason');
+if (!$reasonnum) {
+  $error ||= 'Reason required'
 }
+$cgi->param('reasonnum', $reasonnum) unless $error;
 
 unless ($error) {
   my $new = new FS::cust_credit ( {
diff --git a/httemplate/elements/tr-select-reason.html b/httemplate/elements/tr-select-reason.html
index b7a715b..c5b3d6f 100755
--- a/httemplate/elements/tr-select-reason.html
+++ b/httemplate/elements/tr-select-reason.html
@@ -29,109 +29,119 @@ Example:
 
 </%doc>
 
+% # note style improvements.
+% # - no more conditionally included code here
+% # - callers are not expected to pass javascript fragments
+% # - no redundant checking of ACLs or parameters
+% # - form fields are grouped for easy management
+% # - use the standard select-table widget instead of ad hoc crap
 <SCRIPT TYPE="text/javascript">
-  function sh_add<% $func_suffix %>()
-  {
-    var hints = <% encode_json(\@hints) %>;
+  function <% $id %>_changed() {
+    var hints = <% encode_json(\%all_hints) %>;
     var select_reason = document.getElementById('<% $id %>');
 
-% if ( $class eq 'S' ) {    
     document.getElementById('<% $id %>_hint').innerHTML =
-      hints[select_reason.selectedIndex];
-% }
+      hints[select_reason.value] || '';
 
-    if (select_reason.selectedIndex == 0){
-      <% $controlledbutton ? $controlledbutton.'.disabled = true;' : ';' %>
-    }else{
-      <% $controlledbutton ? $controlledbutton.'.disabled = false;' : ';' %>
+    // toggle submit button state
+    var submit_button = document.getElementById(<% $opt{control_button} |js_string %>);
+    if (submit_button) {
+      submit_button.disabled = ( select_reason.value == 0 );
     }
 
-%if ($curuser->access_right($add_access_right)){
-
-    if (select_reason.selectedIndex == 
-         (select_reason.length - 1)) {
-      document.getElementById('new<% $id %>').disabled = false;
-      document.getElementById('new<% $id %>').style.display = 'inline';
-      document.getElementById('new<% $id %>Label').style.display = 'inline';
-      document.getElementById('new<% $id %>T').disabled = false;
-      document.getElementById('new<% $id %>T').style.display = 'inline';
-      document.getElementById('new<% $id %>TLabel').style.display = 'inline';
+    // toggle visibility of 'new reason' fields
+    var new_fields = document.getElementById('<% $id %>_new_fields');
+    if ( select_reason.value == -1 ) {
+      new_fields.disabled = false;
+      new_fields.style.display = '';
     } else {
-      document.getElementById('new<% $id %>').disabled = true;
-      document.getElementById('new<% $id %>').style.display = 'none';
-      document.getElementById('new<% $id %>Label').style.display = 'none';
-      document.getElementById('new<% $id %>T').disabled = true;
-      document.getElementById('new<% $id %>T').style.display = 'none';
-      document.getElementById('new<% $id %>TLabel').style.display = 'none';
+      new_fields.disabled = true;
+      new_fields.style.display = 'none';
     }
 
-%}
-
   }
+  <&| onload.js &> <% $id %>_changed(); </&>
 </SCRIPT>
 
-<TR>
-  <TD ALIGN="right"><% mt('Reason') |h %></TD>
-  <TD>
-    <SELECT id="<% $id %>" name="<% $name %>" onFocus="sh_add<% $func_suffix %>()" onChange="sh_add<% $func_suffix %>()">
-      <OPTION VALUE="" <% ($init_reason eq '') ? 'SELECTED' : '' %>><% mt('Select Reason...') |h %></OPTION>
-%    foreach my $reason (@reasons) {
-      <OPTION VALUE="<% $reason->reasonnum %>" <% ($init_reason == $reason->reasonnum) ? 'SELECTED' : '' %>><% $reason->reasontype->type %> : <% $reason->reason %></OPTION>
-%    }
-%    if ($curuser->access_right($add_access_right)) {
-      <OPTION VALUE="-1" <% ($init_reason == -1) ? 'SELECTED' : '' %>><% mt('Add new reason') |h %></OPTION>
-%    }
-%
-    </SELECT>
-  </TD>
-</TR>
-
-%   my @types = qsearch( 'reason_type', { 'class' => $class } );
-%   if (scalar(@types) < 1) {  # we should never reach this
-<TR>
-  <TD ALIGN="right">
-    <P><% mt('No reason types. Please add some.') |h %></P>
-  </TD>
-</TR>
-%   }elsif (scalar(@types) == 1) {
-<TR>
-  <TD ALIGN="right">
-    <P id="new<% $name %>TLabel" style="display:<% $display %>"><% mt('Reason Type') |h %></P>
-  </TD>
-  <TD>
-    <P id="new<% $name %>T" disabled="<% $disabled %>" style="display:<% $display %>"><% $types[0]->type %>
-    <INPUT type="hidden" name="new<% $name %>T" value="<% $types[0]->typenum %>">
-  </TD>
-</TR>
-
-%   }else{
-
-<TR>
-  <TD ALIGN="right">
-    <P id="new<% $id %>TLabel" style="display:<% $display %>"><% mt('Reason Type') |h %></P>
-  </TD>
-  <TD>
-    <SELECT id="new<% $id %>T" name="new<% $name %>T" "<% $disabled %>" style="display:<% $display %>">
-%     for my $type (@types) {
-        <OPTION VALUE="<% $type->typenum %>" <% ($init_type == $type->typenum) ? 'SELECTED' : '' %>><% $type->type %></OPTION>
-%     }
-    </SELECT>
-  </TD>
-</TR>
-%   }
+%# sadly can't just use add_inline here, as we have non-text fields
+<& tr-select-table.html,
+  'label'           => 'Reason',
+  'field'           => $name,
+  'id'              => $id,
+  'table'           => 'reason',
+  'records'         => \@reasons,
+  'label_callback'  => sub { my $reason = shift;
+                             $reason->type . ' : ' .  $reason->reason },
+  'disable_empty'   => 1,
+  'pre_options'     => [ 0 => 'Select reason...' ],
+  'post_options'    => [ -1 => 'Add new reason' ],
+  'curr_value'      => $init_reason,
+  'onchange'        => $id.'_changed()',
+&>
+
+% # "add new reason" fields
+% # should be a <fieldset>, but that doesn't fit well into the table
+
+<TR id="<% $id %>_new_fields">
+  <TD COLSPAN=2>
+    <TABLE CLASS="inv" STYLE="text-align: left">
+
+      <& tr-input-text.html,
+        label => 'New reason',
+        field => $id.'_new_reason'
+      &>
+
+% my @types = qsearch( 'reason_type', { 'class' => $class } );
+% if (scalar(@types) < 1) {  # we should never reach this
+      <TR>
+        <TD ALIGN="right">
+          <P><% mt('No reason types. Please add some.') |h %></P>
+        </TD>
+      </TR>
+% } elsif (scalar(@types) == 1) {
+      <& tr-fixed.html,
+        label => 'Reason type',
+        field => $id.'_new_reason_type',
+        curr_value => $types[0]->typenum,
+        formatted_value => $types[0]->type,
+      &>
+% } else { # more than one type, the normal case
+      <& tr-select-table.html,
+        label         => 'Reason type',
+        field         => $id.'_new_reason_type',
+        table         => 'reason_type',
+        name_col      => 'type',
+        hashref       => { 'class' => $class },
+        disable_empty => 1,
+      &>
+% } # scalar(@types)
 
 % if ( $class eq 'S' ) {
-<TR>
-  <TD COLSPAN=2 ALIGN="center" id="<% $id %>_hint">
-  </TD>
-</TR>
+      <& tr-checkbox.html,
+        label => 'Credit the unused portion of service when suspending',
+        field => $id.'_new_unused_credit',
+        value => 'Y'
+      &>
+      <& tr-select-part_pkg.html,
+        label   => 'Charge this fee when unsuspending',
+        field   => $id.'_new_unsuspend_pkgpart',
+        hashref => { disabled => '', freq => '0' },
+        empty_label => 'none',
+      &>
+      <& tr-checkbox.html,
+        label => 'Hold unsuspension fee until the next bill',
+        field => $id.'_new_unsuspend_hold',
+        value => 'Y',
+      &>
 % }
+    </table>
+  </td>
+</tr>
 
+% # container for hints
 <TR>
-  <TD ALIGN="right">
-    <P id="new<% $id %>Label" style="display:<% $display %>"><% mt('New Reason') |h %></P>
+  <TD COLSPAN=2 ALIGN="center" id="<% $id %>_hint" style="font-size:small">
   </TD>
-  <TD><INPUT id="new<% $id %>" name="new<% $name %>" type="text" value="<% $init_newreason |h %>" "<% $disabled %>" style="display:<% $display %>"></TD>
 </TR>
 
 <%init>
@@ -148,11 +158,7 @@ if ( $opt{'cgi'} ) {
   $init_reason = $opt{'curr_value'};
 }
 
-my $controlledbutton = $opt{'control_button'};
-
-( my $func_suffix = $name ) =~ s/\./_/g;
-
-my $id = $opt{'id'} || $func_suffix;
+my $id = $opt{'id'} || $name;
 
 my $add_access_right;
 if ($class eq 'C') {
@@ -167,41 +173,21 @@ if ($class eq 'C') {
   die "illegal class: $class";
 }
 
-my( $display, $disabled ) = ( 'none', 'DISABLED' );
-my( $init_type, $init_newreason ) = ( '', '' );
-if ($init_reason == -1 || ref($init_reason) ) {
-
-  $display = 'inline';
-  $disabled = '';
-
-  if ( ref($init_reason) ) {
-    $init_type      = $init_reason->{'typenum'};
-    $init_newreason = $init_reason->{'reason'};
-    $init_reason = -1;
-  } elsif ( $opt{'cgi'} ) {
-    $init_type      = $opt{'cgi'}->param( "new${name}T" );
-    $init_newreason = $opt{'cgi'}->param( "new$name"    );
-  }
-
-}
-
-my $extra_sql =
-  "WHERE class = '$class' and (disabled = '' OR disabled is NULL)";
-
 my @reasons = qsearch({
-  table     => 'reason', 
-  hashref   => {},
-  extra_sql => $extra_sql,
-  addl_from => 'LEFT JOIN reason_type '.
-               ' ON reason_type.typenum = reason.reason_type',
-  order_by  => 'ORDER BY reason_type.type ASC, reason.reason ASC',
+  'table'           => 'reason',
+  'addl_from'       => ' LEFT JOIN reason_type'.
+                       ' ON (reason.reason_type = reason_type.typenum)',
+  'hashref'         => { disabled => '' },
+  'extra_sql'       => " AND reason_type.class = '$class'",
+  'order_by'        => ' ORDER BY type, reason',
 });
 
-my @hints;
+my %all_hints;
 if ( $class eq 'S' ) {
   my $conf = FS::Conf->new;
-  @hints = ( '' );
+  %all_hints = ( 0 => '', -1 => '' );
   foreach my $reason (@reasons) {
+    my @hints;
     if ( $reason->unsuspend_pkgpart ) {
       my $part_pkg = FS::part_pkg->by_key($reason->unsuspend_pkgpart);
       if ( $part_pkg ) {
@@ -225,15 +211,13 @@ if ( $class eq 'S' ) {
           '<FONT COLOR="#ff0000">Unsuspend pkg #'.$reason->unsuspend_pkgpart.
           ' not found.</FONT>';
       }
-    } else { #no unsuspend_pkgpart
-      push @hints, '';
     }
+    if ( $reason->unused_credit ) {
+      push @hints, mt('The customer will be credited for unused time.');
+    }
+    $all_hints{ $reason->reasonnum } = join('<BR>', @hints);
   }
-  push @hints, ''; # for the "new reason" case
-  @hints = map {'<FONT SIZE="-1">'.$_.'</FONT>'} @hints;
 }
 
-
 my $curuser = $FS::CurrentUser::CurrentUser;
-
 </%init>
diff --git a/httemplate/misc/cancel_cust.html b/httemplate/misc/cancel_cust.html
index 3259a03..e4bfdba 100644
--- a/httemplate/misc/cancel_cust.html
+++ b/httemplate/misc/cancel_cust.html
@@ -50,7 +50,7 @@ STYLE="margin-left:auto; margin-right:auto">
              'field'          => 'reasonnum',
              'reason_class'   => 'C',
              'cgi'            => $cgi,
-             'control_button' => "document.getElementById('confirm_cancel_cust_button')",
+             'control_button' => 'confirm_cancel_cust_button',
 &>
 
 </TABLE>
diff --git a/httemplate/misc/cancel_pkg.html b/httemplate/misc/cancel_pkg.html
index e2734e9..c80b2b2 100755
--- a/httemplate/misc/cancel_pkg.html
+++ b/httemplate/misc/cancel_pkg.html
@@ -6,9 +6,9 @@
 <INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
 <INPUT TYPE="hidden" NAME="method" VALUE="<% $method %>">
 
-<BR><BR>
+<BR>
 <% emt(ucfirst($method)." [_1]", $part_pkg->pkg_comment(cust_pkg=>$cust_pkg) ) %>
-<% ntable("#cccccc", 2) %>
+<table style="background-color: #cccccc; border-spacing: 2; width: 100%">
 
 % my $date_init = 0;
 % if ($method eq 'expire' || $method eq 'adjourn' || $method eq 'resume') {
@@ -58,7 +58,7 @@
        field          => 'reasonnum',
        reason_class   => $class,
        curr_value     => $reasonnum,
-       control_button => "document.getElementById('confirm_cancel_pkg_button')",
+       control_button => "confirm_cancel_pkg_button",
   &>
 % }
 
diff --git a/httemplate/misc/cust_main-cancel.cgi b/httemplate/misc/cust_main-cancel.cgi
index 2ae9f10..a78a8b3 100755
--- a/httemplate/misc/cust_main-cancel.cgi
+++ b/httemplate/misc/cust_main-cancel.cgi
@@ -22,51 +22,43 @@ if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
   $custnum = $1;
 }
 
-#false laziness w/process/cancel_pkg.html
 
-#untaint reasonnum
-my $reasonnum = $cgi->param('reasonnum');
-$reasonnum =~ /^(-?\d+)$/ || die "Illegal reasonnum";
-$reasonnum = $1;
-
-if ($reasonnum == -1) {
-  $reasonnum = {
-    'typenum' => scalar( $cgi->param('newreasonnumT') ),
-    'reason'  => scalar( $cgi->param('newreasonnum' ) ),
-  };
+#untaint reasonnum / create new reason
+my ($reasonnum, $error) = $m->comp('process/elements/reason');
+if (!$reasonnum) {
+  $error ||= 'Reason required'
 }
 
-#eslaf
-
 my $cust_main = qsearchs( {
   'table'     => 'cust_main',
   'hashref'   => { 'custnum' => $custnum },
   'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
 } );
 
-my @errors;
-if($cgi->param('now_or_later')) {
+if ( $error ) {
+  # do nothing
+} elsif ( $cgi->param('now_or_later') ) {
   $expire = parse_datetime($expire);
   if($expire) {
     #warn "setting expire dates on custnum#$custnum\n";
     my @pkgs = $cust_main->ncancelled_pkgs;
-    @errors = grep {$_} map { $_->cancel(
+    my @errors = grep {$_} map { $_->cancel(
       'reason'  => $reasonnum,
       'date'    => $expire,
     ) } @pkgs;
+    $error = join(' / ', @errors);
   }
   else {
-    @errors = ("error parsing expire date: ".$cgi->param('expire'));
+    $error = ("error parsing expire date: ".$cgi->param('expire'));
   }
 }
 else {
   warn "cancelling $cust_main";
-  @errors = $cust_main->cancel(
+  $error = $cust_main->cancel(
     'ban'    => $ban,
     'reason' => $reasonnum,
   );
 }
-my $error = join(' / ', @errors) if scalar(@errors);
 
 if ( $error ) {
   $cgi->param('error', $error);
diff --git a/httemplate/misc/cust_main-suspend.cgi b/httemplate/misc/cust_main-suspend.cgi
index 6185136..7a501d6 100755
--- a/httemplate/misc/cust_main-suspend.cgi
+++ b/httemplate/misc/cust_main-suspend.cgi
@@ -22,50 +22,39 @@ if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
   $custnum = $1;
 }
 
-#false laziness w/process/cancel_pkg.html
-
-#untaint reasonnum
-my $reasonnum = $cgi->param('reasonnum');
-$reasonnum =~ /^(-?\d+)$/ || die "Illegal reasonnum";
-$reasonnum = $1;
-
-if ($reasonnum == -1) {
-  $reasonnum = {
-    'typenum' => scalar( $cgi->param('newreasonnumT') ),
-    'reason'  => scalar( $cgi->param('newreasonnum' ) ),
-  };
+#untaint reasonnum / create new reason
+my ($reasonnum, $error) = $m->comp('process/elements/reason');
+if (!$reasonnum) {
+  $error ||= 'Reason required';
 }
 
-#eslaf
-
 my $cust_main = qsearchs( {
   'table'     => 'cust_main',
   'hashref'   => { 'custnum' => $custnum },
   'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
 } );
 
-my @errors;
-if($cgi->param('now_or_later')) {
+if ( $error ) {
+  # do nothing
+} elsif ( $cgi->param('now_or_later') ) {
   $adjourn = parse_datetime($adjourn);
   if($adjourn) {
     #warn "setting adjourn dates on custnum#$custnum\n";
     my @pkgs = $cust_main->unsuspended_pkgs;
-    @errors = grep {$_} map { $_->suspend(
+    my @errors = grep {$_} map { $_->suspend(
       'reason'  => $reasonnum,
       'date'    => $adjourn,
     ) } @pkgs;
+    $error = join(' / ', @errors);
+  } else {
+    $error = ("error parsing adjourn date: ".$cgi->param('adjourn'));
   }
-  else {
-    @errors = ("error parsing adjourn date: ".$cgi->param('adjourn'));
-  }
-}
-else {
+} else {
   warn "suspending $cust_main";
-  @errors = $cust_main->suspend(
+  $error = $cust_main->suspend(
     'reason' => $reasonnum,
   );
 }
-my $error = join(' / ', @errors) if scalar(@errors);
 
 if ( $error ) {
   $cgi->param('error', $error);
diff --git a/httemplate/misc/process/cancel_pkg.html b/httemplate/misc/process/cancel_pkg.html
index a106b84..47ceca2 100755
--- a/httemplate/misc/process/cancel_pkg.html
+++ b/httemplate/misc/process/cancel_pkg.html
@@ -65,17 +65,12 @@ if ( $method eq 'suspend' ) { #or 'adjourn'
 
 my $cust_pkg = qsearchs( 'cust_pkg', {'pkgnum'=>$pkgnum} );
 
-#untaint reasonnum
-my $reasonnum = $cgi->param('reasonnum');
-if ( $method !~ /^(unsuspend|uncancel)$/ ) {
-  $reasonnum =~ /^(-?\d+)$/ or die "Illegal reasonnum";
-  $reasonnum = $1;
-
-  if ($reasonnum == -1) {
-    $reasonnum = {
-      'typenum' => scalar( $cgi->param('newreasonnumT') ),
-      'reason'  => scalar( $cgi->param('newreasonnum' ) ),
-    };
+#untaint reasonnum, and set up new reason if appropriate
+my ($reasonnum, $error);
+if ($method ne 'resume' and $method ne 'uncancel') {
+  ($reasonnum, $error) = $m->comp('elements/reason');
+  if (!$reasonnum) {
+    $error ||= 'Reason required';
   }
 }
 
@@ -87,7 +82,7 @@ my $bill =
 
 my $svc_fatal = ( $cgi->param('svc_not_fatal') ne 'Y' );
 
-my $error = $cust_pkg->$method( 'reason'      => $reasonnum,
+$error ||=  $cust_pkg->$method( 'reason'      => $reasonnum,
                                 'date'        => $date,
                                 'resume_date' => $resume_date,
                                 'last_bill'   => $last_bill,
diff --git a/httemplate/misc/process/elements/reason b/httemplate/misc/process/elements/reason
new file mode 100644
index 0000000..ae92a75
--- /dev/null
+++ b/httemplate/misc/process/elements/reason
@@ -0,0 +1,17 @@
+<%init>
+#untaint reasonnum, and set up new reason if appropriate
+my $reasonnum = $cgi->param('reasonnum');
+$reasonnum =~ /^(-?\d+)$/ or die "Illegal reasonnum";
+$reasonnum = $1;
+
+my $error;
+if ($reasonnum == -1) {
+  my $new_reason = FS::reason->new({
+    map { $_ => scalar( $cgi->param("reasonnum_new_$_") ) }
+    qw( reason_type reason unsuspend_pkgpart unsuspend_hold unused_credit )
+  }); # not sanitizing them here, but check() will do it
+  $error = $new_reason->insert;
+  $reasonnum = $new_reason->reasonnum;
+}
+return ($reasonnum, $error);
+</%init>
diff --git a/httemplate/misc/suspend_cust.html b/httemplate/misc/suspend_cust.html
index e0d17f3..3a49e13 100644
--- a/httemplate/misc/suspend_cust.html
+++ b/httemplate/misc/suspend_cust.html
@@ -42,7 +42,7 @@ STYLE="margin-left:auto; margin-right:auto">
              'field'          => 'reasonnum',
              'reason_class'   => 'S',
              'cgi'            => $cgi,
-             'control_button' => "document.getElementById('confirm_suspend_cust_button')",
+             'control_button' => 'confirm_suspend_cust_button',
 &>
 
 </TABLE>
diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi
index 4880ac3..833b6d0 100755
--- a/httemplate/view/cust_main.cgi
+++ b/httemplate/view/cust_main.cgi
@@ -60,8 +60,8 @@ function areyousure(href, message) {
                 'actionlabel' => emt('Confirm Suspension'),
                 'color'       => '#ff9900',
                 'cust_main'   => $cust_main,
-                'width'       => 616, #make room for reasons
-                'height'      => 366,
+                'width'       => 768, #make room for reasons
+                'height'      => 450, 
               }
   &> | 
 % }
@@ -91,7 +91,7 @@ function areyousure(href, message) {
                 'color'       => '#ff0000',
                 'cust_main'   => $cust_main,
                 'width'       => 616, #make room for reasons
-                'height'      => 366,
+                'height'      => 410,
               }
   &> | 
 % }
diff --git a/httemplate/view/cust_main/packages/status.html b/httemplate/view/cust_main/packages/status.html
index accdb45..f760d6f 100644
--- a/httemplate/view/cust_main/packages/status.html
+++ b/httemplate/view/cust_main/packages/status.html
@@ -582,6 +582,7 @@ sub pkg_suspend_link {
              'actionlabel' => emt('Suspend'),
              'color'       => '#FF9900',
              'cust_pkg'    => shift,
+             'height'      => 420,
          )
 }
 
@@ -592,6 +593,7 @@ sub pkg_adjourn_link {
              'actionlabel' => emt('Adjourn'),
              'color'       => '#CC6600',
              'cust_pkg'    => shift,
+             'height'      => 445,
          )
 }
 

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

Summary of changes:
 FS/FS/Schema.pm                                   |    1 +
 FS/FS/cust_credit.pm                              |   21 +-
 FS/FS/cust_pkg.pm                                 |   24 ++-
 FS/FS/reason.pm                                   |   13 +-
 httemplate/edit/credit-cust_bill_pkg.html         |    4 +-
 httemplate/edit/cust_credit.cgi                   |    2 +-
 httemplate/edit/process/credit-cust_bill_pkg.html |   26 ++-
 httemplate/edit/process/cust_credit.cgi           |   17 +-
 httemplate/elements/tr-select-reason.html         |  232 ++++++++++-----------
 httemplate/misc/cancel_cust.html                  |    2 +-
 httemplate/misc/cancel_pkg.html                   |    6 +-
 httemplate/misc/cust_main-cancel.cgi              |   30 +--
 httemplate/misc/cust_main-suspend.cgi             |   37 ++--
 httemplate/misc/process/cancel_pkg.html           |   19 +-
 httemplate/misc/process/elements/reason           |   17 ++
 httemplate/misc/suspend_cust.html                 |    2 +-
 httemplate/view/cust_main.cgi                     |    6 +-
 httemplate/view/cust_main/packages/status.html    |    2 +
 18 files changed, 225 insertions(+), 236 deletions(-)
 create mode 100644 httemplate/misc/process/elements/reason




More information about the freeside-commits mailing list