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_BAO_FinancialItem
extends CRM_Financial_DAO_FinancialItem
{
22 public function __construct() {
23 parent
::__construct();
27 * Fetch object based on array of properties.
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.
34 * @return CRM_Financial_DAO_FinancialItem
36 public static function retrieve(&$params, &$defaults) {
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;
47 * Add the financial items and financial trxn.
49 * @param object $lineItem
51 * @param object $contribution
52 * Contribution object.
53 * @param bool $taxTrxnID
57 * @return CRM_Financial_DAO_FinancialItem
59 public static function add($lineItem, $contribution, $taxTrxnID = FALSE, $trxnId = NULL) {
60 $contributionStatuses = CRM_Contribute_PseudoConstant
::contributionStatus(NULL, 'name');
61 $financialItemStatus = CRM_Core_PseudoConstant
::get('CRM_Financial_DAO_FinancialItem', 'status_id');
63 if ($contribution->contribution_status_id
== array_search('Completed', $contributionStatuses)
64 ||
$contribution->contribution_status_id
== array_search('Pending refund', $contributionStatuses)
66 $itemStatus = array_search('Paid', $financialItemStatus);
68 elseif ($contribution->contribution_status_id
== array_search('Pending', $contributionStatuses)
69 ||
$contribution->contribution_status_id
== array_search('In Progress', $contributionStatuses)
71 $itemStatus = array_search('Unpaid', $financialItemStatus);
73 elseif ($contribution->contribution_status_id
== array_search('Partially paid', $contributionStatuses)) {
74 $itemStatus = array_search('Partially paid', $financialItemStatus);
77 'transaction_date' => $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
,
83 'description' => ($lineItem->qty
!= 1 ?
$lineItem->qty
. ' of ' : '') . $lineItem->label
,
84 'status_id' => $itemStatus,
88 $params['amount'] = $lineItem->tax_amount
;
89 $params['description'] = Civi
::settings()->get('tax_term');
90 $accountRelName = 'Sales Tax Account is';
93 $accountRelName = 'Income Account is';
94 if (property_exists($contribution, 'revenue_recognition_date') && !CRM_Utils_System
::isNull($contribution->revenue_recognition_date
)) {
95 $accountRelName = 'Deferred Revenue Account is';
98 if ($lineItem->financial_type_id
) {
99 $params['financial_account_id'] = CRM_Financial_BAO_FinancialAccount
::getFinancialAccountForFinancialTypeByRelationship(
100 $lineItem->financial_type_id
,
104 if (empty($trxnId)) {
105 $trxnId['id'] = CRM_Contribute_BAO_Contribution
::$_trxnIDs;
106 if (empty($trxnId['id'])) {
107 $trxn = CRM_Core_BAO_FinancialTrxn
::getFinancialTrxnId($contribution->id
, 'ASC', TRUE);
108 $trxnId['id'] = $trxn['financialTrxnId'];
111 $financialItem = self
::create($params, NULL, $trxnId);
112 return $financialItem;
116 * Create the financial Items and financial entity trxn.
118 * @param array $params
119 * Associated array to create financial items.
121 * Financial item ids.
122 * @param array $trxnIds
123 * Financial item ids.
125 * @return CRM_Financial_DAO_FinancialItem
127 public static function create(&$params, $ids = NULL, $trxnIds = NULL) {
128 $financialItem = new CRM_Financial_DAO_FinancialItem();
130 if (!empty($ids['id'])) {
131 CRM_Utils_Hook
::pre('edit', 'FinancialItem', $ids['id'], $params);
134 CRM_Utils_Hook
::pre('create', 'FinancialItem', NULL, $params);
137 $financialItem->copyValues($params);
138 if (!empty($ids['id'])) {
139 $financialItem->id
= $ids['id'];
142 $financialItem->save();
143 $financialtrxnIDS = $trxnIds['id'] ??
NULL;
144 if (!empty($financialtrxnIDS)) {
145 if (!is_array($financialtrxnIDS)) {
146 $financialtrxnIDS = [$financialtrxnIDS];
148 foreach ($financialtrxnIDS as $tID) {
149 $entity_financial_trxn_params = [
150 'entity_table' => "civicrm_financial_item",
151 'entity_id' => $financialItem->id
,
152 'financial_trxn_id' => $tID,
153 'amount' => $params['amount'],
155 if (!empty($ids['entityFinancialTrxnId'])) {
156 $entity_financial_trxn_params['id'] = $ids['entityFinancialTrxnId'];
158 self
::createEntityTrxn($entity_financial_trxn_params);
161 if (!empty($ids['id'])) {
162 CRM_Utils_Hook
::post('edit', 'FinancialItem', $financialItem->id
, $financialItem);
165 CRM_Utils_Hook
::post('create', 'FinancialItem', $financialItem->id
, $financialItem);
167 return $financialItem;
171 * Takes an associative array and creates a entity financial transaction object.
173 * @param array $params
174 * an assoc array of name/value pairs.
176 * @return CRM_Financial_DAO_EntityFinancialTrxn
178 public static function createEntityTrxn($params) {
179 $entity_trxn = new CRM_Financial_DAO_EntityFinancialTrxn();
180 $entity_trxn->copyValues($params);
181 $entity_trxn->save();
186 * Retrive entity financial trxn details.
188 * @param array $params
189 * an assoc array of name/value pairs.
191 * To retrieve max id.
195 public static function retrieveEntityFinancialTrxn($params, $maxId = FALSE) {
196 $financialItem = new CRM_Financial_DAO_EntityFinancialTrxn();
197 $financialItem->copyValues($params);
198 // retrieve last entry from civicrm_entity_financial_trxn
200 $financialItem->orderBy('id DESC');
201 $financialItem->limit(1);
203 $financialItem->find();
204 while ($financialItem->fetch()) {
205 $financialItems[$financialItem->id
] = [
206 'id' => $financialItem->id
,
207 'entity_table' => $financialItem->entity_table
,
208 'entity_id' => $financialItem->entity_id
,
209 'financial_trxn_id' => $financialItem->financial_trxn_id
,
210 'amount' => $financialItem->amount
,
213 if (!empty($financialItems)) {
214 return $financialItems;
222 * Check if contact is present in financial_item table.
224 * @see https://issues.civicrm.org/jira/browse/CRM-12929
226 * @param array $contactIds
227 * An array contact id's.
229 * @param array $error
234 public static function checkContactPresent($contactIds, &$error) {
235 if (empty($contactIds)) {
239 $allowPermDelete = Civi
::settings()->get('allowPermDeleteFinancial');
241 if (!$allowPermDelete) {
242 $sql = 'SELECT DISTINCT(cc.id), cc.display_name FROM civicrm_contact cc
243 INNER JOIN civicrm_contribution con ON con.contact_id = cc.id
244 WHERE cc.id IN (' . implode(',', $contactIds) . ') AND con.is_test = 0';
245 $dao = CRM_Core_DAO
::executeQuery($sql);
247 while ($dao->fetch()) {
248 $url = CRM_Utils_System
::url('civicrm/contact/view', "reset=1&cid=$dao->id");
249 $not_deleted[$dao->id
] = "<a href='$url'>$dao->display_name</a>";
253 if (is_array($error)) {
254 $errorStatus = '<ul><li>' . implode('</li><li>', $not_deleted) . '</li></ul>';
257 $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.');
265 * Get most relevant previous financial item relating to the line item.
267 * This function specifically excludes sales tax.
269 * @param int $entityId
273 public static function getPreviousFinancialItem($entityId) {
275 'entity_id' => $entityId,
276 'entity_table' => 'civicrm_line_item',
277 'options' => ['limit' => 1, 'sort' => 'id DESC'],
279 $salesTaxFinancialAccounts = civicrm_api3('FinancialAccount', 'get', ['is_tax' => 1]);
280 if ($salesTaxFinancialAccounts['count']) {
281 $params['financial_account_id'] = ['NOT IN' => array_keys($salesTaxFinancialAccounts['values'])];
283 return civicrm_api3('FinancialItem', 'getsingle', $params);