You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+19Lines changed: 19 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -35,6 +35,25 @@
35
35
36
36
#### 🐛 Исправлено
37
37
38
+
**Дублирование товаров при `includeThumbs` (#281):**
39
+
- В сниппетах `msProducts`, `msCart`, `msGetOrder` LEFT JOIN превью выбирал все картинки галереи товара — `GROUP BY` по URL размножал первую строку столько раз, сколько фото в галерее.
40
+
- Новый общий хелпер `MiniShop3\Utils\ProductThumbnailJoin::buildLeftJoinOn()` формирует SQL ON: одно превью на товар (превью главного фото — `parent_id = 0`, минимальный `position`), аналогично `ProductImageService::updateProductImage()`. Алиасы и size-папка санитизируются.
41
+
- Попутно исправлена опечатка `parent` → `parent_id` в `msGetOrder` (нет такого поля в `ms3_product_files`, JOIN тихо игнорировался).
42
+
43
+
**Дерево категорий в UI привязки опций — поддержка вложенного каталога и мульти-магазина (#237):**
44
+
-`OptionsController::getTree` отдаёт на каждом уровне `msCategory` (выбираемые, с чекбоксом) и `modResource`/`modDocument`/`modWebLink` с `isfolder=1` (навигационные, без чекбокса). `msProduct` и обычные страницы без `isfolder` исключаются.
45
+
- В ответе для каждого узла появился флаг `selectable: bool` — Vue `OptionCategoryTree` рендерит чекбокс только для `selectable=true`, навигационные узлы можно раскрывать, но не выбирать.
46
+
- Системная настройка `ms3_option_category_tree_parent` (была введена в первой попытке) **удалена** — дерево работает на семантике ресурсов, без необходимости в фиксированном root-id.
47
+
48
+
**Очистка числовых полей доставки/оплаты не сохранялась:**
49
+
- В формах настроек способов доставки и оплаты при попытке очистить поле (например, `free_delivery_amount`) старое значение оставалось в БД. Ввод явного `0` сохранялся правильно.
50
+
- Причина — `isset($data[$field])` в `DeliveriesController` / `PaymentsController` возвращал `false` для значения `null` (PrimeVue `InputNumber` при очистке шлёт `null`), и поле пропускалось при сохранении. Заменено на `array_key_exists($field, $data)`.
51
+
- Аналогичный паттерн в других контроллерах Manager API зафиксирован в issue #289.
52
+
53
+
**Импорт товаров — поддержка поля «Остаток на складе» (#283):**
54
+
- В конфигурации импорта (`config/import-fields.php`) добавлены поля `stock` и `remains` (алиас MS2). При обработке CSV `ImportCSV` маппит `remains` → `stock` для совместимости с легаси-настройками `ms3_utility_import_fields`.
55
+
- В Vue-форме маппинга автоподстановка типичных заголовков CSV (`stock`, `remains`, `quantity`, `qty`) → товарное поле `stock`.
56
+
38
57
**Двойной префикс в Phinx defensive-checks из PR #271 (#276):**
39
58
-`TablePrefixAdapter::hasTable($name)` / `$this->table($name)` / `hasColumn` сами добавляют `table_prefix`. Ручной конкат `$prefix . 'ms3_grid_fields'` в defensive-проверках после #271 приводил к двойному префиксу (`modx_modx_*`) — Phinx никогда не находил таблицу и seed-миграции всегда уходили в no-op.
40
59
-**Воздействие**: на свежих установках MS3 ≥ 1.10.1 таблица `ms3_grid_fields` создавалась, но не наполнялась — гриды (заказы, клиенты, доставки, оплаты, вендоры, позиции заказа, товары категории) загружались без default-конфигурации. На существующих установках, где seed успел выполниться до #271, последствий нет.
Copy file name to clipboardExpand all lines: core/components/minishop3/docs/changelog.txt
+35Lines changed: 35 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -5,6 +5,41 @@ All notable changes to this project will be documented in this file.
5
5
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
8
+
## [1.11.0-beta1]
9
+
10
+
### Added
11
+
- New `msOptionGroup` model replaces `modCategory` for grouping product options (#10). Migration converts existing `msOption.modcategory_id` → `option_group_id` automatically (each distinct `modcategory_id` becomes a row in `ms3_option_groups` using `modCategory.category` as name). Admin: separate "Option Groups" tab next to "Options" with CRUD, drag-and-drop ordering, options-per-group counter.
12
+
- Public `window.ms3.refresh()` storefront JS API and `ms3:refresh` DOM event (#274) for integration with third-party AJAX components that replace catalog DOM (mFilter / mSearch2 / custom AJAX / infinite scroll). The component dispatches `ms3:refresh` after its DOM swap — MS3 re-binds `ProductCardUI` / `QuantityUI` state. MS3 does NOT listen for vendor-specific events; dependency direction is component-→-MS3.
13
+
- Manager API endpoint `POST /api/mgr/orders/{id}/recalculate-cost` and "Recalculate cost" button in the order admin (#212). Three modes: `auto` (DefaultDelivery/DefaultPayment by fields, no external provider calls), `manual` (operator-provided `manual_delivery_cost`), `force_provider` (explicit provider call in try/catch). Honours discounts via `PriceAdjustment` and total clamp via `OrderService::clampComputedTotal()`.
14
+
- Negative additional cost for delivery and payment methods (#211): the `price` field now accepts fixed discounts (`-10`) and percent discounts (`-10%`). Common normalizer `MiniShop3\Utils\PriceAdjustment` shared between manager API and legacy processors.
15
+
- Negative total guard `OrderService::clampComputedTotal(?msOrder, float, float, float = 0.0)` (#265): when sum of cart + delivery + payment costs goes below zero (e.g. misconfigured discounts), total is clamped to 0 and a `LOG_LEVEL_WARN` line with the breakdown is written. Wired into all calculation paths.
16
+
- Vue admin: live "Discount" / "Markup" badges on the `price` field of delivery/payment edit forms (#265).
17
+
- Validation rules editor for deliveries now lists model fields and Object Extension fields for `msOrder` / `msOrderAddress` (#215) in addition to the static set.
18
+
- Order fields tabs: "Configure fields" empty-state hint and conditional action bar visibility on Info / Address tabs (#182).
19
+
- Import: product `stock` field is now available in the field mapping (#283), with auto-mapping of typical CSV headers (`stock`, `remains`, `quantity`, `qty`).
20
+
- Web API for customer profile: `POST /api/v1/customer/add` (quick profile field update incl. extra fields, #241/#261), `POST /api/v1/customer/changeAddress`, `GET /api/v1/customer/email/verify` (with HTML redirect support), `POST /api/v1/customer/email/resend-verification` (#226).
21
+
- System settings: `ms3_email_verification_url`, `ms3_email_verification_success_url` for customizing the email-verification flow.
22
+
23
+
### Changed (breaking)
24
+
- **Storefront snippets — numeric placeholders contract** (#242, breaking). Plain placeholders (`cost`, `cart_cost`, `delivery_cost`, `price`, `weight`, …) are now plain `float` for arithmetic and Fenom `|number`. Display strings with locale / currency / unit live in `*_formatted`. Removed `formatPrices` no-op in `msProducts` and `msOrderTotal`. Migration: change `{$order.cost}` (which used to render `5 300 ₽`) to `{$order.cost_formatted}`, or keep `{$order.cost}` only for arithmetic / `|number`. Affects `msOrder`, `msGetOrder`, `msCart`, `msProducts`, `msOrderTotal`, default `ms3_order.tpl`.
25
+
- **Schema — `msOption.modcategory_id` → `msOption.option_group_id`** (#10, breaking for direct DB readers). Data migration is automatic. Custom code reading `modcategory_id` directly must switch to `option_group_id`; the join alias `category_name` in `OptionLoaderService` / `CategoryOptionService` is renamed to `group_name`. Snippet `msProductOptions` filters/sorts by `group_name`.
26
+
- **Manager API — `GET /api/mgr/options/modcategories` removed**, replaced by `/api/mgr/option-groups` (CRUD + reorder + bulk delete + per-group options count).
27
+
- `msCart` snippet no longer suppresses output on `?msorder=...` by default (#249) — the cart loads and renders the chunk as usual, so mini-cart blocks in the global layout keep working on the "thank you" page. New `hideOnThanks=1` parameter brings back the previous "blank on thanks page" behavior for a specific call.
28
+
- `Processors\Product\Update`: option deletion now applies on save (#199 follow-up). Form options are captured in `beforeSet` into `$ms3ProductFormOptions` and passed to `ProductDataService::saveOptions(..., removeOther: true)` after the parent `afterSave` — avoids MODX 3 quirk where the processor's `options` property is often empty post-save.
29
+
- `ProductDataService::saveCategories()`: missing `categories` key in the form payload no longer wipes extra category links (#238). Behavior is now symmetric with `saveLinks()` — explicit empty array still clears, but absence of the key (tab not rendered yet) is a no-op. Integrations relying on "no `categories` in POST → clear all" must pass `categories: []` explicitly.
30
+
- Web API `POST /api/v1/customer/add` allows all columns present in the `msCustomer` xPDO map (including Object Extension after `loadMap()`), with an explicit denylist of sensitive/system fields (#261). Rakit-validation preserved for `first_name` / `last_name` / `email` / `phone`; other allowed columns are normalized by `phptype`.
31
+
32
+
### Fixed
33
+
- Product duplicate via MODX context menu: option values now copy over to the new product (#257). After `modResource::duplicate()`, `OptionService` re-syncs `ms3_product_options` rows from the source.
34
+
- `Processors\Product\Create`: empty option fields no longer wipe options on save. Aligned with `Update` — sync only when the request contained `options-*` keys.
35
+
- Plugin events that mutate data via `returnedValues` (#219, #221): `msOnBeforeSendNotification`, `msOnBeforeImport`, `msOnImportRow`, `msOnProductsLoad`, `msOnProductPrepare` apply mutations from the MODX `returnedValues` channel; `Cart::changeOption`, `Customer::validate`, `Customer::getOrCreate`, `OrderStatusService::change`, `OrderUserResolver::getUserId` consume merged `$response['data']` after `invokeEvent`.
36
+
- Option category tree for nested catalogs and multi-store setups (#237): tree returns `msCategory` (selectable) plus `modResource`/`modDocument`/`modWebLink` with `isfolder=1` (navigation-only) — no system setting required.
37
+
- Product list duplicates on `includeThumbs` (#281): one thumbnail per product via shared `ProductThumbnailJoin` helper in `msProducts`, `msCart`, `msGetOrder`. Fixed `parent` → `parent_id` typo in `msGetOrder`.
38
+
- Delivery / payment numeric fields can finally be cleared from the admin form — the controller no longer silently drops `null` values (`isset` → `array_key_exists`).
39
+
- Email verification flow: link in the email points to Web API by default (`api.php?route=…/email/verify&token=…&html=1`), with optional custom URL via `ms3_email_verification_url` (#226).
40
+
- Phinx defensive checks added in 1.10.x-era seed migrations no longer skip every install due to double `table_prefix` (#276): API methods (`hasTable`, `$this->table()`, `hasColumn`) now receive unprefixed names; raw SQL keeps `{$prefix}name`. Initial schema's foreign-key step also fixed (FK constraints were never being created on fresh installs).
41
+
- Many smaller fixes — see project CHANGELOG.md for details.
0 commit comments