Passed
Pull Request — developer (#17136)
by Arkadiusz
35:03 queued 17:53
created

getUnSupportedCurrencies()   B

Complexity

Conditions 7
Paths 9

Size

Total Lines 23
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 7.0145

Importance

Changes 0
Metric Value
eloc 17
dl 0
loc 23
ccs 14
cts 15
cp 0.9333
rs 8.8333
c 0
b 0
f 0
cc 7
nc 9
nop 1
crap 7.0145
1
<?php
2
3
/**
4
 * @copyright YetiForce S.A.
5
 * @license   YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com)
6
 * @author    Mariusz Krzaczkowski <[email protected]>
7
 * @author    Maciej Stencel <[email protected]>
8
 * @author    Radosław Skrzypczak <[email protected]>
9
 */
10
class Settings_CurrencyUpdate_Module_Model extends \App\Base
11
{
12
	// Returns objects instance
13
14 3
	public static function getCleanInstance()
15
	{
16 3
		return new self();
17
	}
18
19
	/**
20
	 * Returns CRMS active currency name by currency code.
21
	 *
22
	 * @param mixed $code
23
	 *
24 2
	 * @return string - currency name
25
	 */
26 2
	public static function getCRMCurrencyName($code)
27 2
	{
28 2
		return (new \App\Db\Query())
0 ignored issues
show
Bug Best Practice introduced by
The expression return new App\Db\Query(...e' => $code))->scalar() could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
29 2
			->select(['currency_name'])
30 2
			->from('vtiger_currencies')
31
			->where(['currency_code' => $code])
32
			->scalar();
33
	}
34
35
	/**
36
	 * Returns list of active currencies in CRM.
37
	 *
38 1
	 * @return <Integer> - number of currencies
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Integer> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Integer>.
Loading history...
39
	 */
40 1
	public function getCurrencyNum()
41
	{
42
		return \count(\App\Fields\Currency::getAll(true));
43
	}
44
45
	/**
46
	 * Returns currency exchange rates for systems active currencies from bank.
47
	 *
48
	 * @param string $dateCur - date for which to fetch exchange rates
49
	 * @param bool   $cron    - true if fired by server, and so updates systems currency conversion rates
50 1
	 *
51
	 * @return bool - true if fetched new exchange rates, false otherwise
52 1
	 */
53
	public function fetchCurrencyRates($dateCur, $cron = false): bool
0 ignored issues
show
Unused Code introduced by
The parameter $cron is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

53
	public function fetchCurrencyRates($dateCur, /** @scrutinizer ignore-unused */ $cron = false): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
54
	{
55 1
		if (!\App\RequestUtil::isNetConnection() || \count(($currencies = \App\Fields\Currency::getAll(true))) <= 1) {
56 1
			return false;
57 1
		}
58 1
		$notifyNewRates = false;
59 1
60 1
		$defaultId = \App\Fields\Currency::getDefault()['id'];
61 1
		unset($currencies[$defaultId]);
62 1
		$currIds = array_column($currencies, 'id', 'currency_code');
63 1
64 1
		$selectBankName = $this->getActiveBankName();
65 1
		$modelClassName = Vtiger_Loader::getComponentClassName('BankModel', $selectBankName, 'Settings:CurrencyUpdate');
66 1
67 1
		if (class_exists($modelClassName) && (new \App\Db\Query())->from('yetiforce_currencyupdate')
68 1
			->where(['exchange_date' => $dateCur, 'currency_id' => array_values($currIds), 'bank_id' => $this->getActiveBankId()])->count(1) !== \count($currIds)) {
69 1
			$bank = new $modelClassName();
70 1
			$bank->getRates($currIds, $dateCur, false);
71
			$notifyNewRates = true;
72 1
		}
73 1
74 1
		return $notifyNewRates;
75 1
	}
76
77 1
	// Synchronises database banks list with the bank classes existing on ftp
78
79
	public function refreshBanks()
80
	{
81
		$db = App\Db::getInstance();
82
		$dataReader = (new \App\Db\Query())->select(['id', 'bank_name'])
83 1
			->from('yetiforce_currencyupdate_banks')
84
			->createCommand()->query();
85
		while ($row = $dataReader->read()) {
86
			$id = $row['id'];
87
			$bankPath = ROOT_DIRECTORY . "/modules/Settings/CurrencyUpdate/bankmodels/{$row['bank_name']}.php";
88 1
			if (!file_exists($bankPath)) { // delete bank from database
89
				$db->createCommand()->delete('yetiforce_currencyupdate_banks', ['id' => $id])->execute();
90 1
			}
91 1
		}
92 1
		$dataReader->close();
93 1
		foreach (new DirectoryIterator(ROOT_DIRECTORY . '/modules/Settings/CurrencyUpdate/bankmodels/') as $fileInfo) {
94 1
			if (!$fileInfo->isFile() || 'php' !== $fileInfo->getExtension()) {
95
				continue;
96
			}
97
			$bankClassName = $fileInfo->getBasename('.php');
98
			$isExists = (new \App\Db\Query())->from('yetiforce_currencyupdate_banks')->where(['bank_name' => $bankClassName])->exists();
99
			if (!$isExists) {
100
				$db->createCommand()->insert('yetiforce_currencyupdate_banks', ['bank_name' => $bankClassName, 'active' => 0])->execute();
101 1
			}
102 1
		}
103 1
		\App\Cache::delete('ActiveBankForExchangeRate', '');
104 1
	}
105
106 1
	/**
107 1
	 * Update currency rate in archives.
108
	 *
109
	 * @param <Integer> $id       - exchange rate id
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Integer> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Integer>.
Loading history...
110 1
	 * @param <Float>   $exchange - exchange rate
111 1
	 */
112 1
	public function updateCurrencyRate($id, $exchange)
113
	{
114
		\App\Db::getInstance()->createCommand()
115 1
			->update('yetiforce_currencyupdate', ['exchange' => $exchange], ['id' => $id])
116 1
			->execute();
117
	}
118 1
119
	/**
120
	 * Adds currency exchange rate to archive.
121
	 *
122
	 * @param <Integer> $currId       - currency id
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Integer> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Integer>.
Loading history...
123
	 * @param <Date>    $exchangeDate - exchange date
124
	 * @param <Float>   $exchange     - exchange rate
125
	 * @param <Integer> $bankId       - bank id
126 1
	 */
127
	public function addCurrencyRate($currId, $exchangeDate, $exchange, $bankId)
128 1
	{
129 1
		\App\Db::getInstance()->createCommand()->insert('yetiforce_currencyupdate', [
130 1
			'currency_id' => $currId,
131 1
			'fetch_date' => date('Y-m-d'),
132
			'exchange_date' => $exchangeDate,
133
			'exchange' => $exchange,
134
			'bank_id' => $bankId,
135
		])->execute();
136
	}
137
138
	/**
139
	 * Returns currency exchange rate id.
140
	 *
141 1
	 * @param <Integer> $currencyId   - systems currency id
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Integer> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Integer>.
Loading history...
142
	 * @param <Date>    $exchangeDate - date of exchange rate
143 1
	 * @param <Integer> $bankId       - id of bank
144 1
	 *
145 1
	 * @return <Integer> - currency rate id
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Integer> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Integer>.
Loading history...
146 1
	 */
147 1
	public function getCurrencyRateId($currencyId, $exchangeDate, $bankId)
148 1
	{
149 1
		return (new \App\Db\Query())->select(['id'])
150 1
			->from('yetiforce_currencyupdate')
151
			->where(['exchange_date' => $exchangeDate, 'currency_id' => $currencyId, 'bank_id' => $bankId])
152
			->scalar();
153
	}
154
155
	/**
156
	 * Returns currency rates from archive.
157
	 *
158
	 * @param int    $bankId    - bank id
159
	 * @param string $dateStart - date
160 1
	 * @param string $dateEnd   - date
161
	 *
162 1
	 * @return <Array> - array containing currency rates
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Array> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Array>.
Loading history...
163 1
	 */
164 1
	public function getRatesHistory(int $bankId, string $dateStart, string $dateEnd)
165 1
	{
166
		$query = (new App\Db\Query())->select(['exchange', 'currency_name', 'currency_code', 'currency_symbol', 'fetch_date', 'exchange_date', 'currency_id'])
167
			->from('yetiforce_currencyupdate')
168
			->innerJoin('vtiger_currency_info', 'vtiger_currency_info.id = yetiforce_currencyupdate.currency_id')
169
			->innerJoin('yetiforce_currencyupdate_banks', 'yetiforce_currencyupdate_banks.id = yetiforce_currencyupdate.bank_id')
170
			->where(['yetiforce_currencyupdate.bank_id' => $bankId]);
171
		// filter by date - if not exists then display this months history
172
		if ($dateEnd) {
173
			$query->andWhere(['between', 'exchange_date', $dateStart, $dateEnd]);
174
		} else {
175
			$query->andWhere(['exchange_date' => $dateStart]);
176
		}
177
		return $query->orderBy(['exchange_date' => SORT_DESC, 'currency_id' => SORT_ASC])->all();
178
	}
179
180
	/**
181
	 * Returns list of supported currencies by active bank.
182
	 *
183
	 * @param string $bankName - bank name
184
	 *
185
	 * @return <Array> - array of supported currencies
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Array> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Array>.
Loading history...
186
	 */
187
	public function getSupportedCurrencies($bankName = null)
188
	{
189
		if (!\App\RequestUtil::isNetConnection()) {
190
			return [];
191
		}
192
		if (!$bankName) {
193
			$bankName = 'Settings_CurrencyUpdate_' . $this->getActiveBankName() . '_BankModel';
194
		}
195
		$currencies = [];
196
		try {
197 1
			$bank = new $bankName();
198
			$currencies = $bank->getSupportedCurrencies();
199 1
		} catch (\Throwable $ex) {
200
			\App\Log::error('Error during downloading table: ' . PHP_EOL . $ex->__toString() . PHP_EOL, 'CurrencyUpdate');
201
		}
202 1
		return $currencies;
203 1
	}
204
205 1
	/**
206
	 * Returns list of unsupported currencies by active bank.
207 1
	 *
208
	 * @param string $bankName - bank name
209
	 *
210
	 * @return <Array> - array of unsupported currencies
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Array> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Array>.
Loading history...
211
	 */
212
	public function getUnSupportedCurrencies($bankName = null)
213
	{
214
		if (!\App\RequestUtil::isNetConnection()) {
215
			return [];
216 1
		}
217
		if (!$bankName && !empty($this->getActiveBankName())) {
218 1
			$bankName = 'Settings_CurrencyUpdate_' . $this->getActiveBankName() . '_BankModel';
219
		}
220
		if (!empty($this->getActiveBankName())) {
221 1
			$bank = new $bankName();
222 1
			$supported = $bank->getSupportedCurrencies($bankName);
223
		}
224 1
		$dataReader = (new \App\Db\Query())->select(['currency_name', 'currency_code'])
225 1
			->from('vtiger_currency_info')
226 1
			->where(['currency_status' => 'Active', 'deleted' => 0])
227 1
			->createCommand()->query();
228 1
		while ($row = $dataReader->read()) {
229 1
			$name = $row['currency_name'];
230 1
			$code = $row['currency_code'];
231 1
			$unsupported[$name] = $code;
232 1
		}
233 1
		$dataReader->close();
234
		return array_diff($unsupported, !empty($supported) ? $supported : []);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $unsupported does not seem to be defined for all execution paths leading up to this point.
Loading history...
235 1
	}
236
237 1
	/**
238
	 * Sets systems exchange rate for chosen currency.
239
	 *
240
	 * @param string  $currency - currency code
241
	 * @param <Float> $exchange - exchange rate
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Float> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Float>.
Loading history...
242
	 */
243
	public function setCRMConversionRate($currency, $exchange)
244
	{
245
		$rate = (float) $exchange;
246 1
		\App\Db::getInstance()->createCommand()
247
			->update('vtiger_currency_info', ['conversion_rate' => $rate], ['currency_code' => $currency])
248 1
			->execute();
249 1
	}
250 1
251 1
	/**
252 1
	 * Function that retrieves conversion rate from and to specified currency.
253
	 *
254
	 * @param int    $from - currency id
255
	 * @param int    $to   - currency id
256
	 * @param string $date - date of the exchange rate
257
	 *
258
	 * @return <Float> - conversion rate
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Float> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Float>.
Loading history...
259
	 */
260
	public function getCRMConversionRate(int $from, int $to, string $date)
261
	{
262 1
		$mainCurrencyCode = \App\Fields\Currency::getDefault()['id'];
263
		$exchange = 0;
264 1
265 1
		if ($to != $mainCurrencyCode && ($activeBankId = self::getActiveBankId())) {
0 ignored issues
show
Bug Best Practice introduced by
The method Settings_CurrencyUpdate_...odel::getActiveBankId() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

265
		if ($to != $mainCurrencyCode && ($activeBankId = self::/** @scrutinizer ignore-call */ getActiveBankId())) {
Loading history...
266 1
			$exchange = (float) (\App\Fields\Currency::getCurrencyRatesFromArchive($date, $to, $activeBankId)['exchange'] ?? 0);
267 1
			if (empty($exchange) && \App\RequestUtil::isNetConnection()) {
268
				self::fetchCurrencyRates($date);
0 ignored issues
show
Bug Best Practice introduced by
The method Settings_CurrencyUpdate_...l::fetchCurrencyRates() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

268
				self::/** @scrutinizer ignore-call */ 
269
          fetchCurrencyRates($date);
Loading history...
269
				$exchange = (float) (\App\Fields\Currency::getCurrencyRatesFromArchive($date, $to, $activeBankId)['exchange'] ?? 0);
270 1
			}
271
		}
272
273
		if ($exchange) {
274 1
			$exchange = 1 / $exchange;
275 1
		}
276 1
277 1
		if ($from != $mainCurrencyCode && ($activeBankId = self::getActiveBankId())) {
278 1
			$convertToMainCurrency = 0 == $exchange ? 1 : 1 / $exchange;
279 1
280 1
			$fromExchange = (float) (\App\Fields\Currency::getCurrencyRatesFromArchive($date, $from, $activeBankId)['exchange'] ?? 0);
281 1
			if (empty($fromExchange) && \App\RequestUtil::isNetConnection()) {
282
				self::fetchCurrencyRates($date);
283
				$fromExchange = (float) (\App\Fields\Currency::getCurrencyRatesFromArchive($date, $from, $activeBankId)['exchange'] ?? 0);
284
			}
285
286
			if ($to != $mainCurrencyCode) {
287
				$exchange = $fromExchange / $convertToMainCurrency;
288
			} else {
289
				$exchange = $fromExchange * $convertToMainCurrency;
290
			}
291
		}
292
293
		return $exchange = round($exchange, 5);
0 ignored issues
show
Unused Code introduced by
The assignment to $exchange is dead and can be removed.
Loading history...
294
	}
295
296
	/**
297
	 * Returns id of active bank.
298
	 *
299
	 * @return <Integer> - bank id
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Integer> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Integer>.
Loading history...
300
	 */
301
	public function getActiveBankId()
302
	{
303
		return \App\Fields\Currency::getActiveBankForExchangeRateUpdate()['id'] ?? 0;
304
	}
305
306
	/**
307
	 * Saves new active bank by id.
308
	 *
309
	 * @param <Integer> $bankId - bank id
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Integer> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Integer>.
Loading history...
310
	 *
311
	 * @return bool - true on success or false
312
	 */
313
	public function setActiveBankById($bankId)
314
	{
315
		$db = \App\Db::getInstance();
316
		$result = $db->createCommand()->update('yetiforce_currencyupdate_banks', ['active' => 0])->execute();
317
		if (!empty($bankId)) {
318
			$result = $db->createCommand()->update('yetiforce_currencyupdate_banks', ['active' => 1], ['id' => $bankId])->execute();
319
		}
320
		\App\Cache::delete('ActiveBankForExchangeRate', '');
321
322
		return (bool) $result;
323
	}
324
325
	/**
326
	 * Returns active banks name.
327
	 *
328
	 * @return string - bank name
329
	 */
330
	public function getActiveBankName()
331
	{
332
		return \App\Fields\Currency::getActiveBankForExchangeRateUpdate()['bank_name'] ?? '';
333
	}
334
}
335