Merge pull request #21590 from totten/master-msgtplui
[civicrm-core.git] / CRM / Financial / Form / PaymentEdit.php
CommitLineData
9b2e3ee6
MD
1<?php
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
9b2e3ee6 5 | |
bc77d7c0
TO
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 |
9b2e3ee6
MD
9 +--------------------------------------------------------------------+
10 */
11
12/**
13 *
14 * @package CRM
ca5cec67 15 * @copyright CiviCRM LLC https://civicrm.org/licensing
9b2e3ee6
MD
16 */
17class CRM_Financial_Form_PaymentEdit extends CRM_Core_Form {
18
f8c56ac7
EM
19 /**
20 * Should financials be checked after the test but before tear down.
21 *
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.
24 *
25 * @var bool
26 */
27 protected $isValidateFinancialsOnPostAssert = TRUE;
28
9b2e3ee6
MD
29 /**
30 * The id of the financial trxn.
31 *
32 * @var int
33 */
34 protected $_id;
35
e3a78cba 36 /**
37 * The id of the related contribution ID
38 *
39 * @var int
40 */
41 protected $_contributionID;
42
a90b7451 43 /**
44 * Get the related contribution id.
45 *
46 * @return int
47 */
48 public function getContributionID(): int {
49 return $this->_contributionID;
50 }
51
9b2e3ee6
MD
52 /**
53 * The variable which holds the information of a financial transaction
54 *
55 * @var array
56 */
57 protected $_values;
58
d8c01ab5 59 /**
60 * Explicitly declare the form context.
61 */
62 public function getDefaultContext() {
63 return 'create';
64 }
7b966967 65
9b2e3ee6
MD
66 /**
67 * Set variables up before form is built.
68 */
69 public function preProcess() {
d8c01ab5 70 $this->_action = CRM_Core_Action::UPDATE;
9b2e3ee6
MD
71 parent::preProcess();
72 $this->_id = CRM_Utils_Request::retrieve('id', 'Positive', $this);
73 $this->assign('id', $this->_id);
50f8ceb1 74 $this->_contributionID = CRM_Utils_Request::retrieve('contribution_id', 'Positive', $this);
9b2e3ee6 75
be2fb01f 76 $this->_values = civicrm_api3('FinancialTrxn', 'getsingle', ['id' => $this->_id]);
9b2e3ee6 77 if (!empty($this->_values['payment_processor_id'])) {
c485e792 78 CRM_Core_Error::statusBounce(ts('You cannot update this payment as it is tied to a payment processor'));
9b2e3ee6
MD
79 }
80 }
81
82 /**
83 * Set default values.
84 *
85 * @return array
86 */
87 public function setDefaultValues() {
77ea7225 88 $defaults = $this->_values;
7030792a 89 $defaults['total_amount'] = CRM_Utils_Money::formatLocaleNumericRoundedForDefaultCurrency($this->_values['total_amount']);
77ea7225 90 return $defaults;
9b2e3ee6
MD
91 }
92
93 /**
94 * Build quickForm.
95 */
96 public function buildQuickForm() {
94fd9d17 97 $this->setTitle(ts('Update Payment details'));
9b2e3ee6
MD
98
99 $paymentFields = $this->getPaymentFields();
100 $this->assign('paymentFields', $paymentFields);
101 foreach ($paymentFields as $name => $paymentField) {
4ee75265 102 if (!empty($paymentField['add_field'])) {
be2fb01f 103 $attributes = [
a7a8f17d 104 'entity' => 'FinancialTrxn',
105 'name' => $name,
be2fb01f 106 ];
a7a8f17d 107 $this->addField($name, $attributes, $paymentField['is_required']);
4ee75265 108 }
109 else {
110 $this->add($paymentField['htmlType'],
111 $name,
112 $paymentField['title'],
113 $paymentField['attributes'],
114 $paymentField['is_required']
115 );
9b2e3ee6
MD
116 }
117 }
118
119 $this->assign('currency', CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_Currency', $this->_values['currency'], 'symbol', 'name'));
be2fb01f 120 $this->addFormRule([__CLASS__, 'formRule'], $this);
4ee75265 121
be2fb01f
CW
122 $this->addButtons([
123 [
9b2e3ee6
MD
124 'type' => 'submit',
125 'name' => ts('Update'),
126 'isDefault' => TRUE,
be2fb01f
CW
127 ],
128 [
9b2e3ee6
MD
129 'type' => 'cancel',
130 'name' => ts('Cancel'),
be2fb01f
CW
131 ],
132 ]);
9b2e3ee6
MD
133 }
134
4ee75265 135 /**
136 * Global form rule.
137 *
138 * @param array $fields
139 * The input form values.
140 * @param array $files
141 * The uploaded files if any.
142 * @param $self
143 *
144 * @return bool|array
145 * true if no errors, else array of errors
146 */
147 public static function formRule($fields, $files, $self) {
be2fb01f 148 $errors = [];
4ee75265 149
150 // if Credit Card is chosen and pan_truncation is not NULL ensure that it's value is numeric else throw validation error
a90b7451 151 if (CRM_Core_PseudoConstant::getName('CRM_Financial_DAO_FinancialTrxn', 'payment_instrument_id', $fields['payment_instrument_id']) === 'Credit Card' &&
4ee75265 152 !empty($fields['pan_truncation']) &&
153 !CRM_Utils_Rule::numeric($fields['pan_truncation'])
154 ) {
155 $errors['pan_truncation'] = ts('Please enter a valid Card Number');
156 }
157
158 return $errors;
159 }
160
9b2e3ee6
MD
161 /**
162 * Process the form submission.
a90b7451 163 *
164 * @throws \CiviCRM_API3_Exception
9b2e3ee6 165 */
a90b7451 166 public function postProcess(): void {
be2fb01f 167 $params = [
9b2e3ee6 168 'id' => $this->_id,
4ee75265 169 'payment_instrument_id' => $this->_submitValues['payment_instrument_id'],
6b409353 170 'trxn_id' => $this->_submitValues['trxn_id'] ?? NULL,
9b2e3ee6 171 'trxn_date' => CRM_Utils_Array::value('trxn_date', $this->_submitValues, date('YmdHis')),
be2fb01f 172 ];
4ee75265 173
174 $paymentInstrumentName = CRM_Core_PseudoConstant::getName('CRM_Financial_DAO_FinancialTrxn', 'payment_instrument_id', $params['payment_instrument_id']);
a90b7451 175 if ($paymentInstrumentName === 'Credit Card') {
9c1bc317
CW
176 $params['card_type_id'] = $this->_submitValues['card_type_id'] ?? NULL;
177 $params['pan_truncation'] = $this->_submitValues['pan_truncation'] ?? NULL;
4ee75265 178 }
a90b7451 179 elseif ($paymentInstrumentName === 'Check') {
9c1bc317 180 $params['check_number'] = $this->_submitValues['check_number'] ?? NULL;
9b2e3ee6 181 }
4ee75265 182
e3a78cba 183 $this->submit($params);
184
a90b7451 185 $contactId = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $this->getContributionID(), 'contact_id');
501ec37c
CW
186 $url = CRM_Utils_System::url(
187 "civicrm/contact/view/contribution",
ab466314 188 "reset=1&action=update&id=" . $this->getContributionID() . "&cid={$contactId}&context=contribution"
501ec37c
CW
189 );
190 CRM_Core_Session::singleton()->pushUserContext($url);
e3a78cba 191 }
192
e3a78cba 193 /**
194 * Wrapper function to process form submission
195 *
196 * @param array $submittedValues
197 *
d8a1b674 198 * @throws \CiviCRM_API3_Exception
e3a78cba 199 */
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']) {
d8a1b674 206 civicrm_api3('Payment', 'cancel', [
207 'id' => $this->_values['id'],
208 'trxn_date' => $submittedValues['trxn_date'],
209 ]);
a9dec23a 210
d8a1b674 211 $newFinancialTrxn = $submittedValues;
212 unset($newFinancialTrxn['id']);
e3a78cba 213 $newFinancialTrxn['to_financial_account_id'] = CRM_Financial_BAO_FinancialTypeAccount::getInstrumentFinancialAccount($submittedValues['payment_instrument_id']);
d8a1b674 214 $newFinancialTrxn['total_amount'] = $this->_values['total_amount'];
215 $newFinancialTrxn['currency'] = $this->_values['currency'];
a90b7451 216 $newFinancialTrxn['contribution_id'] = $this->getContributionID();
d8a1b674 217 civicrm_api3('Payment', 'create', $newFinancialTrxn);
a9dec23a 218 }
219 else {
220 // simply update the financial trxn
e3a78cba 221 civicrm_api3('FinancialTrxn', 'create', $submittedValues);
a9dec23a 222 }
650b79b4 223
a90b7451 224 CRM_Financial_BAO_Payment::updateRelatedContribution($submittedValues, $this->getContributionID());
9b2e3ee6
MD
225 }
226
a9dec23a 227 /**
e3a78cba 228 * Wrapper for unit testing the post process submit function.
a9dec23a 229 *
e3a78cba 230 * @param array $params
d8a1b674 231 *
232 * @throws \CiviCRM_API3_Exception
a9dec23a 233 */
d8a1b674 234 public function testSubmit(array $params): void {
e3a78cba 235 $this->_id = $params['id'];
236 $this->_contributionID = $params['contribution_id'];
be2fb01f 237 $this->_values = civicrm_api3('FinancialTrxn', 'getsingle', ['id' => $params['id']]);
e3a78cba 238
239 $this->submit($params);
a9dec23a 240 }
241
9b2e3ee6
MD
242 /**
243 * Get payment fields
244 */
245 public function getPaymentFields() {
be2fb01f
CW
246 $paymentFields = [
247 'payment_instrument_id' => [
4ee75265 248 'is_required' => TRUE,
249 'add_field' => TRUE,
be2fb01f
CW
250 ],
251 'check_number' => [
9b2e3ee6 252 'is_required' => FALSE,
4ee75265 253 'add_field' => TRUE,
be2fb01f 254 ],
4ee75265 255 // @TODO we need to show card type icon in place of select field
be2fb01f 256 'card_type_id' => [
4ee75265 257 'is_required' => FALSE,
258 'add_field' => TRUE,
be2fb01f
CW
259 ],
260 'pan_truncation' => [
4ee75265 261 'is_required' => FALSE,
262 'add_field' => TRUE,
be2fb01f
CW
263 ],
264 'trxn_id' => [
a7a8f17d 265 'add_field' => TRUE,
4ee75265 266 'is_required' => FALSE,
be2fb01f
CW
267 ],
268 'trxn_date' => [
9b2e3ee6
MD
269 'htmlType' => 'datepicker',
270 'name' => 'trxn_date',
271 'title' => ts('Transaction Date'),
4ee75265 272 'is_required' => TRUE,
be2fb01f 273 'attributes' => [
9b2e3ee6
MD
274 'date' => 'yyyy-mm-dd',
275 'time' => 24,
be2fb01f
CW
276 ],
277 ],
278 'total_amount' => [
9b2e3ee6
MD
279 'htmlType' => 'text',
280 'name' => 'total_amount',
281 'title' => ts('Total Amount'),
4ee75265 282 'is_required' => TRUE,
be2fb01f 283 'attributes' => [
9b2e3ee6
MD
284 'readonly' => TRUE,
285 'size' => 6,
be2fb01f
CW
286 ],
287 ],
288 ];
9b2e3ee6
MD
289
290 return $paymentFields;
291 }
292
293}