# ─────────────────────────────────────────────────────────────────────────────
# Стандарт «Приём пайщика» — корневой кооперативный процесс приёма в кооператив.
#
# Манифест в стиле «двухуровневое описание»: каждая описательная секция
# содержит короткий tagline и развёрнутый абзац — для тех, кто пробегает
# глазами, и для тех, кто читает вдумчиво.
#
# Источники правды в коде:
#   • cpp/registrator/registrator.hpp                 — actions
#   • cpp/registrator/src/user/{reguser,confirmpay,confirmreg,declinepay,declinereg}.cpp
#   • cpp/lib/core/ledger2/operations.hpp             — OPERATION_REGISTRY (o.reg.inpay, o.reg.setmin, o.reg.setent)
#   • cpp/lib/core/ledger2/processes.hpp              — processes::registrator::ACCEPT
#   • cpp/lib/core/ledger2/wallets.hpp                — w.reg.pend, w.reg.entry, w.reg.minshr
#   • cpp/lib/core/ledger2/accounts.hpp               — 51 / 76 / 80 / 86
# ─────────────────────────────────────────────────────────────────────────────

# ── Секция 1. Паспорт ───────────────────────────────────────────────────────
process_type: p.reg.accept
id: public_registrator_accept_process
title: Приём пайщика
slug: accept
status: proposed
contract: registrator
summary: >
  От подписанного заявления о вступлении до карточки активного пайщика
  и двух взносов, поставленных на учёт в книге Ledger2.
purpose: >
  «Приём пайщика» — корневой кооперативный процесс. Им человек или
  организация входят в кооператив и получают доступ ко всем остальным
  процессам: внесению и возврату паевых взносов, займам, инвестициям
  в программу «Благорост», голосованию в совете и на общих собраниях.
roles:
  - contributor        # будущий пайщик
  - chairman           # председатель / администратор (запускает reguser от имени coopname)
  - gateway_operator   # кассир (роль человека, работающего с контрактом Gateway)
  - soviet             # совет кооператива

# ── Секция 2. Действия контракта (блокчейн-уровень) ─────────────────────────
actions:
  - name: registrator::reguser
    human: Подать заявление
    actor: contributor
    role: opener
    purpose: >
      Кандидат подписывает заявление, контракт открывает карточку и
      поручает кассиру выпустить счёт. В совет уходит повестка `joincoop`.

  - name: registrator::confirmpay
    human: Подтвердить оплату
    actor: gateway_operator
    role: progress
    purpose: >
      Кассир подтверждает зачисление взносов: карточка переходит в `payed`,
      повестка `joincoop` с колбэками отправлена в совет. Деньги получены,
      но взнос ещё не признан — он ставится на расчёты с пайщиком
      (Дт 51 / Кт 76) и ждёт решения совета.

  - name: registrator::declinepay
    human: Отклонить оплату
    actor: gateway_operator
    role: reject
    purpose: >
      Кассир отклоняет платёж: запись кандидата удаляется, операции в книге
      Ledger2 не создаются (деньги ещё не были приняты). Кандидат может
      подать заявление повторно.

  - name: registrator::confirmreg
    human: Утвердить советом
    actor: soviet
    role: closer
    purpose: >
      Совет утверждает приём: статус карточки → `active`, взнос признаётся —
      сумма с расчётов с пайщиком (счёт 76) переносится на паевой фонд (80)
      и целевое финансирование (86) операциями `o.reg.setmin` и
      `o.reg.setent`. Кандидат добавлен в список участников.

  - name: registrator::declinereg
    human: Отклонить советом
    actor: soviet
    role: reject
    purpose: >
      Совет отказывает в приёме: процесс приёма взноса прерывается и
      начинается отдельный процесс возврата «Возврат регистрационного
      взноса» (p.reg.refund) — полученная сумма возвращается кандидату.

# ── Секция 3. Граф состояний ────────────────────────────────────────────────
# Составная сущность: статус отслеживается в таблице `candidates` (created / payed),
# финальный `active` проставляется в таблице `accounts` в действии confirmreg.
# Для BPMN-графа мы показываем единый жизненный цикл процесса.
entity: "registrator::candidate → registrator::account"
entity_human: "Кандидат → пайщик"
entity_source: cpp/registrator/src/user/

states:
  - name: created
    human: Заявление подано
    description: >
      Запись кандидата открыта, документ заявления (#100) сохранён,
      контракт Gateway держит счёт на `initial + minimum`.
    kind: normal

  - name: payed
    human: Взносы оплачены
    description: >
      Деньги получены, карточка в `payed`, в совет ушла повестка `joincoop`.
      Полученная сумма стоит на расчётах с пайщиком (Дт 51 / Кт 76) и ждёт
      решения совета: при одобрении — признаётся взносом, при отказе —
      возвращается.
    kind: normal

  - name: active
    human: Пайщик активен
    description: >
      `accounts.status` = `active`, карточка кандидата удалена, в книге
      Ledger2 взнос признан — сумма перенесена со счёта 76 на 80 и 86
      операциями `o.reg.setmin` и `o.reg.setent`. С этого момента доступны
      все остальные кооперативные процессы.
    kind: final

  - name: removed
    human: Отклонено
    description: >
      Запись кандидата удалена на этапе оплаты (платёж не поступил/отклонён) —
      деньги не принимались, проводок не было.
    kind: virtual
    virtual: true

  - name: refunding
    human: Возврат в процессе
    description: >
      Совет отказал кандидату, чьи деньги уже стоят на счёте 76. Процесс
      приёма прерывается, и управление переходит в отдельный процесс
      «Возврат регистрационного взноса» (p.reg.refund), где касса проводит
      возврат и подтверждает его.
    kind: virtual
    virtual: true

transitions:
  - from: "∅"
    to: created
    action: registrator::reguser
    actor: contributor
    guards:
      - Участник не состоит в кооперативе и не имеет активной карточки участника.
      - Тип пользователя ∈ {individual, entrepreneur, organization}.
      - Заявление подписано ЭЦП.

  - from: created
    to: payed
    action: registrator::confirmpay
    actor: gateway_operator
    ledger_code: p.reg.accept
    operations:
      - o.reg.inpay
    guards:
      - Кассир подтвердил зачисление суммы = initial + minimum.

  - from: created
    to: removed
    action: registrator::declinepay
    actor: gateway_operator
    guards:
      - Оплата не поступила / отклонена.

  - from: payed
    to: active
    action: registrator::confirmreg
    actor: soviet
    ledger_code: p.reg.accept
    operations:
      - o.reg.setmin
      - o.reg.setent
    guards:
      - Совет принял положительное решение по повестке.

  - from: payed
    to: refunding
    action: registrator::declinereg
    actor: soviet
    operations: []
    guards:
      - Совет принял отрицательное решение по повестке.
      - >
        Проводок здесь нет: процесс приёма прерывается и управление переходит
        в отдельный процесс «Возврат регистрационного взноса» (p.reg.refund),
        где возврат проводится на шаге подтверждения кассой (o.reg.refund).

# ── Секция 4. Сценарий ──────────────────────────────────────────────────────
scenario:
  steps:
    - step: 1
      title: Подача заявления
      actor: contributor
      action: registrator::reguser
      description: >
        Кандидат подписывает заявление, контракт открывает карточку.

        Будущий пайщик оформляет и подписывает заявление о вступлении.
        Приложение кооператива вызывает `registrator::reguser`
        (с подписью `coopname`), указывая тип пользователя и
        территориальный участок. Контракт создаёт запись кандидата
        в статусе `created` и поручает контракту Gateway выпустить
        счёт на сумму «вступительный + минимальный паевой взнос».
      pre:
        - Участник ещё не имеет карточки в картотеке и не состоит в кооперативе.
        - Тип пользователя валиден.
      post:
        - В таблице candidates создана запись со статусом `created`.
        - Контракт Gateway выпустил счёт с колбэками confirmpay / declinepay.
        - В совет ушла повестка `joincoop`.

    - step: 2
      title: Оплата взносов
      actor: gateway_operator
      action: registrator::confirmpay
      description: >
        Деньги пришли — встают на расчёты с пайщиком, карточка движется к совету.

        Кандидат оплачивает счёт (банковский перевод или криптоплатёж).
        Кассир, получив подтверждение зачисления от платёжной системы,
        вызывает `confirmpay`. Контракт переводит кандидата в статус
        `payed`, создаёт повестку в совете с колбэками
        `confirmreg` / `declinereg` и ставит полученную сумму на учёт
        операцией `o.reg.inpay` (Дт 51 / Кт 76) — деньги получены, но
        взнос ещё не признан и ждёт решения совета.
      pre:
        - Кандидат в статусе `created`.
        - На расчётный счёт получена сумма initial + minimum.
      post:
        - Кандидат в статусе `payed`.
        - В совете открыта повестка `joincoop`.
        - В книге Ledger2 проведена o.reg.inpay (Дт 51 / Кт 76).

    - step: 3
      title: Утверждение советом
      actor: soviet
      action: registrator::confirmreg
      description: >
        Совет утверждает приём — взнос признаётся, кандидат становится пайщиком.

        Совет рассматривает повестку `joincoop`. При положительном
        решении контракт `confirmreg`: (1) меняет `accounts.status`
        на `active`; (2) добавляет нового пайщика в список участников
        совета (`soviet::addpartcpnt`); (3) признаёт взнос — переносит
        сумму с расчётов с пайщиком (76) на паевой фонд и целевое
        финансирование двумя операциями: `o.reg.setmin` (минимальный
        паевой, Дт 76 / Кт 80) и `o.reg.setent` (вступительный, Дт 76 / Кт 86).
        Запись кандидата удаляется.
      pre:
        - Кандидат в статусе `payed`.
        - Документ `authorization` от совета подписан.
      post:
        - accounts.status = `active` — пайщик стал активным членом кооператива.
        - Пайщик добавлен в soviet::participants.
        - В книге Ledger2 проведены o.reg.setmin + o.reg.setent.
        - Запись кандидата удалена из таблицы candidates.

  alternatives:
    - branch: Отказ на этапе оплаты
      at_step: 2
      action: registrator::declinepay
      actor: gateway_operator
      description: >
        Платёж не прошёл или был отменён.

        Кассир вызывает `declinepay`, кандидат удаляется, операции
        в книге Ledger2 не создаются (деньги ещё не приняты). Кандидат
        может повторить подачу заявления.

    - branch: Отказ совета
      at_step: 3
      action: registrator::declinereg
      actor: soviet
      description: >
        Совет отказывает кандидату.

        Процесс приёма взноса прерывается и начинается отдельный процесс
        «Возврат регистрационного взноса» (p.reg.refund): кандидат переводится
        в состояние возврата, кассе поручается вернуть деньги. Сама проводка
        Дт 76 / Кт 51 и удаление кандидата происходят там — на шаге, когда
        касса фактически проведёт возврат и подтвердит его.

# ── Секция 5. Документы и подписи ───────────────────────────────────────────
documents:
  - action: registrator::reguser
    title: Заявление на вступление в кооператив
    registry_id: 100
    signed_by: [ Кандидат ]
    stored_in: candidates.statement

  - action: registrator::confirmreg
    title: Решение совета о приёме пайщика в кооператив
    registry_id: 501
    signed_by: [ Совет ]
    stored_in: "(authorization — в параметре действия, не хранится в candidates после удаления записи)"

# ── Секция 6. Операции ──────────────────────────────────────────────────────
# Процесс мульти-операционный: три записи OPERATION_REGISTRY с process_type = p.reg.accept.
# Двухфазный учёт: на приёме денег (confirmpay) сумма ставится на расчёты с
# пайщиком (76), на одобрении совета (confirmreg) — признаётся взносом (80/86).
#
# ПЕРЕХОДНЫЙ ПЕРИОД (до 30.07.2026): кандидаты, чей платёж был принят ДО релиза
# двухфазного учёта, не имеют суспенса на счёте 76. Для них одобрение совета
# проводится по старому одношаговому пути — прямой ISSUE Дт 51 / Кт 80
# (o.reg.putmin) и Дт 51 / Кт 86 (o.reg.payent), без переноса с 76. Признак —
# отсутствие баланса кандидата на w.reg.pend (см. registration_migration.hpp).
operations:
  - ledger_code: o.reg.inpay
    human_name: Приём регистрационного взноса в ожидание решения совета
    wallet_op: ISSUE
    wallet_from: ''
    wallet_to: w.reg.pend
    debit: 51
    credit: 76
    amount_ref: candidate.initial + candidate.minimum
    triggered_by: registrator::confirmpay
    description: >
      Постановка полученного регистрационного взноса на учёт. Сумма
      «вступительный + минимальный паевой» зачисляется на кошелёк
      «Регистрационный взнос в ожидании решения совета» (w.reg.pend);
      двойная запись Дт 51 / Кт 76 — деньги на расчётном счёте, обязательство
      перед пайщиком на счёте расчётов. Признание или возврат — позже.

  - ledger_code: o.reg.setmin
    human_name: Зачисление минимального паевого взноса по решению совета
    wallet_op: TRANSFER
    wallet_from: w.reg.pend
    wallet_to: w.reg.minshr
    debit: 76
    credit: 80
    amount_ref: candidate.minimum
    triggered_by: registrator::confirmreg
    description: >
      Признание минимального паевого взноса по решению совета. Сумма
      `candidate.minimum` переносится с кошелька ожидания (w.reg.pend) на
      «Минимальный паевой взнос» (w.reg.minshr); двойная запись Дт 76 / Кт 80 —
      стартовый вклад в паевой фонд.

  - ledger_code: o.reg.setent
    human_name: Зачисление вступительного взноса по решению совета
    wallet_op: TRANSFER
    wallet_from: w.reg.pend
    wallet_to: w.reg.entry
    debit: 76
    credit: 86
    amount_ref: candidate.initial
    triggered_by: registrator::confirmreg
    description: >
      Признание вступительного взноса по решению совета. Сумма
      `candidate.initial` переносится с кошелька ожидания (w.reg.pend) на
      «Вступительные взносы» (w.reg.entry); двойная запись Дт 76 / Кт 86 —
      целевые поступления в кооперативный фонд.

# ── Секция 7. Связи ─────────────────────────────────────────────────────────
related:
  - process_type: p.reg.refund
    id: public_registrator_refund_process
    relation: triggers
    note: >
      При отрицательном решении совета процесс приёма прерывается и
      запускается «Возврат регистрационного взноса» (p.reg.refund): сумма,
      стоящая на расчётах с пайщиком (счёт 76), возвращается кандидату.

  - process_type: p.wal.depo
    id: public_wallet_deposit_process
    relation: triggers
    note: >
      После статуса `active` пайщик может вносить дополнительные паевые
      взносы через процесс «Внесение паевого взноса» (p.wal.depo). Каждый
      такой взнос пополняет кошелёк SHARE_FUND_PAY (w.wal.share) — основу
      для дальнейших операций пайщика (займы, проекты, выходы).

  - process_type: p.wal.wthdrw
    id: public_wallet_withdraw_process
    relation: affects
    note: >
      Выход из кооператива (или частичный возврат паевого взноса деньгами)
      оформляется обратным процессом «Возврат паевого взноса»
      (p.wal.wthdrw) — он списывает средства с кошелька SHARE_FUND_PAY
      по авторизации совета.
