Cleanup variables in event/contribution register forms
[civicrm-core.git] / CRM / Financial / Form / PaymentEdit.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
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 +--------------------------------------------------------------------+
10 */
11
12 /**
13 *
14 * @package CRM
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
16 */
17 class CRM_Financial_Form_PaymentEdit extends CRM_Core_Form {
18
19 /**
20 * The id of the financial trxn.
21 *
22 * @var int
23 */
24 protected $_id;
25
26 /**
27 * The id of the related contribution ID
28 *
29 * @var int
30 */
31 protected $_contributionID;
32
33 /**
34 * The variable which holds the information of a financial transaction
35 *
36 * @var array
37 */
38 protected $_values;
39
40 /**
41 * Explicitly declare the form context.
42 */
43 public function getDefaultContext() {
44 return 'create';
45 }
46
47 /**
48 * Set variables up before form is built.
49 */
50 public function preProcess() {
51 $this->_action = CRM_Core_Action::UPDATE;
52 parent::preProcess();
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);
56
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'));
60 }
61 }
62
63 /**
64 * Set default values.
65 *
66 * @return array
67 */
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]);
74 }
75 return $defaults;
76 }
77
78 /**
79 * Build quickForm.
80 */
81 public function buildQuickForm() {
82 CRM_Utils_System::setTitle(ts('Update Payment details'));
83
84 $paymentFields = $this->getPaymentFields();
85 $this->assign('paymentFields', $paymentFields);
86 foreach ($paymentFields as $name => $paymentField) {
87 if (!empty($paymentField['add_field'])) {
88 $attributes = [
89 'entity' => 'FinancialTrxn',
90 'name' => $name,
91 ];
92 $this->addField($name, $attributes, $paymentField['is_required']);
93 }
94 else {
95 $this->add($paymentField['htmlType'],
96 $name,
97 $paymentField['title'],
98 $paymentField['attributes'],
99 $paymentField['is_required']
100 );
101 }
102 }
103
104 $this->assign('currency', CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_Currency', $this->_values['currency'], 'symbol', 'name'));
105 $this->addFormRule([__CLASS__, 'formRule'], $this);
106
107 $this->addButtons([
108 [
109 'type' => 'submit',
110 'name' => ts('Update'),
111 'isDefault' => TRUE,
112 ],
113 [
114 'type' => 'cancel',
115 'name' => ts('Cancel'),
116 ],
117 ]);
118 }
119
120 /**
121 * Global form rule.
122 *
123 * @param array $fields
124 * The input form values.
125 * @param array $files
126 * The uploaded files if any.
127 * @param $self
128 *
129 * @return bool|array
130 * true if no errors, else array of errors
131 */
132 public static function formRule($fields, $files, $self) {
133 $errors = [];
134
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'])
139 ) {
140 $errors['pan_truncation'] = ts('Please enter a valid Card Number');
141 }
142
143 return $errors;
144 }
145
146 /**
147 * Process the form submission.
148 */
149 public function postProcess() {
150 $params = [
151 'id' => $this->_id,
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')),
155 ];
156
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;
161 }
162 elseif ($paymentInstrumentName == 'Check') {
163 $params['check_number'] = $this->_submitValues['check_number'] ?? NULL;
164 }
165
166 $this->submit($params);
167
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"
172 );
173 CRM_Core_Session::singleton()->pushUserContext($url);
174 }
175
176 /**
177 * Wrapper function to process form submission
178 *
179 * @param array $submittedValues
180 *
181 */
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;
196
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];
200 }
201
202 foreach ([$previousFinanciaTrxn, $newFinancialTrxn] as $financialTrxnParams) {
203 $financialTrxn = civicrm_api3('FinancialTrxn', 'create', $financialTrxnParams);
204 $trxnParams = [
205 'total_amount' => $financialTrxnParams['total_amount'],
206 'contribution_id' => $this->_contributionID,
207 ];
208 $contributionTotalAmount = CRM_Core_DAO::getFieldValue('CRM_Contribute_BAO_Contribution', $this->_contributionID, 'total_amount');
209 CRM_Contribute_BAO_Contribution::assignProportionalLineItems($trxnParams, $financialTrxn['id'], $contributionTotalAmount);
210 }
211 }
212 else {
213 // simply update the financial trxn
214 civicrm_api3('FinancialTrxn', 'create', $submittedValues);
215 }
216
217 CRM_Financial_BAO_Payment::updateRelatedContribution($submittedValues, $this->_contributionID);
218 }
219
220 /**
221 * Wrapper for unit testing the post process submit function.
222 *
223 * @param array $params
224 */
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']]);
229
230 $this->submit($params);
231 }
232
233 /**
234 * Get payment fields
235 */
236 public function getPaymentFields() {
237 $paymentFields = [
238 'payment_instrument_id' => [
239 'is_required' => TRUE,
240 'add_field' => TRUE,
241 ],
242 'check_number' => [
243 'is_required' => FALSE,
244 'add_field' => TRUE,
245 ],
246 // @TODO we need to show card type icon in place of select field
247 'card_type_id' => [
248 'is_required' => FALSE,
249 'add_field' => TRUE,
250 ],
251 'pan_truncation' => [
252 'is_required' => FALSE,
253 'add_field' => TRUE,
254 ],
255 'trxn_id' => [
256 'add_field' => TRUE,
257 'is_required' => FALSE,
258 ],
259 'trxn_date' => [
260 'htmlType' => 'datepicker',
261 'name' => 'trxn_date',
262 'title' => ts('Transaction Date'),
263 'is_required' => TRUE,
264 'attributes' => [
265 'date' => 'yyyy-mm-dd',
266 'time' => 24,
267 ],
268 ],
269 'total_amount' => [
270 'htmlType' => 'text',
271 'name' => 'total_amount',
272 'title' => ts('Total Amount'),
273 'is_required' => TRUE,
274 'attributes' => [
275 'readonly' => TRUE,
276 'size' => 6,
277 ],
278 ],
279 ];
280
281 return $paymentFields;
282 }
283
284 }