3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
17 class CRM_Financial_Form_PaymentEdit
extends CRM_Core_Form
{
20 * The id of the financial trxn.
27 * The id of the related contribution ID
31 protected $_contributionID;
34 * The variable which holds the information of a financial transaction
41 * Explicitly declare the form context.
43 public function getDefaultContext() {
48 * Set variables up before form is built.
50 public function preProcess() {
51 $this->_action
= CRM_Core_Action
::UPDATE
;
53 $this->_id
= CRM_Utils_Request
::retrieve('id', 'Positive', $this);
54 $this->assign('id', $this->_id
);
55 $this->_contributionID
= CRM_Utils_Request
::retrieve('contribution_id', 'Positive', $this);
57 $this->_values
= civicrm_api3('FinancialTrxn', 'getsingle', ['id' => $this->_id
]);
58 if (!empty($this->_values
['payment_processor_id'])) {
59 CRM_Core_Error
::statusBounce(ts('You cannot update this payment as it is tied to a payment processor'));
68 public function setDefaultValues() {
69 $defaults = $this->_values
;
70 // Format money fields - localize for display
71 $moneyFields = ['total_amount', 'fee_amount', 'net_amount'];
72 foreach ($moneyFields as $field) {
73 $defaults[$field] = CRM_Utils_Money
::formatLocaleNumericRoundedForDefaultCurrency($this->_values
[$field]);
81 public function buildQuickForm() {
82 CRM_Utils_System
::setTitle(ts('Update Payment details'));
84 $paymentFields = $this->getPaymentFields();
85 $this->assign('paymentFields', $paymentFields);
86 foreach ($paymentFields as $name => $paymentField) {
87 if (!empty($paymentField['add_field'])) {
89 'entity' => 'FinancialTrxn',
92 $this->addField($name, $attributes, $paymentField['is_required']);
95 $this->add($paymentField['htmlType'],
97 $paymentField['title'],
98 $paymentField['attributes'],
99 $paymentField['is_required']
104 $this->assign('currency', CRM_Core_DAO
::getFieldValue('CRM_Financial_DAO_Currency', $this->_values
['currency'], 'symbol', 'name'));
105 $this->addFormRule([__CLASS__
, 'formRule'], $this);
110 'name' => ts('Update'),
115 'name' => ts('Cancel'),
123 * @param array $fields
124 * The input form values.
125 * @param array $files
126 * The uploaded files if any.
130 * true if no errors, else array of errors
132 public static function formRule($fields, $files, $self) {
135 // if Credit Card is chosen and pan_truncation is not NULL ensure that it's value is numeric else throw validation error
136 if (CRM_Core_PseudoConstant
::getName('CRM_Financial_DAO_FinancialTrxn', 'payment_instrument_id', $fields['payment_instrument_id']) == 'Credit Card' &&
137 !empty($fields['pan_truncation']) &&
138 !CRM_Utils_Rule
::numeric($fields['pan_truncation'])
140 $errors['pan_truncation'] = ts('Please enter a valid Card Number');
147 * Process the form submission.
149 public function postProcess() {
152 'payment_instrument_id' => $this->_submitValues
['payment_instrument_id'],
153 'trxn_id' => $this->_submitValues
['trxn_id'] ??
NULL,
154 'trxn_date' => CRM_Utils_Array
::value('trxn_date', $this->_submitValues
, date('YmdHis')),
157 $paymentInstrumentName = CRM_Core_PseudoConstant
::getName('CRM_Financial_DAO_FinancialTrxn', 'payment_instrument_id', $params['payment_instrument_id']);
158 if ($paymentInstrumentName == 'Credit Card') {
159 $params['card_type_id'] = $this->_submitValues
['card_type_id'] ??
NULL;
160 $params['pan_truncation'] = $this->_submitValues
['pan_truncation'] ??
NULL;
162 elseif ($paymentInstrumentName == 'Check') {
163 $params['check_number'] = $this->_submitValues
['check_number'] ??
NULL;
166 $this->submit($params);
168 $contactId = CRM_Core_DAO
::getFieldValue('CRM_Contribute_DAO_Contribution', $this->_contributionID
, 'contact_id');
169 $url = CRM_Utils_System
::url(
170 "civicrm/contact/view/contribution",
171 "reset=1&action=update&id={$this->_contributionID}&cid={$contactId}&context=contribution"
173 CRM_Core_Session
::singleton()->pushUserContext($url);
177 * Wrapper function to process form submission
179 * @param array $submittedValues
182 protected function submit($submittedValues) {
183 // if payment instrument is changed then
184 // 1. Record a new reverse financial transaction with old payment instrument
185 // 2. Record a new financial transaction with new payment instrument
186 // 3. Add EntityFinancialTrxn records to relate with corresponding financial item and contribution
187 if ($submittedValues['payment_instrument_id'] != $this->_values
['payment_instrument_id']) {
188 $previousFinanciaTrxn = $this->_values
;
189 $newFinancialTrxn = $submittedValues;
190 unset($previousFinanciaTrxn['id'], $newFinancialTrxn['id']);
191 $previousFinanciaTrxn['trxn_date'] = CRM_Utils_Array
::value('trxn_date', $submittedValues, date('YmdHis'));
192 $previousFinanciaTrxn['total_amount'] = -$previousFinanciaTrxn['total_amount'];
193 $previousFinanciaTrxn['net_amount'] = -$previousFinanciaTrxn['net_amount'];
194 $previousFinanciaTrxn['fee_amount'] = -$previousFinanciaTrxn['fee_amount'];
195 $previousFinanciaTrxn['contribution_id'] = $newFinancialTrxn['contribution_id'] = $this->_contributionID
;
197 $newFinancialTrxn['to_financial_account_id'] = CRM_Financial_BAO_FinancialTypeAccount
::getInstrumentFinancialAccount($submittedValues['payment_instrument_id']);
198 foreach (['total_amount', 'fee_amount', 'net_amount', 'currency', 'is_payment', 'status_id'] as $fieldName) {
199 $newFinancialTrxn[$fieldName] = $this->_values
[$fieldName];
202 foreach ([$previousFinanciaTrxn, $newFinancialTrxn] as $financialTrxnParams) {
203 $financialTrxn = civicrm_api3('FinancialTrxn', 'create', $financialTrxnParams);
205 'total_amount' => $financialTrxnParams['total_amount'],
206 'contribution_id' => $this->_contributionID
,
208 $contributionTotalAmount = CRM_Core_DAO
::getFieldValue('CRM_Contribute_BAO_Contribution', $this->_contributionID
, 'total_amount');
209 CRM_Contribute_BAO_Contribution
::assignProportionalLineItems($trxnParams, $financialTrxn['id'], $contributionTotalAmount);
213 // simply update the financial trxn
214 civicrm_api3('FinancialTrxn', 'create', $submittedValues);
217 CRM_Financial_BAO_Payment
::updateRelatedContribution($submittedValues, $this->_contributionID
);
221 * Wrapper for unit testing the post process submit function.
223 * @param array $params
225 public function testSubmit($params) {
226 $this->_id
= $params['id'];
227 $this->_contributionID
= $params['contribution_id'];
228 $this->_values
= civicrm_api3('FinancialTrxn', 'getsingle', ['id' => $params['id']]);
230 $this->submit($params);
236 public function getPaymentFields() {
238 'payment_instrument_id' => [
239 'is_required' => TRUE,
243 'is_required' => FALSE,
246 // @TODO we need to show card type icon in place of select field
248 'is_required' => FALSE,
251 'pan_truncation' => [
252 'is_required' => FALSE,
257 'is_required' => FALSE,
260 'htmlType' => 'datepicker',
261 'name' => 'trxn_date',
262 'title' => ts('Transaction Date'),
263 'is_required' => TRUE,
265 'date' => 'yyyy-mm-dd',
270 'htmlType' => 'text',
271 'name' => 'total_amount',
272 'title' => ts('Total Amount'),
273 'is_required' => TRUE,
281 return $paymentFields;