# ─────────────────────────────────────────────────────────────────────────────
# Стандарт «Возврат регистрационного взноса» — процесс возврата кандидату
# полученного регистрационного взноса при отказе совета в приёме.
#
# Это самостоятельный процесс: приём пайщика (p.reg.accept) прерывается на
# решении совета, и вместо признания взноса начинается его возврат. Возврат
# идёт в два шага: совет выносит отказ и поручает кассе вернуть деньги, а
# списание со счёта происходит только после того, как касса фактически проведёт
# исходящий перевод кандидату и подтвердит это. До подтверждения деньги стоят
# на расчётах с пайщиком (счёт 76).
#
# Источники правды в коде:
#   • cpp/registrator/registrator.hpp                 — действия declinereg / refundpay
#   • cpp/registrator/src/user/declinereg.cpp         — отказ совета, создание исходящего возврата
#   • cpp/registrator/src/user/refundpay.cpp          — подтверждение возврата кассой, проводка и закрытие
#   • cpp/registrator/src/user/declinerfnd.cpp        — страж: отмена возврата невозможна
#   • cpp/lib/core/ledger2/operations.hpp             — OPERATION_REGISTRY (o.reg.refund)
#   • cpp/lib/core/ledger2/processes.hpp              — processes::registrator::REFUND
#   • cpp/lib/core/ledger2/wallets.hpp                — w.reg.pend
#   • cpp/lib/core/ledger2/accounts.hpp               — 51 / 76
# ─────────────────────────────────────────────────────────────────────────────

# ── Секция 1. Паспорт ───────────────────────────────────────────────────────
process_type: p.reg.refund
id: public_registrator_refund_process
title: Возврат регистрационного взноса
slug: refund
status: proposed
contract: registrator
summary: >
  Когда совет отказывает кандидату в приёме, полученный регистрационный
  взнос возвращается ему: совет поручает возврат, касса проводит перевод и
  подтверждает его, после чего запись кандидата закрывается.
purpose: >
  «Возврат регистрационного взноса» — терминальный процесс приёма пайщика
  по отрицательному решению. Полученные кассой деньги стоят на расчётах
  с пайщиком (счёт 76) в ожидании решения; при отказе совета они
  возвращаются кандидату. Возврат денег не может быть отменён — права
  кандидата на свои средства безусловны.
roles:
  - contributor        # несостоявшийся пайщик (получатель возврата)
  - soviet             # совет кооператива (выносит отказ и поручает возврат)
  - chairman           # председатель / кассир (проводит и подтверждает возврат)

# ── Секция 2. Действия контракта (блокчейн-уровень) ─────────────────────────
actions:
  - name: registrator::declinereg
    human: Отклонить советом
    actor: soviet
    role: opener
    purpose: >
      Совет отказывает кандидату в приёме. Процесс приёма прерывается:
      контракт переводит кандидата в состояние возврата и поручает кассе
      вернуть полученный взнос. Деньги остаются на расчётах с пайщиком
      (счёт 76) — со счёта они ещё не уходят.

  - name: registrator::refundpay
    human: Подтвердить возврат
    actor: chairman
    role: closer
    purpose: >
      Касса фактически провела исходящий перевод денег кандидату и
      подтверждает это. Контракт проводит возврат обратной проводкой
      (Дт 76 / Кт 51) операцией `o.reg.refund` и закрывает запись кандидата.
      После этого аккаунт освобождается для повторной подачи заявления на
      том же аккаунте: несостоявшийся пайщик может подать заявку заново.

  - name: registrator::declinerfnd
    human: Отклонить возврат (недопустимо)
    actor: chairman
    role: guard
    purpose: >
      Отмена возврата регистрационного взноса невозможна — действие всегда
      завершается ошибкой. Существует только как обязательная развилка
      процессинга; в интерфейсе кассы кнопки отклонения возврата нет.

# ── Секция 3. Граф состояний ────────────────────────────────────────────────
entity: "registrator::candidate"
entity_human: "Кандидат"
entity_source: cpp/registrator/src/user/declinereg.cpp

states:
  - name: payed
    human: Взносы оплачены
    description: >
      Входное состояние процесса: деньги получены и стоят на расчётах
      с пайщиком (w.reg.pend, счёт 76), повестка `joincoop` рассмотрена
      советом с отрицательным решением.
    kind: normal

  - name: refunding
    human: Возврат в процессе
    description: >
      Совет отказал и поручил кассе вернуть взнос. Создан исходящий платёж
      возврата; деньги по-прежнему стоят на расчётах с пайщиком (w.reg.pend,
      счёт 76) и ждут, пока касса фактически проведёт перевод и подтвердит его.
    kind: normal

  - name: refunded
    human: Взнос возвращён
    description: >
      Касса подтвердила исходящий перевод. В книге Ledger2 проведена
      обратная операция `o.reg.refund` (Дт 76 / Кт 51) — обязательство перед
      кандидатом закрыто, деньги ушли со счёта. Запись кандидата удалена.
    kind: final

transitions:
  - from: payed
    to: refunding
    action: registrator::declinereg
    actor: soviet
    operations: []
    guards:
      - Совет принял отрицательное решение по повестке `joincoop`.
      - Кандидат в статусе `payed` (деньги были получены и стоят на счёте 76).

  - from: refunding
    to: refunded
    action: registrator::refundpay
    actor: chairman
    ledger_code: p.reg.refund
    operations:
      - o.reg.refund
    guards:
      - Касса фактически провела исходящий перевод денег кандидату.
      - Кандидат в статусе `refunding`.

# ── Секция 4. Сценарий ──────────────────────────────────────────────────────
scenario:
  steps:
    - step: 1
      title: Отказ совета и поручение на возврат
      actor: soviet
      action: registrator::declinereg
      description: >
        Совет рассматривает повестку `joincoop` и принимает отрицательное
        решение. Процесс приёма прерывается: кандидат переводится в состояние
        «возврат в процессе», и кассе поручается вернуть полученный
        регистрационный взнос. Деньги остаются на расчётах с пайщиком
        (w.reg.pend, счёт 76) — со счёта они ещё не уходят. Кандидат получает
        уведомление об отказе.
      pre:
        - Кандидат в статусе `payed` — деньги получены и стоят на счёте 76.
        - Совет принял отрицательное решение.
      post:
        - Кандидат в статусе `refunding`.
        - Создан исходящий платёж возврата на сумму взноса.
        - Деньги по-прежнему на счёте 76 (проводки ещё нет).

    - step: 2
      title: Касса возвращает деньги и подтверждает
      actor: chairman
      action: registrator::refundpay
      description: >
        Касса проводит фактический перевод денег кандидату и подтверждает,
        что возврат выполнен. Контракт возвращает полученный регистрационный
        взнос обратной проводкой `o.reg.refund` (Дт 76 / Кт 51): сумма
        «вступительный + минимальный паевой» списывается с кошелька ожидания
        (w.reg.pend), обязательство перед кандидатом закрывается, деньги
        уходят со счёта. Запись кандидата удаляется. Отменить возврат нельзя.
      pre:
        - Кандидат в статусе `refunding`.
        - Касса фактически провела исходящий перевод кандидату.
      post:
        - В книге Ledger2 проведена o.reg.refund (Дт 76 / Кт 51).
        - Запись кандидата удалена из картотеки кандидатов.
        - Кандидат получил свои деньги.

# ── Секция 5. Документы и подписи ───────────────────────────────────────────
documents:
  - action: registrator::declinereg
    title: Решение совета об отказе в приёме пайщика
    registry_id: 501
    signed_by: [ Совет ]
    stored_in: "(решение совета — в повестке joincoop)"

# ── Секция 6. Операции ──────────────────────────────────────────────────────
# Возврат проводится одной операцией o.reg.refund — на шаге подтверждения кассой
# (registrator::refundpay), не на решении совета. Отмена возврата невозможна
# (действие-страж declinerfnd всегда завершается ошибкой).
#
# ПЕРЕХОДНЫЙ ПЕРИОД (до 30.07.2026): кандидаты, чей платёж был принят ДО релиза
# двухфазного учёта, суспенса на счёте 76 не имеют — для них on-chain проводки
# возврата нет (как было раньше), деньги возвращает бэкенд банковским переводом,
# а запись кандидата закрывается сразу при отказе совета. Операция o.reg.refund
# проводится только при наличии баланса на w.reg.pend.
operations:
  - ledger_code: o.reg.refund
    human_name: Возврат регистрационного взноса при отказе совета
    wallet_op: BURN
    wallet_from: w.reg.pend
    wallet_to: ''
    debit: 76
    credit: 51
    amount_ref: candidate.initial + candidate.minimum
    triggered_by: registrator::refundpay
    description: >
      Возврат полученного регистрационного взноса. Сумма «вступительный +
      минимальный паевой» списывается с кошелька «Регистрационный взнос
      в ожидании решения совета» (w.reg.pend); двойная запись Дт 76 / Кт 51 —
      закрытие обязательства перед кандидатом и уход денег с расчётного
      счёта. Получателя на цепи нет — деньги фактически переводит касса.

# ── Секция 7. Связи ─────────────────────────────────────────────────────────
related:
  - process_type: p.reg.accept
    id: public_registrator_accept_process
    relation: interrupts
    note: >
      Возврат — отрицательная развилка процесса «Приём пайщика»
      (p.reg.accept). Деньги, поставленные на расчёты с пайщиком операцией
      `o.reg.inpay` на этапе оплаты, при отказе совета не признаются
      взносом, а возвращаются этим процессом.
