return $null;
}
+ /**
+ * Get the values and resolve the most common mappings.
+ *
+ * Since contribution status is resolved in almost every function that calls getValues it makes
+ * sense to have an extra function to resolve it rather than repeat the code.
+ *
+ * Think carefully before adding more mappings to be resolved as there could be performance implications
+ * if this function starts to be called from more iterative functions.
+ *
+ * @param array $params
+ * Input parameters to find object.
+ *
+ * @return array
+ * Array of the found contribution.
+ * @throws CRM_Core_Exception
+ */
+ public static function getValuesWithMappings($params) {
+ $values = $ids = array();
+ $contribution = self::getValues($params, $values, $ids);
+ if (is_null($contribution)) {
+ throw new CRM_Core_Exception('No contribution found');
+ }
+ $values['contribution_status'] = CRM_Core_PseudoConstant::getName('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $values['contribution_status_id']);
+ return $values;
+ }
+
/**
* Calculate net_amount & fee_amount if they are not set.
*
$params['trxnParams'] = $trxnParams;
if (!empty($params['prevContribution'])) {
+ $updated = FALSE;
$params['trxnParams']['total_amount'] = $trxnParams['total_amount'] = $params['total_amount'] = $params['prevContribution']->total_amount;
$params['trxnParams']['fee_amount'] = $params['prevContribution']->fee_amount;
$params['trxnParams']['net_amount'] = $params['prevContribution']->net_amount;
$params['total_amount'] = $params['trxnParams']['total_amount'] = $trxnParams['total_amount'];
self::updateFinancialAccounts($params);
$params['trxnParams']['to_financial_account_id'] = $trxnParams['to_financial_account_id'];
+ $updated = TRUE;
}
}
) {
//Update Financial Records
self::updateFinancialAccounts($params, 'changedStatus');
+ $updated = TRUE;
}
// change Payment Instrument for a Completed contribution
self::updateFinancialAccounts($params, 'changePaymentInstrument');
$params['total_amount'] = $params['trxnParams']['total_amount'] = $trxnParams['total_amount'];
self::updateFinancialAccounts($params, 'changePaymentInstrument');
+ $updated = TRUE;
}
}
elseif ((!CRM_Utils_System::isNull($params['contribution']->payment_instrument_id) ||
self::updateFinancialAccounts($params, 'changePaymentInstrument');
$params['total_amount'] = $params['trxnParams']['total_amount'] = $trxnParams['total_amount'];
self::updateFinancialAccounts($params, 'changePaymentInstrument');
+ $updated = TRUE;
}
elseif (!CRM_Utils_System::isNull($params['contribution']->check_number) &&
$params['contribution']->check_number != $params['prevContribution']->check_number
$params['trxnParams']['check_number'] = $params['contribution']->check_number;
$params['total_amount'] = $params['trxnParams']['total_amount'] = $trxnParams['total_amount'];
self::updateFinancialAccounts($params, 'changePaymentInstrument');
+ $updated = TRUE;
}
}
//Update Financial Records
$params['trxnParams']['from_financial_account_id'] = NULL;
self::updateFinancialAccounts($params, 'changedAmount');
+ $updated = TRUE;
+ }
+
+ if (!$updated) {
+ // Looks like we might have a data correction update.
+ // This would be a case where a transaction id has been entered but it is incorrect &
+ // the person goes back in & fixes it, as opposed to a new transaction.
+ // Currently the UI doesn't support multiple refunds against a single transaction & we are only supporting
+ // the data fix scenario.
+ // CRM-17751.
+ if (isset($params['refund_trxn_id'])) {
+ $refundIDs = CRM_Core_BAO_FinancialTrxn::getRefundTransactionIDs($params['id']);
+ if ($refundIDs['trxn_id'] != $params['refund_trxn_id']) {
+ civicrm_api3('FinancialTrxn', 'create', array('id' => $refundIDs['financialTrxnId'], 'trxn_id' => $params['refund_trxn_id']));
+ }
+ }
}
}
CRM_Contribute_Form_SoftCredit::setDefaultValues($defaults, $this);
if ($this->_mode) {
+ // @todo - remove this function as the parent does it too.
$config = CRM_Core_Config::singleton();
// Set default country from config if no country set.
if (empty($defaults["billing_country_id-{$this->_bltID}"])) {
$this->assign('is_pay_later', TRUE);
}
$this->assign('contribution_status_id', CRM_Utils_Array::value('contribution_status_id', $defaults));
-
+ if (CRM_Utils_Array::value('contribution_status_id', $defaults) == CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Refunded')) {
+ $defaults['refund_trxn_id'] = CRM_Core_BAO_FinancialTrxn::getRefundTransactionTrxnID($this->_id);
+ }
+ else {
+ $defaults['refund_trxn_id'] = isset($defaults['trxn_id']) ? $defaults['trxn_id'] : NULL;
+ }
$dates = array(
'receive_date',
'receipt_date',
$this->addDateTime('cancel_date', ts('Cancelled / Refunded Date'), FALSE, array('formatType' => 'activityDateTime'));
$this->add('textarea', 'cancel_reason', ts('Cancellation / Refund Reason'), $attributes['cancel_reason']);
-
+ $this->add('text', 'refund_trxn_id', ts('Transaction ID for the refund payment'));
$element = $this->add('select',
'payment_processor_id',
ts('Payment Processor'),
*/
public function preProcess() {
$id = $this->get('id');
- $values = $ids = array();
$params = array('id' => $id);
$context = CRM_Utils_Request::retrieve('context', 'String', $this);
$this->assign('context', $context);
- CRM_Contribute_BAO_Contribution::getValues($params, $values, $ids);
+ $values = CRM_Contribute_BAO_Contribution::getValuesWithMappings($params);
+
if (CRM_Financial_BAO_FinancialType::isACLFinancialTypeStatus() && $this->_action & CRM_Core_Action::VIEW) {
$financialTypeID = CRM_Contribute_PseudoConstant::financialType($values['financial_type_id']);
CRM_Financial_BAO_FinancialType::checkPermissionedLineItems($id, 'view');
$this->assign('noACL', TRUE);
}
CRM_Contribute_BAO_Contribution::resolveDefaults($values);
+ // @todo - I believe this cancelledStatus is unused - if someone reaches the same conclusion
+ // by grepping then the next few lines can go.
$cancelledStatus = TRUE;
$status = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
if (CRM_Utils_Array::value('contribution_status_id', $values) == array_search('Cancelled', $status)) {
$campaigns = CRM_Campaign_BAO_Campaign::getCampaigns($campaignId);
$values['campaign'] = $campaigns[$campaignId];
}
+ if ($values['contribution_status'] == 'Refunded') {
+ $this->assign('refund_trxn_id', CRM_Core_BAO_FinancialTrxn::getRefundTransactionTrxnIDgi($id));
+ }
// assign values to the template
$this->assign($values);
* NOTE: This should be moved to separate BAO for EntityFinancialTrxn when we start adding more code for that object.
*
* @param $entity_id
- * Id of the entity usually the contactID.
+ * Id of the entity usually the contributionID.
* @param string $orderBy
* To get single trxn id for a entity table i.e last or first.
* @param bool $newTrxn
+ * @param string $whereClause
+ * Additional where parameters
*
* @return array
* array of category id's the contact belongs to.
*
*/
- public static function getFinancialTrxnId($entity_id, $orderBy = 'ASC', $newTrxn = FALSE) {
+ public static function getFinancialTrxnId($entity_id, $orderBy = 'ASC', $newTrxn = FALSE, $whereClause = '') {
$ids = array('entityFinancialTrxnId' => NULL, 'financialTrxnId' => NULL);
$condition = "";
$orderBy = CRM_Utils_Type::escape($orderBy, 'String');
}
- $query = "SELECT ceft.id, ceft.financial_trxn_id FROM `civicrm_financial_trxn` cft
+ $query = "SELECT ceft.id, ceft.financial_trxn_id, cft.trxn_id FROM `civicrm_financial_trxn` cft
LEFT JOIN civicrm_entity_financial_trxn ceft
ON ceft.financial_trxn_id = cft.id AND ceft.entity_table = 'civicrm_contribution'
LEFT JOIN civicrm_entity_financial_trxn ceft1
LEFT JOIN civicrm_financial_item cfi ON ceft1.entity_table = 'civicrm_financial_item' and cfi.id = ceft1.entity_id
WHERE ceft.entity_id = %1 AND (cfi.entity_table <> 'civicrm_financial_trxn' or cfi.entity_table is NULL)
{$condition}
+{$whereClause}
ORDER BY cft.id {$orderBy}
LIMIT 1;";
if ($dao->fetch()) {
$ids['entityFinancialTrxnId'] = $dao->id;
$ids['financialTrxnId'] = $dao->financial_trxn_id;
+ $ids['trxn_id'] = $dao->trxn_id;
}
return $ids;
}
+ /**
+ * Get the transaction id for the (latest) refund associated with a contribution.
+ *
+ * @param int $contributionID
+ * @return string
+ */
+ public static function getRefundTransactionTrxnID($contributionID) {
+ $ids = self::getRefundTransactionIDs($contributionID);
+ return isset($ids['trxn_id']) ? $ids['trxn_id'] : NULL;
+ }
+
+ /**
+ * Get the transaction id for the (latest) refund associated with a contribution.
+ *
+ * @param int $contributionID
+ * @return string
+ */
+ public static function getRefundTransactionIDs($contributionID) {
+ $refundStatusID = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Refunded');
+ return self::getFinancialTrxnId($contributionID, 'DESC', FALSE, " AND cft.status_id = $refundStatusID");
+ }
+
/**
* Given an entity_id and entity_table, check for corresponding entity_financial_trxn and financial_trxn record.
* @todo This should be moved to separate BAO for EntityFinancialTrxn when we start adding more code for that object.
<td class="label" style="vertical-align: top;">{$form.cancel_reason.label}</td>
<td>{$form.cancel_reason.html}</td>
</tr>
+ <tr id="refundTrxnID">
+ <td class="label" style="vertical-align: top;">{$form.refund_trxn_id.label}</td>
+ <td>{$form.refund_trxn_id.html}</td>
+ </tr>
</table>
</fieldset>
</td>
<td>{$cancel_reason}</td>
</tr>
{/if}
+ {if $refund_trxn_id}
+ <tr>
+ <td class="label">{ts}Refund Transaction ID{/ts}</td>
+ <td>{$refund_trxn_id}</td>
+ </tr>
+ {/if}
{/if}
<tr>
<td class="label">{ts}Payment Method{/ts}</td>