//if contribution is created with cancelled or refunded status, add credit note id
if (!empty($params['contribution_status_id'])) {
$contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
-
+ // @todo - should we include Chargeback? If so use self::isContributionStatusNegative($params['contribution_status_id'])
if (($params['contribution_status_id'] == array_search('Refunded', $contributionStatus)
|| $params['contribution_status_id'] == array_search('Cancelled', $contributionStatus))
) {
'payment_instrument_id' => $params['contribution']->payment_instrument_id,
'check_number' => CRM_Utils_Array::value('check_number', $params),
);
- if ($contributionStatus == 'Refunded') {
+ if ($contributionStatus == 'Refunded' || $contributionStatus == 'Chargeback') {
$trxnParams['trxn_date'] = !empty($params['contribution']->cancel_date) ? $params['contribution']->cancel_date : date('YmdHis');
if (isset($params['refund_trxn_id'])) {
// CRM-17751 allow a separate trxn_id for the refund to be passed in via api & form.
$contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
$cancelledTaxAmount = 0;
if ($previousContributionStatus == 'Completed'
- && ($params['contribution']->contribution_status_id == array_search('Refunded', $contributionStatus)
- || $params['contribution']->contribution_status_id == array_search('Cancelled', $contributionStatus))
+ && (self::isContributionStatusNegative($params['contribution']->contribution_status_id))
) {
$params['trxnParams']['total_amount'] = -$params['total_amount'];
$cancelledTaxAmount = CRM_Utils_Array::value('tax_amount', $params, '0.00');
$currency = $params['contribution']->currency;
}
$diff = 1;
- if ($context == 'changeFinancialType' || $params['contribution']->contribution_status_id == array_search('Cancelled', $contributionStatus)
- || $params['contribution']->contribution_status_id == array_search('Refunded', $contributionStatus)
- ) {
+ if ($context == 'changeFinancialType' || self::isContributionStatusNegative($params['contribution']->contribution_status_id)) {
$diff = -1;
}
if (!empty($params['is_quick_config'])) {
}
}
+ /**
+ * Is this contribution status a reversal.
+ *
+ * If so we would expect to record a negative value in the financial_trxn table.
+ *
+ * @param int $status_id
+ *
+ * @return bool
+ */
+ public static function isContributionStatusNegative($status_id) {
+ $reversalStatuses = array('Cancelled', 'Chargeback', 'Refunded');
+ return in_array(CRM_Contribute_PseudoConstant::contributionStatus($status_id, 'name'), $reversalStatuses);
+ }
+
/**
* Check status validation on update of a contribution.
*
$contributionStatuses = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
$checkStatus = array(
'Cancelled' => array('Completed', 'Refunded'),
- 'Completed' => array('Cancelled', 'Refunded'),
+ 'Completed' => array('Cancelled', 'Refunded', 'Chargeback'),
'Pending' => array('Cancelled', 'Completed', 'Failed'),
'In Progress' => array('Cancelled', 'Completed', 'Failed'),
'Refunded' => array('Cancelled', 'Completed'),
)));
}
+ /**
+ * Refund a contribution for a financial type with a contra account.
+ *
+ * CRM-17951 the contra account is a financial account with a relationship to a
+ * financial type. It is not always configured but should be reflected
+ * in the financial_trxn & financial_item table if it is.
+ */
+ public function testCreateUpdateChargebackContributionDefaultAccount() {
+ $contribution = $this->callAPISuccess('Contribution', 'create', $this->_params);
+ $this->callAPISuccess('Contribution', 'create', array(
+ 'id' => $contribution['id'],
+ 'contribution_status_id' => 'Chargeback',
+ ));
+ $this->callAPISuccessGetSingle('Contribution', array('contribution_status_id' => 'Chargeback'));
+
+ $lineItems = $this->callAPISuccessGetSingle('LineItem', array(
+ 'contribution_id' => $contribution['id'],
+ 'api.FinancialItem.getsingle' => array('amount' => array('<' => 0)),
+ ));
+ $this->assertEquals(1, $lineItems['api.FinancialItem.getsingle']['financial_account_id']);
+ $this->callAPISuccessGetSingle('FinancialTrxn', array(
+ 'total_amount' => -100,
+ 'status_id' => 'Chargeback',
+ 'to_financial_account_id' => 6,
+ ));
+ }
+
+ /**
+ * Refund a contribution for a financial type with a contra account.
+ *
+ * CRM-17951 the contra account is a financial account with a relationship to a
+ * financial type. It is not always configured but should be reflected
+ * in the financial_trxn & financial_item table if it is.
+ */
+ public function testCreateUpdateChargebackContributionCustomAccount() {
+ $financialAccount = $this->callAPISuccess('FinancialAccount', 'create', array(
+ 'name' => 'Chargeback Account',
+ 'is_active' => TRUE,
+ ));
+
+ $entityFinancialAccount = $this->callAPISuccess('EntityFinancialAccount', 'create', array(
+ 'entity_id' => $this->_financialTypeId,
+ 'entity_table' => 'civicrm_financial_type',
+ 'account_relationship' => 'Chargeback Account is',
+ 'financial_account_id' => 'Chargeback Account',
+ ));
+
+ $contribution = $this->callAPISuccess('Contribution', 'create', $this->_params);
+ $this->callAPISuccess('Contribution', 'create', array(
+ 'id' => $contribution['id'],
+ 'contribution_status_id' => 'Chargeback',
+ ));
+ $this->callAPISuccessGetSingle('Contribution', array('contribution_status_id' => 'Chargeback'));
+
+ $lineItems = $this->callAPISuccessGetSingle('LineItem', array(
+ 'contribution_id' => $contribution['id'],
+ 'api.FinancialItem.getsingle' => array('amount' => array('<' => 0)),
+ ));
+ $this->assertEquals($financialAccount['id'], $lineItems['api.FinancialItem.getsingle']['financial_account_id']);
+
+ $this->callAPISuccess('Contribution', 'delete', array('id' => $contribution['id']));
+ $this->callAPISuccess('EntityFinancialAccount', 'delete', array('id' => $entityFinancialAccount['id']));
+ $this->callAPISuccess('FinancialAccount', 'delete', array('id' => $financialAccount['id']));
+ }
+
/**
* Refund a contribution for a financial type with a contra account.
*
'contribution_status_id' => 'Refunded',
));
- $lineItems = $this->callAPISuccessGetSingle(
- 'LineItem', array(
+ $lineItems = $this->callAPISuccessGetSingle('LineItem', array(
'contribution_id' => $contribution['id'],
'api.FinancialItem.getsingle' => array('amount' => array('<' => 0)),
));
$this->callAPISuccess('Contribution', 'delete', array('id' => $contribution['id']));
$this->callAPISuccess('EntityFinancialAccount', 'delete', array('id' => $entityFinancialAccount['id']));
$this->callAPISuccess('FinancialAccount', 'delete', array('id' => $financialAccount['id']));
-
}
/**
}
/**
+ * Check financial transaction.
+ *
+ * @todo break this down into sensible functions - most calls to it only use a few lines out of the big if.
+ *
* @param array $contribution
* @param string $context
* @param int $instrumentId
+ * @param array $extraParams
*/
public function _checkFinancialTrxn($contribution, $context, $instrumentId = NULL, $extraParams = array()) {
$trxnParams = array(