Merge branch 'dev' into feat/membership-exit
Втягиваем инфраструктуру исходящих платежей (шасси расходов C28) для создания возврата паевого взноса в gateway при выходе пайщика. Конфликты (объединены обе стороны): - gateway payment-type.enum / payment-domain.entity: MEMBERSHIP_EXIT + EXPENSE* - zeus-клиенты (controller, sdk): взята версия dev, регенерация следом Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -82,3 +82,8 @@ export const _apps = {
|
||||
production: 'apps',
|
||||
testnet: 'apps',
|
||||
} as const
|
||||
|
||||
export const _expense = {
|
||||
production: 'expense',
|
||||
testnet: 'expense',
|
||||
} as const
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import * as Permissions from '../../../common/permissions'
|
||||
import type * as Capital from '../../../interfaces/capital'
|
||||
import { Actors } from '../../../common'
|
||||
|
||||
export const authorizations = [{ permissions: [Permissions.active], actor: Actors._chairman }] as const
|
||||
|
||||
/**
|
||||
* Имя действия. Инициатор программного расхода: резервирует
|
||||
* `program_expense_pool` и шлёт inline action в шасси `expense::createexp`
|
||||
* с callback handler `{capital, onpgexpdone}`.
|
||||
*/
|
||||
export const actionName = 'createpgexp'
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
export type ICreateProgramExpense = Capital.ICreatepgexp
|
||||
@@ -48,6 +48,12 @@ export * as CommitDecline from './commitDecline'
|
||||
// Долги
|
||||
export * as CreateDebt from './createDebt'
|
||||
|
||||
// Расходы программы через шасси expense (Эпик 5 шасси)
|
||||
// capital — инициатор+callback, весь flow обслуживает контракт expense.
|
||||
export * as TopupProgramExpense from './topupProgramExpense'
|
||||
export * as CreateProgramExpense from './createProgramExpense'
|
||||
export * as OnProgramExpenseDone from './onProgramExpenseDone'
|
||||
|
||||
// Регистрация участников
|
||||
export * as RegisterContributor from './registerContributor'
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import * as Permissions from '../../../common/permissions'
|
||||
import type * as Capital from '../../../interfaces/capital'
|
||||
import { Actors } from '../../../common'
|
||||
|
||||
/**
|
||||
* Self-callback контракта `capital`. Шасси `expense` шлёт inline action
|
||||
* на capital после терминального перехода (CLOSED либо DECLINED).
|
||||
* Authority — `capital@active`, не пользователь.
|
||||
*/
|
||||
export const authorizations = [{ permissions: [Permissions.active], actor: Actors._contract }] as const
|
||||
|
||||
/**
|
||||
* Имя действия. Callback от шасси expense на финализацию program-расхода.
|
||||
* status == ExpenseProposalStatus.CLOSED (4) → списать `total_actual` из
|
||||
* `program_expense_reserved`, остаток вернуть в `program_expense_pool`,
|
||||
* удалить запись `progexpenses`.
|
||||
* status == ExpenseProposalStatus.DECLINED (5) → вернуть весь резерв в пул,
|
||||
* удалить запись.
|
||||
*/
|
||||
export const actionName = 'onpgexpdone'
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
export type IOnProgramExpenseDone = Capital.IOnpgexpdone
|
||||
@@ -0,0 +1,17 @@
|
||||
import * as Permissions from '../../../common/permissions'
|
||||
import type * as Capital from '../../../interfaces/capital'
|
||||
import { Actors } from '../../../common'
|
||||
|
||||
export const authorizations = [{ permissions: [Permissions.active], actor: Actors._chairman }] as const
|
||||
|
||||
/**
|
||||
* Имя действия. Пополнение пула программных расходов из доступного остатка
|
||||
* `global_available_invest_pool`. Председатель решает сколько денег из
|
||||
* инвестиционного пула программы перевести в пул, доступный для расходов.
|
||||
*/
|
||||
export const actionName = 'topupprogexp'
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
export type ITopupProgramExpense = Capital.ITopupprogexp
|
||||
@@ -6,6 +6,7 @@ export * as Commits from './commits'
|
||||
export * as Contributors from './contributors'
|
||||
export * as Debts from './debts'
|
||||
export * as Expenses from './expenses'
|
||||
export * as ProgramExpenses from './programExpenses'
|
||||
export * as Invests from './invests'
|
||||
export * as ProgramInvests from './programInvests'
|
||||
export * as ProgramProperties from './programProperties'
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import type * as Capital from '../../../interfaces/capital'
|
||||
import { Actors } from '../../../common'
|
||||
|
||||
/**
|
||||
* Имя таблицы
|
||||
*/
|
||||
export const tableName = 'progexpenses'
|
||||
|
||||
/**
|
||||
* Таблица хранится в {@link Actors._coopname | области памяти кооператива}.
|
||||
*/
|
||||
export const scope = Actors._coopname
|
||||
|
||||
/**
|
||||
* @interface
|
||||
* Таблица содержит информацию о расходах программы (Благорост Эпик B).
|
||||
*/
|
||||
export type IProgramExpense = Capital.IProgramExpense
|
||||
@@ -0,0 +1,14 @@
|
||||
import * as Permissions from '../../../common/permissions'
|
||||
import type * as Expense from '../../../interfaces/expense'
|
||||
import { Actors } from '../../../common'
|
||||
|
||||
/**
|
||||
* authexp — авторизация СЗ советом (signact2 decision_doc, type=2011).
|
||||
* CREATED → AUTHORIZED. См. expense.hpp::authexp.
|
||||
*/
|
||||
export const authorizations = [{ permissions: [Permissions.active], actor: Actors._chairman }] as const
|
||||
|
||||
export const actionName = 'authexp'
|
||||
|
||||
/** @interface */
|
||||
export type IAuthExp = Expense.IAuthexp
|
||||
@@ -0,0 +1,15 @@
|
||||
import * as Permissions from '../../../common/permissions'
|
||||
import type * as Expense from '../../../interfaces/expense'
|
||||
import { Actors } from '../../../common'
|
||||
|
||||
/**
|
||||
* closeexp — финализация СЗ-отчёта советом. REPORT_SUBMITTED → CLOSED.
|
||||
* При заполненном callback — inline action (capital::createrid для Благороста).
|
||||
* См. expense.hpp::closeexp.
|
||||
*/
|
||||
export const authorizations = [{ permissions: [Permissions.active], actor: Actors._chairman }] as const
|
||||
|
||||
export const actionName = 'closeexp'
|
||||
|
||||
/** @interface */
|
||||
export type ICloseExp = Expense.ICloseexp
|
||||
@@ -0,0 +1,14 @@
|
||||
import * as Permissions from '../../../common/permissions'
|
||||
import type * as Expense from '../../../interfaces/expense'
|
||||
import { Actors } from '../../../common'
|
||||
|
||||
/**
|
||||
* createexp — создаёт и подаёт СЗ-расход. Подписывает создатель
|
||||
* (signact1 statement_doc, type=2010). См. expense.hpp::createexp.
|
||||
*/
|
||||
export const authorizations = [{ permissions: [Permissions.active], actor: Actors._username }] as const
|
||||
|
||||
export const actionName = 'createexp'
|
||||
|
||||
/** @interface */
|
||||
export type ICreateExp = Expense.ICreateexp
|
||||
@@ -0,0 +1,14 @@
|
||||
import * as Permissions from '../../../common/permissions'
|
||||
import type * as Expense from '../../../interfaces/expense'
|
||||
import { Actors } from '../../../common'
|
||||
|
||||
/**
|
||||
* declexp — отклонение СЗ-предложения. CREATED/REPORT_SUBMITTED → DECLINED.
|
||||
* Capitalization Благороста НЕ запускается. См. expense.hpp::declexp.
|
||||
*/
|
||||
export const authorizations = [{ permissions: [Permissions.active], actor: Actors._chairman }] as const
|
||||
|
||||
export const actionName = 'declexp'
|
||||
|
||||
/** @interface */
|
||||
export type IDeclineExp = Expense.IDeclexp
|
||||
@@ -0,0 +1,11 @@
|
||||
// Actions контракта expense (см. components/contracts/cpp/expense/expense.hpp).
|
||||
// MVP: 8 actions для шасси расходов цифрового кооператива.
|
||||
|
||||
export * as CreateExp from './createExp'
|
||||
export * as AuthExp from './authExp'
|
||||
export * as DeclineExp from './declineExp'
|
||||
export * as PayExp from './payExp'
|
||||
export * as ReportExp from './reportExp'
|
||||
export * as CloseExp from './closeExp'
|
||||
export * as ReturnExp from './returnExp'
|
||||
export * as OverspendExp from './overspendExp'
|
||||
@@ -0,0 +1,15 @@
|
||||
import * as Permissions from '../../../common/permissions'
|
||||
import type * as Expense from '../../../interfaces/expense'
|
||||
import { Actors } from '../../../common'
|
||||
|
||||
/**
|
||||
* overspendexp — доплата при перерасходе ADVANCE.
|
||||
* Контракт зовёт Ledger2::apply(OVERSPEND) + сразу Ledger2::apply(ADVANCE_REPORT) одной транзакцией.
|
||||
* См. expense.hpp::overspendexp.
|
||||
*/
|
||||
export const authorizations = [{ permissions: [Permissions.active], actor: Actors._chairman }] as const
|
||||
|
||||
export const actionName = 'overspendexp'
|
||||
|
||||
/** @interface */
|
||||
export type IOverspendExp = Expense.IOverspendexp
|
||||
@@ -0,0 +1,15 @@
|
||||
import * as Permissions from '../../../common/permissions'
|
||||
import type * as Expense from '../../../interfaces/expense'
|
||||
import { Actors } from '../../../common'
|
||||
|
||||
/**
|
||||
* payexp — оплата item: ADVANCE (выдача аванса) или DIRECT (прямая оплата).
|
||||
* Контракт зовёт Ledger2::apply(operation_code, actual_amount).
|
||||
* Для DIRECT сразу за payexp идёт фоновый reportexp. См. expense.hpp::payexp.
|
||||
*/
|
||||
export const authorizations = [{ permissions: [Permissions.active], actor: Actors._chairman }] as const
|
||||
|
||||
export const actionName = 'payexp'
|
||||
|
||||
/** @interface */
|
||||
export type IPayExp = Expense.IPayexp
|
||||
@@ -0,0 +1,14 @@
|
||||
import * as Permissions from '../../../common/permissions'
|
||||
import type * as Expense from '../../../interfaces/expense'
|
||||
import { Actors } from '../../../common'
|
||||
|
||||
/**
|
||||
* reportexp — закрытие ADVANCE-item чеком. Контракт зовёт Ledger2::apply(ADVANCE_REPORT).
|
||||
* Все items REPORTED → proposal становится REPORT_SUBMITTED. См. expense.hpp::reportexp.
|
||||
*/
|
||||
export const authorizations = [{ permissions: [Permissions.active], actor: Actors._username }] as const
|
||||
|
||||
export const actionName = 'reportexp'
|
||||
|
||||
/** @interface */
|
||||
export type IReportExp = Expense.IReportexp
|
||||
@@ -0,0 +1,14 @@
|
||||
import * as Permissions from '../../../common/permissions'
|
||||
import type * as Expense from '../../../interfaces/expense'
|
||||
import { Actors } from '../../../common'
|
||||
|
||||
/**
|
||||
* returnexp — возврат неиспользованного ADVANCE-остатка.
|
||||
* Контракт зовёт Ledger2::apply(ADVANCE_RETURN). См. expense.hpp::returnexp.
|
||||
*/
|
||||
export const authorizations = [{ permissions: [Permissions.active], actor: Actors._username }] as const
|
||||
|
||||
export const actionName = 'returnexp'
|
||||
|
||||
/** @interface */
|
||||
export type IReturnExp = Expense.IReturnexp
|
||||
@@ -0,0 +1,9 @@
|
||||
import * as contractNames from '../../common/names'
|
||||
|
||||
export * as Actions from './actions'
|
||||
export * as Tables from './tables'
|
||||
|
||||
/** @private */
|
||||
export * as Interfaces from '../../interfaces/expense'
|
||||
|
||||
export const contractName = contractNames._expense
|
||||
@@ -0,0 +1 @@
|
||||
export * as Proposals from './proposals'
|
||||
@@ -0,0 +1,13 @@
|
||||
import type * as Expense from '../../../interfaces/expense'
|
||||
import { Actors } from '../../../common'
|
||||
|
||||
/**
|
||||
* Таблица СЗ-расходов. Scope = coopname.
|
||||
* On-chain индексы: byhash (proposal_hash), byusername (username), bystatus (status).
|
||||
*/
|
||||
export const tableName = 'proposals'
|
||||
|
||||
export const scope = Actors._coopname
|
||||
|
||||
/** @interface */
|
||||
export type IProposal = Expense.IProposal
|
||||
@@ -94,3 +94,13 @@ export * as MeetContract from './meet'
|
||||
* Деплоится на корневой KE-цепи и обслуживает несколько подсетей одновременно.
|
||||
*/
|
||||
export * as AppsContract from './apps'
|
||||
|
||||
/**
|
||||
* Смарт-контракт шасси расходов цифрового кооператива (MVP — Благорост).
|
||||
*
|
||||
* Универсальный движок СЗ-расходов: principal storage = proposal с массивом items,
|
||||
* operation_code из ledger2 OPERATION_REGISTRY передаётся в payexp,
|
||||
* callback на финализацию задаётся при createexp (контракт+action+data).
|
||||
* См. components/contracts/cpp/expense/expense.hpp (C28-29 v3).
|
||||
*/
|
||||
export * as ExpenseContract from './expense'
|
||||
|
||||
@@ -112,6 +112,18 @@ export interface IGenerate extends Omit<Partial<IMetaDocument>, 'title'> {
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
/**
|
||||
* Зарезервированная ссылка на приватный payload документа.
|
||||
* Action конкретного документа расширяет этот интерфейс, если хочет
|
||||
* хранить персональные/приватные данные off-chain — payload лежит в
|
||||
* коллекции `doc_private_data` фабрики, on-chain публикуется только
|
||||
* `doc_data_hash`. См. раздел «Document Generation Pattern: doc_data»
|
||||
* в архитектуре.
|
||||
*/
|
||||
export interface IDocDataRef {
|
||||
doc_data_hash?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Интерфейс генерации заявления на вступление в кооператив
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
import type { IDocDataRef, IGenerate, IMetaDocument } from '../../document'
|
||||
import type { ICommonUser, ICooperativeData, IVars } from '../../model'
|
||||
|
||||
export const registry_id = 2010
|
||||
|
||||
export type ExpenseItemRecipientType = 'SELF' | 'MEMBER' | 'ORG'
|
||||
export type ExpenseItemPaymentMechanics = 'ADVANCE' | 'DIRECT'
|
||||
|
||||
/**
|
||||
* Публичная часть позиции расхода — единственное, что публикуется в meta
|
||||
* документа on-chain. Реквизиты получателя, его имя и назначение платежа
|
||||
* сюда НЕ входят — они приватны (см. {@link IExpensePrivateItem}).
|
||||
*/
|
||||
export interface IExpenseItem {
|
||||
number: string
|
||||
description: string
|
||||
amount: string
|
||||
recipient_type: ExpenseItemRecipientType
|
||||
mechanics: ExpenseItemPaymentMechanics
|
||||
}
|
||||
|
||||
/**
|
||||
* Приватная часть позиции — НЕ публикуется в блокчейн. Имя получателя,
|
||||
* его банковские реквизиты и назначение платежа сохраняются off-chain в
|
||||
* `doc_private_data` фабрики; в meta документа едет только `doc_data_hash`.
|
||||
* Корреляция с публичной позицией — по `number`.
|
||||
*/
|
||||
export interface IExpensePrivateItem {
|
||||
number: string
|
||||
recipient_name?: string
|
||||
requisites?: string
|
||||
/** Назначение платежа — отдельной строкой после реквизитов (для оплаты по счёту) */
|
||||
payment_purpose?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Приватный payload СЗ-сметы целиком (off-chain). Сохраняется в
|
||||
* `DocDataService` фабрики, адресуется публичным `doc_data_hash`.
|
||||
* См. раздел «Document Generation Pattern: doc_data» в архитектуре.
|
||||
*/
|
||||
export interface PrivateData {
|
||||
items: IExpensePrivateItem[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Позиция в модели рендера — публичная + приватная части, склеенные фабрикой
|
||||
* по `number` при генерации документа. Шаблон обращается к полям как `item.*`.
|
||||
*/
|
||||
export interface IExpenseRenderItem extends IExpenseItem {
|
||||
recipient_name?: string
|
||||
requisites?: string
|
||||
payment_purpose?: string
|
||||
}
|
||||
|
||||
export interface IExpenseProposalHeader {
|
||||
description: string
|
||||
total_amount: string
|
||||
items_count: number
|
||||
source_wallet: string
|
||||
/** Срок исполнения («в срок до»), формат DD.MM.YYYY — передаётся при создании расхода */
|
||||
deadline?: string
|
||||
/** Фонд списания в дательном падеже («по …») — подставляет сервер из параметров шасси расходов */
|
||||
fund_name?: string
|
||||
}
|
||||
|
||||
export interface Action extends IGenerate, IDocDataRef {
|
||||
proposal_hash: string
|
||||
proposal: IExpenseProposalHeader
|
||||
/** Публичные позиции расхода — без реквизитов/имени/назначения (они в doc_data). */
|
||||
items: IExpenseItem[]
|
||||
/** sha256 приватного payload (PrivateData) — реквизиты/имя/назначение off-chain. */
|
||||
doc_data_hash: string
|
||||
}
|
||||
|
||||
export type Meta = IMetaDocument & Action
|
||||
|
||||
export interface Model {
|
||||
meta: IMetaDocument
|
||||
coop: ICooperativeData
|
||||
user: ICommonUser
|
||||
vars: IVars
|
||||
proposal_hash: string
|
||||
/** Короткий идентификатор СЗ (первые 16 символов хэша, uppercase) — для шапки документа */
|
||||
proposal_short_hash: string
|
||||
proposal: IExpenseProposalHeader
|
||||
/** Позиции с подмешанной приватной частью (фабрика склеивает по number из doc_data). */
|
||||
items: IExpenseRenderItem[]
|
||||
}
|
||||
|
||||
export const title = 'Служебная записка-смета о расходах'
|
||||
export const description = 'Заявка-смета председателю кооператива на финансирование расходов по программе. Содержит описание цели и массив позиций расхода.'
|
||||
|
||||
// Вёрстка по канону документов реестра (см. 1040): без <style>-блока — превью
|
||||
// его не применяет; только inline text-align на div-обёртках. Шапка-адресат
|
||||
// справа, центрированный заголовок с идентификатором (= proposal_hash, по нему
|
||||
// записку можно найти), позиции — нумерованным списком: описание и сумма,
|
||||
// затем построчно получатель, реквизиты и назначение платежа (для кассира).
|
||||
// Кошелёк-источник в документе не указывается.
|
||||
export const context = `<div class="digital-document"><div style="text-align: right"><p>{% trans 'TO_COUNCIL' %} {{vars.full_abbr_genitive}} «{{vars.name}}»</p><p>{% trans 'FROM_MEMBER' %} {{ user.full_name_or_short_name }}</p></div><div style="text-align: center"><h2>{% trans 'PROPOSAL_TITLE' %} № {{ proposal_short_hash }}</h2></div><p style="text-align: right">{{ coop.city }}, {{ meta.created_at }}</p><p>{% trans 'BODY_INTRO' %}{% if proposal.fund_name %} {% trans 'BY_FUND' %} {{ proposal.fund_name }}{% endif %} {% trans 'IN_TOTAL' %} {{ proposal.total_amount }}{% if proposal.deadline %} {% trans 'DUE_BY' %} {{ proposal.deadline }}{% endif %}, {% trans 'BODY_NAMELY' %}:</p>{% for item in items %}<div style="padding-top: 10px"><p><strong>{{ item.number }}. {{ item.description }} — {{ item.amount }} ({% if item.mechanics == 'ADVANCE' %}{% trans 'MECH_ADVANCE' %}{% else %}{% trans 'MECH_DIRECT' %}{% endif %})</strong></p><p>{% trans 'ITEM_RECIPIENT' %}: {% if item.recipient_type == 'SELF' %}{{ user.full_name_or_short_name }}{% else %}{{ item.recipient_name }}{% endif %}</p>{% if item.requisites %}<p>{% trans 'ITEM_REQUISITES' %}: {{ item.requisites }}</p>{% endif %}{% if item.payment_purpose %}<p>{% trans 'ITEM_PAYMENT_PURPOSE' %}: {{ item.payment_purpose }}</p>{% endif %}</div>{% endfor %}<p>{% trans 'PURPOSE' %}: {{ proposal.description }}</p><div style="padding-top: 30px"><p>{{ user.full_name_or_short_name }}</p><p>{% trans 'SIGNED_DIGITALLY' %}</p></div></div>`
|
||||
|
||||
export const translations = {
|
||||
ru: {
|
||||
TO_COUNCIL: 'В Совет',
|
||||
FROM_MEMBER: 'от пайщика',
|
||||
PROPOSAL_TITLE: 'СЛУЖЕБНАЯ ЗАПИСКА',
|
||||
BODY_INTRO: 'Прошу согласовать списание затрат',
|
||||
BY_FUND: 'по',
|
||||
IN_TOTAL: 'в общей сумме',
|
||||
DUE_BY: 'в срок до',
|
||||
BODY_NAMELY: 'а именно',
|
||||
MECH_ADVANCE: 'аванс под отчёт',
|
||||
MECH_DIRECT: 'оплата по счёту',
|
||||
ITEM_RECIPIENT: 'Получатель',
|
||||
ITEM_REQUISITES: 'Реквизиты',
|
||||
ITEM_PAYMENT_PURPOSE: 'Назначение платежа',
|
||||
PURPOSE: 'Цель расходов',
|
||||
SIGNED_DIGITALLY: 'подписано электронной подписью',
|
||||
},
|
||||
}
|
||||
|
||||
export const exampleData = {
|
||||
coop: { city: 'Москва' },
|
||||
meta: { created_at: '02.06.2026 14:00' },
|
||||
vars: { full_abbr_genitive: 'ПК', name: 'Восход' },
|
||||
user: { full_name_or_short_name: 'Иванов И.И.' },
|
||||
proposal_hash: '55c470039a8c53ce1b4b6e842fe8063ab3d5b85ba2ba8ab0ae6e30be3ad328b7',
|
||||
proposal_short_hash: '55C470039A8C53CE',
|
||||
proposal: {
|
||||
description: 'Закупка хостинга и бухгалтерских услуг на июнь 2026',
|
||||
total_amount: '15000.00 RUB',
|
||||
items_count: 2,
|
||||
source_wallet: 'w.cap.bla',
|
||||
deadline: '30.06.2026',
|
||||
fund_name: 'Фонду хозяйственной деятельности',
|
||||
},
|
||||
items: [
|
||||
{
|
||||
number: '1',
|
||||
description: 'Аренда серверов Yandex Cloud (тариф S, июнь)',
|
||||
amount: '12000.00 RUB',
|
||||
recipient_type: 'ORG',
|
||||
mechanics: 'DIRECT',
|
||||
recipient_name: 'ООО «Яндекс.Облако»',
|
||||
requisites: 'ИНН 7704414297, р/с 40702810000000000000, БИК 044525000',
|
||||
payment_purpose: 'Оплата по счёту № 814 от 01.06.2026 за аренду серверов',
|
||||
},
|
||||
{
|
||||
number: '2',
|
||||
description: 'Канцелярия для офиса',
|
||||
amount: '3000.00 RUB',
|
||||
recipient_type: 'SELF',
|
||||
mechanics: 'ADVANCE',
|
||||
recipient_name: '',
|
||||
requisites: 'Банковский перевод: счёт 40817810000000000000, Банк ВТБ (ПАО), БИК 044525187',
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
import type { IDecisionData, IGenerate, IMetaDocument } from '../../document'
|
||||
import type { ICooperativeData, IVars } from '../../model'
|
||||
import type { IExpenseItem, IExpenseProposalHeader } from '../2010.ExpenseProposalStatement'
|
||||
|
||||
export const registry_id = 2011
|
||||
|
||||
export type ExpenseProposalDecisionKind = 'approve' | 'decline'
|
||||
|
||||
/** Резолюция совета по СЗ: утвердить / отказать (+ причина отказа). */
|
||||
export interface IExpenseProposalDecisionBody {
|
||||
kind: ExpenseProposalDecisionKind
|
||||
reason?: string
|
||||
}
|
||||
|
||||
export interface Action extends IGenerate {
|
||||
proposal_hash: string
|
||||
/** Идентификатор решения совета (повестка) — источник данных голосования */
|
||||
decision_id: number
|
||||
proposal: IExpenseProposalHeader
|
||||
items: IExpenseItem[]
|
||||
resolution: IExpenseProposalDecisionBody
|
||||
}
|
||||
|
||||
export type Meta = IMetaDocument & Action
|
||||
|
||||
export interface Model {
|
||||
meta: IMetaDocument
|
||||
coop: ICooperativeData
|
||||
vars: IVars
|
||||
/** Данные собрания совета (кворум, голоса) — канон протоколов решений */
|
||||
decision: IDecisionData
|
||||
proposal_hash: string
|
||||
/** Короткий идентификатор СЗ (первые 16 символов хэша, uppercase) */
|
||||
proposal_short_hash: string
|
||||
proposal: IExpenseProposalHeader
|
||||
items: IExpenseItem[]
|
||||
resolution: IExpenseProposalDecisionBody
|
||||
}
|
||||
|
||||
export const title = 'Протокол решения совета о расходах'
|
||||
export const description = 'Протокол собрания совета по служебной записке-смете о расходах. Структура — канон протоколов решений совета (кворум, голоса, повестка); меняется только содержание вопроса и принятого решения.'
|
||||
|
||||
// Вёрстка — точная копия канона протоколов решений совета (600.FreeDecision):
|
||||
// форма/место/дата/время, члены совета, правомочность, повестка, голосование,
|
||||
// РЕШИЛИ, подпись председателя. Отличается только содержание вопроса повестки
|
||||
// и принятого решения (смета расходов по СЗ).
|
||||
export const context = '<style> \nh1 {\nmargin: 0px; \ntext-align:center;\n}\nh3{\nmargin: 0px;\npadding-top: 15px;\n}\n.about {\npadding: 20px;\n}\n.about p{\nmargin: 0px;\n}\n.signature {\npadding-top: 20px;\n}\n.digital-document {\npadding: 20px;\nwhite-space: pre-wrap;\n}\n.subheader {\npadding-bottom: 20px; \n}\ntable {\n width: 100%;\n border-collapse: collapse;\n}\nth, td {\n border: 1px solid #ccc;\n padding: 8px;\n text-align: left;\n word-wrap: break-word; \n overflow-wrap: break-word; \n}\nth {\n background-color: #f4f4f4;\n width: 30%;\n}\n</style>\n\n<div class="digital-document"><h1 class="header">{% trans \'protocol_number\', decision.id %}</h1>\n<p style="text-align:center" class="subheader">{% trans \'council_meeting_name\' %} {{vars.full_abbr_genitive}} "{{vars.name}}"</p>\n<p style="text-align: right"> {{ meta.created_at }}, {{ coop.city }}</p>\n<table class="about">\n<tbody>\n<tr>\n<th>{% trans \'meeting_format\' %}</th>\n<td>{% trans \'meeting_format_value\' %}</td>\n</tr>\n<tr>\n<th>{% trans \'meeting_place\' %}</th>\n<td>{{ coop.full_address }}</td>\n</tr>\n<tr>\n<th>{% trans \'meeting_date\' %}</th>\n<td>{{ decision.date }}</td>\n</tr>\n<tr>\n<th>{% trans \'opening_time\' %}</th>\n<td>{{ decision.time }}</td>\n</tr>\n</tbody>\n</table>\n<h3>{% trans \'council_members\' %}</h3>\n<table>\n<tbody>\n{% for member in coop.members %}\n<tr>\n<th>{% if member.is_chairman %}{% trans \'chairman_of_the_council\' %}{% else %}{% trans \'member_of_the_council\' %}{% endif %}</th>\n<td>{{ member.last_name }} {{ member.first_name }} {{ member.middle_name }}</td>\n</tr>\n{% endfor %}\n</tbody>\n</table>\n<h3>{% trans \'meeting_legality\' %} </h3>\n<p>{% trans \'voting_results\', decision.voters_percent %} {% trans \'quorum\' %} {% trans \'chairman_of_the_meeting\', coop.chairman.last_name, coop.chairman.first_name, coop.chairman.middle_name %}.</p>\n<h3>{% trans \'agenda\' %}</h3>\n<table>\n<tbody>\n<tr>\n<th>№</th>\n<td>{% trans \'question\' %}</td>\n</tr>\n<tr>\n<th>1</th>\n<td>{% trans \'question_body\', proposal_short_hash, proposal.total_amount %} {% trans \'question_purpose\' %}: {{ proposal.description }}</td>\n</tr>\n</tbody>\n</table>\n<h3>{% trans \'voting\' %}</h3>\n<p>{% trans \'vote_results\' %} </p><table>\n<tbody>\n<tr>\n<th>{% trans \'votes_for\' %}</th>\n<td>{{ decision.votes_for }}</td>\n</tr>\n<tr>\n<th>{% trans \'votes_against\' %}</th>\n<td>{{ decision.votes_against }}</td>\n</tr>\n<tr>\n<th>{% trans \'votes_abstained\' %}</th>\n<td>{{ decision.votes_abstained }}</td>\n</tr>\n</tbody>\n</table>\n<h3>{% trans \'decision_made\' %}</h3>\n<table>\n<tbody>\n<tr>\n<th>№</th>\n<td>{% trans \'decision\' %}</td>\n</tr>\n<tr>\n<th>1</th>\n<td>{% if resolution.kind == \'approve\' %}<p>{% trans \'decision_approve\', proposal_short_hash, proposal.total_amount %}{% if proposal.deadline %} {% trans \'decision_deadline\', proposal.deadline %}{% endif %}{% trans \'decision_namely\' %}:</p>{% for item in items %}<p>{{ item.number }}. {{ item.description }} — {{ item.amount }} ({% if item.mechanics == \'ADVANCE\' %}{% trans \'mech_advance\' %}{% else %}{% trans \'mech_direct\' %}{% endif %})</p>{% endfor %}{% else %}<p>{% trans \'decision_decline\', proposal_short_hash %}{% if resolution.reason %} {% trans \'decline_reason\' %}: {{ resolution.reason }}{% endif %}</p>{% endif %}</td>\n</tr>\n</tbody>\n</table>\n<hr>\n<p>{% trans \'closing_time\', decision.time %}</p>\n<div class="signature"><p>{% trans \'signature\' %}</p><p>{% trans \'chairman\' %} {{ coop.chairman.last_name }} {{ coop.chairman.first_name }} {{ coop.chairman.middle_name }}</p></div></div>\n'
|
||||
|
||||
export const translations = {
|
||||
ru: {
|
||||
meeting_format: 'Форма',
|
||||
meeting_date: 'Дата',
|
||||
meeting_place: 'Место',
|
||||
opening_time: 'Время открытия',
|
||||
council_members: 'ЧЛЕНЫ СОВЕТА',
|
||||
voting_results: 'Количество голосов составляет {0}% от общего числа членов Совета.',
|
||||
meeting_legality: 'СОБРАНИЕ ПРАВОМОЧНО',
|
||||
chairman_of_the_meeting: 'Председатель собрания совета: {0} {1} {2}',
|
||||
agenda: 'ПОВЕСТКА ДНЯ',
|
||||
vote_results: 'По первому вопросу повестки дня проголосовали:',
|
||||
decision_made: 'РЕШИЛИ',
|
||||
closing_time: 'Время закрытия собрания совета: {0}.',
|
||||
protocol_number: 'ПРОТОКОЛ № {0}',
|
||||
council_meeting_name: 'Собрания Совета',
|
||||
chairman_of_the_council: 'Председатель совета',
|
||||
signature: 'Документ подписан электронной подписью.',
|
||||
chairman: 'Председатель',
|
||||
quorum: 'Кворум для решения поставленных на повестку дня вопросов имеется.',
|
||||
voting: 'ГОЛОСОВАНИЕ',
|
||||
meeting_format_value: 'Заочная',
|
||||
member_of_the_council: 'Член совета',
|
||||
question: 'Вопрос',
|
||||
votes_for: 'ЗА',
|
||||
votes_against: 'ПРОТИВ',
|
||||
votes_abstained: 'ВОЗДЕРЖАЛСЯ',
|
||||
decision: 'Решение',
|
||||
question_body: 'Рассмотрение служебной записки-сметы о расходах № {0} на общую сумму {1}.',
|
||||
question_purpose: 'Цель расходов',
|
||||
decision_approve: 'Утвердить расходы по служебной записке № {0} в общей сумме {1}',
|
||||
decision_deadline: 'со сроком исполнения до {0}',
|
||||
decision_namely: ', а именно',
|
||||
mech_advance: 'аванс под отчёт',
|
||||
mech_direct: 'оплата по счёту',
|
||||
decision_decline: 'Отказать в утверждении расходов по служебной записке № {0}.',
|
||||
decline_reason: 'Основание отказа',
|
||||
},
|
||||
}
|
||||
|
||||
export const exampleData = {
|
||||
meta: {
|
||||
created_at: '03.06.2026 11:00',
|
||||
},
|
||||
coop: {
|
||||
city: 'Москва',
|
||||
full_address: 'г. Москва, ул. Смольная, д. 3, оф. 84',
|
||||
chairman: {
|
||||
last_name: 'Муравьев',
|
||||
first_name: 'Алексей',
|
||||
middle_name: 'Николаевич',
|
||||
},
|
||||
},
|
||||
decision: {
|
||||
time: '11:00',
|
||||
date: '03.06.2026',
|
||||
votes_for: '3',
|
||||
votes_against: '0',
|
||||
votes_abstained: '0',
|
||||
voters_percent: '100',
|
||||
id: '15',
|
||||
},
|
||||
member: {
|
||||
is_chairman: true,
|
||||
last_name: 'Муравьев',
|
||||
first_name: 'Алексей',
|
||||
middle_name: 'Николаевич',
|
||||
},
|
||||
vars: {
|
||||
full_abbr_genitive: 'потребительского кооператива',
|
||||
name: 'ВОСХОД',
|
||||
},
|
||||
proposal_hash: '55c470039a8c53ce1b4b6e842fe8063ab3d5b85ba2ba8ab0ae6e30be3ad328b7',
|
||||
proposal_short_hash: '55C470039A8C53CE',
|
||||
proposal: {
|
||||
description: 'Закупка хостинга и бухгалтерских услуг на июнь 2026',
|
||||
total_amount: '15000.00 RUB',
|
||||
items_count: 2,
|
||||
source_wallet: 'w.cap.bla',
|
||||
deadline: '30.06.2026',
|
||||
fund_name: 'Фонду хозяйственной деятельности',
|
||||
},
|
||||
items: [
|
||||
{ number: '1', description: 'Аренда серверов Yandex Cloud', amount: '12000.00 RUB', recipient_type: 'ORG', mechanics: 'DIRECT' },
|
||||
{ number: '2', description: 'Канцелярия для офиса', amount: '3000.00 RUB', recipient_type: 'SELF', mechanics: 'ADVANCE' },
|
||||
],
|
||||
resolution: {
|
||||
kind: 'approve',
|
||||
},
|
||||
}
|
||||
@@ -44,6 +44,10 @@ export * as InitProjectDecision from './1006.InitProjectDecision'
|
||||
export * as ExpenseStatement from './1010.ExpenseStatement'
|
||||
export * as ExpenseDecision from './1011.ExpenseDecision'
|
||||
|
||||
// Шасси расходов (волна 6, MVP-SINGLE) — C28-30
|
||||
export * as ExpenseProposalStatement from './2010.ExpenseProposalStatement'
|
||||
export * as ExpenseProposalDecision from './2011.ExpenseProposalDecision'
|
||||
|
||||
export * as GenerationMoneyInvestStatement from './1020.GenerationMoneyInvestStatement'
|
||||
export * as GenerationMoneyReturnUnusedStatement from './1025.GenerationMoneyReturnUnusedStatement'
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
// Generated by eosio-abi2ts 1.2.2 - eosio::abi/1.2
|
||||
|
||||
import type { IItem as IExpenseProposalItem } from './expense'
|
||||
|
||||
export type IAsset = string
|
||||
export type IName = string
|
||||
export type IChecksum256 = string
|
||||
export type IPublicKey = string
|
||||
export type ISignature = string
|
||||
export type ITimePointSec = string
|
||||
export type IUint8 = number
|
||||
export type IUint32 = number
|
||||
export type IUint64 = number | string
|
||||
export type IFloat64 = number
|
||||
@@ -359,6 +362,8 @@ export interface IDebt {
|
||||
approved_statement: IDocument2
|
||||
authorization: IDocument2
|
||||
memo: string
|
||||
last_pay_error?: string
|
||||
due_at?: ITimePointSec
|
||||
}
|
||||
|
||||
export interface IDebtauthcnfr {
|
||||
@@ -556,6 +561,8 @@ export interface IGlobalState {
|
||||
program_membership_distributed: IAsset
|
||||
program_membership_cumulative_reward_per_share: IFloat64
|
||||
config: IConfig
|
||||
program_expense_pool?: IAsset
|
||||
program_expense_reserved?: IAsset
|
||||
}
|
||||
|
||||
export interface IImportcontrib {
|
||||
@@ -803,6 +810,9 @@ export interface ISegment {
|
||||
available_for_program: IAsset
|
||||
available_for_wallet: IAsset
|
||||
share_percent: IFloat64
|
||||
approved_rate_per_hour?: IAsset
|
||||
approved_hours_per_day?: IUint64
|
||||
active_debts_count?: IUint32
|
||||
}
|
||||
|
||||
export interface ISetconfig {
|
||||
@@ -827,7 +837,7 @@ export interface ISetplan {
|
||||
|
||||
export interface ISettledebt {
|
||||
coopname: IName
|
||||
username: IName
|
||||
debt_hash: IChecksum256
|
||||
amount: IAsset
|
||||
statement: IDocument2
|
||||
}
|
||||
@@ -912,3 +922,63 @@ export interface IVotingData {
|
||||
amounts: IVotingAmounts
|
||||
voting_deadline: ITimePointSec
|
||||
}
|
||||
|
||||
// ─── Эпик 5 (шасси расходов): програмные расходы через шасси expense ──────
|
||||
|
||||
/**
|
||||
* Инициация программного расхода через шасси expense.
|
||||
* capital резервирует пул, шлёт inline action в expense::createexp с
|
||||
* callback handler `{capital, onpgexpdone}`. Шасси обслуживает весь flow
|
||||
* расхода (auth/pay/report/close|decline) и шлёт callback назад.
|
||||
*/
|
||||
export interface ICreatepgexp {
|
||||
coopname: IName
|
||||
expense_hash: IChecksum256
|
||||
creator: IName
|
||||
/** Позиции СЗ-расхода (Expense.IItem из шасси); механика оплаты — per-item (mechanics: ADVANCE | DIRECT). */
|
||||
items: IExpenseProposalItem[]
|
||||
description: string
|
||||
statement: IDocument2
|
||||
}
|
||||
|
||||
/**
|
||||
* Self-callback `capital`. Шасси `expense` дёргает после CLOSED/DECLINED.
|
||||
* status == ExpenseProposalStatus.CLOSED (4) → consume + release остаток + delete.
|
||||
* status == ExpenseProposalStatus.DECLINED (5) → release полностью + delete.
|
||||
*/
|
||||
export interface IOnpgexpdone {
|
||||
coopname: IName
|
||||
expense_hash: IChecksum256
|
||||
status: IUint8
|
||||
total_actual: IAsset
|
||||
/** Произвольный payload от инициатора (на MVP не используется). */
|
||||
data: string
|
||||
}
|
||||
|
||||
export interface ITopupprogexp {
|
||||
coopname: IName
|
||||
amount: IAsset
|
||||
}
|
||||
|
||||
// Таблицы
|
||||
|
||||
/**
|
||||
* Таблица `progexpenses` — целевые расходы программы «Благорост», не привязанные
|
||||
* к проекту. Создаётся в `createpgexp`, удаляется в `onpgexpdone` после
|
||||
* терминального перехода шасси. На MVP approved_statement / authorization
|
||||
* остаются пустыми (флоу подписания делает шасси expense).
|
||||
*/
|
||||
export interface IProgramExpense {
|
||||
id: IUint64
|
||||
coopname: IName
|
||||
username: IName
|
||||
status: IName
|
||||
expense_hash: IChecksum256
|
||||
fund_id: IUint64
|
||||
amount: IAsset
|
||||
description: string
|
||||
expense_statement: IDocument2
|
||||
approved_statement: IDocument2
|
||||
authorization: IDocument2
|
||||
spended_at: ITimePointSec
|
||||
}
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
// Hand-written from components/contracts/cpp/expense/expense.hpp (C28-29 v3, MVP — Благорост).
|
||||
// До появления codegen из ABI этот файл = SoT для cooptypes/expense.
|
||||
// При regen ABI заменить ровно тем же набором имён интерфейсов, не ломая публичный API.
|
||||
|
||||
export type IAsset = string
|
||||
export type IName = string
|
||||
export type IChecksum256 = string
|
||||
export type ITimePointSec = string
|
||||
export type IUint8 = number
|
||||
export type IUint32 = number
|
||||
export type IUint64 = number | string
|
||||
|
||||
/**
|
||||
* Документ document2 (signact1/signact2 — двухподписные акты).
|
||||
* Точная копия C++ struct document2 из components/contracts/cpp/lib/domain/document_core.hpp.
|
||||
*/
|
||||
export interface IDocument2 {
|
||||
version: string
|
||||
hash: IChecksum256
|
||||
doc_hash: IChecksum256
|
||||
meta_hash: IChecksum256
|
||||
meta: string
|
||||
signatures: ISignature2[]
|
||||
}
|
||||
|
||||
export interface ISignature2 {
|
||||
id: IUint32
|
||||
signed_hash: IChecksum256
|
||||
signer: IName
|
||||
public_key: string
|
||||
signature: string
|
||||
signed_at: ITimePointSec
|
||||
meta: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Перечисления expense::* — в TS экспонируются как `number` (uint8), сами литералы
|
||||
* (`enum`) задаются на стороне backend extension (`expense-proposal-status.enum.ts`
|
||||
* + `expense-item-status.enum.ts` + `expense-mechanics.enum.ts` + `expense-recipient-type.enum.ts`).
|
||||
*/
|
||||
|
||||
export interface IItem {
|
||||
item_hash: IChecksum256
|
||||
/** Mechanics (ADVANCE=0, DIRECT=1). */
|
||||
mechanics: IUint8
|
||||
/** RecipientType (SELF=0, MEMBER=1, ORG=2). */
|
||||
recipient_type: IUint8
|
||||
recipient: IName
|
||||
description: string
|
||||
planned_amount: IAsset
|
||||
actual_amount: IAsset
|
||||
/** ItemStatus (APPROVED=0, PAID=1, REPORTED=2, RETURNED=3, OVERSPENT=4). */
|
||||
status: IUint8
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback на финализацию closeexp. Пустой `contract` (`""`) = нет callback.
|
||||
* `data` — base16/hex (eosio bytes) либо base64 в зависимости от транспорта.
|
||||
*/
|
||||
export interface ICallbackHandler {
|
||||
contract: IName
|
||||
action: IName
|
||||
data: string
|
||||
}
|
||||
|
||||
// ─────────────────────────── Actions ───────────────────────────
|
||||
|
||||
/**
|
||||
* createexp — создание и подача СЗ-расхода (signact1 statement_doc, type=2010).
|
||||
*/
|
||||
export interface ICreateexp {
|
||||
coopname: IName
|
||||
username: IName
|
||||
proposal_hash: IChecksum256
|
||||
source_wallet: IName
|
||||
items: IItem[]
|
||||
callback: ICallbackHandler
|
||||
statement: IDocument2
|
||||
}
|
||||
|
||||
/**
|
||||
* authexp — авторизация СЗ советом (signact2 decision_doc, type=2011).
|
||||
* После — CREATED → AUTHORIZED.
|
||||
*/
|
||||
export interface IAuthexp {
|
||||
coopname: IName
|
||||
proposal_hash: IChecksum256
|
||||
decision: IDocument2
|
||||
}
|
||||
|
||||
/**
|
||||
* declexp — отклонение СЗ-предложения (CREATED/REPORT_SUBMITTED → DECLINED).
|
||||
* Capitalization Благороста НЕ запускается.
|
||||
*/
|
||||
export interface IDeclexp {
|
||||
coopname: IName
|
||||
proposal_hash: IChecksum256
|
||||
reason: string
|
||||
}
|
||||
|
||||
/**
|
||||
* payexp — оплата item (ADVANCE = выдача аванса / DIRECT = прямая оплата).
|
||||
* Контракт: Ledger2::apply(operation_code, actual_amount); для DIRECT сразу за payexp — фоновый reportexp.
|
||||
*/
|
||||
export interface IPayexp {
|
||||
coopname: IName
|
||||
proposal_hash: IChecksum256
|
||||
item_hash: IChecksum256
|
||||
actual_amount: IAsset
|
||||
}
|
||||
|
||||
/**
|
||||
* reportexp — закрытие item чеком (только ADVANCE).
|
||||
* Контракт: Ledger2::apply(ADVANCE_REPORT). Все items reported → PARTIALLY_PAID/CLOSED-эскалация
|
||||
* выносится в closeexp.
|
||||
*/
|
||||
export interface IReportexp {
|
||||
coopname: IName
|
||||
proposal_hash: IChecksum256
|
||||
item_hash: IChecksum256
|
||||
}
|
||||
|
||||
/**
|
||||
* closeexp — финализация СЗ-отчёта советом. REPORT_SUBMITTED → CLOSED.
|
||||
* При наличии callback — inline action на (callback.contract, callback.action, callback.data).
|
||||
* **Триггерит capitalization Благороста** (см. capital::createrid через callback).
|
||||
*/
|
||||
export interface ICloseexp {
|
||||
coopname: IName
|
||||
proposal_hash: IChecksum256
|
||||
}
|
||||
|
||||
/**
|
||||
* returnexp — возврат неиспользованного аванса (ADVANCE-остаток).
|
||||
* Контракт: Ledger2::apply(ADVANCE_RETURN).
|
||||
*/
|
||||
export interface IReturnexp {
|
||||
coopname: IName
|
||||
proposal_hash: IChecksum256
|
||||
item_hash: IChecksum256
|
||||
return_amount: IAsset
|
||||
}
|
||||
|
||||
/**
|
||||
* overspendexp — доплата при перерасходе (только ADVANCE).
|
||||
* Контракт: Ledger2::apply(OVERSPEND) → сразу Ledger2::apply(ADVANCE_REPORT) одной транзакцией.
|
||||
*/
|
||||
export interface IOverspendexp {
|
||||
coopname: IName
|
||||
proposal_hash: IChecksum256
|
||||
item_hash: IChecksum256
|
||||
overspend_amount: IAsset
|
||||
}
|
||||
|
||||
// ─────────────────────────── Tables ───────────────────────────
|
||||
|
||||
/**
|
||||
* Таблица `proposals` (scope = coopname).
|
||||
* Индексы on-chain: byhash (proposal_hash), byusername (username), bystatus (status).
|
||||
*/
|
||||
export interface IProposal {
|
||||
id: IUint64
|
||||
coopname: IName
|
||||
proposal_hash: IChecksum256
|
||||
username: IName
|
||||
source_wallet: IName
|
||||
/** ProposalStatus (CREATED=0, AUTHORIZED=1, PARTIALLY_PAID=2, REPORT_SUBMITTED=3, CLOSED=4, DECLINED=5). */
|
||||
status: IUint8
|
||||
items: IItem[]
|
||||
total_planned: IAsset
|
||||
total_actual: IAsset
|
||||
callback: ICallbackHandler
|
||||
statement_doc: IDocument2
|
||||
decision_doc: IDocument2
|
||||
created_at: ITimePointSec
|
||||
updated_at: ITimePointSec
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
export * as Branch from './branch'
|
||||
export * as Capital from './capital'
|
||||
export * as Draft from './draft'
|
||||
export * as Expense from './expense'
|
||||
export * as Fund from './fund'
|
||||
export * as Gateway from './gateway'
|
||||
export * as Ledger from './ledger'
|
||||
|
||||
@@ -108,6 +108,37 @@ export const LEDGER2_OPERATION_REGISTRY: readonly OperationMeta[] = [
|
||||
|
||||
{ code: 'o.cap.cnvbl', process_type: 'p.cap.rid', contract: 'capital', name: 'CONVERT_TO_BLAGO', wallet_op: 'TRANSFER', wallet_from: 'w.cap.gen', wallet_to: 'w.cap.blago', debit: null, credit: null, human_name: 'Конвертация сегмента: РИД → ЦПП «Благорост»' },
|
||||
|
||||
{ code: 'o.cap.pgtop', process_type: 'p.cap.pgexp', contract: 'capital',
|
||||
name: 'PROGRAM_EXPENSE_TOPUP', wallet_op: 'ISSUE', wallet_from: null, wallet_to: 'w.cap.pgexp',
|
||||
debit: null, credit: null,
|
||||
human_name: 'Пополнение пула программных расходов ЦПП «Благорост»' },
|
||||
|
||||
// expense — шасси расходов (оплата СЗ из кооперативного пула расходов)
|
||||
{ code: 'o.exp.blgadv', process_type: 'p.exp.expns', contract: 'expense',
|
||||
name: 'BLAGO_ADVANCE', wallet_op: 'TRANSFER', wallet_from: 'w.cap.pgexp', wallet_to: 'w.exp.adv',
|
||||
debit: 8, credit: 51,
|
||||
human_name: 'Выдача подотчётных из пула расходов ЦПП «Благорост»' },
|
||||
|
||||
{ code: 'o.exp.blgdir', process_type: 'p.exp.expns', contract: 'expense',
|
||||
name: 'BLAGO_DIRECT', wallet_op: 'BURN', wallet_from: 'w.cap.pgexp', wallet_to: null,
|
||||
debit: 8, credit: 51,
|
||||
human_name: 'Прямая оплата из пула расходов ЦПП «Благорост»' },
|
||||
|
||||
{ code: 'o.exp.advrpt', process_type: 'p.exp.expns', contract: 'expense',
|
||||
name: 'ADVANCE_REPORT', wallet_op: 'BURN', wallet_from: 'w.exp.adv', wallet_to: null,
|
||||
debit: null, credit: null,
|
||||
human_name: 'Закрытие подотчёта пайщика по отчёту' },
|
||||
|
||||
{ code: 'o.exp.advret', process_type: 'p.exp.expns', contract: 'expense',
|
||||
name: 'ADVANCE_RETURN', wallet_op: 'TRANSFER', wallet_from: 'w.exp.adv', wallet_to: 'w.cap.pgexp',
|
||||
debit: 51, credit: 8,
|
||||
human_name: 'Возврат неиспользованного подотчёта в пул расходов' },
|
||||
|
||||
{ code: 'o.exp.over', process_type: 'p.exp.expns', contract: 'expense',
|
||||
name: 'OVERSPEND', wallet_op: 'TRANSFER', wallet_from: 'w.cap.pgexp', wallet_to: 'w.exp.adv',
|
||||
debit: 8, credit: 51,
|
||||
human_name: 'Доплата сверх подотчёта (перерасход)' },
|
||||
|
||||
// marketplace
|
||||
{ code: 'o.mkt.supply', process_type: 'p.mkt.reqst', contract: 'marketplace', name: 'CONFIRM_SUPPLY', wallet_op: 'ISSUE', wallet_from: null, wallet_to: 'w.wal.share', debit: 51, credit: 80, human_name: 'Подтверждение поставки' },
|
||||
|
||||
|
||||
@@ -36,6 +36,10 @@ export const LEDGER2_PROCESS_REGISTRY: readonly ProcessMeta[] = [
|
||||
{ type: 'p.cap.prop', contract: 'capital', name: 'PROPERTY', human_name: 'Приём имущественного паевого взноса' },
|
||||
{ type: 'p.cap.preimp', contract: 'capital', name: 'PREIMP', human_name: 'Первичный учёт РИД-взноса до перехода на электронный учёт' },
|
||||
{ type: 'p.cap.wthcap', contract: 'capital', name: 'WTHCAP', human_name: 'Возврат паевого из ЦПП «Благорост» в кошелёк' },
|
||||
{ type: 'p.cap.pgexp', contract: 'capital', name: 'PGEXP', human_name: 'Пополнение пула программных расходов' },
|
||||
|
||||
// expense
|
||||
{ type: 'p.exp.expns', contract: 'expense', name: 'PROPOSAL', human_name: 'Расход по служебной записке' },
|
||||
|
||||
// marketplace
|
||||
{ type: 'p.mkt.reqst', contract: 'marketplace', name: 'REQUEST', human_name: 'Запрос маркетплейса' },
|
||||
|
||||
@@ -24,6 +24,7 @@ export const LEDGER2_WALLET_REGISTRY: readonly WalletMeta[] = [
|
||||
{ name: "w.wal.member", human_name: "ЦК — членская часть пайщика", kind: "USER_SHARED" },
|
||||
{ name: "w.cap.blago", human_name: "ЦПП «Благорост» — единый кошелёк программы у пайщика", kind: "USER_SHARED" },
|
||||
{ name: "w.cap.preimp", human_name: "Первичный учёт РИД-взносов до перехода на электронный учёт", kind: "USER_SHARED" },
|
||||
{ name: "w.exp.adv", human_name: "Подотчётные средства пайщика", kind: "USER_SHARED" },
|
||||
{ name: "w.reg.pend", human_name: "Регистрационный взнос в ожидании решения совета", kind: "USER_SHARED" },
|
||||
{ name: "w.cap.gen", human_name: "ЦПП «Генератор» — единый кошелёк программы", kind: "COOPERATIVE" },
|
||||
{ name: "w.reg.entry", human_name: "Вступительные взносы", kind: "COOPERATIVE" },
|
||||
@@ -35,6 +36,7 @@ export const LEDGER2_WALLET_REGISTRY: readonly WalletMeta[] = [
|
||||
{ name: "w.sov.mnused", human_name: "Использованные минимальные паевые взносы", kind: "COOPERATIVE" },
|
||||
{ name: "w.cap.loan", human_name: "Выданные пайщикам беспроцентные займы", kind: "COOPERATIVE" },
|
||||
{ name: "w.mkt.payout", human_name: "Выплаты поставщикам", kind: "COOPERATIVE" },
|
||||
{ name: "w.cap.pgexp", human_name: "Пул программных расходов ЦПП «Благорост»", kind: "COOPERATIVE" },
|
||||
] as const
|
||||
|
||||
export interface ProgramWalletMapping {
|
||||
@@ -57,5 +59,6 @@ export const LEDGER2_USER_SHARED_PROGRAM_MAPPING: readonly ProgramWalletMapping[
|
||||
{ wallet_name: "w.cap.blago", required_program_id: 4, program_label: "Благорост" },
|
||||
{ wallet_name: "w.cap.gen", required_program_id: 3, program_label: "Генератор" },
|
||||
{ wallet_name: "w.cap.preimp", required_program_id: 0, program_label: null },
|
||||
{ wallet_name: "w.exp.adv", required_program_id: 0, program_label: null },
|
||||
{ wallet_name: "w.reg.pend", required_program_id: 0, program_label: null },
|
||||
] as const
|
||||
|
||||
Reference in New Issue
Block a user