when refunding against a specific card payment, use the card details from the payment...
[freeside.git] / FS / FS / cust_main.pm
index 9144a81..479b19a 100644 (file)
@@ -175,7 +175,7 @@ FS::Record.  The following fields are currently supported:
 
 =item ship_fax - phone (optional)
 
-=item payby - I<CARD> (credit card - automatic), I<DCRD> (credit card - on-demand), I<CHEK> (electronic check - automatic), I<DCHK> (electronic check - on-demand), I<LECB> (Phone bill billing), I<BILL> (billing), I<COMP> (free), or I<PREPAY> (special billing type: applies a credit - see L<FS::prepay_credit> and sets billing type to I<BILL>)
+=item payby - I<CARD> (credit card - automatic), I<DCRD> (credit card - on-demand), I<CHEK> (electronic check - automatic), I<DCHK> (electronic check - on-demand), I<LECB> (Phone bill billing), I<BILL> (billing), I<COMP> (free), or I<PREPAY> (special billing type: applies a payment from a prepaid card - see L<FS::prepay_credit> - and sets billing type to I<BILL>)
 
 =item payinfo - card number, P.O., comp issuer (4-8 lowercase alphanumerics; think username) or prepayment identifier (see L<FS::prepay_credit>)
 
@@ -271,20 +271,28 @@ sub insert {
   local $FS::UID::AutoCommit = 0;
   my $dbh = dbh;
 
-  my $amount = 0;
+  my $prepay_credit = '';
   my $seconds = 0;
   if ( $self->payby eq 'PREPAY' ) {
     $self->payby('BILL');
-    my $prepay_credit = qsearchs(
+    $prepay_credit = qsearchs(
       'prepay_credit',
       { 'identifier' => $self->payinfo },
       '',
       'FOR UPDATE'
     );
-    warn "WARNING: can't find pre-found prepay_credit: ". $self->payinfo
-      unless $prepay_credit;
-    $amount = $prepay_credit->amount;
+    unless ( $prepay_credit ) {
+      $dbh->rollback if $oldAutoCommit;
+      return "Invalid prepaid card: ". $self->payinfo;
+    }
     $seconds = $prepay_credit->seconds;
+    if ( $prepay_credit->agentnum ) {
+      if ( $self->agentnum && $self->agentnum != $prepay_credit->agentnum ) {
+        $dbh->rollback if $oldAutoCommit;
+        return "prepaid card not valid for agent ". $self->agentnum;
+      }
+      $self->agentnum($prepay_credit->agentnum);
+    }
     my $error = $prepay_credit->delete;
     if ( $error ) {
       $dbh->rollback if $oldAutoCommit;
@@ -321,15 +329,18 @@ sub insert {
     return "No svc_acct record to apply pre-paid time";
   }
 
-  if ( $amount ) {
-    my $cust_credit = new FS::cust_credit {
+  if ( $prepay_credit && $prepay_credit->amount ) {
+    my $cust_pay = new FS::cust_pay {
       'custnum' => $self->custnum,
-      'amount'  => $amount,
+      'paid'    => $prepay_credit->amount,
+      #'_date'   => #date the prepaid card was purchased???
+      'payby'   => 'PREP',
+      'payinfo' => $prepay_credit->identifier,
     };
-    $error = $cust_credit->insert;
+    $error = $cust_pay->insert;
     if ( $error ) {
       $dbh->rollback if $oldAutoCommit;
-      return "inserting credit (transaction rolled back): $error";
+      return "inserting prepayment (transaction rolled back): $error";
     }
   }
 
@@ -2111,6 +2122,7 @@ sub realtime_refund_bop {
 
   #first try void if applicable
   if ( $cust_pay && $cust_pay->paid == $amount ) { #and check dates?
+    warn "FS::cust_main::realtime_bop: attempting void\n" if $DEBUG;
     my $void = new Business::OnlinePayment( $processor, @bop_options );
     $void->content( 'action' => 'void', %content );
     $void->submit();
@@ -2123,10 +2135,14 @@ sub realtime_refund_bop {
         warn $e;
         return $e;
       }
+      warn "FS::cust_main::realtime_bop: void successful\n" if $DEBUG;
       return '';
     }
   }
 
+  warn "FS::cust_main::realtime_bop: void unsuccessful, trying refund\n"
+    if $DEBUG;
+
   #massage data
   my $address = $self->address1;
   $address .= ", ". $self->address2 if $self->address2;
@@ -2143,20 +2159,17 @@ sub realtime_refund_bop {
     $payname =  "$payfirst $paylast";
   }
 
-  if ( $method eq 'CC' ) { 
-
-    $content{card_number} = $self->payinfo;
-    $self->paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
-    $content{expiration} = "$2/$1";
+  if ( $method eq 'CC' ) {
 
-    #$content{cvv2} = $self->paycvv
-    #  if defined $self->dbdef_table->column('paycvv')
-    #     && length($self->paycvv);
-
-    #$content{recurring_billing} = 'YES'
-    #  if qsearch('cust_pay', { 'custnum' => $self->custnum,
-    #                           'payby'   => 'CARD',
-    #                           'payinfo' => $self->payinfo, } );
+    if ( $cust_pay ) {
+      $content{card_number} = $cust_pay->payinfo;
+      #$self->paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
+      #$content{expiration} = "$2/$1";
+    } else {
+      $content{card_number} = $self->payinfo;
+      $self->paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
+      $content{expiration} = "$2/$1";
+    }
 
   } elsif ( $method eq 'ECHECK' ) {
     ( $content{account_number}, $content{routing_code} ) =
@@ -2172,7 +2185,7 @@ sub realtime_refund_bop {
 
   #then try refund
   my $refund = new Business::OnlinePayment( $processor, @bop_options );
-  $refund->content(
+  my %sub_content = $refund->content(
     'action'         => 'credit',
     'customer_id'    => $self->custnum,
     'last_name'      => $paylast,
@@ -2185,6 +2198,8 @@ sub realtime_refund_bop {
     'country'        => $self->country,
     %content, #after
   );
+  warn join('', map { "  $_ => $sub_content{$_}\n" } keys %sub_content )
+    if $DEBUG > 1;
   $refund->submit();
 
   return "$processor error: ". $refund->error_message
@@ -2659,6 +2674,19 @@ sub referral_cust_pkg {
       $self->referral_cust_main($depth);
 }
 
+=item referring_cust_main
+
+Returns the single cust_main record for the customer who referred this customer
+(referral_custnum), or false.
+
+=cut
+
+sub referring_cust_main {
+  my $self = shift;
+  return '' unless $self->referral_custnum;
+  qsearchs('cust_main', { 'custnum' => $self->referral_custnum } );
+}
+
 =item credit AMOUNT, REASON
 
 Applies a credit to this customer.  If there is an error, returns the error,