Skip to content

Посібник з операцій із виплатами (для адмінів)

Внутрішнє — лише для операторів

Ця сторінка документує Admin → Payout Management для адміністраторів платформи FundlyHub. Вона описує інструменти, що переміщують реальні гроші та пишуть у фінансовий реєстр (ledger). Прочитайте правила безпеки грошей перед запуском будь-чого. Деструктивні дії потребують права manage_system_settings. Назви елементів інтерфейсу (UI) наведено англійською — саме так вони відображаються в адмінпанелі.

Payout Management розташований на адмінсторінці Payout Management і має три вкладки: Transfers (реєстр по кожній пожертві), Creator Payouts (виплати Stripe на банківські рахунки творців) і Connected Accounts. Цей посібник зосереджений на вкладці Transfers, де відбуваються релізи та ремедіація.


Модель статусів переказів на основі доказів

Кожен рядок пожертви на вкладці Transfers несе один із п'яти бейджів статусу. Статус виводиться з доказів, а не з одного прапорця — рядок вважається «гроші переказано» лише тоді, коли Stripe це справді підтверджує. Це ключовий інваріант, який не дає платформі платити двічі або мовчки «втрачати» кошти.

БейджЗначенняГотовий до релізу?
HeldКошти утримуються платформою, і відповідне списання пройшло розрахунок (settled), і у творця є активний connected account. Готовий до релізу зараз.Так
Pending settlementУтримується, але списання ще не пройшло розрахунок. Стане Held автоматично, щойно Stripe його розрахує.Ще ні
TransferredІснує аудит-рядок реєстру з реальним tr_… — Stripe доказово перемістив гроші.Готово
DirectDestination charge: Stripe переказав гроші творцеві у момент списання. Окремий переказ не потрібен.Готово
AnomalyЧервоний бейдж. Реєстр стверджує, що гроші переказано, але ніщо в Stripe цього не підтверджує (клас баги #1126). Потребує ремедіації.Потрібна перевірка

Чому «Held» складається з двох частин: рядок вважається готовим до релізу лише коли списання пройшло розрахунок і connected account творця активний (has_connected_account && charges_enabled). Розраховані, але не онбординговані кошти відстежуються окремо як Held — awaiting onboarding — гроші в безпеці, їх просто не можна переказати, поки творець не завершить Stripe Connect.

Фільтр статусу вгорі вкладки Transfers дозволяє обмежити таблицю будь-яким одним статусом (Held, Pending settlement, Transferred, Direct, Anomaly).


KPI-плитки

Над таблицею розташовані чотири основні плитки. Перші три клікабельні — клік веде на вкладку Transfers, відфільтровану за цим статусом.

ПлиткаЩо рахуєДія по кліку
Ready to releaseHeld-рядки, що пройшли розрахунок і з активним connected account — переказувані просто зараз. Підказка показує чисту суму.Фільтрує Transfers за held
Awaiting settlementPending-settlement рядки — релізяться автоматично після розрахунку.Фільтрує Transfers за pending_settlement
AnomaliesРядки, чий реєстр стверджує рух грошей без доказів Stripe. При 0 підказка показує «ledger clean».Фільтрує Transfers за anomaly
Connected accountsУсього connected accounts, у підказці N verified · M pending setup.

Під плитками допоміжна смуга несе метрики меншої ваги:

  • Monthly volume — перекази за цей місяць
  • Platform fees — чайові за цей місяць
  • Held — awaiting onboarding — розраховані утримані кошти, які платформа поки не може переказати, бо творець не підключив Stripe (чиста сума в підказці)
  • Transferred — підтверджені Stripe + direct, за весь час
  • Total donations — за весь час

Сама мітка вкладки Transfers показує живі бейджі: N ready (warning) і N anomalies (error), коли ці лічильники ненульові.


Меню Actions

Випадне меню Actions (угорі праворуч на вкладці Transfers) захищене правом manage_system_settings. У ньому чотири пункти.

Release N ready ($X)

Створює реальні перекази Stripe для кожного Held-рядка, готового до релізу. Поведінка:

  • Проходить по кожному творцеві з утриманими коштами і запускає шлях релізу по кожній пожертві для тих, чий connected account активний. Творці без активного connected account пропускаються (рахуються окремо, не як помилки).
  • Кожен переказ запускається по одному на пожертву зі встановленим source_transaction, тому кожна пожертва відображається окремим рядком у connected account творця.
  • Перекази — за вирахуванням комісій (net): сума в реєстрі Held уже є чистою сумою до виплати творцеві.
  • Адоптувати, а не платити двічі: перед створенням переказу шлях релізу перевіряє в Stripe наявність уже наявного живого переказу для цього списання (через charge.transfer або per-donation transfer_group). Якщо такий уже є, він його адоптує — пише аудит-рядок і перемикає запис реєстру без нового руху грошей — замість створення другого переказу.
  • Рядки, чиє списання ще не пройшло розрахунок, відхиляються Stripe і залишаються Held; webhook повторить їх при наступному balance.available.

Діалог підтвердження резюмує обсяг перед запуском. Після прогону таблиця та лічильники KPI перечитуються із сервера (без оптимістичних перемикань — бейдж змінюється, лише якщо оновлення реєстру в БД справді зафіксувалося).

Remediate anomalies

Відкриває діалог Remediate transfer anomalies. Це інструмент відновлення для Anomaly-рядків — реєстр каже про рух грошей, але доказів Stripe немає. Він ніколи не створює перекази Stripe.

Робочий процес: Detect → перевірка → ExecuteAttest як операторським перевизначенням):

  1. Creator user ID (необов'язково). Порожньо — сканує всю платформу на аномалії. Обмеження одним творцем також включає ще утримувані рядки цього творця, щоб підтверджені ручні виплати можна було засвідчити (attest).

  2. Detect — лише читання. Перевіряє кожну аномалію проти Stripe і класифікує її. Перевірте чипи класифікації:

    ЧипЗначенняПоведінка Execute
    restore_to_heldДоказово «застрягло» — переказу Stripe не знайдено.Відновлюється в held → знову потрапляє в звичайний пайплайн релізу.
    already_transferredРеальний переказ Stripe існує; бракувало лише аудит-рядка.Аудит-рядок дописується (гроші не рухаються).
    direct_confirmedПідтверджений destination charge.Позначається як direct (гроші не рухаються).
    subscription_excludedЗапис підписки, виключена з цього шляху.Без змін.
    held_unprovenУсе ще held, без доказів Stripe у будь-який бік — лише attest.Execute не чіпає.
    attestedПозначено оператором як оплачено поза платформою.
    errorПомилка Stripe/БД по цьому рядку; друкується під рядком. Нічого не змінено.
  3. Execute — restore N ($X) + backfill M — застосовує не-attest класифікації: відновлює недоведені не-held рядки в Held, дописує аудит-рядки для підтверджених переказів, позначає підтверджені destination charges. Перекази Stripe не створюються. Діалог залишається відкритим, показуючи класифікацію після Execute (щоб помилки запису не ховалися за тостом успіху).

  4. Attest paid off-platform — N ($X) — операторське перевизначення, показується лише коли обрано творця і є кандидати на attest. Позначає пожертви творця як оплачені БЕЗ доказів Stripe. Використовуйте лише коли ви особисто перевірили, що гроші дійшли до творця (наприклад, ручний переказ через дашборд Stripe чи банківська виплата). Записує виплату як доказ без руху грошей і запитує причину для аудит-логу.

Restore проти Attest — правило подвійної оплати

Execute-restore повертає недоведені рядки в Held, щоб звичайний пайплайн їх оплатив. Attest фіксує, що вони вже оплачені поза платформою, і грошей не рухає. НІКОЛИ не робіть Execute-restore для творця, якому ви вже заплатили вручну — це оплатить двічі. Якщо ви не на 100% упевнені, що гроші вже перемістилися, attest — неправильний інструмент; якщо ви на 100% упевнені, що перемістилися, restore — неправильний інструмент. У сумнівах — скасуйте і спершу перевірте в дашборді Stripe.

Reconcile held with Stripe

Проходить по кожному Held-рядку і запитує Stripe, чи існує вже живий переказ для його списання — розв'язується з будь-якого джерела доказів: charge.transfer (епоха source-transaction) або per-donation transfer_group (donation-<id>, епоха plain-transfer). Якщо знайдено живий, нереверсований переказ, він його адоптує: пише аудит-рядок і перемикає запис у Transferred без руху грошей.

Це інструмент відновлення для «Stripe заплатив творцеві, але відкат БД залишив рядок Held». Безпечний для запуску будь-коли — він лише адоптує наявні перекази, ніколи не створює нові. Тост показує checked / reconciled (збіглося з наявними переказами) / genuinely held / skipped / errors.

Backfill settlement data

Старі утримані пожертви передують settlement-вебхукам, тому їхнє stripe_available_on дорівнює NULL — вони вічно відображаються як Pending settlement, і шлях релізу їх пропускає. Ця дія підтягує реальне stripe_available_on зі Stripe для таких рядків і лагодить хибні позначки destination-charge. Ідемпотентно — безпечно перезапускати. Тост повідомляє, скільки з відсутніх рядків було дозаповнено і скільки ще лишилося.


Дерево рішень

Рядок показує Anomaly → Відкрийте Remediate anomalies, запустіть Detect (обмежте творцем, якщо знаєте його). Перевірте чипи: рядки already_transferred / direct_confirmed потребують лише Execute для дозаповнення доказів (гроші не рухаються). Рядки restore_to_held справді «застрягли» — Execute відновить їх у Held, щоб пайплайн їх оплатив, якщо тільки у вас немає доказів, що творцеві вже заплатили вручну, — тоді Attest. Ніколи не відновлюйте рядок для творця, якому ви заплатили вручну.

Рядок показує Held, але творець каже, що йому заплатили → Не релізьте. Спершу запустіть Reconcile held with Stripe — якщо в Stripe уже є живий переказ для цього списання, reconcile його адоптує, і рядок перемкнеться в Transferred без руху грошей. Якщо reconcile нічого не знайшов, але ви особисто перевірили виплату поза платформою, обмежте Remediate anomalies цим творцем і зробіть Attest paid off-platform із зазначенням причини. Реліз натомість призведе до подвійної оплати.

Pending settlement багатомісячної давнини → Рядок, імовірно, передує settlement-вебхукам і має NULL дату розрахунку. Запустіть Backfill settlement data, щоб підтягнути stripe_available_on зі Stripe. Після дозаповнення та розрахунку він перейде в Held і стане готовим до релізу (або релізнеться автоматично на наступному прогоні).


Правила безпеки грошей

Прочитайте перед запуском будь-якої дії

  • Кожне перемикання статусу потребує доказів. Рядок перемикається в Transferred/Direct лише за наявності реального tr_… Stripe, charge.transfer, відповідного transfer_group чи аудитованого операторського attestation. Жоден прапорець не перемикається лише за метаданими.
  • Ремедіація не рухає гроші. Detect — лише читання; Execute, Reconcile і Backfill лише адоптують наявні перекази, дозаповнюють аудит-рядки чи позначають підтверджені стани. Жоден із них ніколи не викликає transfers.create. Лише Release N ready створює перекази Stripe.
  • Захист точного збігу. Execute і Attest несуть числа цього прогону Detect (expectedCandidates / expectedRestoreCents) у серверний захист точного збігу. Якщо реєстр змінився між Detect і Execute, сервер повертає 409 → «State changed — re-run Detect». При 409 не повторюйте наосліп — перезапустіть Detect і перевірте свіжу класифікацію перед дією.
  • Ніколи не платіть двічі. Не робіть Execute-restore для творця, якому вже заплатили вручну. Використовуйте Attest для підтверджених виплат поза платформою; Restore — лише для справді «застряглих» коштів.
  • Release адоптує перед оплатою. Шлях релізу перевіряє в Stripe уже наявний живий переказ і адоптує його замість створення другого — але ця підстраховка не замінює правила вище.

Питання щодо конкретного рядка чи завислого прогону ремедіації? Напишіть на tech@cyty.io з ID пожертви та текстом тоста Detect/Execute.

Built with VitePress