Skip to content

feat(manager): пересчёт стоимости заказа в админке#255

Open
Ibochkarev wants to merge 2 commits into
modx-pro:betafrom
Ibochkarev:feat/gh-212-mgr-order-cost-recalculation
Open

feat(manager): пересчёт стоимости заказа в админке#255
Ibochkarev wants to merge 2 commits into
modx-pro:betafrom
Ibochkarev:feat/gh-212-mgr-order-cost-recalculation

Conversation

@Ibochkarev
Copy link
Copy Markdown
Member

Описание

Добавлен явный пересчёт итогов заказа в менеджере по сохранённым позициям и текущим delivery_id / payment_id: backend-сервис, POST /api/mgr/orders/{id}/recalculate-cost, UI на вкладке «Информация» (кнопка, предупреждение при несохранённой смене доставки/оплаты, ручная стоимость доставки при предупреждении API), лексиконы ru/en и запись в CHANGELOG.

В .gitignore добавлено явное имя AGENTS.md (файл остаётся локальным под общим игнором *.md).

Тип изменений

  • Исправление бага (non-breaking change)
  • Новая функциональность (non-breaking change)
  • Breaking change (изменение, ломающее обратную совместимость)
  • Рефакторинг (без изменения функциональности)
  • Документация
  • Другое (опишите): правка .gitignore для локального AGENTS.md

Связанные Issues

Closes #212

Как это было протестировано?

Локально: php -l по затронутым PHP-файлам, npm run lint по изменённым Vue-компонентам; ручная проверка сценариев auto / manual delivery / предупреждений после смены доставки/оплаты.

  • Ручное тестирование
  • Автоматические тесты (PHPStan, ESLint) — точечные (lint / syntax), полный PHPStan CI не запускался в этой сессии
  • Тестирование на разных версиях PHP/MODX

Конфигурация тестирования:

  • MiniShop3: ветка feat/gh-212-mgr-order-cost-recalculation
  • MODX: по окружению разработчика
  • PHP: 8.2+

Скриншоты (если применимо)

До После

Чеклист

  • Код соответствует стилю проекта
  • Добавлены/обновлены комментарии в сложных местах
  • Изменения не ломают существующую функциональность
  • Лексиконы добавлены на двух языках (ru/en)
  • PHPStan проходит без новых ошибок
  • ESLint проходит без ошибок (для JS/Vue изменений)
  • Обновлён CHANGELOG.md (для значимых изменений)

Дополнительные заметки

Комиссия способа оплаты по-прежнему только в агрегированном поле cost (отдельной колонки нет — как оговорено в #212).

@Ibochkarev Ibochkarev force-pushed the feat/gh-212-mgr-order-cost-recalculation branch 2 times, most recently from 590ab5d to 907936b Compare May 18, 2026 01:45
Copy link
Copy Markdown
Member

@biz87 biz87 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Спасибо за PR — архитектура отдельного сервиса с тремя режимами (auto / manual / force_provider) и warning-flags вместо exception'ов мне нравится, защита от падения внешних провайдеров типа CDEK/Яндекс реализована корректно. PHPStan проходит.

Однако PR писался до мержа #246 и #266, и его расчётная часть конфликтует с уже принятым контрактом. Прошу учесть в v2.

1. Регрессия отрицательных значений (#246)

После #246 поле price у msDelivery / msPayment поддерживает отрицательные значения и проценты (-10, -10%) — это легитимные скидки за способ доставки/оплаты. В ManagerOrderCostRecalculator они отбрасываются:

// calculateDefaultDeliveryCost():
if ($percent < 0 || $percent > 100) {
    return round($deliveryCost, 6);  // отрицательный процент → 0 надбавки
}
// ...
if ($addPrice < 0) {
    return round($deliveryCost, 6);  // отрицательная сумма → 0 надбавки
}
// calculateDefaultPaymentCommission():
if ($percent < 0 || $percent > 100) {
    return 0.0;
}
return $fixed < 0 ? 0.0 : round($fixed, 6);

Сценарий: настроил «−5% за самовывоз» (-5% в msDelivery.price) → менеджер жмёт «Пересчитать» → скидка теряется, итог завышен на 5%.

То же в FORCE_PROVIDER:

'payment_fee' => round(max(0, $withFee - $paymentBase), 6),

max(0, …) срезает отрицательную комиссию.

Что нужно: использовать общий MiniShop3\Utils\PriceAdjustment (введён в #246) — те же методы isPercent / getPercent / isAllowedPercent / calculate, что в Controllers\Delivery\Delivery::getCost() и Controllers\Payment\Payment::getCost(). Это устранит и регрессию, и дубль логики (три места теперь делают одно и то же по-разному).

isAllowedPercent корректно считает диапазон -100..100, calculate корректно работает с отрицательными — пересчёт даст тот же результат, что и при оформлении заказа.

2. Защита от отрицательного total (#266)

В #266 добавлен OrderService::clampComputedTotal(?msOrder, float $cartCost, float $deliveryCost, float $paymentCost = 0.0): float — финальная защита от ухода cost в минус с логом и разбивкой слагаемых. Применён во всех расчётах: OrderCostCalculator, OrderDraftManager, OrderFinalizeService, OrderService::updateProducts, OrdersController::createOrder/updateProducts.

В ManagerOrderCostRecalculator::recalculate():

$cost = round($cartCost + $deliveryCost + $paymentFee, 6);
// ...
$order->set('cost', $cost);

Сложение без clampComputedTotal. Сейчас в минус не уйдёт, потому что отрицательные срезаются (см. п.1). Когда п.1 будет исправлен — защита станет необходимой.

Что нужно: заменить сложение на $cost = $orderService->clampComputedTotal($order, $cartCost, $deliveryCost, $paymentFee) (ms3_order_service).

3. .gitignore — избыточная строка

 # Personal AI assistant files
+AGENTS.md
 *.md
 !CHANGELOG.md

Правило *.md уже покрывает AGENTS.md — явное упоминание ничего не меняет (no-op). Если задумывалось исключить из общего *.md — нужно было бы !AGENTS.md, но AGENTS.md это personal-файл и явный игнор не нужен.

Что нужно: убрать строку, либо вынести правку .gitignore в отдельный косметический PR (не смешивать с фичей).

Прочее

  • Логирование изменений через OrderLogService::addEntry(ACTION_FIELD, ['fields' => $changedFields]) — ок.
  • Warning-flags (delivery_manual_required / payment_manual_required / *_provider_error) и UI вокруг них — ок, защита от падения CDEK/Яндекс корректная.
  • isSimpleDelivery / isSimplePayment через сравнение FQCN с DefaultDelivery::class / DefaultPayment::class — рабочее решение, хотя «handler наследуется от Default» будет считаться кастомным. Edge case, не блокер.
  • updatedon set с date('Y-m-d H:i:s') — проверил, поле string, ок.

Итого: запрос на v2 — устранить регрессию отрицательных значений через PriceAdjustment, применить clampComputedTotal, убрать строку из .gitignore. После этого PR хороший и можно мержить.

@Ibochkarev
Copy link
Copy Markdown
Member Author

@biz87 👍 сделаю

POST /api/mgr/orders/{id}/recalculate-cost with ManagerOrderCostRecalculator;
Vue summary controls, lexicons ru/en; refactors after review.

chore: list AGENTS.md in .gitignore for local AI context.
@Ibochkarev Ibochkarev force-pushed the feat/gh-212-mgr-order-cost-recalculation branch from 907936b to 4a4c604 Compare May 18, 2026 17:01
…odx-pro#212)

Use shared PriceAdjustment for delivery/payment surcharges (negative discounts),
OrderService::clampComputedTotal for total; remove redundant AGENTS.md from .gitignore;
drop CHANGELOG entry from this branch.
@Ibochkarev Ibochkarev requested a review from biz87 May 18, 2026 17:05
@Ibochkarev Ibochkarev changed the title feat(manager): пересчёт стоимости заказа в админке (#212) feat(manager): пересчёт стоимости заказа в админке May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Пересчет стоимости заказа при смене способа доставки в админке

2 participants