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' => 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
,
83 'description' => ($lineItem->qty
!= 1 ?
$lineItem->qty
. ' of ' : '') . $lineItem->label
,
84 'status_id' => $itemStatus,
88 $invoiceSettings = Civi
::settings()->get('contribution_invoice_settings');
89 $taxTerm = CRM_Utils_Array
::value('tax_term', $invoiceSettings);
90 $params['amount'] = $lineItem->tax_amount
;
91 $params['description'] = $taxTerm;
92 $accountRelName = 'Sales Tax Account is';
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';
100 if ($lineItem->financial_type_id
) {
101 $params['financial_account_id'] = CRM_Financial_BAO_FinancialAccount
::getFinancialAccountForFinancialTypeByRelationship(
102 $lineItem->financial_type_id
,
106 if (empty($trxnId)) {
107 $trxnId['id'] = CRM_Contribute_BAO_Contribution
::$_trxnIDs;
108 if (empty($trxnId['id'])) {
109 $trxn = CRM_Core_BAO_FinancialTrxn
::getFinancialTrxnId($contribution->id
, 'ASC', TRUE);
110 $trxnId['id'] = $trxn['financialTrxnId'];
113 $financialItem = self
::create($params, NULL, $trxnId);
114 return $financialItem;
118 * Create the financial Items and financial entity trxn.
120 * @param array $params
121 * Associated array to create financial items.
123 * Financial item ids.
124 * @param array $trxnIds
125 * Financial item ids.
127 * @return CRM_Financial_DAO_FinancialItem
129 public static function create(&$params, $ids = NULL, $trxnIds = NULL) {
130 $financialItem = new CRM_Financial_DAO_FinancialItem();
132 if (!empty($ids['id'])) {
133 CRM_Utils_Hook
::pre('edit', 'FinancialItem', $ids['id'], $params);
136 CRM_Utils_Hook
::pre('create', 'FinancialItem', NULL, $params);
139 $financialItem->copyValues($params);
140 if (!empty($ids['id'])) {
141 $financialItem->id
= $ids['id'];
144 $financialItem->save();
145 $financialtrxnIDS = CRM_Utils_Array
::value('id', $trxnIds);
146 if (!empty($financialtrxnIDS)) {
147 if (!is_array($financialtrxnIDS)) {
148 $financialtrxnIDS = [$financialtrxnIDS];
150 foreach ($financialtrxnIDS as $tID) {
151 $entity_financial_trxn_params = [
152 'entity_table' => "civicrm_financial_item",
153 'entity_id' => $financialItem->id
,
154 'financial_trxn_id' => $tID,
155 'amount' => $params['amount'],
157 if (!empty($ids['entityFinancialTrxnId'])) {
158 $entity_financial_trxn_params['id'] = $ids['entityFinancialTrxnId'];
160 self
::createEntityTrxn($entity_financial_trxn_params);
163 if (!empty($ids['id'])) {
164 CRM_Utils_Hook
::post('edit', 'FinancialItem', $financialItem->id
, $financialItem);
167 CRM_Utils_Hook
::post('create', 'FinancialItem', $financialItem->id
, $financialItem);
169 return $financialItem;
173 * Takes an associative array and creates a entity financial transaction object.
175 * @param array $params
176 * an assoc array of name/value pairs.
178 * @return CRM_Financial_DAO_EntityFinancialTrxn
180 public static function createEntityTrxn($params) {
181 $entity_trxn = new CRM_Financial_DAO_EntityFinancialTrxn();
182 $entity_trxn->copyValues($params);
183 $entity_trxn->save();
188 * Retrive entity financial trxn details.
190 * @param array $params
191 * an assoc array of name/value pairs.
193 * To retrieve max id.
197 public static function retrieveEntityFinancialTrxn($params, $maxId = FALSE) {
198 $financialItem = new CRM_Financial_DAO_EntityFinancialTrxn();
199 $financialItem->copyValues($params);
200 // retrieve last entry from civicrm_entity_financial_trxn
202 $financialItem->orderBy('id DESC');
203 $financialItem->limit(1);
205 $financialItem->find();
206 while ($financialItem->fetch()) {
207 $financialItems[$financialItem->id
] = [
208 'id' => $financialItem->id
,
209 'entity_table' => $financialItem->entity_table
,
210 'entity_id' => $financialItem->entity_id
,
211 'financial_trxn_id' => $financialItem->financial_trxn_id
,
212 'amount' => $financialItem->amount
,
215 if (!empty($financialItems)) {
216 return $financialItems;
224 * Check if contact is present in financial_item table.
228 * @param array $contactIds
229 * An array contact id's.
231 * @param array $error
236 public static function checkContactPresent($contactIds, &$error) {
237 if (empty($contactIds)) {
241 $allowPermDelete = Civi
::settings()->get('allowPermDeleteFinancial');
243 if (!$allowPermDelete) {
244 $sql = 'SELECT DISTINCT(cc.id), cc.display_name FROM civicrm_contact cc
245 INNER JOIN civicrm_contribution con ON con.contact_id = cc.id
246 WHERE cc.id IN (' . implode(',', $contactIds) . ') AND con.is_test = 0';
247 $dao = CRM_Core_DAO
::executeQuery($sql);
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>";
255 if (is_array($error)) {
256 $errorStatus = '<ul><li>' . implode('</li><li>', $not_deleted) . '</li></ul>';
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.');
267 * Get most relevant previous financial item relating to the line item.
269 * This function specifically excludes sales tax.
271 * @param int $entityId
275 public static function getPreviousFinancialItem($entityId) {
277 'entity_id' => $entityId,
278 'entity_table' => 'civicrm_line_item',
279 'options' => ['limit' => 1, 'sort' => 'id DESC'],
281 $salesTaxFinancialAccounts = civicrm_api3('FinancialAccount', 'get', ['is_tax' => 1]);
282 if ($salesTaxFinancialAccounts['count']) {
283 $params['financial_account_id'] = ['NOT IN' => array_keys($salesTaxFinancialAccounts['values'])];
285 return civicrm_api3('FinancialItem', 'getsingle', $params);