Skip to content

feat: add _formatted placeholders for currency and weight display#147

Merged
biz87 merged 2 commits intobetafrom
feat/144-formatted-currency-weight-placeholders
Mar 16, 2026
Merged

feat: add _formatted placeholders for currency and weight display#147
biz87 merged 2 commits intobetafrom
feat/144-formatted-currency-weight-placeholders

Conversation

@Ibochkarev
Copy link
Copy Markdown
Member

@Ibochkarev Ibochkarev commented Mar 13, 2026

Описание

Системные настройки становятся единственным источником истины для символа
валюты и единиц веса. Сниппеты теперь предварительно форматируют значения
через Format::price($value, true) и Format::weightWithUnit() и передают
результат в чанки через новые *_formatted плейсхолдеры. Чанки используют
готовые строки без лексиконных вызовов для валюты и веса.

Ранее символ валюты и единица веса отображались в чанках через лексиконы
({'ms3_frontend_currency'|lexicon}, {'ms3_frontend_weight_unit'|lexicon}),
хотя системные настройки (ms3_currency_symbol, ms3_currency_position) уже
управляли форматированием в PHP. Изменение символа валюты в системной
настройке не затрагивало вывод в чанках.

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

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

Связанные Issues

Closes #144

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

  • Ручное тестирование
  • Автоматические тесты (PHPStan, ESLint)
  • Тестирование на разных версиях PHP/MODX

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

  • MiniShop3:
  • MODX:
  • PHP:

Чеклист

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

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

Обратная совместимость:

  • Сырые числовые поля (price, cost, weight) не удалены — JS-логика не затронута
  • Лексиконные ключи ms3_frontend_currency и ms3_frontend_weight_unit сохранены,
    но не используются core-чанками
  • Пользовательские чанки продолжат работать; рекомендуется обновить их по образцу
    обновлённых чанков, заменив лексиконные вызовы на *_formatted плейсхолдеры

Особые места кода:

  • ms3_order.tpl — JS динамически обновляет span'ы #ms3_order_cost и др., поэтому
    лексикон заменён на {$order.currency_symbol} (передаётся из сниппета), а не на
    _formatted плейсхолдер
  • ms3_get_order.php — сохраняются raw-числа до форматирования, чтобы _formatted
    поля получали корректный числовой вход

System settings become the single source of truth for currency symbol,
currency position, and weight unit. Snippets now pre-format values via
Format::price($value, true) and Format::weightWithUnit() and pass them
to chunks as *_formatted fields, eliminating lexicon calls for display.

- Format.php: add weightWithUnit(), getWeightUnit(), getCurrencySymbol(),
  extend getSettings() with weight_unit
- settings.php + lexicons (ru/en): add ms3_weight_unit system setting
- Snippets (ms3_cart, ms3_order_total, ms3_order, ms3_get_order): add
  price_formatted, cost_formatted, weight_formatted, cart_cost_formatted,
  delivery_cost_formatted, total_cost_formatted alongside raw numeric fields
- ms3_order.php: expose currency_symbol for JS-updated cost spans
- OrdersPageService: add _formatted fields to order list and detail data,
  fix raw numeric values before formatting in getOrderProducts()
- Notification.php: add _formatted fields to products and total array
- Chunks: replace {'ms3_frontend_currency'|lexicon} and
  {'ms3_frontend_weight_unit'|lexicon} with *_formatted placeholders

Lexicon keys ms3_frontend_currency and ms3_frontend_weight_unit are
retained for backward compatibility but no longer used by core chunks.
@Ibochkarev
Copy link
Copy Markdown
Member Author

@biz87 проверь плиз туда ли я пошел или нужно было сделать иначе

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.

Code Review

Идея правильная — single source of truth для валюты и единиц. Реализация в целом хорошая, но есть баги и недочёты.


Баги

1. ms3_minicart.tplold_cost потерял валюту

Было:

{$product.old_cost} {'ms3_frontend_currency' | lexicon}

Стало:

{$product.old_cost}

Но old_cost_formatted нигде не генерируется (ни в ms3_cart.php, ни в других сниппетах). Результат: старая стоимость отображается как голое число без валюты. Нужно либо добавить old_cost_formatted в сниппет корзины и использовать его, либо сохранить лексикон для этого поля.

2. ms3_customer_order_details.tplold_price без валюты рядом с price_formatted

Строка 68 (в PR):

<div class="text-decoration-line-through text-muted small">{$product.old_price}</div>

old_price — это format::price() (число без валюты: "150"), а рядом price_formatted — число с валютой: "100 ₽". Визуальная несогласованность. Аналогично в ms3_get_order.tpl (строка 72).

3. Docblock discount() в Format.php повреждён

После вставки weightWithUnit() и getWeightUnit() у метода discount() пропала строка описания. Было * Calculate discount percentage, стало пустая строка в docblock.


Проблемы дизайна

4. Нейминг: cost_with_currency vs *_formatted

В OrdersPageService для списка заказов используется cost_with_currency, а во всех остальных местах — *_formatted. В чанке ms3_customer_order_row.tpl{$cost_with_currency}. Нужно привести к единому паттерну.

5. ms3_order_total.php — дублирование ternary

7 строк подряд с одинаковым паттерном $response['success'] ? $response['data']['...'] ?? 0 : 0. Стоит вынести в переменную:

$data = $response['success'] ? ($response['data'] ?? []) : [];
$total['cost_formatted'] = $ms3->format->price($data['cost'] ?? 0, true);
// ...

Пропущенные места

6. Отсутствующие _formatted плейсхолдеры

Не сгенерированы, но могут понадобиться в кастомных чанках:

  • old_price_formatted — есть только в ms3_cart.php, но отсутствует в ms3_get_order.php, OrdersPageService, Notification
  • old_cost_formatted — отсутствует везде
  • discount_price_formatted, discount_cost_formatted — отсутствуют

Как минимум old_price_formatted стоит добавить во все точки, где генерируется price_formatted, для консистентности.


Мелкое

7. ms3_weight_unit — дефолт kg

Для русскоязычного проекта дефолт kg спорный. Может стоит кг? Или оставить kg как интернациональный вариант и указать в описании настройки.


Резюме

Основное перед мержем:

  1. Исправить old_cost в minicart (баг — пропала валюта)
  2. Добавить old_price_formatted в ms3_get_order.php, OrdersPageService, Notification или привести чанки к согласованному виду
  3. Привести нейминг к единому *_formatted (убрать cost_with_currency)
  4. Восстановить docblock discount()

@Ibochkarev Ibochkarev self-assigned this Mar 16, 2026
Replaced raw price variables with formatted versions across multiple templates and snippets to ensure consistent currency display. Introduced new formatted fields for old prices and discount calculations, enhancing the presentation of pricing information in the customer order details, order rows, minicart, and notifications. This change improves user experience by providing clearer pricing information.
@Ibochkarev Ibochkarev requested a review from biz87 March 16, 2026 07:28
@Ibochkarev Ibochkarev marked this pull request as ready for review March 16, 2026 07:28
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.

Code Review (повторный)

Все замечания из первого ревью исправлены во втором коммите. PR стал значительно лучше.

Что исправлено

  • ms3_minicart.tplold_cost_formatted теперь генерируется и используется
  • ms3_customer_order_details.tpl и ms3_get_order.tplold_price_formatted с корректным условием
  • Нейминг унифицирован: cost_with_currency убран, везде *_formatted
  • ms3_order_total.php$data вынесен, ternary не дублируется
  • Docblock discount() — сохранён
  • Notification.php — batch-загрузка productData для old_price, полный набор _formatted полей

Оставшееся замечание (некритичное, не блокирует мерж)

Семантика cost_formatted в OrdersPageService изменена:

Было: price($cost) → число без валюты ("1 500"), чанк добавлял {'ms3_frontend_currency' | lexicon}
Стало: price($cost, true) → число с валютой ("1 500 ₽")

Это breaking change для кастомных чанков ms3_customer_order_row, которые используют {$cost_formatted} и сами добавляют валюту — получат двойной символ. Стоит упомянуть в CHANGELOG / release notes.

Мелкое

Notification::getOrderProducts() вызывает $this->order->getMany('Products') дважды (сбор ID + основной цикл). Второй вызов вернёт кеш, но можно было итерировать один раз.

LGTM

@biz87 biz87 merged commit a93ef1d into beta Mar 16, 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.

[Refactor] Дублирование механизмов отображения валюты и единиц измерения

2 participants