CRM-20392 (IIDA-108), Fixed submit Credit Card transaction for partially paid contrib...
authordeb.monish <monish.deb@jmaconsulting.biz>
Sat, 29 Apr 2017 02:23:32 +0000 (14:23 +1200)
committereileen <emcnaughton@wikimedia.org>
Sat, 29 Apr 2017 02:24:03 +0000 (14:24 +1200)
CRM/Contribute/Form/AbstractEditPayment.php
CRM/Contribute/Form/AdditionalPayment.php
CRM/Financial/Page/FinancialAccount.php
CRM/Financial/Page/FinancialBatch.php
CRM/Financial/Page/FinancialType.php
templates/CRM/Contribute/Form/AdditionalPayment.tpl
tests/phpunit/CRM/Contribute/Form/AdditionalPaymentTest.php

index ceed89165e91018413f93cce4e524ca4a0ac864f..241638a015a5dd161ef80753fc61f7be4640f729 100644 (file)
@@ -611,6 +611,8 @@ WHERE  contribution_id = {$id}
         CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_contactID, 'contact_type')
       );
     }
+
+    $this->assignBillingName($this->_params);
   }
 
   /**
index 9d33d5c9d053f3d2211c16dc3f6eccceb9904c65..aa72650c7db5ca18dc02339d9f34f40b3c5c1af0 100644 (file)
@@ -211,9 +211,10 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
     }
 
     CRM_Core_Payment_Form::buildPaymentForm($this, $this->_paymentProcessor, FALSE, TRUE, CRM_Utils_Request::retrieve('payment_instrument_id', 'Integer'));
+    $this->add('select', 'payment_processor_id', ts('Payment Processor'), $this->_processors, NULL);
+
     $attributes = CRM_Core_DAO::getAttribute('CRM_Financial_DAO_FinancialTrxn');
 
-    $this->add('select', 'payment_processor_id', ts('Payment Processor'), $this->_processors, NULL);
     $label = ($this->_refund) ? ts('Refund Amount') : ts('Payment Amount');
     $this->addMoney('total_amount',
       $label,
@@ -222,16 +223,6 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
       TRUE, 'currency', NULL
     );
 
-    $this->add('select', 'payment_instrument_id',
-      ts('Payment Method'),
-      array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::paymentInstrument(),
-      FALSE,
-      array('onChange' => "return showHideByValue('payment_instrument_id','4','checkNumber','table-row','select',false);")
-    );
-
-    $this->add('text', 'check_number', ts('Check Number'), $attributes['financial_trxn_check_number']);
-    $this->add('text', 'trxn_id', ts('Transaction ID'), array('class' => 'twelve') + $attributes['trxn_id']);
-
     //add receipt for offline contribution
     $this->addElement('checkbox', 'is_email_receipt', ts('Send Receipt?'));
 
@@ -254,19 +245,30 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
     $this->assign('component', $this->_component);
     $this->assign('email', $this->_contributorEmail);
 
-    $this->add('text', 'fee_amount', ts('Fee Amount'),
-      $attributes['fee_amount']
-    );
-    $this->addRule('fee_amount', ts('Please enter a valid monetary value for Fee Amount.'), 'money');
-
-    $this->add('text', 'net_amount', ts('Net Amount'),
-      $attributes['net_amount']
-    );
-    $this->addRule('net_amount', ts('Please enter a valid monetary value for Net Amount.'), 'money');
-
     $js = NULL;
+    // render backoffice payment fields only on offline mode
     if (!$this->_mode) {
       $js = array('onclick' => "return verify( );");
+
+      $this->add('select', 'payment_instrument_id',
+        ts('Payment Method'),
+        array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::paymentInstrument(),
+        FALSE,
+        array('onChange' => "return showHideByValue('payment_instrument_id','4','checkNumber','table-row','select',false);")
+      );
+
+      $this->add('text', 'check_number', ts('Check Number'), $attributes['financial_trxn_check_number']);
+      $this->add('text', 'trxn_id', ts('Transaction ID'), array('class' => 'twelve') + $attributes['trxn_id']);
+
+      $this->add('text', 'fee_amount', ts('Fee Amount'),
+        $attributes['fee_amount']
+      );
+      $this->addRule('fee_amount', ts('Please enter a valid monetary value for Fee Amount.'), 'money');
+
+      $this->add('text', 'net_amount', ts('Net Amount'),
+        $attributes['net_amount']
+      );
+      $this->addRule('net_amount', ts('Please enter a valid monetary value for Net Amount.'), 'money');
     }
 
     $buttonName = $this->_refund ? 'Record Refund' : 'Record Payment';
@@ -339,6 +341,8 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
   public function submit($submittedValues) {
     $this->_params = $submittedValues;
     $this->beginPostProcess();
+    $this->_contributorContactID = $this->_contactID;
+    $this->processBillingAddress();
     $participantId = NULL;
     if ($this->_component == 'event') {
       $participantId = $this->_id;
@@ -361,7 +365,7 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
     if ($this->_mode) {
       // process credit card
       $this->assign('contributeMode', 'direct');
-      $this->processCreditCard($this->_params);
+      $this->processCreditCard();
     }
 
     $defaults = array();
@@ -392,78 +396,22 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
     CRM_Core_Session::setStatus($statusMsg, ts('Saved'), 'success');
   }
 
-  /**
-   * @param $submittedValues
-   */
-  public function processCreditCard($submittedValues) {
+  public function processCreditCard() {
     $config = CRM_Core_Config::singleton();
     $session = CRM_Core_Session::singleton();
 
-    $unsetParams = array(
-      'trxn_id',
-      'payment_instrument_id',
-      'contribution_status_id',
-    );
-    foreach ($unsetParams as $key) {
-      if (isset($submittedValues[$key])) {
-        unset($submittedValues[$key]);
-      }
-    }
-
-    // Get the required fields value only.
-    $params = $submittedValues;
-
     $now = date('YmdHis');
     $fields = array();
 
     // we need to retrieve email address
-    if ($this->_context == 'standalone' && !empty($submittedValues['is_email_receipt'])) {
+    if ($this->_context == 'standalone' && !empty($this->_params['is_email_receipt'])) {
       list($this->userDisplayName,
         $this->userEmail
         ) = CRM_Contact_BAO_Contact_Location::getEmailDetails($this->_contactId);
       $this->assign('displayName', $this->userDisplayName);
     }
 
-    //set email for primary location.
-    $fields['email-Primary'] = 1;
-    $params['email-Primary'] = $this->_contributorEmail;
-
-    // now set the values for the billing location.
-    foreach ($this->_fields as $name => $dontCare) {
-      $fields[$name] = 1;
-    }
-
-    // also add location name to the array
-    $params["address_name-{$this->_bltID}"] = CRM_Utils_Array::value('billing_first_name', $params) . ' ' . CRM_Utils_Array::value('billing_middle_name', $params) . ' ' . CRM_Utils_Array::value('billing_last_name', $params);
-    $params["address_name-{$this->_bltID}"] = trim($params["address_name-{$this->_bltID}"]);
-    $fields["address_name-{$this->_bltID}"] = 1;
-
-    $ctype = civicrm_api3('Contact', 'getvalue', array(
-      'return' => "contact_type",
-      'id' => $this->_contactId,
-    ));
-
-    $nameFields = array('first_name', 'middle_name', 'last_name');
-    foreach ($nameFields as $name) {
-      $fields[$name] = 1;
-      if (array_key_exists("billing_$name", $params)) {
-        $params[$name] = $params["billing_{$name}"];
-        $params['preserveDBName'] = TRUE;
-      }
-    }
-
-    if (!empty($params['source'])) {
-      unset($params['source']);
-    }
-    $contactID = CRM_Contact_BAO_Contact::createProfileContact($params, $fields,
-      $this->_contactId,
-      NULL, NULL,
-      $ctype
-    );
-
-    // Add all the additional payment params we need.
-    $this->_params["state_province-{$this->_bltID}"] = $this->_params["billing_state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($this->_params["billing_state_province_id-{$this->_bltID}"]);
-    $this->_params["country-{$this->_bltID}"] = $this->_params["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($this->_params["billing_country_id-{$this->_bltID}"]);
+    $this->formatParamsForPaymentProcessor($this->_params);
 
     $this->_params['amount'] = $this->_params['total_amount'];
     // @todo - stop setting amount level in this function & call the CRM_Price_BAO_PriceSet::getAmountLevel
@@ -480,6 +428,10 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
       $this->_params['receive_date'] = $this->_params['trxn_date'];
     }
 
+    if (empty($this->_params['receive_date'])) {
+      $this->_params['receive_date'] = date('YmdHis');
+    }
+
     if (empty($this->_params['invoice_id'])) {
       $this->_params['invoiceID'] = md5(uniqid(rand(), TRUE));
     }
@@ -487,13 +439,13 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
       $this->_params['invoiceID'] = $this->_params['invoice_id'];
     }
 
-    $this->assignBillingName($params);
     $this->assign('address', CRM_Utils_Address::getFormattedBillingAddressFieldsFromParameters(
-      $params,
+      $this->_params,
       $this->_bltID
     ));
 
     //Add common data to formatted params
+    $params = $this->_params;
     CRM_Contribute_Form_AdditionalInfo::postProcessCommon($params, $this->_params, $this);
     // at this point we've created a contact and stored its address etc
     // all the payment processors expect the name and address to be in the
@@ -505,17 +457,10 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
     $paymentParams['contributionPageID'] = NULL;
     if (!empty($this->_params['is_email_receipt'])) {
       $paymentParams['email'] = $this->_contributorEmail;
-      $paymentParams['is_email_receipt'] = 1;
+      $paymentParams['is_email_receipt'] = TRUE;
     }
     else {
-      $paymentParams['is_email_receipt'] = 0;
-      $this->_params['is_email_receipt'] = 0;
-    }
-    if (!empty($this->_params['receive_date'])) {
-      $paymentParams['receive_date'] = $this->_params['receive_date'];
-    }
-    if (!empty($this->_params['receive_date'])) {
-      $paymentParams['receive_date'] = $this->_params['receive_date'];
+      $paymentParams['is_email_receipt'] = $this->_params['is_email_receipt'] = FALSE;
     }
 
     $result = NULL;
@@ -527,17 +472,13 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
         $result = $payment->doPayment($paymentParams);
       }
       catch (\Civi\Payment\Exception\PaymentProcessorException $e) {
-        //set the contribution mode.
-        $urlParams = "action=add&cid={$this->_contactId}&id={$this->_id}&component={$this->_component}";
-        if ($this->_mode) {
-          $urlParams .= "&mode={$this->_mode}";
-        }
-        CRM_Core_Error::displaySessionError($result);
-        CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/payment/add', $urlParams));
+        Civi::log()->error('Payment processor exception: ' . $e->getMessage());
+        $urlParams = "action=add&cid={$this->_contactId}&id={$this->_contributionId}&component={$this->_component}&mode={$this->_mode}";
+        CRM_Core_Error::statusBounce(CRM_Utils_System::url($e->getMessage(), 'civicrm/payment/add', $urlParams));
       }
     }
 
-    if ($result) {
+    if (!empty($result)) {
       $this->_params = array_merge($this->_params, $result);
     }
 
@@ -568,13 +509,13 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
     // email receipt sending
     // send message template
     if ($this->_component == 'event') {
-      $eventId = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Participant', $this->_id, 'event_id', 'id');
 
-      $returnProperties = array('fee_label', 'start_date', 'end_date', 'is_show_location', 'title');
-      CRM_Core_DAO::commonRetrieveAll('CRM_Event_DAO_Event', 'id', $eventId, $events, $returnProperties);
-      $event = $events[$eventId];
-      unset($event['start_date']);
-      unset($event['end_date']);
+      // fetch event information from participant ID using API
+      $eventId = civicrm_api3('Participant', 'getvalue', array(
+        'return' => "event_id",
+        'id' => $this->_id,
+      ));
+      $event = civicrm_api3('Event', 'getsingle', array('id' => $eventId));
 
       $this->assign('event', $event);
       $this->assign('isShowLocation', $event['is_show_location']);
@@ -591,18 +532,19 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
     // assign payment info here
     $paymentConfig['confirm_email_text'] = CRM_Utils_Array::value('confirm_email_text', $params);
     $this->assign('paymentConfig', $paymentConfig);
+
+    $this->assign('totalAmount', $this->_amtTotal);
+
     $isRefund = ($this->_paymentType == 'refund') ? TRUE : FALSE;
     $this->assign('isRefund', $isRefund);
     if ($isRefund) {
       $this->assign('totalPaid', $this->_amtPaid);
-      $this->assign('totalAmount', $this->_amtTotal);
       $this->assign('refundAmount', $params['total_amount']);
     }
     else {
       $balance = $this->_amtTotal - ($this->_amtPaid + $params['total_amount']);
       $paymentsComplete = ($balance == 0) ? 1 : 0;
       $this->assign('amountOwed', $balance);
-      $this->assign('totalAmount', $this->_amtTotal);
       $this->assign('paymentAmount', $params['total_amount']);
       $this->assign('paymentsComplete', $paymentsComplete);
     }
@@ -611,14 +553,11 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
     // assign trxn details
     $this->assign('trxn_id', CRM_Utils_Array::value('trxn_id', $params));
     $this->assign('receive_date', CRM_Utils_Array::value('trxn_date', $params));
-    $paymentInstrument = CRM_Contribute_PseudoConstant::paymentInstrument();
-    if (array_key_exists('payment_instrument_id', $params)) {
-      $this->assign('paidBy',
-        CRM_Utils_Array::value($params['payment_instrument_id'],
-          $paymentInstrument
-        )
-      );
-    }
+    $this->assign('paidBy', CRM_Core_PseudoConstant::getLabel(
+      'CRM_Contribute_BAO_Contribute',
+      'payment_instrument_id',
+      $params['payment_instrument_id']
+    ));
     $this->assign('checkNumber', CRM_Utils_Array::value('check_number', $params));
 
     $sendTemplateParams = array(
@@ -687,6 +626,8 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
     }
 
     $this->_fields = array();
+    $this->set('cid', $this->_contactId);
+    parent::preProcess();
     $this->submit($params);
   }
 
index 0d4718b6e2883fcd7a447f70f42e04be935b436b..3bfe8862a2b6c3d9ee8b2ea2d36b596978052289 100644 (file)
@@ -90,6 +90,30 @@ class CRM_Financial_Page_FinancialAccount extends CRM_Core_Page_Basic {
     return self::$_links;
   }
 
+  /**
+   * Run the page.
+   *
+   * This method is called after the page is created. It checks for the
+   * type of action and executes that action.
+   * Finally it calls the parent's run method.
+   */
+  public function run() {
+    // get the requested action
+    $action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE, 'browse'); // default to 'browse'
+
+    // assign vars to templates
+    $this->assign('action', $action);
+    $id = CRM_Utils_Request::retrieve('id', 'Positive', $this, FALSE, 0);
+
+    // what action to take ?
+    if ($action & (CRM_Core_Action::UPDATE | CRM_Core_Action::ADD)) {
+      $this->edit($action, $id);
+    }
+
+    // parent run
+    return parent::run();
+  }
+
   /**
    * Browse all custom data groups.
    */
index bf3da74b7aec937fc24e812d49aaf943f4e6b102..17b9cf84b7ef00c1d862a91a1855251e0c5646f3 100644 (file)
@@ -76,6 +76,19 @@ class CRM_Financial_Page_FinancialBatch extends CRM_Core_Page_Basic {
   public function run() {
     $context = CRM_Utils_Request::retrieve('context', 'String', $this);
     $this->set("context", $context);
+    // assign vars to templates
+    $id = CRM_Utils_Request::retrieve('id', 'Positive', $this, FALSE, 0);
+    $action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE, 'browse'); // default to 'browse'
+
+    // what action to take ?
+    if ($action & (CRM_Core_Action::UPDATE |
+        CRM_Core_Action::ADD |
+        CRM_Core_Action::CLOSE |
+        CRM_Core_Action::REOPEN |
+        CRM_Core_Action::EXPORT)
+    ) {
+      $this->edit($action, $id);
+    }
     // parent run
     return parent::run();
   }
index 53d31b84b674e10358f93af7889d12e866cd350d..7d3ff037d8020915e8df98dc381d619ab86c4b8c 100644 (file)
@@ -96,6 +96,30 @@ class CRM_Financial_Page_FinancialType extends CRM_Core_Page_Basic {
     return self::$_links;
   }
 
+  /**
+   * Run the page.
+   *
+   * This method is called after the page is created. It checks for the
+   * type of action and executes that action.
+   * Finally it calls the parent's run method.
+   */
+  public function run() {
+    // get the requested action
+    $action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE, 'browse'); // default to 'browse'
+
+    // assign vars to templates
+    $this->assign('action', $action);
+    $id = CRM_Utils_Request::retrieve('id', 'Positive', $this, FALSE, 0);
+
+    // what action to take ?
+    if ($action & (CRM_Core_Action::UPDATE | CRM_Core_Action::ADD)) {
+      $this->edit($action, $id);
+    }
+
+    // parent run
+    return parent::run();
+  }
+
   /**
    * Browse all financial types.
    */
index 9a18a9c9e187ba98b05b8f8473e4abca291f6b12..93c93b6211cc9b3d1c54f9c6aef4fd5debe0b953 100644 (file)
@@ -63,9 +63,9 @@
 <div class="crm-block crm-form-block crm-payment-form-block">
 
   {if !$email}
-  <div class="messages status no-popup">
-    <div class="icon inform-icon"></div>&nbsp;{ts}You will not be able to send an automatic email receipt for this payment because there is no email address recorded for this contact. If you want a receipt to be sent when this payment is recorded, click Cancel and then click Edit from the Summary tab to add an email address before recording the payment.{/ts}
-  </div>
+    <div class="messages status no-popup">
+      <div class="icon inform-icon"></div>&nbsp;{ts}You will not be able to send an automatic email receipt for this payment because there is no email address recorded for this contact. If you want a receipt to be sent when this payment is recorded, click Cancel and then click Edit from the Summary tab to add an email address before recording the payment.{/ts}
+    </div>
   {/if}
   {if $newCredit AND $contributionMode EQ null}
     {if $contactId}
       <td>
         <span id='totalAmount'>{$form.currency.html|crmAddClass:eight}&nbsp;{$form.total_amount.html|crmAddClass:eight}</span>&nbsp; <span class="status">{if $paymentType EQ 'refund'}{ts}Refund Due{/ts}{else}{ts}Balance Owed{/ts}{/if}:&nbsp;{$paymentAmt|crmMoney}</span>
       </td>
+      {if $email and $outBound_option != 2}
+        <tr class="crm-payment-form-block-is_email_receipt">
+          <td class="label">
+            {$form.is_email_receipt.label}
+          </td>
+          <td>{$form.is_email_receipt.html}&nbsp;
+              <span class="description">{ts 1=$email}Automatically email a receipt to %1?{/ts}</span>
+          </td>
+        </tr>
+        <tr id="fromEmail" class="crm-payment-form-block-from_email_address" style="display:none;">
+          <td class="label">{$form.from_email_address.label}</td>
+          <td>{$form.from_email_address.html}</td>
+        </tr>
+      {/if}
     </tr>
    </table>
 
             <td class="label">{$form.trxn_id.label}</td>
             <td>{$form.trxn_id.html} {help id="id-trans_id"}</td>
           </tr>
-          {if $email and $outBound_option != 2}
-            <tr class="crm-payment-form-block-is_email_receipt">
-              <td class="label">
-                {$form.is_email_receipt.label}</td><td>{$form.is_email_receipt.html}&nbsp;
-                <span class="description">{ts 1=$email}Automatically email a receipt to %1?{/ts}</span>
-              </td>
-            </tr>
-          {/if}
-          <tr id="fromEmail" class="crm-payment-form-block-receipt_date" style="display:none;">
-            <td class="label">{$form.from_email_address.label}</td>
-            <td>{$form.from_email_address.html}</td>
-          </tr>
-          <tr id='notice' class="crm-event-eventfees-form-block-receipt_text">
-            <td class="label">{$form.receipt_text.label}</td>
-            <td><span class="description">
-                {ts}Enter a message you want included at the beginning of the confirmation email.{/ts}
-                </span><br />
-                {$form.receipt_text.html|crmAddClass:huge}
-            </td>
-          </tr>
-           <tr class="crm-payment-form-block-fee_amount"><td class="label">{$form.fee_amount.label}</td><td>{$form.fee_amount.html|crmMoney:$currency:'XXX':'YYY'}<br />
+          <tr class="crm-payment-form-block-fee_amount"><td class="label">{$form.fee_amount.label}</td><td{$valueStyle}>{$form.fee_amount.html|crmMoney:$currency:'XXX':'YYY'}<br />
             <span class="description">{ts}Processing fee for this transaction (if applicable).{/ts}</span></td></tr>
            <tr class="crm-payment-form-block-net_amount"><td class="label">{$form.net_amount.label}</td><td>{$form.net_amount.html|crmMoney:$currency:'':1}<br />
             <span class="description">{ts}Net value of the payment (Total Amount minus Fee).{/ts}</span></td></tr>
index 544f8ab1adb2e88a605a8797c18a75b01b2590b1..07055bf7bbd35aca3d9e02b980ba8e8cad5fad41 100644 (file)
@@ -322,6 +322,7 @@ class CRM_Contribute_Form_AdditionalPaymentTest extends CiviUnitTestCase {
         'check_number' => 'check-12345',
       );
     }
+    $form->cid = $this->_individualId;
     $form->testSubmit($submitParams, $mode);
   }