multiple payment options, RT#23741
authorIvan Kohler <ivan@freeside.biz>
Thu, 12 Sep 2013 11:28:25 +0000 (04:28 -0700)
committerIvan Kohler <ivan@freeside.biz>
Thu, 12 Sep 2013 11:28:25 +0000 (04:28 -0700)
FS/FS/cust_main.pm
FS/FS/payby.pm
httemplate/edit/cust_main-contacts.html
httemplate/edit/cust_payby.html [new file with mode: 0644]
httemplate/edit/elements/edit.html
httemplate/edit/process/cust_payby.html [new file with mode: 0644]
httemplate/elements/tr-select-month_year.html [new file with mode: 0644]

index 0c50b84..641d54a 100644 (file)
@@ -2092,6 +2092,21 @@ sub cust_contact {
   qsearch('contact', { 'custnum' => $self->custnum } );
 }
 
+=item cust_payby
+
+Returns all payment methods (see L<FS::cust_payby>) for this customer.
+
+=cut
+
+sub cust_payby {
+  my $self = shift;
+  qsearch({
+    'table'    => 'cust_payby',
+    'hashref'  => { 'custnum' => $self->custnum },
+    'order_by' => 'ORDER BY weight ASC',
+  });
+}
+
 =item unsuspend
 
 Unsuspends all unflagged suspended packages (see L</unflagged_suspended_pkgs>
@@ -5125,7 +5140,6 @@ sub _upgrade_data { #class method
       die $error if $error;
 
       $cust_main->setfield($_, '') foreach @payfields;
-      $DEBUG = 2;
       $error = $cust_main->replace;
       die $error if $error;
 
index e223a05..b33f8f3 100644 (file)
@@ -70,12 +70,12 @@ tie %hash, 'Tie::IxHash',
     cust_pay  => 'CHEK', #this is a customer type only, payments are CHEK...
     realtime  => 1,
   },
-  'LECB' => {
-    tinyname  => 'phone bill',
-    shortname => 'Phone bill billing',
-    longname  => 'Phone bill billing',
-    realtime  => 1,
-  },
+  #'LECB' => {
+  #  tinyname  => 'phone bill',
+  #  shortname => 'Phone bill billing',
+  #  longname  => 'Phone bill billing',
+  #  realtime  => 1,
+  #},
   'BILL' => {
     tinyname  => 'billing',
     shortname => 'Billing',
index bae58bd..cd83a29 100644 (file)
@@ -1,8 +1,9 @@
-<% include('elements/edit.html',
+<& elements/edit.html,
      'name_singular'   => 'customer contacts', #yes, we're editing all of them
      'table'           => 'cust_main',
-     'post_url'       => popurl(1). 'process/cust_main-contacts.html',
-     'labels'          => { 'custnum'     => ' ', #XXX supress this line entirely, its being redundant
+     'post_url'        => popurl(1). 'process/cust_main-contacts.html',
+     'no_pkey_display' => 1,
+     'labels'          => {
                             'contactnum'  => 'Contact',
                             #'locationnum' => '&nbsp;',
                           },
      #'edit_callback'   => $edit_callback,
      #'error_callback'  => $error_callback,
      'agent_virt'      => 1,
-     'menubar'          => [], #remove "view all" link
+     'menubar'         => [], #remove "view all" link
 
      #XXX it would be nice if this could instead be after the error but before
      # the table
-     'html_init'        => include('/elements/small_custview.html',
-                                     $custnum,
-                                     $conf->config('countrydefault') || 'US',
-                                     1, #no balance
-                                  ),
-   )
-%>
+     'html_init'       => include('/elements/small_custview.html',
+                                    $custnum,
+                                    $conf->config('countrydefault') || 'US',
+                                    1, #no balance
+                                 ).
+                          '<BR>',
+&>
 <%init>
 
 my $curuser = $FS::CurrentUser::CurrentUser;
diff --git a/httemplate/edit/cust_payby.html b/httemplate/edit/cust_payby.html
new file mode 100644 (file)
index 0000000..67eb40a
--- /dev/null
@@ -0,0 +1,184 @@
+%# #based on / some false laziness w/ cust_main-contacts.html
+<& elements/edit.html,
+     'name_singular'   => 'payment methods', #"customer payment methods" ?
+     'table'           => 'cust_main',
+     'post_url'        => popurl(1). 'process/cust_payby.html',
+     'no_pkey_display' => 1,
+     'labels'          => {
+                            'custpaybynum'  => ' ', #'Payment method',
+                            #'locationnum' => '&nbsp;',
+                          },
+     'fields'          => [
+       { field                 => 'custpaybynum',
+         type                  => 'selectlayers',
+         options               => [ '',
+                                    grep { ! /^(DCRD|DCHK)$/ }
+                                      FS::payby->cust_payby
+                                  ],
+         labels                => { '' => 'Select payment method',
+                                    FS::payby->payby2shortname
+                                  },
+         layer_fields          => \%payby_fields,
+         layer_values_callback => $payby_layer_values,
+         m2m_method            => 'cust_payby',
+         m2m_dstcol            => 'custpaybynum',   
+         m2_label              => ' ', #'Payment method',
+         m2_error_callback     => $m2_error_callback,
+       },
+     ],
+     #'new_callback'    => $new_callback,
+     #'edit_callback'   => $edit_callback,
+     #'error_callback'  => $error_callback,
+     'agent_virt'      => 1,
+     'menubar'         => [], #remove "view all" link
+
+     #XXX it would be nice if this could instead be after the error but before
+     # the table
+     'html_init'       => include('/elements/small_custview.html',
+                                    $custnum,
+                                    $conf->config('countrydefault') || 'US',
+                                    1, #no balance
+                                 ).
+                          '<BR>',
+&>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+my $conf = new FS::Conf;
+
+my $custnum;
+if ( $cgi->param('error') ) {
+  $custnum = scalar($cgi->param('custnum'));
+
+  die "access denied"
+    unless $curuser->access_right(($custnum ? 'Edit' : 'New'). ' customer'); #payment methods?
+
+} elsif ( $cgi->keywords ) { #editing
+  $custnum = ($cgi->keywords)[0];
+
+  die "access denied"
+    unless $curuser->access_right('Edit customer');
+
+} else { #new customer
+
+  #this doesn't really work here, we're an edit only
+  die "guru meditation #53";
+
+  die "access denied"
+    unless $curuser->access_right('New customer');
+
+}
+
+
+#XXX
+my %payby_fields = (
+  'CARD' => [ 'CARD_payinfo' => mt('Card number'),
+              'CARD_exp'     => {
+                                  label => 'Expiration',
+                                  type  => 'select-month_year',
+                                  #XXX prefix?
+                                },
+              'CARD_paycvv'  => 'CVV2', #XXX help popup
+              'CARD_payname' => mt('Exact name on card'),
+              'CARD_payauto' => { label => mt('Charge future payments to this credit card automatically'),
+                                  type  => 'checkbox',
+                                },
+            ],
+  'CHEK' => [ 'CHEK_payinfo1'  => mt('Account number'),
+              'CHEK_paytype'   => { label => 'Type',
+                                    #XXX select values
+                                    #@FS::cust_main::paytypes #??
+                                  },
+              'CHEK_payinfo2'  => mt('ABA/Routing number'), #XXX help popup
+              'CHEK_exp_month' => { type  => 'hidden',
+                                    value => 12,
+                                  },
+              'CHEK_exp_year'  => { type  => 'hidden',
+                                    value => 2037,
+                                  },
+              'CHEK_payname'   => mt('Bank name'),
+              #'CHEK_paystate'  => { label => $paystate_label,
+              #                      type  => 'select-state',
+              #                    },
+              'CHEK_payauto' => { label => mt('Charge future payments to this electronic check automatically'),
+                                  type  => 'checkbox',
+                                },
+            ],
+  #'LECB'
+  'BILL' => [ 'BILL_payinfo' => mt('P.O.'),
+              'BILL_exp_month' => { type  => 'hidden',
+                                    value => 12,
+                                  },
+              'BILL_exp_year'  => { type  => 'hidden',
+                                    value => 2037,
+                                  },
+              'BILL_payname'   => mt('Attention'),
+            ],
+  'COMP' => [
+              'COMP_payinfo' => mt('Approved by'),
+            ],
+
+);
+
+#XXX
+my $payby_layer_values = sub {
+  my ( $cgi, $cust_payby, $switches ) = @_;
+  +{
+#     #map { $_ => { $part_event_condition->options } }
+#     #    keys %condition_fields
+#     map { my $conditionname = $_;
+#           my %opts = $switches->{'mode'} eq 'error'
+#                      ? %{ $cgi_conditions{$conditionname} || {} }
+#                      : $part_event_condition->options;
+#           %opts = (
+#             map { ( "$conditionname.$_" => $opts{$_} ); }
+#                 keys %opts
+#           );
+#           ( $conditionname => \%opts );
+#         }
+#         keys %condition_fields
+  };
+};
+
+
+#my $new_callback = sub {
+#  my( $cgi, $cust_main, $fields_listref, $opt_hashref ) = @_;
+#};
+
+#my $edit_callback = sub {
+# my( $cgi, $cust_main, $fields_listref, $opt_hashref ) = @_;
+#};
+
+#my $error_callback = sub {
+#  my( $cgi, $cust_main, $fields_listref, $opt_hashref ) = @_;
+#};
+
+my $m2_error_callback = sub {
+  my($cgi, $object) = @_;
+
+  #XXX
+
+  #process_o2m fields in process/cust_main-contacts.html
+  my @fields = qw( first last title comment );
+  my @gfields = ( '', map "_$_", @fields );
+
+  map {
+        if ( /^contactnum(\d+)$/ ) {
+          my $num = $1;
+          if ( grep $cgi->param("contactnum$num$_"), @gfields ) {
+            my $x = new FS::contact {
+              'contactnum' => scalar($cgi->param("contactnum$num")),
+              map { $_ => scalar($cgi->param("contactnum${num}_$_")) } @fields,
+            };
+            $x;
+          } else {
+            ();
+          }
+        } else {
+          ();
+        }
+      }
+      $cgi->param;
+};
+
+</%init>
index 3270f04..0602811 100644 (file)
@@ -116,6 +116,9 @@ Example:
     # display of primary key, no submit button, no html_foot, no footer)
     'embed' => $object, #need to pass the object
 
+    #don't show the primary key label and value
+    'no_pkey_display' => 1,
+
     ###
     # HTML callbacks
     ###
@@ -236,13 +239,17 @@ Example:
   <INPUT TYPE="hidden" NAME="svcdb" VALUE="<% $table %>">
   <INPUT TYPE="hidden" NAME="<% $pkey %>" VALUE="<% $clone ? '' : $object->$pkey() %>">
 
-  <FONT SIZE="+1"><B>
-  <% ( $opt{labels} && exists $opt{labels}->{$pkey} )
-        ? $opt{labels}->{$pkey}
-        : $pkey
-  %>
-  </B></FONT>
-  #<% ( !$clone && $object->$pkey() ) || "(NEW)" %>
+%   unless ( $opt{'no_pkey_display'} ) {
+
+      <FONT SIZE="+1"><B>
+      <% ( $opt{labels} && exists $opt{labels}->{$pkey} )
+            ? $opt{labels}->{$pkey}
+            : $pkey
+      %>
+      </B></FONT>
+      #<% ( !$clone && $object->$pkey() ) || "(NEW)" %>
+
+%   }
 
 % }
 
diff --git a/httemplate/edit/process/cust_payby.html b/httemplate/edit/process/cust_payby.html
new file mode 100644 (file)
index 0000000..a999e4d
--- /dev/null
@@ -0,0 +1,19 @@
+<% include('elements/process.html',
+     'table'          => 'cust_main',
+     'error_redirect' => popurl(3). 'edit/cust_payby.html?',
+     'agent_virt'     => 1,
+     'skip_process'   => 1, #we don't want to make any changes to cust_main
+     'process_o2m' => {
+       'table'  => 'cust_payby',
+       'fields' => \@payby_fields,
+     },
+     'redirect' => popurl(3). 'view/cust_main.cgi?',
+   )
+%>
+<%init>
+
+#XXX
+my @payby_fields = qw();
+}
+
+</%init>
diff --git a/httemplate/elements/tr-select-month_year.html b/httemplate/elements/tr-select-month_year.html
new file mode 100644 (file)
index 0000000..b1943bd
--- /dev/null
@@ -0,0 +1,22 @@
+% unless ( $opt{'js_only'} ) {
+
+    <% include('tr-td-label.html', %opt ) %>
+
+      <TD <% $colspan %> <% $style %>>
+% }
+
+    <% include('select-month_year.html', %opt ) %>
+
+% unless ( $opt{'js_only'} ) {
+      </TD>
+    </TR>
+% }
+<%init>
+
+my %opt = @_;
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+my $colspan = $opt{'colspan'} ? 'COLSPAN="'.$opt{'colspan'}.'"' : '';
+
+</%init>