Реестр кошельков
"Реестр кошельков" отображает кошельки кооператива для управленческого учёта. Баланс кошельков изменяются на основе правил стандартов смарт-контрактов следующими операциями: "увеличение", "уменьшение", "блокировка", перевод, "списание".
Реестр кошельков служит звеном контроля целостности экономического баланса кооператива, не допуская операции, которые уменьшают баланс кошелька ниже нуля, и одновременно с этим, ограничивая возможность двойных трат. Как именно - мы рассмотрим ниже в примере.
на аналогичных идентификаторах, что и номера счетов в бухгалтерии, однако, суммы на них могут отличаться, т.к. принципы бухгалтерского учёта несколько отличаются от принципов управленческого учёта:

Выше мы видим кошельки кооператива, каждый из которых обладает тремя колонками своего баланса: доступно, заблокировано и списано. Доступные к использованию средства согласно стандартам и их бизнес-процессам расположены в колонке "доступно". Имеющиеся средства, уже используемые в каких-либо бизнес-процессах находятся в статусе "заблокировано". В колонке "списано" находятся средства, которые вышли из системы управленческого учёта по указанному кошельку.
При нажатии на зеленую стрелку у номера кошелька откроется история движения средств по конкретному кошельку:

При переходе на вкладку "История операций", система покажет полный список всех операций по всем кошелькам:

Данный реестр является публичным, он хранится в распределенной базе данных блокчейна и изменяется на основе стандартов смарт-контрактов. В описании причин движений средств по кошелькам нет и не будет персональных данных пайщиков, но там содержатся идентификаторы и имена аккаунтов, по которым пайщик, обладающий доступом к реестру документов, аккаунтов и платежей, сможет восстановить причину любого движения с полным восстановлением хронологии.
Пример работы¶
Рассмотрим пример того, как система кошельков работает с учётом членских взносов. Свободные членские взносы, которые поступили в кооператив, всегда фиксируются на кошельке расчетного счета (51), т.к. войти в систему деньги могут только через паевой взнос в главный кошелек, откуда в дальнейшем они транслируются в целевые потребительские программы (см. подробнее раздел Кошелек). Потому, любые денежные средства, которые введены в систему - находятся в кошельке расчетного счета (51).
Предположим, пайщик принял участие в целевой потребительской программе "Стол заказов" и заказал имущество, оплатив членский взнос в размере 30% от его стоимости. Этот членский взнос попадет в кошелек доступных членских взносов (86) после того, как срок гарантийного возврата по имуществу истечёт.
Так, когда у совета возникнет необходимость оплаты хозяйственных расходов по служебной записке, система произведет проверку на достаточность средств членских взносов в кошельке членских взносов (86), и отклонит операцию, если средств на нем недостаточно. Если средств достаточно, то система заблокирует средства на кошельке членских взносов (86) до приёма решения совета по служебной записке.
Таким образом, как только служебная записка будет создана на весь доступный баланс кошелька 86, все средства на кошельке 86 будут заблокированы, что приведет к невозможности создания новой записки и двойной траты средств.
После того, как решение совета по слубежной записке будет принято, средства разблокируются на кошельке 86 и будут немедленно автоматически переведены на кошелек 86.4, где также будут немедленно заблокированы до момента фактической оплаты кассиром. Подтверждение оплаты кассиром разблокирует средства на кошельке хозрасходов (86.4) и немедленно спишет их по тому же кошельку, одновременно с тем, уменьшив баланс кошелька расчетного счёта (51) по факту наличия подтвержденного исходящего платежа от кассира.
Связь с бухучетом¶
Бухгалтерский учёт ведется по иным принципам и на других основаниях. Бухгалтерский учёт мы реализуем на основе событий действий, которые регистрируются в блокчейне.
Нам всегда известно какое действие является закрывающим для пакета документов, и на основе этого действия мы формируем пакет данных, которые 1C:Бухгалтерия может получить с п
На основе этих действий формируются наборы данных, которые содержат в себе необходиму информацию для совершения бухгалтерских проводок.
Средства в кошельке 86 могут быть использованы для списания по целевым фондам кооператива (идентификаторы 86.1-86.5).
При создании членом совета служебной записки на расход средств членских взносов по фонду обеспечения хозяйственной деятельности (86.4),
Разработчикам¶
Канонические имена полей и типов — в файле components/controller/schema.gql монорепозитория; интерактивно — в документации GraphQL-API.
План счетов (ledger)¶
🛠️ SDK: Queries.Ledger.GetLedger | Query.getLedger
Получить полное состояние плана счетов кооператива. Возвращает все счета из стандартного плана счетов с актуальными данными из блокчейна. Если счет не активен в блокчейне, возвращает нулевые значения. Требуемые роли: chairman, member.
import { Queries } from '@coopenomics/sdk';
const variables: Queries.Ledger.GetLedger.IInput = {
data: {
coopname: <string>; // Имя кооператива для получения состояния ledger
};
};
const { [Queries.Ledger.GetLedger.name]: result } = await client.Query(
Queries.Ledger.GetLedger.query,
{ variables }
);
Результат:
interface IOutput {
getLedger: {
chartOfAccounts: <{
available: <string>; // Доступные средства
blocked: <string>; // Заблокированные средства
displayId: <string>; // Идентификатор счета для отображения (может быть дробным, например "86.6")
id: <number>; // Идентификатор счета
name: <string>; // Название счета
writeoff: <string>; // Списанные средства
}[]>; // План счетов с актуальными данными
coopname: <string>; // Имя кооператива
};
}
История операций по счетам¶
🛠️ SDK: Queries.Ledger.GetLedgerHistory | Query.getLedgerHistory
Получить историю операций по счетам кооператива. Возвращает список операций с возможностью фильтрации по account_id и пагинацией. Операции сортируются по дате создания (новые первыми). Требуемые роли: chairman, member.
import { Queries } from '@coopenomics/sdk';
const variables: Queries.Ledger.GetLedgerHistory.IInput = {
data: {
account_id?: <null | number>; // ID счета для фильтрации. Если не указан, возвращаются операции по всем счетам
coopname: <string>; // Имя кооператива
limit?: <null | number>; // Количество записей на странице (по умолчанию 10, максимум 100)
page?: <null | number>; // Номер страницы (по умолчанию 1)
sortBy?: <null | string>; // Поле для сортировки (created_at, global_sequence)
sortOrder?: <null | string>; // Направление сортировки (ASC или DESC)
};
};
const { [Queries.Ledger.GetLedgerHistory.name]: result } = await client.Query(
Queries.Ledger.GetLedgerHistory.query,
{ variables }
);
Результат:
interface IOutput {
getLedgerHistory: {
currentPage: <number>; // Текущая страница
items: <{
account_id: <number>; // ID счета
action: <string>; // Тип операции
comment?: <null | string>; // Комментарий к операции
coopname: <string>; // Имя кооператива
created_at: <unknown>; // Дата и время создания операции
global_sequence: <number>; // Номер глобальной последовательности блокчейна
hash?: <null | string>; // Хеш пакета документов операции
quantity: <string>; // Сумма операции
username?: <null | string>; // Имя пользователя, совершившего операцию
}[]>; // Список операций
totalCount: <number>; // Общее количество операций
totalPages: <number>; // Общее количество страниц
};
}
Программные кошельки (список)¶
🛠️ SDK: Queries.Wallet.GetProgramWallets | Query.getProgramWallets
Получить список программных кошельков с фильтрацией и пагинацией Требуемые роли: chairman, member.
import { Queries } from '@coopenomics/sdk';
const variables: Queries.Wallet.GetProgramWallets.IInput = {
filter?: {
coopname?: <null | string>; // Фильтр по имени кооператива
program_id?: <null | string>; // Фильтр по ID программы
program_type?: <null | ProgramType>; // Фильтр по типу программы
username?: <null | string>; // Фильтр по имени пользователя
};
options?: {
limit: <number>; // Количество элементов на странице
page: <number>; // Номер страницы
sortBy?: <null | string>; // Ключ сортировки (например, "name")
sortOrder: <string>; // Направление сортировки ("ASC" или "DESC")
};
};
const { [Queries.Wallet.GetProgramWallets.name]: result } = await client.Query(
Queries.Wallet.GetProgramWallets.query,
{ variables }
);
Результат:
interface IOutput {
getProgramWallets: {
currentPage: <number>; // Текущая страница
items: <{
agreement_id: <unknown>; // Идентификатор соглашения
available: <string>; // Доступный баланс (формат: "100.0000 RUB")
blockNum?: <null | number>; // Номер блока последнего обновления
blocked: <string>; // Заблокированный баланс (формат: "100.0000 RUB")
coopname: <string>; // Имя кооператива
id: <unknown>; // Уникальный идентификатор кошелька в блокчейне
membership_contribution: <string>; // Паевой взнос (формат: "100.0000 RUB")
program_id: <unknown>; // Идентификатор программы
program_type?: <null | ProgramType>; // Тип программы
username: <string>; // Имя пользователя
}[]>; // Элементы текущей страницы
totalCount: <number>; // Общее количество элементов
totalPages: <number>; // Общее количество страниц
};
}
Программный кошелёк (один)¶
🛠️ SDK: Queries.Wallet.GetProgramWallet | Query.getProgramWallet
Получить один программный кошелек по фильтру Требуемые роли: chairman, member.
import { Queries } from '@coopenomics/sdk';
const variables: Queries.Wallet.GetProgramWallet.IInput = {
filter: {
coopname?: <null | string>; // Фильтр по имени кооператива
program_id?: <null | string>; // Фильтр по ID программы
program_type?: <null | ProgramType>; // Фильтр по типу программы
username?: <null | string>; // Фильтр по имени пользователя
};
options: {
limit: <number>; // Количество элементов на странице
page: <number>; // Номер страницы
sortBy?: <null | string>; // Ключ сортировки (например, "name")
sortOrder: <string>; // Направление сортировки ("ASC" или "DESC")
};
};
const { [Queries.Wallet.GetProgramWallet.name]: result } = await client.Query(
Queries.Wallet.GetProgramWallet.query,
{ variables }
);
Результат:
interface IOutput {
getProgramWallet?: <undefined | {
agreement_id: <unknown>; // Идентификатор соглашения
available: <string>; // Доступный баланс (формат: "100.0000 RUB")
blockNum?: <null | number>; // Номер блока последнего обновления
blocked: <string>; // Заблокированный баланс (формат: "100.0000 RUB")
coopname: <string>; // Имя кооператива
id: <unknown>; // Уникальный идентификатор кошелька в блокчейне
membership_contribution: <string>; // Паевой взнос (формат: "100.0000 RUB")
program_id: <unknown>; // Идентификатор программы
program_type?: <null | ProgramType>; // Тип программы
username: <string>; // Имя пользователя
}>; // Получить один программный кошелек по фильтру
Требуемые роли: chairman, member.
}
Часть шагов (голос по решению совета, исполнение ряда решений) выполняется подписью и отправкой транзакции в блокчейн через Client.Blockchain / класс Blockchain в пакете @coopenomics/sdk, а не отдельной мутацией GraphQL; см. 🛠️ Classes.Blockchain и 🛠️ Classes.Client.