Merge pull request #23009 from seamuslee001/dev_core_3132
[civicrm-core.git] / CRM / Financial / BAO / FinancialItem.php
CommitLineData
6a488035 1<?php
6a488035
TO
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
6a488035 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 |
6a488035 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
6a488035
TO
11
12/**
13 *
14 * @package CRM
ca5cec67 15 * @copyright CiviCRM LLC https://civicrm.org/licensing
6a488035 16 */
6a488035
TO
17class CRM_Financial_BAO_FinancialItem extends CRM_Financial_DAO_FinancialItem {
18
6a488035 19 /**
4f940304 20 * Retrieve DB object and copy to defaults array.
6a488035 21 *
ed5dd492 22 * @param array $params
4f940304 23 * Array of criteria values.
ed5dd492 24 * @param array $defaults
4f940304 25 * Array to be populated with found values.
6a488035 26 *
4f940304
CW
27 * @return self|null
28 * The DAO object, if found.
29 *
30 * @deprecated
6a488035 31 */
4f940304
CW
32 public static function retrieve($params, &$defaults) {
33 return self::commonRetrieve(self::class, $params, $defaults);
6a488035
TO
34 }
35
36 /**
fe482240 37 * Add the financial items and financial trxn.
6a488035 38 *
ed5dd492
TO
39 * @param object $lineItem
40 * Line item object.
41 * @param object $contribution
42 * Contribution object.
43 * @param bool $taxTrxnID
03e04002 44 *
54957108 45 * @param int $trxnId
46 *
47 * @return CRM_Financial_DAO_FinancialItem
6a488035 48 */
a191ff3d 49 public static function add($lineItem, $contribution, $taxTrxnID = FALSE, $trxnId = NULL) {
6a488035 50 $contributionStatuses = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
7611ae71 51 $financialItemStatus = CRM_Core_PseudoConstant::get('CRM_Financial_DAO_FinancialItem', 'status_id');
b81ee58c 52 $itemStatus = NULL;
0bdf3091 53 if ($contribution->contribution_status_id == array_search('Completed', $contributionStatuses)
353ffa53
TO
54 || $contribution->contribution_status_id == array_search('Pending refund', $contributionStatuses)
55 ) {
6a488035 56 $itemStatus = array_search('Paid', $financialItemStatus);
03e04002 57 }
f6bae84f 58 elseif ($contribution->contribution_status_id == array_search('Pending', $contributionStatuses)
353ffa53
TO
59 || $contribution->contribution_status_id == array_search('In Progress', $contributionStatuses)
60 ) {
6a488035 61 $itemStatus = array_search('Unpaid', $financialItemStatus);
03e04002 62 }
f8325309
PJ
63 elseif ($contribution->contribution_status_id == array_search('Partially paid', $contributionStatuses)) {
64 $itemStatus = array_search('Partially paid', $financialItemStatus);
65 }
be2fb01f 66 $params = [
f1518315 67 'transaction_date' => $contribution->receive_date,
353ffa53
TO
68 'contact_id' => $contribution->contact_id,
69 'amount' => $lineItem->line_total,
70 'currency' => $contribution->currency,
71 'entity_table' => 'civicrm_line_item',
72 'entity_id' => $lineItem->id,
cf28d075 73 'description' => ($lineItem->qty != 1 ? $lineItem->qty . ' of ' : '') . $lineItem->label,
353ffa53 74 'status_id' => $itemStatus,
be2fb01f 75 ];
03e04002 76
0b7bd9dd 77 if ($taxTrxnID) {
78 $params['amount'] = $lineItem->tax_amount;
530f1e12 79 $params['description'] = Civi::settings()->get('tax_term');
53d294ba 80 $accountRelName = 'Sales Tax Account is';
0b7bd9dd 81 }
82 else {
8cf6bd83
PN
83 $accountRelName = 'Income Account is';
84 if (property_exists($contribution, 'revenue_recognition_date') && !CRM_Utils_System::isNull($contribution->revenue_recognition_date)) {
85 $accountRelName = 'Deferred Revenue Account is';
86 }
0b7bd9dd 87 }
6a488035 88 if ($lineItem->financial_type_id) {
928a340b 89 $params['financial_account_id'] = CRM_Financial_BAO_FinancialAccount::getFinancialAccountForFinancialTypeByRelationship(
53d294ba
PN
90 $lineItem->financial_type_id,
91 $accountRelName
6a488035 92 );
6a488035 93 }
a191ff3d 94 if (empty($trxnId)) {
85726d00 95 if (empty($trxnId['id'])) {
9c472292
PN
96 $trxn = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($contribution->id, 'ASC', TRUE);
97 $trxnId['id'] = $trxn['financialTrxnId'];
98 }
a191ff3d 99 }
8cf6bd83
PN
100 $financialItem = self::create($params, NULL, $trxnId);
101 return $financialItem;
03e04002 102 }
6a488035
TO
103
104 /**
54957108 105 * Create the financial Items and financial entity trxn.
6a488035 106 *
ed5dd492
TO
107 * @param array $params
108 * Associated array to create financial items.
109 * @param array $ids
110 * Financial item ids.
111 * @param array $trxnIds
112 * Financial item ids.
03e04002 113 *
54957108 114 * @return CRM_Financial_DAO_FinancialItem
6a488035 115 */
00be9182 116 public static function create(&$params, $ids = NULL, $trxnIds = NULL) {
6a488035 117 $financialItem = new CRM_Financial_DAO_FinancialItem();
045f52a3 118
a9ed1dc0
PN
119 if (!empty($ids['id'])) {
120 CRM_Utils_Hook::pre('edit', 'FinancialItem', $ids['id'], $params);
121 }
122 else {
123 CRM_Utils_Hook::pre('create', 'FinancialItem', NULL, $params);
124 }
045f52a3 125
6a488035 126 $financialItem->copyValues($params);
a7488080 127 if (!empty($ids['id'])) {
03e04002 128 $financialItem->id = $ids['id'];
6a488035
TO
129 }
130
131 $financialItem->save();
9c1bc317 132 $financialtrxnIDS = $trxnIds['id'] ?? NULL;
9c472292
PN
133 if (!empty($financialtrxnIDS)) {
134 if (!is_array($financialtrxnIDS)) {
be2fb01f 135 $financialtrxnIDS = [$financialtrxnIDS];
9c472292
PN
136 }
137 foreach ($financialtrxnIDS as $tID) {
be2fb01f 138 $entity_financial_trxn_params = [
9c472292
PN
139 'entity_table' => "civicrm_financial_item",
140 'entity_id' => $financialItem->id,
141 'financial_trxn_id' => $tID,
142 'amount' => $params['amount'],
be2fb01f 143 ];
9c472292
PN
144 if (!empty($ids['entityFinancialTrxnId'])) {
145 $entity_financial_trxn_params['id'] = $ids['entityFinancialTrxnId'];
146 }
147 self::createEntityTrxn($entity_financial_trxn_params);
6a488035 148 }
6a488035 149 }
a9ed1dc0
PN
150 if (!empty($ids['id'])) {
151 CRM_Utils_Hook::post('edit', 'FinancialItem', $financialItem->id, $financialItem);
152 }
045f52a3 153 else {
a9ed1dc0
PN
154 CRM_Utils_Hook::post('create', 'FinancialItem', $financialItem->id, $financialItem);
155 }
6a488035 156 return $financialItem;
03e04002 157 }
6a488035
TO
158
159 /**
fe482240 160 * Takes an associative array and creates a entity financial transaction object.
6a488035 161 *
ed5dd492 162 * @param array $params
5b541553 163 * an assoc array of name/value pairs.
6a488035 164 *
5b541553 165 * @return CRM_Financial_DAO_EntityFinancialTrxn
6a488035 166 */
00be9182 167 public static function createEntityTrxn($params) {
6a488035
TO
168 $entity_trxn = new CRM_Financial_DAO_EntityFinancialTrxn();
169 $entity_trxn->copyValues($params);
170 $entity_trxn->save();
171 return $entity_trxn;
172 }
173
174 /**
f044623d
EM
175 * Retrieve entity financial trxn details.
176 *
177 * @deprecated - only called by tests - to be replaced with
178 * $trxn = (array) EntityFinancialTrxn::get()
179 * ->addWhere('id', '=', $contributionID)
180 * ->addWhere('entity_table', '=', 'civicrm_contribution')
181 * ->addSelect('*')->execute();
6a488035 182 *
ed5dd492 183 * @param array $params
5b541553 184 * an assoc array of name/value pairs.
ed5dd492 185 * @param bool $maxId
5b541553 186 * To retrieve max id.
6a488035
TO
187 *
188 * @return array
6a488035 189 */
00be9182 190 public static function retrieveEntityFinancialTrxn($params, $maxId = FALSE) {
6a488035
TO
191 $financialItem = new CRM_Financial_DAO_EntityFinancialTrxn();
192 $financialItem->copyValues($params);
cded2ebf 193 // retrieve last entry from civicrm_entity_financial_trxn
6a488035
TO
194 if ($maxId) {
195 $financialItem->orderBy('id DESC');
196 $financialItem->limit(1);
197 }
198 $financialItem->find();
199 while ($financialItem->fetch()) {
be2fb01f 200 $financialItems[$financialItem->id] = [
353ffa53
TO
201 'id' => $financialItem->id,
202 'entity_table' => $financialItem->entity_table,
203 'entity_id' => $financialItem->entity_id,
6a488035 204 'financial_trxn_id' => $financialItem->financial_trxn_id,
353ffa53 205 'amount' => $financialItem->amount,
be2fb01f 206 ];
03e04002 207 }
6a488035
TO
208 if (!empty($financialItems)) {
209 return $financialItems;
210 }
211 else {
045f52a3 212 return NULL;
6a488035
TO
213 }
214 }
2efcf0c2 215
f182074e 216 /**
fe482240 217 * Check if contact is present in financial_item table.
f182074e 218 *
0e480632 219 * @see https://issues.civicrm.org/jira/browse/CRM-12929
f182074e 220 *
ed5dd492
TO
221 * @param array $contactIds
222 * An array contact id's.
f182074e 223 *
ed5dd492
TO
224 * @param array $error
225 * Error to display.
f182074e 226 *
a2fb4683 227 * @return array|bool
f182074e 228 */
00be9182 229 public static function checkContactPresent($contactIds, &$error) {
f182074e
PN
230 if (empty($contactIds)) {
231 return FALSE;
232 }
2efcf0c2 233
aaffa79f 234 $allowPermDelete = Civi::settings()->get('allowPermDeleteFinancial');
f182074e
PN
235
236 if (!$allowPermDelete) {
237 $sql = 'SELECT DISTINCT(cc.id), cc.display_name FROM civicrm_contact cc
238INNER JOIN civicrm_contribution con ON con.contact_id = cc.id
045f52a3 239WHERE cc.id IN (' . implode(',', $contactIds) . ') AND con.is_test = 0';
f182074e
PN
240 $dao = CRM_Core_DAO::executeQuery($sql);
241 if ($dao->N) {
242 while ($dao->fetch()) {
243 $url = CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid=$dao->id");
244 $not_deleted[$dao->id] = "<a href='$url'>$dao->display_name</a>";
245 }
2efcf0c2 246
f182074e
PN
247 $errorStatus = '';
248 if (is_array($error)) {
249 $errorStatus = '<ul><li>' . implode('</li><li>', $not_deleted) . '</li></ul>';
250 }
2efcf0c2 251
86bfa4f6 252 $error['_qf_default'] = $errorStatus . ts('This contact(s) can not be permanently deleted because the contact record is linked to one or more live financial transactions. Deleting this contact would result in the loss of financial data.');
2efcf0c2 253 return $error;
f182074e
PN
254 }
255 }
256 return FALSE;
257 }
96025800 258
00b4d571 259 /**
cf28d075 260 * Get most relevant previous financial item relating to the line item.
00b4d571 261 *
cf28d075 262 * This function specifically excludes sales tax.
00b4d571 263 *
cf28d075 264 * @param int $entityId
00b4d571 265 *
81716ddb 266 * @return array
00b4d571 267 */
cf28d075 268 public static function getPreviousFinancialItem($entityId) {
be2fb01f 269 $params = [
cf28d075 270 'entity_id' => $entityId,
271 'entity_table' => 'civicrm_line_item',
be2fb01f
CW
272 'options' => ['limit' => 1, 'sort' => 'id DESC'],
273 ];
274 $salesTaxFinancialAccounts = civicrm_api3('FinancialAccount', 'get', ['is_tax' => 1]);
cf28d075 275 if ($salesTaxFinancialAccounts['count']) {
be2fb01f 276 $params['financial_account_id'] = ['NOT IN' => array_keys($salesTaxFinancialAccounts['values'])];
cf28d075 277 }
278 return civicrm_api3('FinancialItem', 'getsingle', $params);
00b4d571
PN
279 }
280
6844be64
MD
281 /**
282 * Whitelist of possible values for the entity_table field
283 *
284 * @return array
285 */
286 public static function entityTables(): array {
287 return [
288 'civicrm_line_item' => ts('Line Item'),
289 'civicrm_financial_trxn' => ts('Financial Trxn'),
290 ];
291 }
292
6a488035 293}