diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 83c00b77..66ad22ff 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -4,7 +4,10 @@ "Bash(head:*)", "Bash(cp:*)", "Bash(cd:*)", - "Bash(curl:*)" + "Bash(curl:*)", + "mcp__plugin_serena_serena__activate_project", + "mcp__plugin_serena_serena__check_onboarding_performed", + "mcp__plugin_serena_serena__list_dir" ] } } diff --git a/.serena/project.yml b/.serena/project.yml index 1f3bf6b2..610826f6 100644 --- a/.serena/project.yml +++ b/.serena/project.yml @@ -124,3 +124,12 @@ initial_prompt: "" # This overrides the corresponding setting in the global configuration; see the documentation there. # If null or missing, use the setting from the global configuration. symbol_info_budget: + +# line ending convention to use when writing source files. +# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default) +# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings. +line_ending: + +# list of regex patterns which, when matched, mark a memory entry as read‑only. +# Extends the list from the global configuration, merging the two lists. +read_only_memory_patterns: [] diff --git a/.vscode/ftp-kr.json b/.vscode/ftp-kr.json index a50740aa..9dcbdcee 100644 --- a/.vscode/ftp-kr.json +++ b/.vscode/ftp-kr.json @@ -14,6 +14,7 @@ ".git", "/.vscode", "/.serena", - "/.claude" + "/.claude", + "CLAUDE.md" ] } \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..64527e51 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,69 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +This is a **PrestaShop 1.7.x e-commerce store** (interblue.pl) with a custom theme and multiple custom/third-party modules. The codebase is a live PrestaShop installation deployed via FTP to the production server. + +## Architecture + +### Directory Structure + +- **`themes/InterBlue/`** — Custom theme based on PrestaShop's classic theme. Templates use Smarty (`.tpl`), CSS is compiled from SCSS via VSCode Live Sass Compiler. +- **`modules/`** — 130+ modules. Custom/in-house modules: `customfeaturetab`, `AddOrderExtraFields`. Key third-party: `x13allegro` (Allegro marketplace), `onepagecheckoutps` (one-page checkout), `baselinker`, `empikmarketplace`, `dpdpoland`/`sensbitinpost`/`sensbitpaczkawruchu`/`sensbitpocztapolska` (shipping carriers). +- **`override/`** — PrestaShop class/controller overrides. Critical overrides: + - `override/classes/order/Order.php` — Modified by `modrefchange` module to fire hooks (`actionBeforeAddOrder`, `actionBeforeAddOrderInvoice`, `actionBeforeAddDeliveryNumber`) before invoice/delivery number assignment. + - `override/controllers/front/OrderController.php` — Modified by `onepagecheckoutps` module for one-page checkout flow. +- **`src/`** — Extended PrestaShop core: `src/Adapter/Order/QueryHandler/` and `src/Core/Domain/Order/` for order viewing query pattern (CQRS). + +### Theme Architecture + +- **SCSS workflow**: Edit `themes/InterBlue/assets/css/custom.scss` (or `theme.scss`). The VSCode Live Sass Compiler auto-compiles to `custom.css` with autoprefixer on save. +- Templates override classic theme templates in `themes/InterBlue/templates/`. +- Default layout is full-width; category pages use left column. + +### Module Architecture + +Custom modules follow standard PrestaShop module structure: +- Main PHP class extends `Module` +- `views/templates/` for Smarty templates +- `classes/` for business logic +- DB install/uninstall in `install()`/`uninstall()` methods +- Hooks registered via `registerHook()` in `install()` + +The `customfeaturetab` module (`modules/customfeaturetab/`) uses a custom DB table `ps_custom_feature_tab` to map product features/values to extra product page tabs, displayed via the `displayProductExtraContent` hook. + +### Override Conflicts + +When adding overrides, check for existing overrides that multiple modules may have contributed to. The `Order.php` override was generated by `AddOrderExtraFields` copying files from `modules/AddOrderExtraFields/_overrides/`. If `modrefchange` module is installed, a different version is used. + +**Known issue**: After updating `empikmarketplace`, the admin product catalog list view is overridden by: +- `modules/empikmarketplace/views/PrestaShop/Admin/Product/CatalogPage/Lists/list.html.twig` +- `modules/empikmarketplace/views/PrestaShop/Admin/Product/CatalogPage/Lists/products_table.html.twig` + +## Development Workflow + +### CSS/SCSS + +Use the VSCode **Live Sass Compiler** extension. It watches on launch (configured in `.vscode/settings.json`) and compiles SCSS to compressed CSS with sourcemaps and autoprefixing automatically on save. + +Main file to edit: [themes/InterBlue/assets/css/custom.scss](themes/InterBlue/assets/css/custom.scss) + +### Deployment + +Files are deployed to production via FTP using the **SFTP/FTP Sync** VSCode extension (configured in `.vscode/ftp-kr.json`). Upload is not automatic on save — files must be manually synced. + +### PrestaShop Cache + +After modifying PHP classes, overrides, or templates, PrestaShop's cache must be cleared from the admin panel: **Advanced Parameters → Performance → Clear cache**, or by deleting `var/cache/` on the server. + +When creating or modifying overrides, PrestaShop also needs to rebuild the class index (`var/cache/*/class_index.php`). + +## Key Conventions + +- All custom module display strings use `$this->l('...')` for translation support (Polish locale is primary). +- Override classes extend `*Core` (e.g., `class Order extends OrderCore`). +- Module DB tables use `_DB_PREFIX_` constant (typically `ps_`). +- PrestaShop hooks are the integration point — prefer hooks over direct core edits. +- The `admin658c34/` directory is the custom admin panel path (security through obscurity). diff --git a/docs/empik.md b/docs/empik.md new file mode 100644 index 00000000..e7a47fc0 --- /dev/null +++ b/docs/empik.md @@ -0,0 +1,134 @@ +# Modyfikacje modułu empikmarketplace + +Data modyfikacji: 2026-03-11 + +## Problem + +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 + +### `src/Processor/OrderProcessor.php` + +Dodany import `Mail` na górze pliku: + +```php +use Mail; +``` + +Dodana stała z adresem email do powiadomień: + +```php +class OrderProcessor +{ + const CODE_WAITING_ACCEPTANCE = 'WAITING_ACCEPTANCE'; + const CODE_SHIPPING = 'SHIPPING'; + const ERROR_NOTIFICATION_EMAIL = 'jacek.pyziak@project-pro.pl'; +``` + +Zmodyfikowana metoda `import()` — dodano wywołanie resetu AUTO_INCREMENT i wysyłki emaila w bloku catch: + +```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(); + + $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); + } +} +``` + +Dodana metoda `resetOrderAutoIncrement()` — zapobiega dziurom w numeracji zamówień: + +```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())); + } +} +``` + +Dodana metoda `sendFailureNotification()` — wysyła email z informacją o błędzie: + +```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/` diff --git a/modules/empikmarketplace/NOTATKA-OVERRIDE-TABELI-PRODUKTOW.md b/modules/empikmarketplace/NOTATKA-OVERRIDE-TABELI-PRODUKTOW.md new file mode 100644 index 00000000..84ed8c0d --- /dev/null +++ b/modules/empikmarketplace/NOTATKA-OVERRIDE-TABELI-PRODUKTOW.md @@ -0,0 +1,9 @@ +# Notatka: override tabeli produktow BO + +Data: 2026-02-09 + +Po aktualizacji modulu `empikmarketplace` wyglad tabeli produktow w panelu administratora PrestaShop zostal nadpisany przez: + +- `modules/empikmarketplace/views/PrestaShop/Admin/Product/CatalogPage/Lists/list.html.twig` + +To ten plik odpowiada za modyfikacje widoku listy produktow (katalog, BO). diff --git a/modules/empikmarketplace/mails/pl/empik_import_error.html b/modules/empikmarketplace/mails/pl/empik_import_error.html new file mode 100644 index 00000000..242c3948 --- /dev/null +++ b/modules/empikmarketplace/mails/pl/empik_import_error.html @@ -0,0 +1,26 @@ + + +
+ +| Zamówienie EMPIK: | +{empik_order_id} | +
| Data: | +{error_date} | +
| Komunikat błędu: | +{error_message} | +
{stack_trace}
+
+
diff --git a/modules/empikmarketplace/mails/pl/empik_import_error.txt b/modules/empikmarketplace/mails/pl/empik_import_error.txt
new file mode 100644
index 00000000..e305aa94
--- /dev/null
+++ b/modules/empikmarketplace/mails/pl/empik_import_error.txt
@@ -0,0 +1,8 @@
+Błąd importu zamówienia EMPIK
+
+Zamówienie EMPIK: {empik_order_id}
+Data: {error_date}
+Komunikat błędu: {error_message}
+
+Stack trace:
+{stack_trace}
diff --git a/modules/empikmarketplace/src/Processor/OrderProcessor.php b/modules/empikmarketplace/src/Processor/OrderProcessor.php
index 29136e00..b90f97d0 100644
--- a/modules/empikmarketplace/src/Processor/OrderProcessor.php
+++ b/modules/empikmarketplace/src/Processor/OrderProcessor.php
@@ -13,12 +13,14 @@ use Empik\Marketplace\OrderFulfiller\OrderFulfiller;
use Exception;
use Configuration;
use Db;
+use Mail;
use Empik\Marketplace\Provider\Order\ProductRefResolver;
class OrderProcessor
{
const CODE_WAITING_ACCEPTANCE = 'WAITING_ACCEPTANCE';
const CODE_SHIPPING = 'SHIPPING';
+ const ERROR_NOTIFICATION_EMAIL = 'jacek.pyziak@project-pro.pl';
/** @var EmpikClientFactory */
protected $empikClientFactory;
@@ -98,7 +100,74 @@ class OrderProcessor
Db::getInstance()->execute('COMMIT');
} catch (Exception $e) {
Db::getInstance()->execute('ROLLBACK');
- $this->logger->logError(sprintf('Error importing order [%s]', $e->getMessage()));
+ $this->resetOrderAutoIncrement();
+
+ $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);
+ }
+ }
+
+ /**
+ * Resetuje AUTO_INCREMENT tabeli ps_orders do MAX(id_order) + 1
+ * aby uniknąć dziur w numeracji zamówień po ROLLBACK.
+ */
+ 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()));
+ }
+ }
+
+ /**
+ * Wysyła email z powiadomieniem o nieudanym imporcie zamówienia EMPIK.
+ *
+ * @param string $empikOrderId
+ * @param Exception $exception
+ */
+ 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()));
}
}
diff --git a/modules/empikmarketplace/vendor/composer/platform_check.php b/modules/empikmarketplace/vendor/composer/platform_check.php
index 8b379f44..589e9e77 100644
--- a/modules/empikmarketplace/vendor/composer/platform_check.php
+++ b/modules/empikmarketplace/vendor/composer/platform_check.php
@@ -4,8 +4,8 @@
$issues = array();
-if (!(PHP_VERSION_ID >= 50600)) {
- $issues[] = 'Your Composer dependencies require a PHP version ">= 5.6.0". You are running ' . PHP_VERSION . '.';
+if (!(PHP_VERSION_ID >= 70200)) {
+ $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {