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 * Should financials be checked after the test but before tear down.
22 * Ideally all tests (or at least all that call any financial api calls ) should do this but there
23 * are some test data issues and some real bugs currently blocking.
27 protected $isValidateFinancialsOnPostAssert = TRUE;
30 * The id of the financial trxn.
37 * The id of the related contribution ID
41 protected $_contributionID;
44 * Get the related contribution id.
48 public function getContributionID(): int {
49 return $this->_contributionID
;
53 * The variable which holds the information of a financial transaction
60 * Explicitly declare the form context.
62 public function getDefaultContext() {
67 * Set variables up before form is built.
69 public function preProcess() {
70 $this->_action
= CRM_Core_Action
::UPDATE
;
72 $this->_id
= CRM_Utils_Request
::retrieve('id', 'Positive', $this);
73 $this->assign('id', $this->_id
);
74 $this->_contributionID
= CRM_Utils_Request
::retrieve('contribution_id', 'Positive', $this);
76 $this->_values
= civicrm_api3('FinancialTrxn', 'getsingle', ['id' => $this->_id
]);
77 if (!empty($this->_values
['payment_processor_id'])) {
78 CRM_Core_Error
::statusBounce(ts('You cannot update this payment as it is tied to a payment processor'));
87 public function setDefaultValues() {
88 $defaults = $this->_values
;
89 $defaults['total_amount'] = CRM_Utils_Money
::formatLocaleNumericRoundedForDefaultCurrency($this->_values
['total_amount']);
96 public function buildQuickForm() {
97 $this->setTitle(ts('Update Payment details'));
99 $paymentFields = $this->getPaymentFields();
100 $this->assign('paymentFields', $paymentFields);
101 foreach ($paymentFields as $name => $paymentField) {
102 if (!empty($paymentField['add_field'])) {
104 'entity' => 'FinancialTrxn',
107 $this->addField($name, $attributes, $paymentField['is_required']);
110 $this->add($paymentField['htmlType'],
112 $paymentField['title'],
113 $paymentField['attributes'],
114 $paymentField['is_required']
119 $this->assign('currency', CRM_Core_DAO
::getFieldValue('CRM_Financial_DAO_Currency', $this->_values
['currency'], 'symbol', 'name'));
120 $this->addFormRule([__CLASS__
, 'formRule'], $this);
125 'name' => ts('Update'),
130 'name' => ts('Cancel'),
138 * @param array $fields
139 * The input form values.
140 * @param array $files
141 * The uploaded files if any.
145 * true if no errors, else array of errors
147 public static function formRule($fields, $files, $self) {
150 // if Credit Card is chosen and pan_truncation is not NULL ensure that it's value is numeric else throw validation error
151 if (CRM_Core_PseudoConstant
::getName('CRM_Financial_DAO_FinancialTrxn', 'payment_instrument_id', $fields['payment_instrument_id']) === 'Credit Card' &&
152 !empty($fields['pan_truncation']) &&
153 !CRM_Utils_Rule
::numeric($fields['pan_truncation'])
155 $errors['pan_truncation'] = ts('Please enter a valid Card Number');
162 * Process the form submission.
164 * @throws \CiviCRM_API3_Exception
166 public function postProcess(): void
{
169 'payment_instrument_id' => $this->_submitValues
['payment_instrument_id'],
170 'trxn_id' => $this->_submitValues
['trxn_id'] ??
NULL,
171 'trxn_date' => CRM_Utils_Array
::value('trxn_date', $this->_submitValues
, date('YmdHis')),
174 $paymentInstrumentName = CRM_Core_PseudoConstant
::getName('CRM_Financial_DAO_FinancialTrxn', 'payment_instrument_id', $params['payment_instrument_id']);
175 if ($paymentInstrumentName === 'Credit Card') {
176 $params['card_type_id'] = $this->_submitValues
['card_type_id'] ??
NULL;
177 $params['pan_truncation'] = $this->_submitValues
['pan_truncation'] ??
NULL;
179 elseif ($paymentInstrumentName === 'Check') {
180 $params['check_number'] = $this->_submitValues
['check_number'] ??
NULL;
183 $this->submit($params);
185 $contactId = CRM_Core_DAO
::getFieldValue('CRM_Contribute_DAO_Contribution', $this->getContributionID(), 'contact_id');
186 $url = CRM_Utils_System
::url(
187 "civicrm/contact/view/contribution",
188 "reset=1&action=update&id=" . $this->getContributionID() . "&cid={$contactId}&context=contribution"
190 CRM_Core_Session
::singleton()->pushUserContext($url);
194 * Wrapper function to process form submission
196 * @param array $submittedValues
198 * @throws \CiviCRM_API3_Exception
200 protected function submit($submittedValues) {
201 // if payment instrument is changed then
202 // 1. Record a new reverse financial transaction with old payment instrument
203 // 2. Record a new financial transaction with new payment instrument
204 // 3. Add EntityFinancialTrxn records to relate with corresponding financial item and contribution
205 if ($submittedValues['payment_instrument_id'] != $this->_values
['payment_instrument_id']) {
206 civicrm_api3('Payment', 'cancel', [
207 'id' => $this->_values
['id'],
208 'trxn_date' => $submittedValues['trxn_date'],
211 $newFinancialTrxn = $submittedValues;
212 unset($newFinancialTrxn['id']);
213 $newFinancialTrxn['to_financial_account_id'] = CRM_Financial_BAO_FinancialTypeAccount
::getInstrumentFinancialAccount($submittedValues['payment_instrument_id']);
214 $newFinancialTrxn['total_amount'] = $this->_values
['total_amount'];
215 $newFinancialTrxn['currency'] = $this->_values
['currency'];
216 $newFinancialTrxn['contribution_id'] = $this->getContributionID();
217 civicrm_api3('Payment', 'create', $newFinancialTrxn);
220 // simply update the financial trxn
221 civicrm_api3('FinancialTrxn', 'create', $submittedValues);
224 CRM_Financial_BAO_Payment
::updateRelatedContribution($submittedValues, $this->getContributionID());
228 * Wrapper for unit testing the post process submit function.
230 * @param array $params
232 * @throws \CiviCRM_API3_Exception
234 public function testSubmit(array $params): void
{
235 $this->_id
= $params['id'];
236 $this->_contributionID
= $params['contribution_id'];
237 $this->_values
= civicrm_api3('FinancialTrxn', 'getsingle', ['id' => $params['id']]);
239 $this->submit($params);
245 public function getPaymentFields() {
247 'payment_instrument_id' => [
248 'is_required' => TRUE,
252 'is_required' => FALSE,
255 // @TODO we need to show card type icon in place of select field
257 'is_required' => FALSE,
260 'pan_truncation' => [
261 'is_required' => FALSE,
266 'is_required' => FALSE,
269 'htmlType' => 'datepicker',
270 'name' => 'trxn_date',
271 'title' => ts('Transaction Date'),
272 'is_required' => TRUE,
274 'date' => 'yyyy-mm-dd',
279 'htmlType' => 'text',
280 'name' => 'total_amount',
281 'title' => ts('Total Amount'),
282 'is_required' => TRUE,
290 return $paymentFields;