PluginProbe
Moloni / trunk
Moloni vtrunk
5.0.10 5.0.09 5.0.08 5.0.07 5.0.06 trunk 0.4.0.00 0.4.8.1 3.0.10 3.0.11 3.0.35 3.0.36 3.0.37 3.0.38 3.0.40 3.0.41 3.0.42 3.0.43 3.0.44 3.0.45 3.0.46 3.0.47 3.0.48 3.0.49 3.0.50 All 98 releases
moloni / src / Controllers / OrderShipping.php

OrderShipping.php in Moloni trunk, at src/Controllers/OrderShipping.php

370 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 namespace Moloni\Controllers;
4
5 use Moloni\Curl;
6 use Moloni\Exceptions\APIException;
7 use Moloni\Exceptions\GenericException;
8 use Moloni\Tools;
9 use WC_Order;
10
11 class OrderShipping
12 {
13
14 /** @var int */
15 public $product_id = 0;
16
17 /** @var int */
18 private $index;
19
20 /** @var array */
21 private $taxes = [];
22
23 /** @var float */
24 private $qty;
25
26 /** @var float */
27 private $price;
28
29 /** @var string */
30 private $exemption_reason;
31
32 /** @var string */
33 private $name;
34
35 /** @var float */
36 private $discount;
37
38 /** @var WC_Order */
39 private $order;
40
41 /** @var string */
42 private $reference;
43
44 /** @var int */
45 private $category_id;
46
47 private $type = 2;
48 private $summary = '';
49 private $ean = '';
50 private $unit_id;
51 private $has_stock = 0;
52 private $stock = 0;
53 private $at_product_category = 'M';
54
55 /** @var bool */
56 private $hasIVA = false;
57
58 /** @var array */
59 private $fiscalData;
60
61 /**
62 * OrderProduct constructor.
63 * @param WC_Order $order
64 * @param int $index
65 */
66 public function __construct($order, $index = 0, $fiscalData = [])
67 {
68 $this->order = $order;
69 $this->index = $index;
70 $this->fiscalData = $fiscalData;
71 }
72
73 /**
74 * @return $this
75 *
76 * @throws APIException
77 * @throws GenericException
78 */
79 public function create()
80 {
81 $this
82 ->setQuantity()
83 ->setPrice()
84 ->setReference()
85 ->setDiscount()
86 ->setTaxes()
87 ->setName()
88 ->setSummary()
89 ->setProductId();
90
91 return $this;
92 }
93
94 // Sets //
95
96 private function setQuantity()
97 {
98 $this->qty = 1;
99
100 return $this;
101 }
102
103 private function setPrice()
104 {
105 $price = (float)$this->order->get_shipping_total();
106
107 $refundedValue = (float)$this->order->get_total_shipping_refunded();
108
109 if ($refundedValue > 0) {
110 $price -= $refundedValue;
111 }
112
113 if ($price < 0) {
114 $price = 0;
115 }
116
117 $this->price = (float)apply_filters('moloni_after_order_shipping_setPrice', $price, $this->order);
118
119 return $this;
120 }
121
122 /**
123 * @return $this
124 */
125 private function setReference()
126 {
127 $this->reference = 'Portes';
128 return $this;
129 }
130
131 /**
132 * @return $this
133 *
134 * @throws APIException
135 * @throws GenericException
136 */
137 private function setProductId()
138 {
139 $searchProduct = Curl::simple('products/getByReference', ['reference' => $this->reference, 'with_invisible' => true, 'exact' => 1]);
140
141 if (!empty($searchProduct) && isset($searchProduct[0]['product_id'])) {
142 if ($searchProduct[0]['visibility_id'] === 1) {
143 $this->product_id = $searchProduct[0]['product_id'];
144 } else {
145 throw new GenericException('Produto com referência ' . $this->reference . ' tem de estar ativo.');
146 }
147
148 return $this;
149 }
150
151 // Let's create the shipping product
152 $this
153 ->setCategory()
154 ->setUnitId();
155
156 $insert = Curl::simple('products/insert', $this->mapPropsToValues(true));
157 if (isset($insert['product_id'])) {
158 $this->product_id = $insert['product_id'];
159 return $this;
160 }
161
162 throw new GenericException('Erro ao inserir portes de envio');
163 }
164
165 /**
166 * @return OrderShipping
167 *
168 * @throws APIException
169 * @throws GenericException
170 */
171 private function setCategory()
172 {
173 $categoryName = 'Loja Online';
174
175 $categoryObj = new ProductCategory($categoryName);
176
177 if (!$categoryObj->loadByName()) {
178 $categoryObj->create();
179 }
180
181 $this->category_id = $categoryObj->category_id;
182
183 return $this;
184 }
185
186 /**
187 * @return $this
188 *
189 * @throws GenericException
190 */
191 private function setUnitId()
192 {
193 if (defined('MEASURE_UNIT')) {
194 $this->unit_id = MEASURE_UNIT;
195 } else {
196 throw new GenericException('Unidade de medida não definida!');
197 }
198
199 return $this;
200 }
201
202 /**
203 * Set the discount in percentage
204 * @return $this
205 */
206 private function setDiscount()
207 {
208 $this->discount = $this->price <= 0 ? 100 : 0;
209
210 if ($this->discount < 0) {
211 $this->discount = 0;
212 } elseif ($this->discount > 100) {
213 $this->discount = 100;
214 }
215
216 return $this;
217 }
218
219 /**
220 * Set the taxes of a product
221 *
222 * @return OrderShipping
223 *
224 * @throws APIException
225 */
226 private function setTaxes()
227 {
228 $shippingTotal = 0;
229
230 foreach ($this->order->get_shipping_methods() as $item_id => $item) {
231 $taxes = $item->get_taxes();
232 foreach ($taxes['total'] as $tax_rate_id => $tax) {
233 $shippingTotal += (float)$tax;
234 }
235 }
236
237 $taxRate = round(($shippingTotal * 100) / $this->order->get_shipping_total(), 1);
238
239 if ((float)$taxRate > 0) {
240 $this->taxes[] = $this->setTax($taxRate);
241 }
242
243 if (!$this->hasIVA) {
244 $exemptionReason = '';
245
246 if ($this->isCountryIntraCommunity()) {
247 $exemptionReason = defined('EXEMPTION_REASON_SHIPPING') ? EXEMPTION_REASON_SHIPPING : '';
248 } else {
249 if (defined('EXEMPTION_REASON_SHIPPING_EXTRA_COMMUNITY')) {
250 $exemptionReason = EXEMPTION_REASON_SHIPPING_EXTRA_COMMUNITY;
251 } elseif (defined('EXEMPTION_REASON_SHIPPING')) {
252 $exemptionReason = EXEMPTION_REASON_SHIPPING;
253 }
254 }
255
256 $this->exemption_reason = $exemptionReason;
257 }
258
259 return $this;
260 }
261
262 /**
263 * @param float $taxRate Tax Rate in percentage
264 *
265 * @return array
266 *
267 * @throws APIException
268 */
269 private function setTax($taxRate)
270 {
271 $moloniTax = Tools::getTaxFromRate((float)$taxRate, $this->fiscalData['code']);
272
273 $tax = [];
274 $tax['tax_id'] = $moloniTax['tax_id'];
275 $tax['value'] = $taxRate;
276 $tax['order'] = is_array($this->taxes) ? count($this->taxes) : 0;
277 $tax['cumulative'] = 0;
278
279 if ((int)$moloniTax['saft_type'] === 1) {
280 $this->hasIVA = true;
281 }
282
283 return $tax;
284 }
285
286 /**
287 * @param string $name
288 * @return $this
289 */
290 public function setName($name = '')
291 {
292 $name = empty($name) ? $this->order->get_shipping_method() : $name;
293
294 $this->name = apply_filters('moloni_after_order_shipping_setName', $name, $this->order);
295
296 return $this;
297 }
298
299 /**
300 * @param string $summary
301 * @return $this
302 */
303 public function setSummary($summary = '')
304 {
305 $summary = empty($summary) ? '' : $summary;
306
307 $this->summary = apply_filters('moloni_after_order_shipping_setSummary', $summary, $this->order);
308
309 return $this;
310 }
311
312 // Gets //
313
314 public function getPrice()
315 {
316 return $this->price ?? 0.0;
317 }
318
319 /**
320 * @param bool $toInsert
321 * @return array
322 */
323 public function mapPropsToValues($toInsert = false)
324 {
325 $values = [];
326
327 $values['product_id'] = $this->product_id;
328 $values['name'] = $this->name;
329 $values['summary'] = '';
330 $values['qty'] = $this->qty;
331 $values['price'] = $this->price;
332 $values['discount'] = $this->discount;
333 $values['order'] = $this->index;
334 $values['exemption_reason'] = $this->exemption_reason;
335 $values['taxes'] = $this->taxes;
336
337 if ($toInsert) {
338 $values['reference'] = $this->reference;
339 $values['type'] = $this->type;
340 $values['stock'] = $this->stock;
341 $values['has_stock'] = $this->has_stock;
342 $values['at_product_category'] = $this->at_product_category;
343 $values['summary'] = $this->summary;
344 $values['ean'] = $this->ean;
345 $values['unit_id'] = $this->unit_id;
346 $values['category_id'] = $this->category_id;
347 }
348
349 return $values;
350 }
351
352 /**
353 * Check if country is intra community
354 *
355 * @return bool
356 */
357 private function isCountryIntraCommunity(): bool
358 {
359 if (!isset(Tools::$europeanCountryCodes[$this->fiscalData['code']])) {
360 return false;
361 }
362
363 if ($this->fiscalData['code'] === 'ES' && in_array($this->fiscalData['state'], ['TF', 'GC'])) {
364 return false;
365 }
366
367 return true;
368 }
369 }
370