NFC cleanup to financial classes
[civicrm-core.git] / CRM / Financial / BAO / FinancialItem.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2018 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2018
32 */
33 class CRM_Financial_BAO_FinancialItem extends CRM_Financial_DAO_FinancialItem {
34
35 /**
36 * Class constructor.
37 */
38 public function __construct() {
39 parent::__construct();
40 }
41
42 /**
43 * Fetch object based on array of properties.
44 *
45 * @param array $params
46 * (reference ) an assoc array of name/value pairs.
47 * @param array $defaults
48 * (reference ) an assoc array to hold the flattened values.
49 *
50 * @return CRM_Financial_DAO_FinancialItem
51 */
52 public static function retrieve(&$params, &$defaults) {
53 $financialItem = new CRM_Financial_DAO_FinancialItem();
54 $financialItem->copyValues($params);
55 if ($financialItem->find(TRUE)) {
56 CRM_Core_DAO::storeValues($financialItem, $defaults);
57 return $financialItem;
58 }
59 return NULL;
60 }
61
62 /**
63 * Add the financial items and financial trxn.
64 *
65 * @param object $lineItem
66 * Line item object.
67 * @param object $contribution
68 * Contribution object.
69 * @param bool $taxTrxnID
70 *
71 * @param int $trxnId
72 *
73 * @return CRM_Financial_DAO_FinancialItem
74 */
75 public static function add($lineItem, $contribution, $taxTrxnID = FALSE, $trxnId = NULL) {
76 $contributionStatuses = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
77 $financialItemStatus = CRM_Core_PseudoConstant::get('CRM_Financial_DAO_FinancialItem', 'status_id');
78 $itemStatus = NULL;
79 if ($contribution->contribution_status_id == array_search('Completed', $contributionStatuses)
80 || $contribution->contribution_status_id == array_search('Pending refund', $contributionStatuses)
81 ) {
82 $itemStatus = array_search('Paid', $financialItemStatus);
83 }
84 elseif ($contribution->contribution_status_id == array_search('Pending', $contributionStatuses)
85 || $contribution->contribution_status_id == array_search('In Progress', $contributionStatuses)
86 ) {
87 $itemStatus = array_search('Unpaid', $financialItemStatus);
88 }
89 elseif ($contribution->contribution_status_id == array_search('Partially paid', $contributionStatuses)) {
90 $itemStatus = array_search('Partially paid', $financialItemStatus);
91 }
92 $params = array(
93 'transaction_date' => CRM_Utils_Date::isoToMysql($contribution->receive_date),
94 'contact_id' => $contribution->contact_id,
95 'amount' => $lineItem->line_total,
96 'currency' => $contribution->currency,
97 'entity_table' => 'civicrm_line_item',
98 'entity_id' => $lineItem->id,
99 'description' => ($lineItem->qty != 1 ? $lineItem->qty . ' of ' : '') . $lineItem->label,
100 'status_id' => $itemStatus,
101 );
102
103 if ($taxTrxnID) {
104 $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
105 $taxTerm = CRM_Utils_Array::value('tax_term', $invoiceSettings);
106 $params['amount'] = $lineItem->tax_amount;
107 $params['description'] = $taxTerm;
108 $accountRelName = 'Sales Tax Account is';
109 }
110 else {
111 $accountRelName = 'Income Account is';
112 if (property_exists($contribution, 'revenue_recognition_date') && !CRM_Utils_System::isNull($contribution->revenue_recognition_date)) {
113 $accountRelName = 'Deferred Revenue Account is';
114 }
115 }
116 if ($lineItem->financial_type_id) {
117 $params['financial_account_id'] = CRM_Contribute_PseudoConstant::getRelationalFinancialAccount(
118 $lineItem->financial_type_id,
119 $accountRelName
120 );
121 }
122 if (empty($trxnId)) {
123 $trxnId['id'] = CRM_Contribute_BAO_Contribution::$_trxnIDs;
124 if (empty($trxnId['id'])) {
125 $trxn = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($contribution->id, 'ASC', TRUE);
126 $trxnId['id'] = $trxn['financialTrxnId'];
127 }
128 }
129 $financialItem = self::create($params, NULL, $trxnId);
130 return $financialItem;
131 }
132
133 /**
134 * Create the financial Items and financial entity trxn.
135 *
136 * @param array $params
137 * Associated array to create financial items.
138 * @param array $ids
139 * Financial item ids.
140 * @param array $trxnIds
141 * Financial item ids.
142 *
143 * @return CRM_Financial_DAO_FinancialItem
144 */
145 public static function create(&$params, $ids = NULL, $trxnIds = NULL) {
146 $financialItem = new CRM_Financial_DAO_FinancialItem();
147
148 if (!empty($ids['id'])) {
149 CRM_Utils_Hook::pre('edit', 'FinancialItem', $ids['id'], $params);
150 }
151 else {
152 CRM_Utils_Hook::pre('create', 'FinancialItem', NULL, $params);
153 }
154
155 $financialItem->copyValues($params);
156 if (!empty($ids['id'])) {
157 $financialItem->id = $ids['id'];
158 }
159
160 $financialItem->save();
161 $financialtrxnIDS = CRM_Utils_Array::value('id', $trxnIds);
162 if (!empty($financialtrxnIDS)) {
163 if (!is_array($financialtrxnIDS)) {
164 $financialtrxnIDS = array($financialtrxnIDS);
165 }
166 foreach ($financialtrxnIDS as $tID) {
167 $entity_financial_trxn_params = array(
168 'entity_table' => "civicrm_financial_item",
169 'entity_id' => $financialItem->id,
170 'financial_trxn_id' => $tID,
171 'amount' => $params['amount'],
172 );
173 if (!empty($ids['entityFinancialTrxnId'])) {
174 $entity_financial_trxn_params['id'] = $ids['entityFinancialTrxnId'];
175 }
176 self::createEntityTrxn($entity_financial_trxn_params);
177 }
178 }
179 if (!empty($ids['id'])) {
180 CRM_Utils_Hook::post('edit', 'FinancialItem', $financialItem->id, $financialItem);
181 }
182 else {
183 CRM_Utils_Hook::post('create', 'FinancialItem', $financialItem->id, $financialItem);
184 }
185 return $financialItem;
186 }
187
188 /**
189 * Takes an associative array and creates a entity financial transaction object.
190 *
191 * @param array $params
192 * an assoc array of name/value pairs.
193 *
194 * @return CRM_Financial_DAO_EntityFinancialTrxn
195 */
196 public static function createEntityTrxn($params) {
197 $entity_trxn = new CRM_Financial_DAO_EntityFinancialTrxn();
198 $entity_trxn->copyValues($params);
199 $entity_trxn->save();
200 return $entity_trxn;
201 }
202
203 /**
204 * Retrive entity financial trxn details.
205 *
206 * @param array $params
207 * an assoc array of name/value pairs.
208 * @param bool $maxId
209 * To retrieve max id.
210 *
211 * @return array
212 */
213 public static function retrieveEntityFinancialTrxn($params, $maxId = FALSE) {
214 $financialItem = new CRM_Financial_DAO_EntityFinancialTrxn();
215 $financialItem->copyValues($params);
216 // retrieve last entry from civicrm_entity_financial_trxn
217 if ($maxId) {
218 $financialItem->orderBy('id DESC');
219 $financialItem->limit(1);
220 }
221 $financialItem->find();
222 while ($financialItem->fetch()) {
223 $financialItems[$financialItem->id] = array(
224 'id' => $financialItem->id,
225 'entity_table' => $financialItem->entity_table,
226 'entity_id' => $financialItem->entity_id,
227 'financial_trxn_id' => $financialItem->financial_trxn_id,
228 'amount' => $financialItem->amount,
229 );
230 }
231 if (!empty($financialItems)) {
232 return $financialItems;
233 }
234 else {
235 return NULL;
236 }
237 }
238
239 /**
240 * Check if contact is present in financial_item table.
241 *
242 * CRM-12929
243 *
244 * @param array $contactIds
245 * An array contact id's.
246 *
247 * @param array $error
248 * Error to display.
249 *
250 * @return array|bool
251 */
252 public static function checkContactPresent($contactIds, &$error) {
253 if (empty($contactIds)) {
254 return FALSE;
255 }
256
257 $allowPermDelete = Civi::settings()->get('allowPermDeleteFinancial');
258
259 if (!$allowPermDelete) {
260 $sql = 'SELECT DISTINCT(cc.id), cc.display_name FROM civicrm_contact cc
261 INNER JOIN civicrm_contribution con ON con.contact_id = cc.id
262 WHERE cc.id IN (' . implode(',', $contactIds) . ') AND con.is_test = 0';
263 $dao = CRM_Core_DAO::executeQuery($sql);
264 if ($dao->N) {
265 while ($dao->fetch()) {
266 $url = CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid=$dao->id");
267 $not_deleted[$dao->id] = "<a href='$url'>$dao->display_name</a>";
268 }
269
270 $errorStatus = '';
271 if (is_array($error)) {
272 $errorStatus = '<ul><li>' . implode('</li><li>', $not_deleted) . '</li></ul>';
273 }
274
275 $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.');
276 return $error;
277 }
278 }
279 return FALSE;
280 }
281
282 /**
283 * Get most relevant previous financial item relating to the line item.
284 *
285 * This function specifically excludes sales tax.
286 *
287 * @param int $entityId
288 *
289 * @return array
290 */
291 public static function getPreviousFinancialItem($entityId) {
292 $params = array(
293 'entity_id' => $entityId,
294 'entity_table' => 'civicrm_line_item',
295 'options' => array('limit' => 1, 'sort' => 'id DESC'),
296 );
297 $salesTaxFinancialAccounts = civicrm_api3('FinancialAccount', 'get', array('is_tax' => 1));
298 if ($salesTaxFinancialAccounts['count']) {
299 $params['financial_account_id'] = array('NOT IN' => array_keys($salesTaxFinancialAccounts['values']));
300 }
301 return civicrm_api3('FinancialItem', 'getsingle', $params);
302 }
303
304 }