PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.16
VikBooking Hotel Booking Engine & PMS v1.8.16
1.8.16 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 All 37 releases
← All changes | admin/helpers/src/currency/ota.php +319 -0 1.6.3 → 1.8.16 View file →
@@ -1,0 +1,319 @@
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 +}