Repository navigation
Рефералка: процент на баланс, уровни, скидка и удержание - #400
spacesarmat wants to merge 4 commits into
Conversation
Процент на баланс, уровни, скидка другу и удержание считаются при расчете. Задержка и годовой лимит правятся в админке. Миграция 013 подключает журнал. Co-authored-by: ANDY BUM <spacesarmat@users.noreply.github.com>
Co-authored-by: ANDY BUM <spacesarmat@users.noreply.github.com>
Co-authored-by: ANDY BUM <spacesarmat@users.noreply.github.com>
| for (let i = 0; i < rows.length; i++) { | ||
| const row = rows[i]; | ||
| if (!row || row.accountId !== friendId || row.pending || row.error) continue; | ||
| const t = Number(row.at) || 0; | ||
| if (t >= from && (at === 0 || t < at)) at = t; | ||
| if (t >= from) out.push(row); |
There was a problem hiding this comment.
Device purchases count as months
friendPayments includes extra-device purchases as subscription payments. Those rows carry the same accountId, so buying device slots 27–45 days apart can satisfy retentionMonths without renewing the subscription. The same helper also lets a device purchase consume the first-subscription discount. Resolve buy: orders to their saved kind and include only subscription purchases for these checks.
Prompt To Fix With AI
This is a comment left during a code review.
Path: ops/billing/src/logic.mjs
Line: 1289-1293
Comment:
**Device purchases count as months**
`friendPayments` includes extra-device purchases as subscription payments. Those rows carry the same `accountId`, so buying device slots 27–45 days apart can satisfy `retentionMonths` without renewing the subscription. The same helper also lets a device purchase consume the first-subscription discount. Resolve `buy:` orders to their saved `kind` and include only subscription purchases for these checks.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.…Greptile Каждая оплата подписки дает свой процент на баланс. Скидка друга одноразовая и не достается повторному заказу. Устройство не считается месяцем удержания. Co-authored-by: ANDY BUM <spacesarmat@users.noreply.github.com>
| if (quote && Number(quote.referralOff) > 0) { | ||
| const payer = quote.accountId || (act.indexOf('new:') === 0 ? act.slice(4) : ((state.subscriptions || []).find((s) => s.id === act.slice(4)) || {}).accountId); | ||
| if (payer && subscriptionPaidBefore(state, payer, operationId)) return rejectAmount(state, row); |
There was a problem hiding this comment.
Stars charged without subscription time
A second discounted Stars order can still charge the friend after their first payment succeeds. starCheckoutDecision checks whether that order was paid, but not whether another order already used the referral discount. This new check then rejects the successful charge with error: 'amount', without adding subscription time or returning the Stars. The admin refund route also refuses payments with an error.
Check discount eligibility before approving checkout, and return the payment if eligibility changes before the charge arrives.
Prompt To Fix With AI
This is a comment left during a code review.
Path: ops/billing/src/logic.mjs
Line: 1688-1690
Comment:
**Stars charged without subscription time**
A second discounted Stars order can still charge the friend after their first payment succeeds. `starCheckoutDecision` checks whether that order was paid, but not whether another order already used the referral discount. This new check then rejects the successful charge with `error: 'amount'`, without adding subscription time or returning the Stars. The admin refund route also refuses payments with an error.
Check discount eligibility before approving checkout, and return the payment if eligibility changes before the charge arrives.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
Четыре варианта рефералки считаются в биллинге. Пока Andy не включит переключатель, прод остается как сейчас: дни рефереру и другу, задержка и годовой лимит.
Варианты (все выключены по умолчанию)
creditRubподписки реферера. Параметры: процент, максимум за оплату, потолок за календарный месяц (МСК). Списывается при следующей оплате, как админский зачет.Задержка и годовой лимит правятся в админке. Журнал показывает тип строки: дни, баланс, удержание.
Отмена
Ожидающая строка просто отменяется. Выданная строка снимает дни с конца подписки и рубли с баланса. Если часть уже потрачена, в журнале, во вспышке и в аудите написано, что именно не снято. Аудит: действие
referral_cancel, актор и время МСК. Повтор той же отмены ничего не меняет. Повторный расчет тоже не начисляет второй раз.Миграция
013_referral_variants. Таблицыreferral_bindsиreferral_accrualsиз 011 получаютord,extraи колонки варианта и подключаются к хранилищу. Настройки по-прежнему вsettings.referral. Старый JSON изlegacy_stateпереносится в таблицы при первой записи.Не вливать и не выкатывать
Нужно слово Andy. Если в проде переключатели уровней, скидки или удержания уже нажаты, а числа нулевые, начисления не меняются. Процент на баланс включается только новым переключателем, сохраненный процент сам по себе не включается.
Админка рефералки
To show artifacts inline, enable in settings.
Fix the charged-but-rejected Stars payment path and preserve device-payment checks after old orders are removed before merging.
Fix with agent prompt
Summary
Adds referral balance credits, tiers, first-payment discounts, retention rewards, and cancellation records. The new variants remain off by default.
Diagram
%%{init: {'theme': 'neutral'}}%% flowchart TD A[Create two discounted Stars orders] --> B[Pay first order] B --> C[Approve checkout for second order] C --> D[Telegram charges Stars] D --> E[Prior subscription payment found] E --> F[Reject payment without adding days] F --> G[Admin refund refuses error row]Reviews (2) · Last reviewed commit: "Рефералка: скидка в Stars и crypto, удер..." · Reviewed by Greptile