update empik
This commit is contained in:
187
docs/empik.md
187
docs/empik.md
@@ -1,134 +1,85 @@
|
||||
# Modyfikacje modułu empikmarketplace
|
||||
# Modyfikacje modulu empikmarketplace
|
||||
|
||||
Data modyfikacji: 2026-03-11
|
||||
## 2026-03-11 - powiadomienia i AUTO_INCREMENT
|
||||
|
||||
## Problem
|
||||
### Problem
|
||||
Przy nieudanym imporcie zamowienia z EMPIK do PrestaShop:
|
||||
1. Nie bylo powiadomienia email o bledzie importu.
|
||||
2. Powstawaly dziury w numeracji zamowien (`id_order`) po `ROLLBACK`.
|
||||
|
||||
Moduł empikmarketplace przy nieudanym imporcie zamówienia z EMPIK do PrestaShop powodował:
|
||||
1. Brak powiadomienia o błędzie — nikt nie wiedział, że zamówienie nie przeszło
|
||||
2. Dziury w numeracji zamówień (`id_order`) — MySQL AUTO_INCREMENT nie cofa się po ROLLBACK transakcji
|
||||
### Zmodyfikowane pliki
|
||||
|
||||
## Zmodyfikowane pliki
|
||||
#### `src/Processor/OrderProcessor.php`
|
||||
- Dodano `use Mail;`.
|
||||
- Dodano stala `ERROR_NOTIFICATION_EMAIL`.
|
||||
- W `import()` po bledzie dodano:
|
||||
- `ROLLBACK`,
|
||||
- `resetOrderAutoIncrement()`,
|
||||
- log bledu,
|
||||
- `sendFailureNotification(...)`.
|
||||
- Dodano metode `resetOrderAutoIncrement()`.
|
||||
- Dodano metode `sendFailureNotification()`.
|
||||
|
||||
### `src/Processor/OrderProcessor.php`
|
||||
#### `mails/pl/empik_import_error.html`
|
||||
- Dodany szablon HTML maila z placeholderami:
|
||||
- `{empik_order_id}`
|
||||
- `{error_date}`
|
||||
- `{error_message}`
|
||||
- `{stack_trace}`
|
||||
|
||||
Dodany import `Mail` na górze pliku:
|
||||
#### `mails/pl/empik_import_error.txt`
|
||||
- Dodana tekstowa wersja szablonu maila.
|
||||
|
||||
```php
|
||||
use Mail;
|
||||
```
|
||||
## 2026-03-15 - dokladniejsza diagnoza blednych zamowien
|
||||
|
||||
Dodana stała z adresem email do powiadomień:
|
||||
### Cel
|
||||
W mailu z bledem importu bylo widac tylko ogolny komunikat:
|
||||
`Invalid order data for order: ...`.
|
||||
Brakowalo informacji, ktore pole w danych zamowienia bylo niepoprawne.
|
||||
|
||||
```php
|
||||
class OrderProcessor
|
||||
{
|
||||
const CODE_WAITING_ACCEPTANCE = 'WAITING_ACCEPTANCE';
|
||||
const CODE_SHIPPING = 'SHIPPING';
|
||||
const ERROR_NOTIFICATION_EMAIL = 'jacek.pyziak@project-pro.pl';
|
||||
```
|
||||
### Zmodyfikowane pliki
|
||||
|
||||
Zmodyfikowana metoda `import()` — dodano wywołanie resetu AUTO_INCREMENT i wysyłki emaila w bloku catch:
|
||||
#### `src/OrderFulfiller/OrderFulfiller.php`
|
||||
- Rozszerzono walidacje w `validate($data)`.
|
||||
- Zamiast jednego ogolnego bledu zbierana jest lista konkretnych problemow, np.:
|
||||
- oba adresy puste: `customer.shipping_address` i `customer.billing_address`,
|
||||
- puste `order_id`,
|
||||
- puste `order_lines`,
|
||||
- puste `order_state`,
|
||||
- puste `total_price`.
|
||||
- Rzucany wyjatek zawiera teraz liste tych bledow (`Validation errors: ...`).
|
||||
|
||||
```php
|
||||
protected function import(EmpikOrderWrapper $empikOrder)
|
||||
{
|
||||
try {
|
||||
Db::getInstance()->execute('START TRANSACTION');
|
||||
$this->orderFulfiller->fulfill($empikOrder);
|
||||
Db::getInstance()->execute('COMMIT');
|
||||
} catch (Exception $e) {
|
||||
Db::getInstance()->execute('ROLLBACK');
|
||||
$this->resetOrderAutoIncrement();
|
||||
#### `src/Processor/OrderProcessor.php`
|
||||
- W `import()` do `sendFailureNotification(...)` przekazywany jest payload zamowienia (`$data`).
|
||||
- `sendFailureNotification(...)` przyjmuje teraz trzeci argument: `array $orderData = []`.
|
||||
- Dodano metode `buildOrderContext(array $orderData)` budujaca skrot payloadu do maila:
|
||||
- `order_id`
|
||||
- `order_state`
|
||||
- `total_price`
|
||||
- `shipping_price`
|
||||
- `order_lines_count`
|
||||
- `has_shipping_address`
|
||||
- `has_billing_address`
|
||||
- Do placeholderow maila dodano:
|
||||
- `{order_context}`
|
||||
- `{order_context_html}`
|
||||
|
||||
$data = $empikOrder->getData();
|
||||
$empikOrderId = isset($data['order_id']) ? $data['order_id'] : 'unknown';
|
||||
$errorMsg = sprintf('Error importing EMPIK order [%s]: %s', $empikOrderId, $e->getMessage());
|
||||
$this->logger->logError($errorMsg);
|
||||
$this->sendFailureNotification($empikOrderId, $e);
|
||||
}
|
||||
}
|
||||
```
|
||||
#### `mails/pl/empik_import_error.html`
|
||||
- Dodano sekcje `Szczegoly zamowienia` z placeholderem `{order_context_html}`.
|
||||
|
||||
Dodana metoda `resetOrderAutoIncrement()` — zapobiega dziurom w numeracji zamówień:
|
||||
#### `mails/pl/empik_import_error.txt`
|
||||
- Dodano sekcje `Szczegoly zamowienia` z placeholderem `{order_context}`.
|
||||
|
||||
```php
|
||||
protected function resetOrderAutoIncrement()
|
||||
{
|
||||
try {
|
||||
$lastId = (int) Db::getInstance()->getValue(
|
||||
'SELECT MAX(id_order) FROM ' . _DB_PREFIX_ . 'orders'
|
||||
);
|
||||
Db::getInstance()->execute(
|
||||
'ALTER TABLE ' . _DB_PREFIX_ . 'orders AUTO_INCREMENT = ' . ($lastId + 1)
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
$this->logger->logError(sprintf('Error resetting AUTO_INCREMENT: %s', $e->getMessage()));
|
||||
}
|
||||
}
|
||||
```
|
||||
### Efekt
|
||||
Kolejny mail z nieudanym importem pokazuje:
|
||||
1. konkretny powod walidacji,
|
||||
2. skrot kluczowych pol payloadu zamowienia,
|
||||
3. stack trace.
|
||||
|
||||
Dodana metoda `sendFailureNotification()` — wysyła email z informacją o błędzie:
|
||||
To powinno wystarczyc do szybkiej diagnozy, co bylo nie tak w danych zamowienia z EMPIK.
|
||||
|
||||
```php
|
||||
protected function sendFailureNotification($empikOrderId, Exception $exception)
|
||||
{
|
||||
try {
|
||||
$shopName = Configuration::get('PS_SHOP_NAME');
|
||||
$subject = sprintf('[%s] Błąd importu zamówienia EMPIK: %s', $shopName, $empikOrderId);
|
||||
|
||||
$body = sprintf(
|
||||
"Zamówienie EMPIK: %s\nData: %s\nBłąd: %s\n\nStack trace:\n%s",
|
||||
$empikOrderId,
|
||||
date('Y-m-d H:i:s'),
|
||||
$exception->getMessage(),
|
||||
$exception->getTraceAsString()
|
||||
);
|
||||
|
||||
Mail::send(
|
||||
(int) Configuration::get('PS_LANG_DEFAULT'),
|
||||
'empik_import_error',
|
||||
$subject,
|
||||
[
|
||||
'{empik_order_id}' => $empikOrderId,
|
||||
'{error_message}' => $exception->getMessage(),
|
||||
'{error_date}' => date('Y-m-d H:i:s'),
|
||||
'{stack_trace}' => nl2br($exception->getTraceAsString()),
|
||||
],
|
||||
self::ERROR_NOTIFICATION_EMAIL,
|
||||
null,
|
||||
Configuration::get('PS_SHOP_EMAIL'),
|
||||
$shopName,
|
||||
null,
|
||||
null,
|
||||
_PS_MODULE_DIR_ . 'empikmarketplace/mails/'
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
$this->logger->logError(sprintf('Error sending failure notification email: %s', $e->getMessage()));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Dodane pliki
|
||||
|
||||
### `mails/pl/empik_import_error.html`
|
||||
|
||||
Szablon HTML emaila z powiadomieniem o błędzie. Zawiera placeholdery:
|
||||
- `{empik_order_id}` — ID zamówienia EMPIK
|
||||
- `{error_date}` — data błędu
|
||||
- `{error_message}` — komunikat błędu
|
||||
- `{stack_trace}` — stack trace wyjątku
|
||||
|
||||
### `mails/pl/empik_import_error.txt`
|
||||
|
||||
Wersja tekstowa tego samego szablonu (wymagana przez PrestaShop `Mail::send()`).
|
||||
|
||||
## Po aktualizacji modułu
|
||||
|
||||
Jeśli moduł empikmarketplace zostanie zaktualizowany, powyższe zmiany zostaną nadpisane. Należy ponownie:
|
||||
|
||||
1. Dodać `use Mail;` do importów w `OrderProcessor.php`
|
||||
2. Dodać stałą `ERROR_NOTIFICATION_EMAIL`
|
||||
3. Zmodyfikować metodę `import()` zgodnie z powyższym kodem
|
||||
4. Dodać metody `resetOrderAutoIncrement()` i `sendFailureNotification()`
|
||||
5. Skopiować szablony emaili do `mails/pl/`
|
||||
## Po aktualizacji modulu
|
||||
Jesli modul `empikmarketplace` zostanie zaktualizowany i nadpisze zmiany, trzeba ponownie naniesc modyfikacje:
|
||||
1. `OrderProcessor.php` (import, auto-increment, powiadomienia, `buildOrderContext`).
|
||||
2. `OrderFulfiller.php` (rozszerzona walidacja i szczegolowe komunikaty).
|
||||
3. Szablony maili `mails/pl/empik_import_error.html` i `mails/pl/empik_import_error.txt`.
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Błąd importu zamówienia EMPIK</title>
|
||||
<title>Blad importu zamowienia EMPIK</title>
|
||||
</head>
|
||||
<body style="font-family: Arial, sans-serif; font-size: 14px; color: #333;">
|
||||
<h2 style="color: #c0392b;">Błąd importu zamówienia EMPIK</h2>
|
||||
<h2 style="color: #c0392b;">Blad importu zamowienia EMPIK</h2>
|
||||
<table style="border-collapse: collapse; width: 100%; max-width: 600px;">
|
||||
<tr>
|
||||
<td style="padding: 8px; border: 1px solid #ddd; font-weight: bold;">Zamówienie EMPIK:</td>
|
||||
<td style="padding: 8px; border: 1px solid #ddd; font-weight: bold;">Zamowienie EMPIK:</td>
|
||||
<td style="padding: 8px; border: 1px solid #ddd;">{empik_order_id}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -16,10 +16,12 @@
|
||||
<td style="padding: 8px; border: 1px solid #ddd;">{error_date}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 8px; border: 1px solid #ddd; font-weight: bold;">Komunikat błędu:</td>
|
||||
<td style="padding: 8px; border: 1px solid #ddd; font-weight: bold;">Komunikat bledu:</td>
|
||||
<td style="padding: 8px; border: 1px solid #ddd;">{error_message}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Szczegoly zamowienia:</h3>
|
||||
<pre style="background: #f5f5f5; padding: 10px; font-size: 12px; overflow-x: auto;">{order_context_html}</pre>
|
||||
<h3>Stack trace:</h3>
|
||||
<pre style="background: #f5f5f5; padding: 10px; font-size: 12px; overflow-x: auto;">{stack_trace}</pre>
|
||||
</body>
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
Błąd importu zamówienia EMPIK
|
||||
Blad importu zamowienia EMPIK
|
||||
|
||||
Zamówienie EMPIK: {empik_order_id}
|
||||
Zamowienie EMPIK: {empik_order_id}
|
||||
Data: {error_date}
|
||||
Komunikat błędu: {error_message}
|
||||
Komunikat bledu: {error_message}
|
||||
|
||||
Szczegoly zamowienia:
|
||||
{order_context}
|
||||
|
||||
Stack trace:
|
||||
{stack_trace}
|
||||
|
||||
@@ -106,17 +106,39 @@ class OrderFulfiller
|
||||
*/
|
||||
protected function validate($data)
|
||||
{
|
||||
if (
|
||||
(
|
||||
empty($data['customer']['shipping_address']) &&
|
||||
empty($data['customer']['billing_address'])
|
||||
) ||
|
||||
empty($data['order_id']) ||
|
||||
empty($data['order_lines']) ||
|
||||
empty($data['order_state']) ||
|
||||
empty($data['total_price'])
|
||||
) {
|
||||
throw new OrderProcessException(sprintf('Invalid order data for order: %s', $data['order_id']));
|
||||
$customer = isset($data['customer']) && is_array($data['customer']) ? $data['customer'] : [];
|
||||
$shippingAddress = isset($customer['shipping_address']) ? $customer['shipping_address'] : null;
|
||||
$billingAddress = isset($customer['billing_address']) ? $customer['billing_address'] : null;
|
||||
$orderId = isset($data['order_id']) ? $data['order_id'] : 'unknown';
|
||||
|
||||
$errors = [];
|
||||
|
||||
if (empty($shippingAddress) && empty($billingAddress)) {
|
||||
$errors[] = 'both customer.shipping_address and customer.billing_address are empty';
|
||||
}
|
||||
|
||||
if (empty($data['order_id'])) {
|
||||
$errors[] = 'order_id is empty';
|
||||
}
|
||||
|
||||
if (empty($data['order_lines'])) {
|
||||
$errors[] = 'order_lines is empty';
|
||||
}
|
||||
|
||||
if (empty($data['order_state'])) {
|
||||
$errors[] = 'order_state is empty';
|
||||
}
|
||||
|
||||
if (empty($data['total_price'])) {
|
||||
$errors[] = 'total_price is empty';
|
||||
}
|
||||
|
||||
if (!empty($errors)) {
|
||||
throw new OrderProcessException(sprintf(
|
||||
'Invalid order data for order: %s. Validation errors: %s',
|
||||
$orderId,
|
||||
implode('; ', $errors)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,8 +58,8 @@ class OrderProcessor
|
||||
|
||||
$this->empikClient = $this->empikClientFactory->createClient();
|
||||
|
||||
$this->allowAccept = (bool)Configuration::get(ConfigurationAdapter::CONF_AUTO_ACCEPT_ORDERS);
|
||||
$this->allowImport = (bool)Configuration::get(ConfigurationAdapter::CONF_IMPORT_ORDERS);
|
||||
$this->allowAccept = (bool) Configuration::get(ConfigurationAdapter::CONF_AUTO_ACCEPT_ORDERS);
|
||||
$this->allowImport = (bool) Configuration::get(ConfigurationAdapter::CONF_IMPORT_ORDERS);
|
||||
}
|
||||
|
||||
public function process()
|
||||
@@ -85,7 +85,7 @@ class OrderProcessor
|
||||
$this->import($empikOrder);
|
||||
}
|
||||
} catch (OrderProcessException $exception) {
|
||||
$this->logger->logError('Empikplaces: import order process, order id ' . $order['order_id'] . ', message:' . $exception->getMessage());
|
||||
$this->logger->logError('Empikplaces: import order process, order id ' . $order['order_id'] . ', message:' . $exception->getMessage());
|
||||
} catch (Exception $exception) {
|
||||
$this->logger->logError('Empikplaces: ' . $exception->getMessage());
|
||||
}
|
||||
@@ -106,13 +106,13 @@ class OrderProcessor
|
||||
$empikOrderId = isset($data['order_id']) ? $data['order_id'] : 'unknown';
|
||||
$errorMsg = sprintf('Error importing EMPIK order [%s]: %s', $empikOrderId, $e->getMessage());
|
||||
$this->logger->logError($errorMsg);
|
||||
$this->sendFailureNotification($empikOrderId, $e);
|
||||
$this->sendFailureNotification($empikOrderId, $e, $data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resetuje AUTO_INCREMENT tabeli ps_orders do MAX(id_order) + 1
|
||||
* aby uniknąć dziur w numeracji zamówień po ROLLBACK.
|
||||
* Resets AUTO_INCREMENT of ps_orders to MAX(id_order) + 1
|
||||
* to avoid gaps after ROLLBACK.
|
||||
*/
|
||||
protected function resetOrderAutoIncrement()
|
||||
{
|
||||
@@ -129,24 +129,18 @@ class OrderProcessor
|
||||
}
|
||||
|
||||
/**
|
||||
* Wysyła email z powiadomieniem o nieudanym imporcie zamówienia EMPIK.
|
||||
* Sends notification email when EMPIK order import fails.
|
||||
*
|
||||
* @param string $empikOrderId
|
||||
* @param Exception $exception
|
||||
* @param array $orderData
|
||||
*/
|
||||
protected function sendFailureNotification($empikOrderId, Exception $exception)
|
||||
protected function sendFailureNotification($empikOrderId, Exception $exception, array $orderData = [])
|
||||
{
|
||||
try {
|
||||
$shopName = Configuration::get('PS_SHOP_NAME');
|
||||
$subject = sprintf('[%s] Błąd importu zamówienia EMPIK: %s', $shopName, $empikOrderId);
|
||||
|
||||
$body = sprintf(
|
||||
"Zamówienie EMPIK: %s\nData: %s\nBłąd: %s\n\nStack trace:\n%s",
|
||||
$empikOrderId,
|
||||
date('Y-m-d H:i:s'),
|
||||
$exception->getMessage(),
|
||||
$exception->getTraceAsString()
|
||||
);
|
||||
$subject = sprintf('[%s] Blad importu zamowienia EMPIK: %s', $shopName, $empikOrderId);
|
||||
$orderContext = $this->buildOrderContext($orderData);
|
||||
|
||||
Mail::send(
|
||||
(int) Configuration::get('PS_LANG_DEFAULT'),
|
||||
@@ -156,6 +150,8 @@ class OrderProcessor
|
||||
'{empik_order_id}' => $empikOrderId,
|
||||
'{error_message}' => $exception->getMessage(),
|
||||
'{error_date}' => date('Y-m-d H:i:s'),
|
||||
'{order_context}' => $orderContext,
|
||||
'{order_context_html}' => nl2br(htmlspecialchars($orderContext, ENT_QUOTES, 'UTF-8')),
|
||||
'{stack_trace}' => nl2br($exception->getTraceAsString()),
|
||||
],
|
||||
self::ERROR_NOTIFICATION_EMAIL,
|
||||
@@ -171,6 +167,32 @@ class OrderProcessor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $orderData
|
||||
* @return string
|
||||
*/
|
||||
protected function buildOrderContext(array $orderData)
|
||||
{
|
||||
if (empty($orderData)) {
|
||||
return 'No order payload available.';
|
||||
}
|
||||
|
||||
$customer = isset($orderData['customer']) && is_array($orderData['customer']) ? $orderData['customer'] : [];
|
||||
$summary = [
|
||||
'order_id' => isset($orderData['order_id']) ? $orderData['order_id'] : null,
|
||||
'order_state' => isset($orderData['order_state']) ? $orderData['order_state'] : null,
|
||||
'total_price' => isset($orderData['total_price']) ? $orderData['total_price'] : null,
|
||||
'shipping_price' => isset($orderData['shipping_price']) ? $orderData['shipping_price'] : null,
|
||||
'order_lines_count' => isset($orderData['order_lines']) && is_array($orderData['order_lines']) ? count($orderData['order_lines']) : 0,
|
||||
'has_shipping_address' => !empty($customer['shipping_address']) ? 1 : 0,
|
||||
'has_billing_address' => !empty($customer['billing_address']) ? 1 : 0,
|
||||
];
|
||||
|
||||
$json = json_encode($summary, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
|
||||
|
||||
return $json !== false ? $json : 'Unable to serialize order payload summary.';
|
||||
}
|
||||
|
||||
protected function accept(EmpikOrderWrapper $empikOrder)
|
||||
{
|
||||
$acceptLines = $empikOrder->getAcceptanceLines();
|
||||
|
||||
Reference in New Issue
Block a user