consider csv/xls imported payments "manual" for payment receipt purposes, RT#33681
[freeside.git] / FS / FS / cust_pay.pm
index 0a36aca..b81f161 100644 (file)
@@ -116,6 +116,10 @@ books closed flag, empty or `Y'
 
 Desired pkgnum when using experimental package balances.
 
+=item no_auto_apply
+
+Flag to only allow manual application of payment, empty or 'Y'
+
 =item bank
 
 The bank where the payment was deposited.
@@ -539,6 +543,7 @@ sub check {
     || $self->ut_textn('paybatch')
     || $self->ut_textn('payunique')
     || $self->ut_enum('closed', [ '', 'Y' ])
+    || $self->ut_flag('no_auto_apply')
     || $self->ut_foreign_keyn('pkgnum', 'cust_pkg', 'pkgnum')
     || $self->ut_textn('bank')
     || $self->ut_alphan('depositor')
@@ -1170,75 +1175,77 @@ sub process_upgrade_paybatch {
 sub process_batch_import {
   my $job = shift;
 
-  #agent_custid isn't a cust_pay field, see hash callback
-  my $format = [ qw(custnum agent_custid paid payinfo invnum) ];
   my $hashcb = sub {
     my %hash = @_;
     my $custnum = $hash{'custnum'};
+    my $agentnum = $hash{'agentnum'};
     my $agent_custid = $hash{'agent_custid'};
     #standardize date
     $hash{'_date'} = parse_datetime($hash{'_date'})
       if $hash{'_date'} && $hash{'_date'} =~ /\D/;
+    #remove custnum_prefix
+    my $custnum_prefix = $conf->config('cust_main-custnum-display_prefix');
+    my $custnum_length = $conf->config('cust_main-custnum-display_length') || 8;
+    if (
+      $custnum_prefix 
+      && $custnum =~ /^$custnum_prefix(0*([1-9]\d*))$/
+      && length($1) == $custnum_length 
+    ) {
+      $custnum = $2;
+    }
+    # check agentnum against custnum and
     # translate agent_custid into regular custnum
     if ($custnum && $agent_custid) {
       die "can't specify both custnum and agent_custid\n";
-    } elsif ($agent_custid) {
+    } elsif ($agentnum || $agent_custid) {
       # here is the agent virtualization
       my $extra_sql = ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql;
-      my $agentnum = $hash{'agentnum'};
-      my %search = (
-        'agent_custid' => $agent_custid,
-        'agentnum'     => $agentnum,
-      );
+      my %search;
+      $search{'agentnum'} = $agentnum
+        if $agentnum;
+      $search{'agent_custid'} = $agent_custid
+        if $agent_custid;
+      $search{'custnum'} = $custnum
+        if $custnum;
       my $cust_main = qsearchs({
         'table'     => 'cust_main',
         'hashref'   => \%search,
         'extra_sql' => $extra_sql,
       });
-      die "can't find customer with agent_custid $agent_custid\n"
+      die "can't find customer with" .
+        ($agentnum ? " agentnum $agentnum" : '') .
+        ($custnum  ? " custnum $custnum" : '') .
+        ($agent_custid ? " agent_custid $agent_custid" : '') . "\n"
         unless $cust_main;
+      die "mismatched customer number\n"
+        if $custnum && ($custnum ne $cust_main->custnum);
       $custnum = $cust_main->custnum;
     }
-    #remove custnum_prefix
-    my $custnum_prefix = $conf->config('cust_main-custnum-display_prefix');
-    my $custnum_length = $conf->config('cust_main-custnum-display_length') || 8;
-    if (
-      $custnum_prefix 
-      && $custnum =~ /^$custnum_prefix(0*([1-9]\d*))$/
-      && length($1) == $custnum_length 
-    ) {
-      $custnum = $2;
-    }
     $hash{'custnum'} = $custnum;
     delete($hash{'agent_custid'});
     return %hash;
   };
 
-  my $opt = { 'table'   => 'cust_pay',
-              'params'  => [ '_date', 'agentnum', 'payby', 'paybatch' ],
-              'formats' => {
-                'simple-csv' => $format,
-                'simple-xls' => $format,
-              },
-              'format_types' => {
-                'simple-csv' => 'csv',
-                'simple-xls' => 'xls',
-              },
-              'default_csv' => 1,
-              'format_hash_callbacks' => { 
-                'simple-csv' => $hashcb,
-                'simple-xls' => $hashcb,
-              },
-              'postinsert_callback' => sub {
-                 my $cust_pay = shift;
-                 my $cust_main = $cust_pay->cust_main ||
-                   return "can't find customer to which payments apply";
-                 my $error = $cust_main->apply_payments_and_credits;
-                 return $error
-                   ? "can't apply payments to customer ".$cust_pay->custnum."$error"
-                   : '';
-              },
-            };
+  my $opt = {
+    'table'        => 'cust_pay',
+    'params'       => [ '_date', 'agentnum', 'payby', 'paybatch' ],
+                        #agent_custid isn't a cust_pay field, see hash callback
+    'formats'      => { 'simple' =>
+                          [ qw(custnum agent_custid paid payinfo invnum) ] },
+    'format_types' => { 'simple' => '' }, #force infer from file extension
+    'default_csv'  => 1, #if not .xls, will read as csv, regardless of extension
+    'format_hash_callbacks' => { 'simple' => $hashcb },
+    'insert_args_callback'  => sub { ( 'manual'=>1 ) },
+    'postinsert_callback'   => sub {
+      my $cust_pay = shift;
+      my $cust_main = $cust_pay->cust_main
+                        or return "can't find customer to which payments apply";
+      my $error = $cust_main->apply_payments_and_credits;
+      return $error
+               ? "can't apply payments to customer ".$cust_pay->custnum."$error"
+               : '';
+    },
+  };
 
   FS::Record::process_batch_import( $job, $opt, @_ );