From da88a16b5b96f6dbee18b315d0076868a513915c Mon Sep 17 00:00:00 2001
From: Eileen <eileen@fuzion.co.nz>
Date: Tue, 12 Nov 2013 11:37:39 +1300
Subject: [PATCH] CRM-13743 use paypal receive date on ipn

----------------------------------------
* CRM-13743: receive_date on paypal contribution should be taken from IPN
  http://issues.civicrm.org/jira/browse/CRM-13743

----------------------------------------
* CRM-13743: receive_date on paypal contribution should be taken from IPN
  http://issues.civicrm.org/jira/browse/CRM-13743
---
 CRM/Core/Payment/PayPalProIPN.php             |  5 ++--
 .../CRM/Core/Payment/PayPalProIPNTest.php     | 27 +++++++++++++++++++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/CRM/Core/Payment/PayPalProIPN.php b/CRM/Core/Payment/PayPalProIPN.php
index a11d39d971..86cee3efef 100644
--- a/CRM/Core/Payment/PayPalProIPN.php
+++ b/CRM/Core/Payment/PayPalProIPN.php
@@ -274,16 +274,16 @@ class CRM_Core_Payment_PayPalProIPN extends CRM_Core_Payment_BaseIPN {
       $contribution->financial_type_id  = $objects['contributionType']->id;
       $contribution->contribution_page_id = $ids['contributionPage'];
       $contribution->contribution_recur_id = $ids['contributionRecur'];
-      $contribution->receive_date = $now;
       $contribution->currency = $objects['contribution']->currency;
       $contribution->payment_instrument_id = $objects['contribution']->payment_instrument_id;
       $contribution->amount_level = $objects['contribution']->amount_level;
       $contribution->honor_contact_id = $objects['contribution']->honor_contact_id;
       $contribution->honor_type_id = $objects['contribution']->honor_type_id;
       $contribution->campaign_id = $objects['contribution']->campaign_id;
-
       $objects['contribution'] = &$contribution;
     }
+    // CRM-13737 - am not aware of any reason why payment_date would not be set - this if is a belt & braces
+    $objects['contribution']->receive_date = !empty($input['payment_date']) ? date('YmdHis', strtotime($input['payment_date'])): $now;
 
     $this->single($input, $ids, $objects,
       TRUE, $first
@@ -462,6 +462,7 @@ INNER JOIN civicrm_membership_payment mp ON m.id = mp.membership_id AND mp.contr
     $input['fee_amount'] = self::retrieve('mc_fee', 'Money', 'POST', FALSE);
     $input['net_amount'] = self::retrieve('settle_amount', 'Money', 'POST', FALSE);
     $input['trxn_id']    = self::retrieve('txn_id', 'String', 'POST', FALSE);
+    $input['payment_date'] = self::retrieve('payment_date', 'String', 'POST', FALSE);
   }
 
   /**
diff --git a/tests/phpunit/CRM/Core/Payment/PayPalProIPNTest.php b/tests/phpunit/CRM/Core/Payment/PayPalProIPNTest.php
index 2441ca9eb8..cf22aa8d54 100644
--- a/tests/phpunit/CRM/Core/Payment/PayPalProIPNTest.php
+++ b/tests/phpunit/CRM/Core/Payment/PayPalProIPNTest.php
@@ -99,6 +99,33 @@ class CRM_Core_Payment_PayPalProIPNTest extends CiviUnitTestCase {
     $this->assertEquals('secondone', $contribution['values'][1]['trxn_id']);
   }
 
+  /**
+   * CRM-13743 test IPN edge case where the first transaction fails and the second succeeds
+   * We are checking that the created contribution has the same date as IPN says it should
+   * Note that only one contribution will be created (no evidence of the failed contribution is left)
+   * It seems likely that may change in future & this test will start failing (I point this out in the hope it
+   * will help future debuggers)
+   */
+  function testIPNPaymentCRM13743() {
+    $this->setupPaymentProcessorTransaction();
+    $firstPaymentParams = $this->getPaypalProRecurTransaction();
+    $firstPaymentParams['txn_type'] = 'recurring_payment_failed';
+    $paypalIPN = new CRM_Core_Payment_PayPalProIPN($firstPaymentParams);
+    $paypalIPN->main();
+
+    $contribution = $this->callAPISuccess('contribution', 'getsingle', array('id' => $this->_contributionID));
+    $this->assertEquals(2, $contribution['contribution_status_id']);
+    $this->assertEquals('', $contribution['trxn_id']);
+    $contributionRecur = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $this->_contributionRecurID));
+    $this->assertEquals(2, $contributionRecur['contribution_status_id']);
+    $paypalIPN = new CRM_Core_Payment_PayPalProIPN($this->getPaypalProRecurSubsequentTransaction());
+    $paypalIPN->main();
+    $contribution = $this->callAPISuccess('contribution', 'get', array('contribution_recur_id' => $this->_contributionRecurID, 'sequential' => 1));
+    $this->assertEquals(1, $contribution['count']);
+    $this->assertEquals('secondone', $contribution['values'][0]['trxn_id']);
+    $this->assertEquals(strtotime('03:59:05 Jul 14, 2013 PDT'), strtotime($contribution['values'][0]['receive_date']));
+  }
+
   /**
    * check a payment express IPN call does not throw any errors
    * At this stage nothing it supposed to happen so it's a pretty blunt test
-- 
2.25.1