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 / OrderCustomer.php

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

356 lines 9.4 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 WC_Order;
6 use Moloni\Curl;
7 use Moloni\Tools;
8 use Moloni\Exceptions\APIException;
9 use Moloni\Exceptions\GenericException;
10
11 class OrderCustomer
12 {
13 /**
14 * @var WC_Order
15 */
16 private $order;
17
18 /**
19 * List of some invalid vat numbers
20 * @var array
21 */
22 private $invalidVats = [
23 '999999999',
24 '000000000',
25 '111111111'
26 ];
27
28 /**
29 * Documents constructor.
30 * @param WC_Order $order
31 */
32 public function __construct($order)
33 {
34 $this->order = $order;
35 }
36
37 /**
38 * @return mixed
39 *
40 * @throws APIException
41 * @throws GenericException
42 */
43 public function create($retry = 0)
44 {
45 $nameData = $this->getCustomerName();
46
47 $values = [
48 'vat' => $this->getVatNumber(),
49 'name' => $nameData['name'],
50 'contact_name' => $nameData['contact_name'],
51 'address' => $this->getCustomerBillingAddress(),
52 'zip_code' => $this->getCustomerZip(),
53 'city' => $this->getCustomerBillingCity(),
54 'country_id' => $this->getCustomerCountryId(),
55 'email' => $this->order->get_billing_email(),
56 'phone' => $this->order->get_billing_phone(),
57 'maturity_date_id' => defined('MATURITY_DATE') ? MATURITY_DATE : '',
58 'payment_method_id' => defined('PAYMENT_METHOD') ? PAYMENT_METHOD : '',
59 'salesman_id' => '',
60 'payment_day' => '',
61 'discount' => '',
62 'credit_limit' => '',
63 'delivery_method_id' => '',
64 'field_notes' => '',
65 ];
66
67 $values['language_id'] = $this->getCustomerLanguageId($values['country_id']);
68
69 $values = apply_filters('moloni_before_search_customer', $values);
70
71 if (!empty($values['customer_id'])) {
72 return (int)$values['customer_id'];
73 }
74
75 $customerExists = $this->searchForCustomer($values);
76
77 if (!$customerExists) {
78 $values['number'] = $this->nextNumberCreator();
79
80 $result = Curl::simple('customers/insert', $values);
81 } else {
82 $values['customer_id'] = $customerExists['customer_id'];
83 $result = Curl::simple('customers/update', $values);
84 }
85
86 if (!isset($result['customer_id'])) {
87 if ($retry < 3 && !$customerExists && $this->shouldRetryInsert($result)) {
88 return $this->create($retry + 1);
89 }
90
91 throw new GenericException(__('Atenção, houve um erro ao inserir o cliente.'));
92 }
93
94 return (int)$result['customer_id'];
95 }
96
97 /**
98 * Get the vat number of an order
99 * Get it from a custom field and validate if Portuguese
100 * @return string
101 */
102 public function getVatNumber(): string
103 {
104 $vat = '999999990';
105
106 if (defined('VAT_FIELD')) {
107 $metaVat = trim($this->order->get_meta(VAT_FIELD));
108 if (!empty($metaVat)) {
109 $vat = $metaVat;
110 }
111 }
112
113 $billingCountry = $this->order->get_billing_country();
114
115 // Do some more verifications if the vat number is Portuguese
116 if ($billingCountry === 'PT') {
117 // Remove the PT part from the beginning
118 if (stripos($vat, strtoupper('PT')) === 0) {
119 $vat = str_ireplace('PT', '', $vat);
120 }
121
122 // Check if the vat is one of this
123 if (empty($vat) || in_array($vat, $this->invalidVats, false)) {
124 $vat = '999999990';
125 }
126 }
127
128 return $vat;
129 }
130
131 /**
132 * Checks if the company name is set
133 * If the order has a company we issue the document to the company
134 * And add the name of the person to the contact name
135 *
136 * @return array
137 */
138 public function getCustomerName(): array
139 {
140 $billingName = trim($this->order->get_billing_first_name() ?? '');
141 $billingLastName = trim($this->order->get_billing_last_name() ?? '');
142 $billingCompany = trim($this->order->get_billing_company() ?? '');
143
144 if (!empty($billingLastName)) {
145 $billingName .= ' ' . $billingLastName;
146 }
147
148 $name = 'Cliente';
149 $contactName = '';
150
151 if (!empty($billingCompany)) {
152 $name = $billingCompany;
153 $contactName = $billingName;
154 } elseif (!empty($billingName)) {
155 $name = $billingName;
156 }
157
158 return ['name' => $name, 'contact_name' => $contactName];
159 }
160
161 /**
162 * Create a customer billing a address
163 * @return string
164 */
165 public function getCustomerBillingAddress(): string
166 {
167 $billingAddress = trim($this->order->get_billing_address_1() ?? '');
168 $billingAddress2 = trim($this->order->get_billing_address_2() ?? '');
169
170 if (!empty($billingAddress2)) {
171 $billingAddress .= ' ' . $billingAddress2;
172 }
173
174 return empty($billingAddress) ? 'Desconhecida' : $billingAddress;
175 }
176
177 /**
178 * Create a customer billing City
179 * @return string
180 */
181 public function getCustomerBillingCity(): string
182 {
183 $city = trim($this->order->get_billing_city() ?? '');
184
185 return empty($city) ? 'Desconhecida' : $city;
186 }
187
188 /**
189 * Gets the zip code of a customer
190 * If the customer is Portuguese validate the Vat Number
191 * @return string
192 */
193 public function getCustomerZip(): string
194 {
195 $zipCode = $this->order->get_billing_postcode() ?? '';
196
197 if ($this->order->get_billing_country() === 'PT') {
198 $zipCode = Tools::zipCheck($zipCode);
199 }
200
201 return empty($zipCode ?? '') ? '1000-100' : $zipCode;
202 }
203
204 /**
205 * Get the customer next available number for incremental inserts
206 *
207 * @throws APIException
208 */
209 public static function getCustomerNextNumber()
210 {
211 $results = Curl::simple('customers/getNextNumber', []);
212
213 if (!empty($results['number'])) {
214 return ($results['number']);
215 }
216
217 return (mt_rand(10000000000, 100000000000));
218 }
219
220 /**
221 * Get the country_id based on a ISO value
222 *
223 * @throws APIException
224 */
225 public function getCustomerCountryId(): string
226 {
227 $countryCode = $this->order->get_billing_country();
228
229 return Tools::getCountryIdFromCode($countryCode);
230 }
231
232 /**
233 * If the country of the customer is one of the available we set it to Portuguese
234 */
235 public function getCustomerLanguageId($countryId): int
236 {
237 return (int)$countryId === 1 ? 1 : 2;
238 }
239
240 /**
241 * Search for a customer based on vat or email
242 *
243 * @param array $values
244 *
245 * @return bool|array
246 *
247 * @throws APIException
248 */
249 public function searchForCustomer(array $values = [])
250 {
251 $search = [
252 'exact' => 1,
253 ];
254
255 $values['vat'] = $values['vat'] ?? '999999990';
256
257 if ($values['vat'] !== '999999990') {
258 $search['vat'] = $values['vat'];
259
260 $searchResult = Curl::simple('customers/getByVat', $search);
261
262 if (empty($searchResult) || !is_array($searchResult)) {
263 return false;
264 }
265
266 foreach ($searchResult as $customer) {
267 if (!isset($customer['customer_id'])) {
268 continue;
269 }
270
271 if ((string)$customer['vat'] !== (string)$values['vat']) {
272 continue;
273 }
274
275 return $customer;
276 }
277 } elseif (!empty($values['email'])) {
278 $search['email'] = $values['email'];
279
280 $searchResult = Curl::simple('customers/getByEmail', $search);
281
282 if (empty($searchResult) || !is_array($searchResult)) {
283 return false;
284 }
285
286 foreach ($searchResult as $customer) {
287 if (!isset($customer['customer_id']) || !isset($customer['vat'])) {
288 continue;
289 }
290
291 if ($customer['vat'] !== '999999990') {
292 continue;
293 }
294
295 return $customer;
296 }
297 }
298
299 return false;
300 }
301
302 // Auxiliary //
303
304 private function nextNumberCreator()
305 {
306 // Normal way
307
308 if (!defined('CUSTOMER_NUMBER_PREFIX') || empty(CUSTOMER_NUMBER_PREFIX)) {
309 $results = Curl::simple('customers/getNextNumber', []);
310
311 if (!empty($results['number'])) {
312 return ($results['number']);
313 }
314
315 return (mt_rand(10000000000, 100000000000));
316 }
317
318 // Find by prefix
319
320 $results = Curl::simple('customers/getByNumber', [
321 'number' => CUSTOMER_NUMBER_PREFIX . "%",
322 'order_by_field' => 'customer_id',
323 'order_by_ordering' => 'desc',
324 'qty' => 1,
325 'exact' => 1,
326 ]);
327
328 if (!isset($results[0]['number'])) {
329 return CUSTOMER_NUMBER_PREFIX . '1';
330 }
331
332 $number = substr($results[0]['number'], strlen(CUSTOMER_NUMBER_PREFIX));
333
334 return CUSTOMER_NUMBER_PREFIX . ((int)$number + 1);
335 }
336
337 private function shouldRetryInsert($result): bool
338 {
339 if (empty($result) || !is_array($result)) {
340 return false;
341 }
342
343 foreach ($result as $error) {
344 if (!isset($error["code"])) {
345 continue;
346 }
347
348 if ($error["code"] === '4 number') {
349 return true;
350 }
351 }
352
353 return false;
354 }
355 }
356