Skip to content

Commit 67bc426

Browse files
committed
Обновлена документация компонента ms3FirstTimeBuyerDiscount: уточнены условия применения скидки, добавлены новые параметры и улучшены описания методов. Включены изменения для поддержки исключения текущего заказа из подсчёта оплаченных, а также обновлены настройки и интеграция с MiniShop3.
1 parent 2042f36 commit 67bc426

File tree

6 files changed

+170
-122
lines changed

6 files changed

+170
-122
lines changed

docs/components/ms3firsttimebuyerdiscount/api.md

Lines changed: 60 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ public function __construct(modX $modx)
1818

1919
#### isEligible
2020

21-
Проверяет, можно ли применить скидку: включена настройка и 0 оплаченных заказов.
21+
Проверяет право на скидку: настройка включена и найдено 0 оплаченных заказов.
2222

23-
- Для авторизованного пользователя проверка выполняется по `user_id`.
24-
- Для гостя (`user_id = 0`) проверка выполняется по `email` или `phone` из `draft->getOne('Address')`.
23+
- Для авторизованных: проверка по `user_id`
24+
- Для гостей: проверка по `email`/`phone` из `draft -> Address`
25+
- При наличии `draft` текущий заказ исключается из подсчёта
2526

2627
```php
2728
public function isEligible(int $userId, ?object $draft = null): bool
@@ -30,64 +31,70 @@ public function isEligible(int $userId, ?object $draft = null): bool
3031
| Параметр | Тип | Описание |
3132
|----------|-----|----------|
3233
| `userId` | int | ID пользователя |
33-
| `draft` | object\|null | Объект черновика заказа (опционально), используется для гостей |
34+
| `draft` | object\|null | Черновик заказа (опционально) |
3435

3536
**Возврат:** `true`, если скидку можно применить, иначе `false`.
3637

3738
---
3839

3940
#### getPaidOrdersCount
4041

41-
Количество оплаченных заказов пользователя в статусах из настройки MiniShop3 `ms3_status_for_stat`.
42+
Количество оплаченных заказов пользователя в статусах из `ms3_status_for_stat`.
4243

4344
```php
44-
public function getPaidOrdersCount(int $userId): int
45+
public function getPaidOrdersCount(int $userId, int $excludeOrderId = 0): int
4546
```
4647

4748
| Параметр | Тип | Описание |
4849
|----------|-----|----------|
4950
| `userId` | int | ID пользователя |
51+
| `excludeOrderId` | int | ID заказа, который нужно исключить из подсчёта (`0` — не исключать) |
5052

5153
**Возврат:** число заказов (0 и больше).
5254

5355
---
5456

5557
#### getGuestContactFromDraft
5658

57-
Извлекает контакты гостя (email/phone) из `draft`.
59+
Извлекает контакты гостя из `draft -> Address` и нормализует значения.
5860

5961
```php
6062
public function getGuestContactFromDraft(?object $draft): array
6163
```
6264

6365
| Параметр | Тип | Описание |
6466
|----------|-----|----------|
65-
| `draft` | object\|null | Черновик заказа (ожидается связь `Address`) |
67+
| `draft` | object\|null | Черновик заказа |
6668

6769
**Возврат:** массив вида `['email' => string, 'phone' => string]`.
6870

6971
---
7072

7173
#### getPaidOrdersCountByContact
7274

73-
Количество оплаченных заказов по контактам гостя (совпадение по `Address.email` или `Address.phone`).
75+
Количество оплаченных заказов гостя по email/phone.
7476

7577
```php
76-
public function getPaidOrdersCountByContact(string $email, string $phone): int
78+
public function getPaidOrdersCountByContact(string $email, string $phone, int $excludeOrderId = 0): int
7779
```
7880

7981
| Параметр | Тип | Описание |
8082
|----------|-----|----------|
8183
| `email` | string | Email гостя |
8284
| `phone` | string | Телефон гостя |
85+
| `excludeOrderId` | int | ID заказа, который нужно исключить из подсчёта (`0` — не исключать) |
86+
87+
Сравнение:
88+
- `email` — в lower-case
89+
- `phone` — по нормализованным цифрам (для телефона используется tail-10 сопоставление через `LIKE`)
8390

8491
**Возврат:** число заказов (0 и больше).
8592

8693
---
8794

8895
#### calculateDiscount
8996

90-
Вычисляет стоимость после скидки (процент или фиксированная сумма).
97+
Вычисляет стоимость после скидки (процент или фикс).
9198

9299
```php
93100
public function calculateDiscount(float $cost, string $type, float $value): float
@@ -96,85 +103,82 @@ public function calculateDiscount(float $cost, string $type, float $value): floa
96103
| Параметр | Тип | Описание |
97104
|----------|-----|----------|
98105
| `cost` | float | Исходная сумма |
99-
| `type` | string | `percent` или `fixed` (сравнение без учёта регистра) |
106+
| `type` | string | `percent` или `fixed` |
100107
| `value` | float | Процент (0–100) или фиксированная сумма |
101108

102-
**Возврат:** новая сумма (`fixed`: `max(0, cost - max(0, value))`; `percent`: диапазон 0–100%).
109+
**Возврат:** новая сумма (`fixed`: `max(0, cost - max(0, value))`; `percent`: c ограничением 0–100%).
103110

104111
---
105112

106113
#### apply
107114

108-
Полный цикл: проверка права → `ftbOnBeforeApply` → расчёт → `ftbOnApply`. Используется плагином из `msOnGetCartCost`.
115+
Полный цикл: проверка права → `ftbOnBeforeApply` → расчёт → `ftbOnApply`.
109116

110117
```php
111118
public function apply(array $scriptProperties): ?float
112119
```
113120

114-
**Вход (scriptProperties):** массив из события `msOnGetCartCost`:
121+
| Ключ | Тип | Описание |
122+
|------|-----|----------|
123+
| `cost` | float | Текущая стоимость корзины |
124+
| `cart` | mixed | Объект/данные корзины MiniShop3 |
125+
| `draft` | object\|null | Черновик заказа |
115126

116-
| Ключ | Тип | Описание |
117-
|--------|--------|----------|
118-
| `cost` | float | Текущая стоимость корзины |
119-
| `cart` | mixed | Данные корзины (зависит от MS3) |
120-
| `draft`| object\|null | Черновик заказа (если есть) |
127+
Дополнительно учитывается настройка `ftb_allow_combination`:
128+
- если `false` и в корзине уже есть скидка (`total_discount > 0`), FTB-скидка не применяется
121129

122-
**Возврат:** новая стоимость (`float`) при успешном применении скидки, иначе `null`.
130+
**Возврат:** новая стоимость (`float`) или `null`.
123131

124132
---
125133

126134
## События MODX
127135

128136
### ftbOnBeforeApply
129137

130-
Вызывается до расчёта скидки. Плагины могут отменить применение или подменить базовую сумму.
131-
132-
**Параметры:**
133-
134-
| Ключ | Тип | Описание |
135-
|------------|--------|----------|
136-
| `user_id` | int | ID пользователя |
137-
| `cost` | float | Текущая стоимость |
138-
| `draft` | object\|null | Черновик заказа |
139-
| `cart` | mixed | Корзина |
140-
| `settings` | array | Текущие настройки (`ftb_enabled`, `ftb_discount_type`, `ftb_discount_value`) |
138+
Вызывается до расчёта скидки. Позволяет отменить применение или подменить базовую сумму.
141139

142-
**Возвращаемые значения (returnedValues):**
140+
| Ключ | Тип | Описание |
141+
|------|-----|----------|
142+
| `user_id` | int | ID пользователя |
143+
| `cost` | float | Текущая стоимость |
144+
| `draft` | object\|null | Черновик заказа |
145+
| `cart` | mixed | Корзина |
146+
| `settings` | array | `ftb_enabled`, `ftb_discount_type`, `ftb_discount_value`, `ftb_allow_combination` |
143147

144-
| Ключ | Тип | Описание |
145-
|--------|-------|----------|
146-
| `apply`| bool | `false` — отменить применение скидки |
147-
| `cost` | float | Подменить сумму, к которой применяется скидка |
148+
`returnedValues`:
148149

149-
Если `apply === false`, сервис возвращает `null`. Если задан `cost`, он используется вместо исходного `cost` для расчёта.
150+
| Ключ | Тип | Описание |
151+
|------|-----|----------|
152+
| `apply` | bool | `false` — отменить применение скидки |
153+
| `cost` | float | Подменить сумму для расчёта скидки |
150154

151155
---
152156

153157
### ftbOnApply
154158

155-
Уведомление после успешного применения скидки (для логирования, аналитики).
159+
Вызывается после успешного применения скидки.
156160

157-
**Параметры:**
158-
159-
| Ключ | Тип | Описание |
160-
|------------------|--------|----------|
161-
| `user_id` | int | ID пользователя |
162-
| `cost_before` | float | Стоимость до скидки |
163-
| `cost_after` | float | Стоимость после скидки |
164-
| `discount_amount`| float | Размер скидки |
165-
| `draft` | object\|null | Черновик заказа |
161+
| Ключ | Тип | Описание |
162+
|------|-----|----------|
163+
| `user_id` | int | ID пользователя |
164+
| `cost_before` | float | Стоимость до скидки |
165+
| `cost_after` | float | Стоимость после скидки |
166+
| `discount_amount` | float | Размер скидки |
167+
| `draft` | object\|null | Черновик заказа |
166168

167169
---
168170

169171
## Системные настройки
170172

171-
Префикс в конфиге: `ms3firsttimebuyerdiscount_` (например, `ms3firsttimebuyerdiscount_ftb_enabled`).
173+
Префикс: `ms3firsttimebuyerdiscount_`.
172174

173175
| Ключ | xtype | По умолчанию | Описание |
174-
|------|--------|--------------|----------|
175-
| `ftb_enabled` | combo-boolean | true | Включить скидку для первых покупок |
176-
| `ftb_discount_type` | textfield | percent | Тип: `percent` (процент) или `fixed` (фиксированная сумма). Ввод вручную; сравнение без учёта регистра. |
177-
| `ftb_discount_value` | number | 10 | Значение: процент (0–100) или сумма в валюте |
178-
| `ftb_allow_combination` | combo-boolean | true | Зарезервировано на будущее (совмещение с другими скидками) |
179-
180-
Получение в коде: `$modx->getOption('ms3firsttimebuyerdiscount_ftb_enabled', null, true)`.
176+
|------|-------|--------------|----------|
177+
| `ftb_enabled` | combo-boolean | true | Включить скидку для first-time buyer |
178+
| `ftb_discount_type` | textfield | percent | Тип: `percent` или `fixed` (регистр не важен) |
179+
| `ftb_discount_value` | number | 10 | Значение скидки: процент (0–100) или сумма |
180+
| `ftb_allow_combination` | combo-boolean | true | Разрешить совмещение с уже применёнными скидками корзины |
181+
182+
Связанные настройки MiniShop3:
183+
- `ms3_status_for_stat` — статусы оплаченных заказов
184+
- `ms3_status_new` — добавляется в список учитываемых статусов как маркер первого заказа

docs/components/ms3firsttimebuyerdiscount/extension.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@ $modx->services->add('ms3ftb_discount', function () use ($modx) {
1818
});
1919
```
2020

21-
Ваша реализация должна предоставлять метод `apply(array $scriptProperties): ?float` (и при необходимости остальные публичные методы, если вы вызываете их из своего кода).
21+
Реализация должна предоставлять минимум метод `apply(array $scriptProperties): ?float`; остальные публичные методы — по необходимости при вызове из своего кода.
2222

2323
## Наследование FtbDiscountService
2424

2525
Сервис спроектирован так, чтобы ключевую логику можно было переопределить в наследнике:
2626

2727
- **isEligible(int $userId, ?object $draft): bool** — изменить условия права на скидку (например, по группе пользователя или по полю черновика).
28-
- **getPaidOrdersCount(int $userId): int** — изменить способ подсчёта оплаченных заказов.
29-
- **getGuestContactFromDraft(?object $draft): array** — изменить извлечение email/phone гостя из черновика.
30-
- **getPaidOrdersCountByContact(string $email, string $phone): int** — изменить подсчёт оплаченных заказов для гостей по контактам.
28+
- **getPaidOrdersCount(int $userId, int $excludeOrderId = 0): int** — изменить способ подсчёта оплаченных заказов (с исключением текущего заказа).
29+
- **getGuestContactFromDraft(?object $draft): array** — изменить извлечение/нормализацию email/phone гостя из черновика.
30+
- **getPaidOrdersCountByContact(string $email, string $phone, int $excludeOrderId = 0): int** — изменить подсчёт оплаченных заказов для гостей.
3131
- **calculateDiscount(float $cost, string $type, float $value): float** — изменить формулу (например, минимум суммы заказа).
3232

3333
Пример: скидка только для группы «Партнёр»:
@@ -44,7 +44,7 @@ class PartnerFtbService extends FtbDiscountService
4444
if (!parent::isEligible($userId, $draft)) {
4545
return false;
4646
}
47-
$user = $this->modx->getObject(\modUser::class, $userId);
47+
$user = $this->modx->getObject(\MODX\Revolution\modUser::class, $userId);
4848
if (!$user) {
4949
return false;
5050
}
@@ -96,6 +96,10 @@ $modx->log(modX::LOG_LEVEL_INFO, sprintf(
9696
// или отправить в CRM/аналитику по $params['user_id'], $params['discount_amount']
9797
```
9898

99+
## Константы и настройки
100+
101+
В сервисе используются внутренние константы типов скидки: `percent`, `fixed`. Ключи настроек: `ftb_enabled`, `ftb_discount_type`, `ftb_discount_value`, `ftb_allow_combination`. Полный список и типы см. в [API](api#системные-настройки).
102+
99103
## Логирование
100104

101105
Плагин пишет в лог MODX при успешном применении скидки:

docs/components/ms3firsttimebuyerdiscount/index.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,16 @@ items: [
1414
---
1515
# ms3FirstTimeBuyerDiscount
1616

17-
Компонент для [MiniShop3](/components/minishop3/): автоматическая скидка на первый заказ. При нуле оплаченных заказов к стоимости корзины применяется скидка (процент или фиксированная сумма). Для авторизованных учитывается `user_id`, для гостей — `email`/`phone` из `Address` черновика заказа. Оплаченные заказы определяются по настройке MiniShop3 `ms3_status_for_stat`.
18-
19-
**Именование:** для пользователя — **ms3FirstTimeBuyerDiscount**; в коде (папки, namespace, плагины) — **ms3firsttimebuyerdiscount**.
17+
Компонент для [MiniShop3](/components/minishop3/): автоматическая скидка на первый заказ. При нуле оплаченных заказов к стоимости корзины применяется скидка (процент или фиксированная сумма). Для авторизованных учитывается `user_id`, для гостей — `email`/`phone` из `Address` черновика заказа. Статусы оплаченных заказов берутся из `ms3_status_for_stat` с учётом `ms3_status_new`.
2018

2119
## Возможности
2220

2321
- **Скидка на первый заказ** — применяется при расчёте корзины (событие `msOnGetCartCost`), без правки шаблонов
2422
- **Тип скидки** — процент от суммы или фиксированная сумма в валюте магазина
2523
- **Определение «первого» покупателя** — для пользователя по `user_id`, для гостя по `email`/`phone`, с учётом статусов из `ms3_status_for_stat`
24+
- **Контроль комбинации скидок** — настройка `ftb_allow_combination` позволяет запретить применение FTB, если в корзине уже есть скидка
2625
- **События**`ftbOnBeforeApply` (отмена или подмена суммы), `ftbOnApply` (логирование, аналитика)
27-
- **Интеграция с фронтендом**в ответ `getCost()` добавляется `ftb_discount` (`amount`, `message`) для показа уведомления
26+
- **Плашка на странице заказа**сниппет `ms3ftbDiscountBanner` + frontend-логика проверки eligibility по email/phone
2827
- **Расширяемость** — подмена сервиса в контейнере `ms3ftb_discount`, наследование `FtbDiscountService`
2928

3029
## Системные требования
@@ -51,14 +50,14 @@ items: [
5150

5251
### После установки
5352

54-
Включите плагин **ms3FirstTimeBuyerDiscount** и привяжите его к событию **msOnGetCartCost**. Задайте настройки скидки в **Настройки → ms3firsttimebuyerdiscount**.
53+
Задайте настройки скидки в **Настройки → ms3firsttimebuyerdiscount**.
5554

5655
Подробнее: [Быстрый старт](quick-start).
5756

5857
## Термины
5958

6059
| Термин | Описание |
6160
|--------|----------|
62-
| **First-Time Buyer** | Авторизованный пользователь или гость с нулём заказов в статусах из настройки MiniShop3 `ms3_status_for_stat` |
61+
| **First-Time Buyer** | Авторизованный пользователь или гость с нулём заказов в статусах из `ms3_status_for_stat` (с учётом `ms3_status_new`) |
6362
| **Оплаченный заказ** | Заказ в одном из статусов, перечисленных в `ms3_status_for_stat` (например, «Оплачен», «Доставлен») |
64-
| **Скидка** | Сумма или процент, вычитаемые из стоимости корзины при расчёте в `msOnGetCartCost`; дополнительно в API-ответ добавляется `ftb_discount` |
63+
| **Скидка** | Сумма или процент, вычитаемые из стоимости корзины при расчёте в `msOnGetCartCost` |

0 commit comments

Comments
 (0)