PluginProbe
VikBooking Hotel Booking Engine & PMS / trunk
VikBooking Hotel Booking Engine & PMS vtrunk
1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 All 36 releases
vikbooking / admin / helpers / src / currency / ota.php

ota.php in VikBooking Hotel Booking Engine & PMS trunk, at admin/helpers/src/currency/ota.php

320 lines 8.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage core
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2022 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 /**
15 * Helper class to allow currency conversion for OTA bookings.
16 * Extends JObject and expects to be constructed with the booking record.
17 * Used to convert OTA bookings in foreign currencies into the local currency.
18 *
19 * @since 1.15.0 (J) - 1.5.0 (WP)
20 */
21 class VBOCurrencyOta extends JObject
22 {
23 /**
24 * The default currency name.
25 *
26 * @var string
27 */
28 protected $currency_name = '';
29
30 /**
31 * The default currency number format data.
32 *
33 * @var array
34 */
35 protected $currency_format = [];
36
37 /**
38 * The list of columns that can be converted for the reservation.
39 *
40 * @var array
41 */
42 protected $convertable_res_keys = [
43 'totpaid',
44 'total',
45 'tot_taxes',
46 'tot_city_taxes',
47 'tot_fees',
48 'cmms',
49 ];
50
51 /**
52 * The list of columns that can be converted for the rooms booked.
53 *
54 * @var array
55 */
56 protected $convertable_room_keys = [
57 'cust_cost',
58 'room_cost',
59 ];
60
61 /**
62 * Tells whether the injected reservation array/object
63 * supports and allows a currency conversion.
64 *
65 * @param float $def_rate the default rate to use to check if conversion works.
66 *
67 * @return bool|float false if conversion not supported/allowed or float exchange rate.
68 */
69 public function supportsConversion($def_rate = 1)
70 {
71 $ota_currency = $this->get('chcurrency', '');
72 if (empty($ota_currency)) {
73 // not an OTA reservation, or empty OTA currency
74 return false;
75 }
76 $ota_currency = strtoupper($ota_currency);
77
78 // import currency converter class
79 if (!VikBooking::import('currencyconverter')) {
80 return false;
81 }
82
83 // make sure the default rate is greater than zero
84 $def_rate = $def_rate <= 0 ? 1 : $def_rate;
85
86 // invoke currency converter
87 $converter = new VboCurrencyConverter($ota_currency, $this->getCurrencyName(), [$def_rate], $this->getFormatData());
88
89 // make sure the OTA currency is supported for conversion
90 if (!$converter->currencyExists($ota_currency)) {
91 return false;
92 }
93
94 // default currency must be valid as well
95 if (!$converter->currencyExists($this->getCurrencyName())) {
96 return false;
97 }
98
99 // make sure currencies are different
100 if ($ota_currency == $this->getCurrencyName()) {
101 return false;
102 }
103
104 // attempt to get the exchange rate
105 $exchange_rate = $converter->getConversionRate();
106
107 if ($exchange_rate === false) {
108 // exchanging the currencies was not allowed
109 return false;
110 }
111
112 // get the default rate exchanged
113 $exchanged = $converter->convert(true);
114
115 if (!is_array($exchanged) || !$exchanged) {
116 // something went wrong
117 return false;
118 }
119
120 // return the converted default rate
121 return $exchanged[0];
122 }
123
124 /**
125 * If currency conversion is supported, converts all the amounts of
126 * a reservation into the ones of the default website currency.
127 *
128 * @return bool true on success, false otherwise.
129 */
130 public function convertReservationCurrency()
131 {
132 $dbo = JFactory::getDbo();
133
134 // make sure the booking ID is valid
135 $vbo_bid = $this->get('id');
136 if (empty($vbo_bid)) {
137 return false;
138 }
139
140 // load the reservation record from Vik Booking
141 $reservation = new JObject(VikBooking::getBookingInfoFromID($vbo_bid));
142 if (!$reservation->get('id')) {
143 // booking not found
144 return false;
145 }
146
147 // import currency converter class
148 if (!VikBooking::import('currencyconverter')) {
149 return false;
150 }
151
152 // load rooms data array
153 $reservation_rooms = VikBooking::loadOrdersRoomsData($vbo_bid);
154
155 // import currency converter and make sure conversion is allowed
156 if ($this->supportsConversion() === false) {
157 return false;
158 }
159
160 // the OTA (supported) currency
161 $ota_currency = strtoupper($this->get('chcurrency'));
162
163 // build the associative list of the rates to exchange for the reservation
164 $raw_rates = [];
165 foreach ($this->convertable_res_keys as $res_key) {
166 $raw_rates[$res_key] = $reservation->get($res_key, 0);
167 }
168
169 // invoke the converter class to actually exchange the rates
170 $converter = new VboCurrencyConverter($ota_currency, $this->getCurrencyName(), $raw_rates, $this->getFormatData());
171
172 // get the raw rates exchanged
173 $exchanged = $converter->convert(true);
174
175 if (!$exchanged || $exchanged === $raw_rates) {
176 // converting was not possible
177 return false;
178 }
179
180 // apply converted rates for the reservation
181 $res_record = new stdClass;
182 $res_record->id = $vbo_bid;
183 foreach ($exchanged as $key => $excrate) {
184 $res_record->{$key} = $excrate;
185 }
186 // make sure to update the original OTA currency so that
187 // this reservation will no longer require conversion
188 $res_record->chcurrency = $this->getCurrencyName();
189
190 // update reservation record with the new information
191 $dbo->updateObject('#__vikbooking_orders', $res_record, 'id');
192
193 // loop through all room records
194 foreach ($reservation_rooms as $order_room) {
195 // build the list of raw rates to exchange for this room
196 $raw_rates = [];
197 foreach ($this->convertable_room_keys as $room_key) {
198 if (!isset($order_room[$room_key])) {
199 continue;
200 }
201 $raw_rates[$room_key] = $order_room[$room_key];
202 }
203 if (!$raw_rates) {
204 // all null or invalid values that do not need a conversion
205 continue;
206 }
207
208 // update rates to convert in converter object
209 $converter->setPrices($raw_rates);
210
211 // get the raw rates exchanged
212 $exchanged = $converter->convert(true);
213
214 if (!$exchanged || $exchanged === $raw_rates) {
215 // converting did not produce results
216 continue;
217 }
218
219 // apply converted rates for this room record
220 $room_record = new stdClass;
221 $room_record->id = $order_room['id'];
222 foreach ($exchanged as $key => $excrate) {
223 $room_record->{$key} = $excrate;
224 }
225
226 /**
227 * We need to statically take care of another room-reservation property
228 * which requires a JSON structure: "extracosts" for the extra services.
229 *
230 * @since 1.16.3 (J) - 1.6.3 (WP)
231 */
232 if (!empty($order_room['extracosts'])) {
233 $room_extra_costs = is_string($order_room['extracosts']) ? json_decode($order_room['extracosts'], true) : $order_room['extracosts'];
234 if (is_array($room_extra_costs) && $room_extra_costs) {
235 // build a map for converting the extra cost amounts
236 $room_extra_costs_assoc = [];
237 foreach ($room_extra_costs as $rec_k => $room_ec) {
238 if (!is_array($room_ec) || empty($room_ec['cost'])) {
239 continue;
240 }
241 $room_extra_costs_assoc[$rec_k] = (float)$room_ec['cost'];
242 }
243
244 // check if some costs need to be converted
245 if ($room_extra_costs_assoc) {
246 // update rates to convert in converter object
247 $converter->setPrices($room_extra_costs_assoc);
248
249 // get the raw rates exchanged
250 $exchanged = $converter->convert(true);
251
252 if ($exchanged) {
253 // apply back the converted costs for the custom extras
254 foreach ($exchanged as $rec_k => $excrate) {
255 $room_extra_costs[$rec_k]['cost'] = $excrate;
256 }
257
258 // set the new object property for this room record for the update
259 $room_record->extracosts = json_encode($room_extra_costs);
260 }
261 }
262 }
263 }
264
265 // update room record with the new information
266 $dbo->updateObject('#__vikbooking_ordersrooms', $room_record, 'id');
267 }
268
269 // update booking history
270 VikBooking::getBookingHistoryInstance()->setBid($vbo_bid)->store('CM', JText::sprintf('VBO_CONV_RES_OTA_CURRENCY_HISTORY', $ota_currency, $this->getCurrencyName()));
271
272 // process completed with success
273 return true;
274 }
275
276 /**
277 * Returns the default currency name for the website.
278 *
279 * @return string the default currency name.
280 */
281 public function getCurrencyName()
282 {
283 if (!empty($this->currency_name)) {
284 return $this->currency_name;
285 }
286
287 // load default currency from VikBooking
288 $this->currency_name = VikBooking::getCurrencyName($iso = true);
289
290 return $this->currency_name;
291 }
292
293 /**
294 * Returns the OTA currency name for the current reservation.
295 *
296 * @return string the OTA currency name to convert from.
297 */
298 public function getOTACurrency()
299 {
300 return strtoupper($this->get('chcurrency', ''));
301 }
302
303 /**
304 * Returns the array information for formatting the numbers.
305 *
306 * @return array the exploded formatting data
307 */
308 public function getFormatData()
309 {
310 if (!empty($this->currency_format)) {
311 return $this->currency_format;
312 }
313
314 // load default currency from VikBooking
315 $this->currency_format = explode(':', VikBooking::getNumberFormatData());
316
317 return $this->currency_format;
318 }
319 }
320