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