Финансы, курсы и тарифы¶
Баланс клиента и леджер¶
У клиента два независимых счёта (client_balance_accounts): RUB и CNY. Оплаты заказов — в CNY.
RUR → RUB и новые денежные возможности
Код рублёвой валюты унифицирован: RUR → RUB (миграция unify_rur_to_rub). Добавлены: овердрафт клиента (clients.overdraft_limit — баланс может уходить в минус в пределах лимита), пополнение баланса вне заказа (standalone top-up: topup_requests.order_id стал nullable + currency + note), валюта доп. услуг (agent_rate_settings.services_currency), снимок курсов на отгрузке (shipments.currency_rates).
Все движения средств идут через LedgerService — единственную точку с lockForUpdate (атомарность). Каждое движение пишется в balance_ops со знаком и остатком после операции (balance_after), со ссылками на заказ/отгрузку/счёт.
flowchart LR
Top[Пополнение баланса] --> Bal[Баланс клиента ¥]
Bal -->|«Оплатить с баланса»| Order[Заказ → Выкуп]
Bal -->|оплата доставки| Ship[Отгрузка → Оплачена]
Платёжный флоу¶
Оплата ≠ списание в заказ
Это ключевое решение. Подтверждение реквизитов пополняет общий баланс, а не списывает в конкретный заказ.
- Посредник выдаёт реквизиты/счёт (
invoices): карта (payment_cards, номер шифруется) / наличные / платёжный агент. Короткий код для просмотра без логина —requisite_codes(/r/{code}). - Клиент отметил «оплачено» → посредник «Реквизиты оплачены» →
ConfirmInvoicePaidпополняет общий ¥-баланс клиента (topUpFromInvoice). - Клиент жмёт «Оплатить с баланса» →
PayOrderFromBalance: если баланс ≥ суммы заказа → списание + снимок расчёта + переходawait_pay → buyout. - Не хватает → «Запросить пополнение» (на любую сумму) → запись
topup_requests(pending→fulfilled) + сообщение посреднику; после подтверждения — пополнение общего баланса.
Мультивалютные счёта
У invoices добавлены base_currency / pay_currency / auto_convert — счёт может выставляться в одной валюте, а оплачиваться в другой с авто-конвертацией. Клиент может сменить валюту счёта (orders.invoice-currency). Валюта клиента — clients.currency.
Комиссия¶
CommissionService — ступенчатая комиссия по тарифу клиента (client_tariffs / client_subtariffs / client_tariff_steps):
- ступени
from_cny → pct(ладдер); - особая ставка первого заказа (
first_order_pct), включается флагомfirst_order_commission_enabled; - подтариф выбирается по сайту товара (подтариф, чьи сайты покрывают сайт; иначе «Основной»).
Курсы валют¶
Курс посредника rates (₽ за 1 ¥), value через RateService::effectiveValue($agent, ?$amountCny):
| Режим / источник | Поведение |
|---|---|
manual |
Фиксированное значение |
auto + cbr |
Курс ЦБ РФ × (1 + наценка markup_pct) |
auto + bestchange |
Средний курс топ-N обменников × (1 + наценка) |
Ладдер (rate_steps, kind=order) |
Ступенчатый курс по сумме заказа |
Ладдеры стали мультивалютными: у rate_steps добавлены from_cur/to_cur (валютная пара ступени), а у agent_rate_settings — delivery_base (базовая валюта доставки). Это позволяет вести курсы не только ¥→₽.
Дополнительно agent_rate_settings: курс usd_rub, кросс usd_cny, режим приёма (self/bestchange), срок действия курса, тексты о доставке. В шапке кабинета — три виджета: $ → ₽, 元 От {курс}, $ → 元.
Источники курсов¶
- ЦБ РФ (
CbrRateService): парситXML_daily.asp, берёт CNY и USD за один запрос. Командаrates:fetch-cbr(ежечасно), кэшcbr:CNY:RUB/cbr:USD:RUB. - bestchange (
BestchangeService): курсы обменников и сами обменники, средний курс топ-N «проверенных» под лимит. Командаbestchange:fetch(каждые 15 мин).
Мультивалютность¶
currencies— справочник валют;agent_currencies— валюты посредника + основная (is_main).- Внутренний учёт в ¥/$, клиент видит суммы в
display_currency(валюта страны). - Конвертация —
CurrencyServiceпо курсам посредника.
СРМ-тарифы посредника¶
Посредник платит за пользование платформой (crm_tariffs): месячная плата, лимит сотрудников, бесплатные заказы/товары, плата за превышение.
agent_invoices— счета СРМ (пополнениеagents.balance_cny); подтверждает админ.crm_charges— аудит списаний:subscription(месячная плата),over_order,over_item,renew_downgrade.order_idуникален дляover_*(анти-дубль).- Команда
crm:renew-tariffs— авто-продление ежедневно в 03:00.
Пополнение Alipay/WeChat¶
wallet_topups — доп.услуга, не влияет на баланс: клиент создаёт заявку (система + кошелёк + сумма), передаёт деньги вне системы, посредник помечает «оплачено». Отдельная история пополнений.