Compare commits

...

74 Commits

Author SHA1 Message Date
Alex Ant 196f3bcba1 level & energy system 2025-10-27 21:36:02 +05:00
Alex Ant bc73c5ca86 contract gamification 2025-10-27 16:19:56 +05:00
Alex Ant f4badc15d1 редактирование участника, шаблон "о себе" 2025-10-27 12:50:51 +05:00
Alex Ant 76f731d0cd poll requests for update content 2025-10-26 18:27:08 +05:00
Alex Ant 5e22858ab4 some bugs and permissions 2025-10-26 15:45:15 +05:00
Alex Ant bc1c54c43e notifications on novu improve (sanity), make a coop settings for chairman and select default workspace / page 2025-10-25 20:19:10 +05:00
Alex Ant 95ac0d36f8 a lot of changes 2025-10-22 19:53:40 +05:00
Alex Ant 2bee3eb179 unique participants count and workflow notification 2025-10-21 17:13:20 +05:00
Alex Ant 52165f2a0b microWallet & workspaceMenu rework 2025-10-20 21:12:53 +05:00
Alex Ant 9f2da226f4 extensionsStore refactoring and make it with multi-desktops 2025-10-20 17:26:24 +05:00
Alex Ant 46b999317d result submission 2025-10-20 15:35:32 +05:00
Alex Ant 80bce3c9c2 refactoring, optimization and improvement 2025-10-17 19:33:07 +05:00
Alex Ant 90b25b4bd8 fab | visual refactoring 2025-10-16 20:34:56 +05:00
Alex Ant f562f1eafd Merge branch 'dev' into capital 2025-10-16 10:27:23 +05:00
Alex Ant ff520622ff chore(release): publish 2025-10-16 10:25:26 +05:00
Alex Ant 1a6c6a4f31 fix parser 2025-10-16 01:32:23 +05:00
Alex Ant 4a9e0388f4 fix parser start block 2025-10-16 01:30:55 +05:00
Alex Ant e47b2a971e chore(release): publish 2025-10-15 23:12:28 +05:00
Alex Ant 96777ec095 delete mongo transactions 2025-10-15 23:00:23 +05:00
Alex Ant 52019deef5 ComponentPage 2025-10-15 22:51:30 +05:00
Alex Ant c26a534ff6 secondary route menu 2025-10-15 20:36:24 +05:00
Alex Ant e5be5c0b05 syncers refactoring and frontend 2025-10-15 13:49:20 +05:00
Alex Ant 5b07f52641 hard update 2025-10-14 22:06:23 +05:00
Alex Ant e0109cb530 pushResult подготовка и отправка документов с ожиданием решения совета 2025-10-12 19:41:53 +05:00
Alex Ant 1496dd1598 approvals with auth start 2025-10-07 19:41:54 +05:00
Alex Ant efcaeb2f00 set plan and other | going to voting 2025-10-07 11:31:56 +05:00
Alex Ant 1252946fe5 permissions and booter 2025-10-05 10:55:53 +05:00
Alex Ant 2913d5f636 some widgets and filters 2025-10-02 17:35:06 +05:00
Alex Ant c50beb3d43 some updates 2025-09-29 13:34:52 +05:00
Alex Ant 46b559001a some refactoring 2025-09-28 16:38:19 +05:00
Alex Ant 55a2e2e060 agreement repo and mutation 2025-09-28 15:48:56 +05:00
Alex Ant 12364a052f desktop agremeent features 2025-09-28 13:18:38 +05:00
Alex Ant 45ac971035 entity log 2025-09-28 11:19:50 +05:00
Alex Ant 26b818c9a6 update 2025-09-27 17:58:04 +05:00
Alex Ant 007836f52e contributor registration #1 2025-09-25 20:16:58 +05:00
Alex Ant ed0982770b mutations for all document generations 2025-09-25 12:47:17 +05:00
Alex Ant dcc72e90b7 factory capital documents basic templates 2025-09-24 21:52:34 +05:00
Alex Ant b428660944 project voting skeleton 2025-09-23 12:56:22 +05:00
Alex Ant 0008dcc0ee time tracker #3 2025-09-22 22:56:45 +05:00
Alex Ant e3fbf3981d time tracker personal time limit 2025-09-22 17:04:09 +05:00
Alex Ant c5e9244a08 selector fix 2025-09-21 23:55:11 +05:00
Alex Ant e1fd823c13 time tracker 2025-09-21 23:53:21 +05:00
Alex Ant 346f0d636c time tracker sdk queries 2025-09-21 20:42:28 +05:00
Alex Ant 315a259e5b lang refactoring 2025-09-21 16:09:19 +05:00
Alex Ant 3157a03c74 time tracking service prototype 2025-09-21 14:50:18 +05:00
Alex Ant 045807a748 edit project and create commit simple button on tasks 2025-09-20 20:52:53 +05:00
Alex Ant ea0e12ac80 update 2025-09-20 17:33:07 +05:00
Alex Ant 692060af6c update 2025-09-19 20:42:16 +05:00
Alex Ant d8b23a4b5c issues create 2025-09-19 10:41:29 +05:00
Alex Ant 074bf55d6c stories complete 2025-09-18 16:28:51 +05:00
Alex Ant 84e505b817 before make pain 2025-09-17 21:23:52 +05:00
Alex Ant a12e6ff603 taskPage 2025-09-17 16:40:18 +05:00
Alex Ant b01d662a1c components 2025-09-16 23:28:34 +05:00
Alex Ant e631dad499 getState, fix some bugs 2025-09-16 17:28:01 +05:00
Alex Ant 7ab0bfdd6b optional right drawer 2025-09-15 22:52:17 +05:00
Alex Ant 35a4db43fb add all entities and make extension store better 2025-09-13 01:02:21 +05:00
Alex Ant 094028006b make new queries and selectors 2025-09-11 22:21:53 +05:00
Alex Ant c12f42fcac some selectors, queries, features and entities 2025-09-11 19:10:37 +05:00
Alex Ant 3e498b098b refactoring #2 2025-09-11 13:03:21 +05:00
Alex Ant bbf1a1a544 refactoring 2025-09-11 12:15:05 +05:00
Alex Ant 42d57f30bf update names 2025-09-10 19:28:13 +05:00
Alex Ant 19967a9ad0 update 2025-09-10 15:23:33 +05:00
Alex Ant 9d1a8f12d8 main domain model 2025-09-10 14:22:14 +05:00
Alex Ant 57bebebe09 domain entities synced with blockchain 2025-09-08 13:47:40 +05:00
Alex Ant d19303cd62 typeorm repositories 2025-09-07 21:06:54 +05:00
Alex Ant 7c96e46a37 domain entities and infrastructure mappers 2025-09-07 20:44:28 +05:00
Alex Ant f75e68f8ce before refactoring 2025-09-06 16:42:29 +05:00
Alex Ant c8d9ee2457 migration fixs 2025-09-05 23:22:49 +05:00
Alex Ant a29f23086a update migrations 2025-09-05 23:07:27 +05:00
Alex Ant 4a76365df4 migrator fix 2025-09-05 22:56:08 +05:00
Alex Ant 972264844a migrator commands and subcommands 2025-09-05 22:46:39 +05:00
Alex Ant e23e6f3c1a some domain modules for capital 2025-09-05 15:03:48 +05:00
Alex Ant 03c10382d1 save deltas and actions and forks to main repositories 2025-09-04 14:21:20 +05:00
Alex Ant 3abe24aa18 refactoring, double bus refactoring, delete notificator module, desktop fix 2025-09-03 22:30:05 +05:00
2291 changed files with 113258 additions and 20568 deletions
+1
View File
@@ -1,5 +1,6 @@
---
alwaysApply: true
globs: **/desktop/**
---
# DESKTOP
+20
View File
@@ -0,0 +1,20 @@
---
globs: notifications/src/workflows/**/*.ts
---
# Правила валидации воркфлоу
## 🚫 ID воркфлоу
- **Длина ID не должна превышать 32 символа**
- Используйте описательные, но короткие идентификаторы малыми латинскими буквами и тире.
## 🚫 Условия в шаблонах
- **Запрещено использовать JavaScript выражения в шаблонах Novu**
- Нельзя использовать:
- Тернарные операторы: `{{condition ? "text1" : "text2"}}`
- Логические операторы: `{{field && "text"}}`
- Любые другие JS конструкции
## ✅ Рекомендации
- Добавляйте текстовые поля в payload для условной логики
- Вычисляйте значения на стороне сервера перед отправкой уведомления
- Используйте только простые переменные: `{{payload.fieldName}}`
+7
View File
@@ -0,0 +1,7 @@
{
"recommendations": [
"vue.volar",
"vue.vscode-typescript-vue-plugin"
]
}
+21 -9
View File
@@ -13,9 +13,7 @@
// Оптимизация для монорепозитория
"typescript.preferences.useAliasesForRenames": false,
"typescript.preferences.include": false,
"typescript.disableAutomaticTypeAcquisition": true,
"typescript.preferences.includePackageJsonAutoImports": "off",
"typescript.preferences.includePackageJsonAutoImports": "on",
"typescript.suggest.autoImports": true,
"typescript.suggest.paths": true,
"typescript.updateImportsOnFileMove.enabled": "always",
@@ -47,13 +45,27 @@
"**/node_modules/.cache": true
},
// TypeScript server настройки
// TypeScript server настройки для монорепозитория
"typescript.tsserver.maxTsServerMemory": 8192,
"typescript.tsserver.watchOptions": {
"excludeFiles": [
"**/node_modules/**/*",
"**/dist/**/*",
"**/.cache/**/*"
"excludeDirectories": [
"**/node_modules",
"**/dist",
"**/.cache",
"**/.quasar",
"**/build"
]
}
},
// Использовать локальный TypeScript из монорепо
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
// КРИТИЧЕСКИ ВАЖНО: включить project references для монорепозитория
"typescript.tsserver.useSyntaxServer": "auto",
"typescript.tsserver.experimental.enableProjectDiagnostics": true,
// Оптимизация для больших монорепозиториев
"typescript.disableAutomaticTypeAcquisition": true,
"typescript.surveys.enabled": false
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@coopenomics/boot",
"type": "module",
"version": "2025.9.1",
"version": "2025.10.16",
"private": true,
"packageManager": "pnpm@9.0.6",
"description": "",
+47
View File
@@ -0,0 +1,47 @@
#!/bin/bash
# Останавливаем и удаляем контейнеры вместе с volumes
echo "Останавливаем и удаляем контейнеры с volumes..."
docker compose down -v mongo postgres cooparser || true
# Останавливаем blockchain контейнер перед удалением данных
echo "Останавливаем blockchain контейнер..."
docker compose stop node || true
# Удаляем blockchain data
echo "Удаляем blockchain data..."
# sudo chmod -R 755 ../blockchain-data/ 2>/dev/null || true
sudo rm -rf ../blockchain-data/
# Пересоздаем и запускаем базы данных
echo "Пересоздаем и запускаем базы данных..."
docker compose up -d mongo postgres
# Ждем готовности MongoDB
echo "Ждем готовности MongoDB..."
until docker exec mongo mongosh --eval "db.adminCommand('ping')" --quiet > /dev/null 2>&1; do
echo "MongoDB еще не готов, ждем..."
sleep 2
done
echo "MongoDB готов!"
# Ждем готовности PostgreSQL
echo "Ждем готовности PostgreSQL..."
until docker exec postgres pg_isready -U postgres -d voskhod > /dev/null 2>&1; do
echo "PostgreSQL еще не готов, ждем..."
sleep 2
done
echo "PostgreSQL готов!"
# Запускаем boot процесс
echo "Запускаем boot процесс..."
pnpm run boot
# Запускаем parser
echo "Запускаем parser..."
docker compose up -d cooparser
echo "Запускаем контроллер..."
docker compose restart coopback || true
echo "Перезапуск завершен!"
-2
View File
@@ -120,8 +120,6 @@ program
}
try {
await clearDirectory(basePath)
await clearDB()
await runContainer()
await sleep(5000)
+32
View File
@@ -54,6 +54,38 @@ export class CooperativeClass {
meta: '',
is_can_coop_spend_share_contributions: false,
})
await this.blockchain.createProgram({
coopname,
username: coopname,
type: 'source',
title: 'Генерация',
announce: '',
description: '',
preview: '',
images: '',
calculation_type: 'free',
fixed_membership_contribution: `${Number(0).toFixed(4)} ${GOVERN_SYMBOL}`,
membership_percent_fee: 0, // 10%
meta: '',
is_can_coop_spend_share_contributions: true,
})
await this.blockchain.createProgram({
coopname,
username: coopname,
type: 'capital',
title: 'Благосостояние',
announce: '',
description: '',
preview: '',
images: '',
calculation_type: 'free',
fixed_membership_contribution: `${Number(0).toFixed(4)} ${GOVERN_SYMBOL}`,
membership_percent_fee: 0, // 10%
meta: '',
is_can_coop_spend_share_contributions: true,
})
}
async createCooperative(username: string, keys?: Keys) {
@@ -293,6 +293,8 @@ describe('тест контракта CAPITAL', () => {
parent_hash: parentHash,
title: `Мета-проект ${metaHash.slice(0, 10)}`,
description: `Описание мета-проекта ${metaHash.slice(0, 10)}`,
invite: '',
data: '',
meta: '',
can_convert_to_project: true,
}
@@ -334,6 +336,8 @@ describe('тест контракта CAPITAL', () => {
title: `Компонент-проект ${componentHash.slice(0, 10)}`,
description: `Описание компонент-проекта ${componentHash.slice(0, 10)}`,
meta: '',
data: '',
invite: '',
can_convert_to_project: true,
}
@@ -1743,6 +1747,8 @@ describe('тест контракта CAPITAL', () => {
title: `Новый компонент-проект ${newComponentHash.slice(0, 10)}`,
description: `Описание нового компонент-проекта ${newComponentHash.slice(0, 10)}`,
meta: '',
invite: '',
data: '',
can_convert_to_project: true,
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@coopenomics/cleos",
"version": "2025.9.1",
"version": "2025.10.16",
"private": true,
"description": "",
"scripts": {
@@ -21,7 +21,7 @@ alwaysApply: false
* @brief Завершение голосования для конкретного участника по методу Водянова.
* Рассчитывает полные итоговые суммы участника включая:
* - Результаты голосования по Водянову: (сумма голосов + общая сумма распределения) / количество голосующих
* - Фиксированные распределения: 61.8% авторских премий равно между авторами, 61.8% создательских премий прямо создателям
* - Фиксированные распределения: 61.8% авторских премий равно между авторами, 61.8% исполнительских премий прямо создателям
* Обновляет сегмент участника с итоговыми суммами раздельно по пулам
* @param coopname Наименование кооператива
* @param username Наименование пользователя-участника голосования
@@ -25,7 +25,7 @@ alwaysApply: false
### Диаграммы последовательности:
- Использовать ТОЛЬКО sequenceDiagram вместо graph или flowchart
- Участники (participant) называть понятными русскими именами:
- "Вкладчик" вместо "User" или "Участник"
- "Участник" вместо "User" или "Участник"
- "Capital Contract" вместо технических названий
- "Soviet Contract", "Gateway Contract" для системных контрактов
- В сообщениях использовать ЧЕЛОВЕКО-ЧИТАЕМЫЕ описания вместо технических имен методов:
@@ -47,7 +47,7 @@ alwaysApply: false
\htmlonly
<div class="mermaid">
sequenceDiagram
participant V as Вкладчик
participant V as Участник
participant C as Capital Contract
participant S as Soviet Contract
@@ -66,12 +66,12 @@ sequenceDiagram
Пример оформления процесса
/**
@defgroup public_capital_registration_process Процесс регистрации вкладчиков
@defgroup public_capital_registration_process Процесс регистрации участников
@ingroup public_capital_processes
@pre предварительные условия
Процесс приёма договора УХД от пайщика, фиксации его статуса как вкладчика
Процесс приёма договора УХД от пайщика, фиксации его статуса как участника
и обеспечения технической возможности участвовать в проектах и программе капитализации.
``` cpp
@@ -35,7 +35,7 @@ alwaysApply: false
* @brief Завершение голосования для конкретного участника по методу Водянова.
* Рассчитывает полные итоговые суммы участника включая:
* - Результаты голосования по Водянову: (сумма голосов + общая сумма распределения) / количество голосующих
* - Фиксированные распределения: 61.8% авторских премий равно между авторами, 61.8% создательских премий прямо создателям
* - Фиксированные распределения: 61.8% авторских премий равно между авторами, 61.8% исполнительских премий прямо создателям
* Обновляет сегмент участника с итоговыми суммами раздельно по пулам
* @param coopname Наименование кооператива
* @param username Наименование пользователя-участника голосования
@@ -25,7 +25,7 @@ alwaysApply: false
### Диаграммы последовательности:
- Использовать ТОЛЬКО sequenceDiagram вместо graph или flowchart
- Участники (participant) называть понятными русскими именами:
- "Вкладчик" вместо "User" или "Участник"
- "Участник" вместо "User" или "Участник"
- "Capital Contract" вместо технических названий
- "Soviet Contract", "Gateway Contract" для системных контрактов
- В сообщениях использовать ЧЕЛОВЕКО-ЧИТАЕМЫЕ описания вместо технических имен методов:
@@ -47,7 +47,7 @@ alwaysApply: false
\htmlonly
<div class="mermaid">
sequenceDiagram
participant V as Вкладчик
participant V as Участник
participant C as Capital Contract
participant S as Soviet Contract
@@ -66,12 +66,12 @@ sequenceDiagram
Пример оформления процесса
/**
@defgroup public_capital_registration_process Процесс регистрации вкладчиков
@defgroup public_capital_registration_process Процесс регистрации участников
@ingroup public_capital_processes
@pre предварительные условия
Процесс приёма договора УХД от пайщика, фиксации его статуса как вкладчика
Процесс приёма договора УХД от пайщика, фиксации его статуса как участника
и обеспечения технической возможности участвовать в проектах и программе капитализации.
``` cpp
@@ -0,0 +1,284 @@
# 🎮 Система "Уровень и Энергия" - Благорост
## 🌿 Что это такое
**Благорост** — это система роста благосостояния через создание и использование результатов интеллектуальной деятельности. Система "Уровень и Энергия" создаёт живую модель роста, где участники чувствуют не только экономический эффект, но и личную динамику вовлечённости.
### Основные понятия
**Уровень** — отражает достигнутую ступень развития участника. Он показывает, насколько человек укоренён в системе, сколько уже вложил и создал. Уровень **может только расти** — это накопленный результат, фундамент, который не теряется.
**Энергия** — отражает текущую активность. Она **увеличивается**, когда человек проявляется через взносы, и **уменьшается**, когда он бездействует. Это показатель "жизни участия".
### Как это работает
- Каждый участник имеет числовые показатели: `level` (целое число) и `energy` (0100%)
- При внесении взноса (деньги, труд, идеи) участник получает **прирост энергии (gain)**
- Каждый день энергия **естественно уменьшается (decay_rate)** при отсутствии новых проявлений
- При достижении энергии 100% происходит **переход на следующий уровень** с обнулением энергии
### Поведение и мотивация
Уровень не снижается — он фиксирует достигнутое. Энергия постоянно колеблется: при активности растёт, при бездействии падает. Это создаёт **мягкое давление к развитию** — человек не теряет результат, но теряет "тонус" при остановке.
В отличие от чисто финансовых показателей, система делает взнос **ощутимым во времени**: активность чувствуется как движение вверх, бездействие — как постепенное угасание.
> **Человек растёт, пока проявляется. Благорост делает этот рост видимым.**
---
## ⚙️ Параметры конфигурации
Система управляется четырьмя основными параметрами, которые определяют баланс и динамику игры:
### `level_depth_base` - Базовый взнос для уровня 1
**Значение:** 10,000 RUB (по умолчанию)
**На что влияет:**
- Определяет стоимость достижения первого уровня
- Влияет на общую сложность прогрессии
- Базовый взнос, от которого рассчитываются все последующие уровни
**Примеры:**
- `10,000 RUB` → первый уровень требует 10,000 RUB взноса
- `5,000 RUB` → упрощает вход в систему
- `50,000 RUB` → усложняет вход в систему
### `level_growth_coefficient` - Коэффициент роста уровней
**Значение:** 1.5 (по умолчанию)
**На что влияет:**
- Определяет, насколько быстрее растут требования к последующим уровням
- Влияет на общую кривизну прогрессии
**Примеры:**
- `1.0` → линейный рост (каждый уровень требует одинаково больше)
- `1.5` → экспоненциальный рост (требования растут в 1.5 раза)
- `2.0` → агрессивный рост (требования удваиваются каждый уровень)
### `energy_gain_coefficient` - Коэффициент прироста энергии
**Значение:** 10.0 (по умолчанию)
**На что влияет:**
- Определяет, сколько энергии даёт каждый взнос
- Влияет на скорость набора энергии и частоту переходов уровней
**Примеры:**
- `5.0` → взносы дают меньше энергии (медленнее прогресс)
- `10.0` → сбалансированный прирост энергии
- `20.0` → взносы дают много энергии (быстрее прогресс)
### `energy_decay_rate_per_day` - Скорость снижения энергии
**Значение:** 1.11% в день (по умолчанию)
**На что влияет:**
- Определяет, как быстро угасает энергия без активности
- Влияет на требуемую регулярность участия
**Примеры:**
- `0.5%` → энергия угасает медленно (200 дней до нуля)
- `1.11%` → сбалансированное угасание (90 дней до нуля)
- `2.0%` → энергия угасает быстро (50 дней до нуля)
---
## 📊 Математическая модель
### Расчёт требований для уровня N
```
level_requirement(N) = level_depth_base × level_growth_coefficient^(N-1)
```
**Примеры прогрессии** (при базовых настройках):
- Уровень 1: 10,000 RUB
- Уровень 2: 15,000 RUB
- Уровень 3: 22,500 RUB
- Уровень 4: 33,750 RUB
- Уровень 5: 50,625 RUB
- Уровень 10: ~383,437 RUB
### Расчёт прироста энергии от взноса
```
gain = (contribution_amount / level_requirement(current_level)) × energy_gain_coefficient
```
**Пример:** взнос 1,000 RUB на уровне 1 даёт 1% энергии (при коэффициенте 10.0)
### Расчёт снижения энергии со временем
```
days_passed = (current_time - last_energy_update) / 86400
decay = days_passed × energy_decay_rate_per_day
new_energy = max(0, current_energy - decay)
```
**Пример:** За 90 дней энергия снижается от 99.9% до 0% (при decay_rate = 1.11%)
### Переход на новый уровень (с поддержкой перескока)
```
if (energy >= 100.0) {
levels_gained = floor(energy / 100.0) // Количество уровней для перехода
level += levels_gained // Перескок через несколько уровней
energy = energy % 100.0 // Остаток энергии (0.0-99.9)
// Отправка уведомления о переходе уровня
}
```
**Примеры перескока:**
- Энергия 250% → +2 уровня, остаток 50%
- Энергия 500% → +5 уровней, остаток 0%
- Энергия 99.9% → +0 уровней, остаток 99.9%
---
## 🔧 Техническая реализация
### Структура данных участника
```cpp
struct contributor {
// ... существующие поля ...
// Геймификация: уровень и энергия
uint32_t level = 1; // Уровень участника (от 1 и выше, только растет)
double energy = 99.9999999999; // Текущая энергия участника (0.0 - 100.0)
time_point_sec last_energy_update; // Время последнего обновления энергии
};
```
### Функциональность
#### Расчетные функции
- `calculate_level_requirement(level, config)` — требования для уровня
- `calculate_energy_gain(amount, level, config)` — прирост энергии от взноса
- `update_energy_with_decay(coopname, username)` — применение decay
- `add_energy_and_check_levelup(coopname, username, gain)` — добавление энергии и проверка перехода
- `update_gamification_from_segment(coopname, segment)` — обновление из сегмента
#### Действия контракта
**refreshcontr** — обновление энергии с decay
```cpp
void capital::refreshcontr(eosio::name coopname, eosio::name username);
```
- Авторизация: coopname
- Назначение: периодическое обновление энергии участников
**lvlnotify** — уведомление о переходе уровня
```cpp
void capital::lvlnotify(eosio::name coopname, eosio::name username,
uint32_t prev_level, uint32_t new_level);
```
- Авторизация: _capital (inline action)
- Назначение: автоматическое уведомление при переходе уровня
### Интеграция с бизнес-процессами
#### Автоматическое обновление при взносах
Приём результата (действие `signact2`):
```
signact2()
→ update_contributor_ratings_from_segment()
→ update_gamification_from_segment()
→ add_energy_and_check_levelup()
→ [если energy >= 100] lvlnotify()
```
#### Начальное состояние участника
При создании или импорте:
- `level = 1`
- `energy = 99.9999999999` (почти полная энергия для старта)
- `last_energy_update = current_time_point()`
### Жизненный цикл энергии
```
99.9999999999% (старт, уровень 1)
[взносы добавляют энергию]
100% → ПЕРЕХОД УРОВНЯ (+1 или больше) → остаток энергии (0.0-99.9%)
[взносы добавляют энергию]
[время уменьшает энергию (decay)]
[цикл повторяется]
```
**Пример большого взноса:**
```
Уровень 1, энергия 50%
взнос даёт +250% энергии → всего 300%
300% / 100 = 3 уровня → Уровень 4, остаток 0%
```
### Сценарии использования
#### Активный участник
- День 1: Регистрация, energy=99.9999999999%
- День 5: взнос 5,000 RUB → energy=99.9999999999% + 5% = 100% → Уровень 2
- День 10: взнос 10,000 RUB → energy=0% + 6.67% = 6.67%
#### Неактивный участник
- День 1: Регистрация, energy=99.9999999999%
- День 30: Нет взносов, energy=99.9999999999% - 33.3% = 66.6%
- День 90: Нет взносов, energy=0%
- День 95: взнос 10,000 RUB → energy=0% + 10% = 10%
### Настройка системы
#### Быстрая прогрессия
```cpp
energy_decay_rate_per_day = 2.0; // Снижение за 50 дней
level_growth_coefficient = 1.3; // Пологая прогрессия
energy_gain_coefficient = 15.0; // Быстрый прирост энергии
```
#### Долгосрочная мотивация
```cpp
energy_decay_rate_per_day = 0.5; // Снижение за 200 дней
level_growth_coefficient = 2.0; // Крутая прогрессия
energy_gain_coefficient = 5.0; // Медленный прирост энергии
```
---
## 🎯 Эксплуатация системы
### Обязательные действия контроллера
#### 1. Планировщик decay (критично)
```typescript
cron.schedule('0 0 * * *', async () => {
const contributors = await getActiveContributors();
for (const contributor of contributors) {
await contract.refreshcontr(coopname, contributor.username);
}
});
```
#### 2. Обработчик уведомлений (важно)
```typescript
contract.on('lvlnotify', async ({ coopname, username, prev_level, new_level }) => {
await notificationService.send(username, {
title: '🎉 Поздравляем!',
message: `Вы достигли ${new_level} уровня!`,
data: { prev_level, new_level }
});
});
```
### Рекомендуемые действия
#### Интерфейс
Отображать:
- Текущий уровень и энергию
- Прогресс до следующего уровня
- Требования для следующего уровня
- Историю достижений
#### Балансировка
Периодически анализировать статистику переходов уровней и корректировать параметры конфигурации для достижения желаемой динамики роста.
### Валидация параметров
- `energy_decay_rate_per_day`: 0.0 - 100.0
- `level_depth_base`: > 0
- `level_growth_coefficient`: 1.0 - 3.0
- `energy_gain_coefficient`: 0.0 - 100.0
@@ -21,6 +21,16 @@ void capital::setconfig(eosio::name coopname, Capital::config config) {
eosio::check(config.authors_voting_percent >= 0.0 && config.authors_voting_percent <= 100, "Процент премий авторов на голосовании должен быть между 0 и 100");
eosio::check(config.creators_voting_percent >= 0.0 && config.creators_voting_percent <= 100, "Процент премий создателей на голосовании должен быть между 0 и 100");
// Валидация параметров геймификации
eosio::check(config.energy_decay_rate_per_day >= 0.0 && config.energy_decay_rate_per_day <= 100.0,
"Скорость уменьшения энергии должна быть между 0 и 100% в день");
eosio::check(config.level_depth_base > 0,
"Базовая сумма для уровня должна быть положительной");
eosio::check(config.level_growth_coefficient >= 1.0 && config.level_growth_coefficient <= 3.0,
"Коэффициент роста уровней должен быть между 1.0 и 3.0");
eosio::check(config.energy_gain_coefficient > 0.0 && config.energy_gain_coefficient <= 100.0,
"Коэффициент прироста энергии должен быть между 0 и 100");
Capital::global_state_table global_state_inst(_self, _self.value);
auto itr = global_state_inst.find(coopname.value);
@@ -5,14 +5,15 @@
* - Обновляет статус долга на approved
* - Создает повестку в совете для рассмотрения долга
* @param coopname Наименование кооператива
* @param username Наименование пользователя, одобрившего долг
* @param debt_hash Хеш долга для одобрения
* @param approved_statement Одобренное заявление о долге
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p _soviet
* @note Авторизация требуется от контракта совета
*/
void capital::approvedebt(eosio::name coopname, checksum256 debt_hash, document2 approved_statement)
void capital::approvedebt(eosio::name coopname, eosio::name username, checksum256 debt_hash, document2 approved_statement)
{
require_auth(_soviet);
@@ -3,14 +3,14 @@
* @defgroup public_capital_debt_process Выдача ссуды
* @ingroup public_capital_processes
*
* Процесс выдачи беспроцентных ссуд Вкладчикам проекта на основании их трудовых
* Процесс выдачи беспроцентных ссуд Участникам проекта на основании их трудовых
* и иных вкладов. Ссуды ограничены provisional_amount сегмента и погашаются
* автоматически при внесении результата в кооператив.
*
* ## Назначение процесса
*
* Система ссуд обеспечивает Вкладчикам компенсацию трудозатрат в процессе работы над проектом:
* - Вкладчики получают средства до завершения проекта
* Система ссуд обеспечивает Участникам компенсацию трудозатрат в процессе работы над проектом:
* - Участники получают средства до завершения проекта
* - Размер ссуды ограничен фактическими вкладами и привлечёнными инвестициями
* - Ссуды беспроцентные, что стимулирует активное участие
* - Ссулы автоматически погашаются при внесении результата исключает проблемы с возвратом
@@ -18,7 +18,7 @@
* ## Математические основы расчёта ссуд
*
* ### Базовая формула доступной себестоимости
* Доступная себестоимость - это себестоимость труда, которую вкладчик может использовать для получения ссуды.
* Доступная себестоимость - это себестоимость труда, которую участник может использовать для получения ссуды.
*
* ``` cpp
* provisional_amount = (creator_base + author_base + coordinator_base) × (return_base_percent / 100)
@@ -31,15 +31,15 @@
* - return_base_percent - коэффициент доступности средств (зависит от количества инвестиций)
*
* ### Ограничения на выдачу
* - Долг Вкладчика по проекту меньше доступной себестоимости (debt_amount < provisional_amount)
* - Вкладчик находится в одной из или нескольких ролях: автор, создатель или координатор
* - Долг Участника по проекту меньше доступной себестоимости (debt_amount < provisional_amount)
* - Участник находится в одной из или нескольких ролях: автор, исполнитель или координатор
*
* ## Диаграмма процесса
*
* \htmlonly
* <div class="mermaid">
* sequenceDiagram
* participant P as Вкладчик
* participant P as Участник
* participant C as Capital Contract
* participant S as Soviet Contract
* participant G as Gateway Contract
@@ -48,7 +48,7 @@
* P->>C: 1. createdebt(заявление на ссуду)
* Note over C: Проверка лимитов
* Note over C: debt_amount + amount ≤ provisional_amount
* Note over C: Увеличение debt_amount в сегменте вкладчика
* Note over C: Увеличение debt_amount в сегменте участника
*
* C->>S: 2. soviet::create_approval
*
@@ -88,19 +88,19 @@
*
* ### Шаг 1: Создание заявления на получение ссуды
*
* Вкладчик подаёт заявление на получение беспроцентной ссуды через действие @ref capital::createdebt.
* Участник подаёт заявление на получение беспроцентной ссуды через действие @ref capital::createdebt.
*
* @pre Предварительные условия:
* - Проект находится в активном статусе
* - Вкладчик имеет активный сегмент в проекте
* - Общий долг Вкладчика плюс запрашиваемая сумма меньше или равна сумме доступной себестоимости
* - Участник имеет активный сегмент в проекте
* - Общий долг Участника плюс запрашиваемая сумма меньше или равна сумме доступной себестоимости
* - Сумма доступной себестоимости больше нуля (есть вклады, обеспеченные инвестициями)
*
* @note Доступная себестоимость (provisional_amount) представляет собой себестоимость вкладов Вкладчика,
* @note Доступная себестоимость (provisional_amount) представляет собой себестоимость вкладов Участника,
* скорректированную на коэффициент возврата. Этот коэффициент показывает, какая часть базовых
* затрат обеспечена привлечёнными в проект инвестициями. Чем больше инвестиций привлечено,
* тем выше коэффициент и тем больше средств доступно для выдачи в виде ссуд.
* Коэффициент возврата себестоимости не превышает 100% от себестоимости затрат Вкладчиков.
* Коэффициент возврата себестоимости не превышает 100% от себестоимости затрат Участников.
* При превышении количества инвестиций суммы затрат, у инвесторов уменьшается коэффициент использования инвестиций, и они получат часть средств назад при закрытии проекта.
*
* <b>Входящие параметры:</b>
@@ -110,7 +110,7 @@
*
* @post Результат выполнения:
* - 📄 Создаётся заявление в таблице Capital::debts
* - Резервируется сумма долга в сегменте Вкладчика, что не позволяет повторно отправлять заявления
* - Резервируется сумма долга в сегменте Участника, что не позволяет повторно отправлять заявления
*
* ### Шаг 2: Одобрение заявки председателем
*
@@ -138,23 +138,23 @@
* - При отклонении заявка закрывается
*
* @note Совет рассматривает целесообразность выдачи, оценивает риски для проекта
* и утверждает выдачу ссуды по заявлению вкладчика или отклоняет его.
* и утверждает выдачу ссуды по заявлению участника или отклоняет его.
*
* ### Шаг 4: Подтверждение оплаты
* Лицо, обладающее доступом к расчётному счёту кооператива совершает исходящий платеж и отмечает его выполненным.
* Контракт @ref public_gateway "Шлюза" подтверждает успешное перечисление средств Вкладчику через действие @ref capital::debtpaycnfrm.
* Контракт @ref public_gateway "Шлюза" подтверждает успешное перечисление средств Участнику через действие @ref capital::debtpaycnfrm.
*
* @pre Предварительные условия:
* - 📄 Совет авторизовал выдачу ссуды
* - Gateway инициировал платёж
* @post Результат выполнения:
* - 📄 Фиксируется факт получения средств Вкладчиком
* - 📄 Фиксируется факт получения средств Участником
* - Создаётся запись в контракте @ref public_loan "Ссуд"
* - Увеличивается общий долг Вкладчика в системе
* - Вкладчик получает средства на свой банковский счёт
* - Увеличивается общий долг Участника в системе
* - Участник получает средства на свой банковский счёт
*
* @note Создание записи о долге в контракте loan фиксирует обязательство Вкладчика
* @note Создание записи о долге в контракте loan фиксирует обязательство Участника
* по возврату полученных средств, информация о котором доступна в том числе и в других контрактах.
*
* ### Альтернативные пути: Отклонение и отказы
@@ -166,7 +166,7 @@
* @post Результат выполнения:
* - Заявка удаляется из системы
* - Размер долга в сегменте уменьшается
* - Вкладчик может подать заявку повторно
* - Участник может подать заявку повторно
*
* #### Отклонение заявки
*
@@ -181,20 +181,20 @@
* Ссуды погашаются автоматически при внесении результата через действие @ref capital::pushrslt.
*
* @pre Предварительные условия:
* - Вкладчик вносит результат через pushrslt
* - Участник вносит результат через pushrslt
* - Указывается сумма долга для погашения
*
* @post Результат выполнения:
* - Сумма долга вычитается из стоимости результата после его внесения
* - Производится зачёт через контракт @ref public_loan
* - Списывается долг в контракте @ref public_loan
* - Уменьшаются обязательства Вкладчика
* - Уменьшаются обязательства Участника
*
* @note Автоматическое погашение обеспечивает защиту от рисков невозврата средств.
*
* ## Примеры расчёта доступных ссуд
*
* ### Пример 1: Создатель с коммитами
* ### Пример 1: Исполнитель с коммитами
* - Себестоимость работы создателя = 100,000 рублей (50 часов × 2000 рублей/час)
* - Коэффициент возврата = 80% (инвестиции покрывают 80% себестоимости затрат)
* - Обеспеченная сумма = 100,000 × 0.8 = 80,000 рублей
@@ -212,8 +212,8 @@
* - Обеспеченная сумма = 6,400 × 0.8 = 5,120 рублей
* - <b>Доступная ссуда: до 5,120 рублей</b>
*
* @note В примерах показано, как размер доступной ссуды зависит от фактических вкладов Вкладчика и
* коэффициента обеспеченности инвестициями. Чем больше Вкладчик вложил и чем больше инвестиций
* @note В примерах показано, как размер доступной ссуды зависит от фактических вкладов Участника и
* коэффициента обеспеченности инвестициями. Чем больше Участник вложил и чем больше инвестиций
* привлечено в проект, тем больше средств доступно для получения в виде ссуды.
*
* ## Влияние на конвертацию сегмента
@@ -6,16 +6,17 @@
* - Уменьшает debt_amount в сегменте
* - Удаляет долг из базы данных
* @param coopname Наименование кооператива
* @param username Наименование пользователя, отклонившего долг
* @param debt_hash Хеш долга для отклонения
* @param reason Причина отклонения долга
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p _gateway
* @note Авторизация требуется от контракта совета
*/
void capital::declinedebt(name coopname, checksum256 debt_hash, std::string reason) {
void capital::declinedebt(name coopname, eosio::name username, checksum256 debt_hash, std::string reason) {
//вызывается при отклонении советом или председателем из контракта совета
require_auth(_gateway);
name payer = check_auth_and_get_payer_or_fail({_gateway, _soviet});
// Получаем долг
auto exist_debt = Capital::Debts::get_debt_or_fail(coopname, debt_hash);
@@ -3,14 +3,14 @@
* @defgroup public_capital_fundprog_process Фондирование членских взносов на программу
* @ingroup public_capital_processes
*
* Кооператив может направлять накопленные членские взносы на распределение между всеми вкладчиками программы "Капитализация" в целях обеспечения возвратов их вкладов.
* Кооператив может направлять накопленные членские взносы на распределение между всеми участниками программы "Капитализация" в целях обеспечения возвратов их вкладов.
* Источником для регистрации входящих членских взносов является кошелек накопленных членских взносов кооператива.
*
* Процесс использует механизм CRPS - обновляет кумулятивный показатель на уровне программы
* без одновременного пересчета персональных кошельков вкладчиков. Расчёты долей по каждому вкладчику запрашиваются отдельно по @ref public_capital_refresh_program_process "процессу обновления кошелька программы".
* без одновременного пересчета персональных кошельков участников. Расчёты долей по каждому участнику запрашиваются отдельно по @ref public_capital_refresh_program_process "процессу обновления кошелька программы".
*
* @note CRPS помогает обойти ограничения блокчейна на количество одновременных математических вычислений, которые должны быть выполнены при приёме блока в цепочку каждым делегатом.
* Алгоритм позволяет динамично распределять общий пул среди вкладчиков независимо друг от друга и производя вычисления только для одного вкладчика за раз. Подробнее о алгоритме здесь: @ref public_capital_crps_algorithm.
* Алгоритм позволяет динамично распределять общий пул среди участников независимо друг от друга и производя вычисления только для одного участника за раз. Подробнее о алгоритме здесь: @ref public_capital_crps_algorithm.
*
* Формула обновления кумулятивного показателя:
*
@@ -39,9 +39,9 @@
* ### Шаг 1: Регистрация членских взносов программы
* @ref capital::fundprog "Регистрация входящих членских взносов по программе"
*
* Кооператив направляет накопленные членские взносы на распределение между вкладчиками программы капитализации.
* Кооператив направляет накопленные членские взносы на распределение между участниками программы капитализации.
* Для этого требуется вызов от авторизованного контракта (soviet/gateway) с указанием кооператива,
* суммы взноса и мемо. Метод валидирует сумму и обновляет кумулятивный показатель CRPS. После регистрации взноса вкладчики могут самостоятельно обновить свои начисления через @ref public_capital_refresh_program_process "процесс обновления кошелька программы". Или, кооператив может обновить эту информацию за них, но по одному.
* суммы взноса и мемо. Метод валидирует сумму и обновляет кумулятивный показатель CRPS. После регистрации взноса участники могут самостоятельно обновить свои начисления через @ref public_capital_refresh_program_process "процесс обновления кошелька программы". Или, кооператив может обновить эту информацию за них, но по одному.
*
* @post Обновление показателя CRPS для программы капитализации
*
@@ -3,12 +3,12 @@
@defgroup public_capital_refresh_program_process Обновление кошелька программы
@ingroup public_capital_processes
Процесс обновления в кошельке вкладчика информации о накопленном обеспечения членскими взносами в программе для возврата.
Процесс обновления в кошельке участника информации о накопленном обеспечения членскими взносами в программе для возврата.
Использует алгоритм CRPS для расчёта персональных начислений на основе
кумулятивного показателя программы и доли вкладчика.
кумулятивного показателя программы и доли участника.
Процесс обновляет доступные средства в кошельке программы вкладчика на основе разности между
текущим кумулятивным показателем программы и персональным слепком вкладчика.
Процесс обновляет доступные средства в кошельке программы участника на основе разности между
текущим кумулятивным показателем программы и персональным слепком участника.
@note кошелёк программы содержит информацию о накопленных членских взносах, доступных к возврату.
@@ -17,7 +17,7 @@
\htmlonly
<div class="mermaid">
sequenceDiagram
participant P as Вкладчик
participant P as Участник
participant C as Capital Contract
P->>C: 1. Обновление кошелька программы
@@ -29,27 +29,27 @@ sequenceDiagram
</div>
\endhtmlonly
@pre Вкладчик имеет баланс в программе капитализации
@pre Участник имеет баланс в программе капитализации
## Пошаговое описание
### Шаг 1: Обновление кошелька программы
@ref capital::refreshprog "Обновление кошелька программы"
Вкладчик инициирует обновление своего кошелька программы для обновления информации о доступных средствах к возврату из числа членских взносов в программу.
Участник инициирует обновление своего кошелька программы для обновления информации о доступных средствах к возврату из числа членских взносов в программу.
Механика расчёта:
- доля участника равна сумме заблокированных средств и доступных средств в кошельке программы
- delta_crps равна разности кумулятивного показателя программы и персонального слепка вкладчика
- delta_crps равна разности кумулятивного показателя программы и персонального слепка участника
- новые начисления равны произведению delta_crps на долю участника
Вкладчик получает начисления пропорционально своей доле в программе.
Участник получает начисления пропорционально своей доле в программе.
Алгоритм CRPS обеспечивает справедливое распределение с учётом времени
вхождения в программу и исключает начисления задним числом.
@note Математический пример:
Вкладчик с долей 100000 рублей при кумулятивном показателе программы равном 0.15
и персональном слепке вкладчика равном 0.05 получит: (0.15 - 0.05) * 100000 = 10000 рублей.
Участник с долей 100000 рублей при кумулятивном показателе программы равном 0.15
и персональном слепке участника равном 0.05 получит: (0.15 - 0.05) * 100000 = 10000 рублей.
@post доступные средства в кошельке программы увеличиваются на сумму новых начислений
@post персональный слепок CRPS устанавливается равным кумулятивному показателю программы
@@ -37,10 +37,10 @@ void capital::capdeclwthd3(name coopname, checksum256 withdraw_hash, std::string
});
// Обновляем глобальное состояние - возвращаем средства
auto state = Capital::get_global_state(coopname);
auto state = Capital::State::get_global_state(coopname);
state.program_membership_distributed -= withdraw->amount;
state.program_membership_available += withdraw->amount;
update_global_state(state);
Capital::State::update_global_state(state);
}
}
@@ -3,20 +3,20 @@
@defgroup public_capital_withdraw_from_program_process Возврат паевого взноса из программы
@ingroup public_capital_processes
Процесс возврата накопленных средств вкладчикам из программы капитализации представляет
Процесс возврата накопленных средств участникам из программы капитализации представляет
собой формализованную процедуру частичного или полного вывода членских взносов,
ранее внесенных вкладчиком в программу. Процесс включает подачу заявления вкладчиком,
ранее внесенных участником в программу. Процесс включает подачу заявления участником,
проверку достаточности накопленных средств, резервирование запрашиваемой суммы,
принятие решения советом кооператива и непосредственный перевод средств в
главный кошелёкек вкладчика. При отклонении заявления советом зарезервированная сумма возвращается
в кошелек вкладчика в программе капитализации.
главный кошелёкек участника. При отклонении заявления советом зарезервированная сумма возвращается
в кошелек участника в программе капитализации.
## Диаграмма процесса
\htmlonly
<div class="mermaid">
sequenceDiagram
participant P as Вкладчик
participant P as Участник
participant C as Capital Contract
participant S as Soviet Contract
participant W as Wallet Contract
@@ -33,17 +33,17 @@ sequenceDiagram
S->>C: 5. Авторизация возврата
Note over C: Подтверждение операции
C->>W: 6. Перевод средств в главный кошелёкёк
Note over W: Средства становятся<br/>доступны вкладчику
Note over W: Средства становятся<br/>доступны участнику
else Отклонение советом
S->>C: 5. Отклонение заявления
Note over C: Возврат зарезервированной<br/>суммы в кошелек вкладчика
Note over C: Возврат зарезервированной<br/>суммы в кошелек участника
end
</div>
\endhtmlonly
## Подача заявления вкладчиком
## Подача заявления участником
Вкладчик указывает сумму для возврата из программы капитализации. Система проверяет достаточность накопленных средств в программе. При успешной проверке запрашиваемая сумма резервируется (блокируется) в кошельке вкладчика в программе.
Участник указывает сумму для возврата из программы капитализации. Система проверяет достаточность накопленных средств в программе. При успешной проверке запрашиваемая сумма резервируется (блокируется) в кошельке участника в программе.
## Рассмотрение председателем
@@ -55,16 +55,16 @@ sequenceDiagram
## Исполнение решения
При одобрении средства переводятся в главный кошелёкек вкладчика. При отклонении зарезервированная сумма возвращается в кошелек вкладчика в программе капитализации.
При одобрении средства переводятся в главный кошелёкек участника. При отклонении зарезервированная сумма возвращается в кошелек участника в программе капитализации.
## Создание заявления на возврат из программы
@ref capital::createwthd3 "Создание заявления на возврат из программы"
Вкладчик подаёт заявление на возврат части накопленных членских взносов из программы капитализации:
Участник подаёт заявление на возврат части накопленных членских взносов из программы капитализации:
@pre <b>Входящий документ:</b> Заявление на возврат части паевого взноса из программы "Капитализация"
@pre <b>Предварительные условия:</b>
- Вкладчик имеет положительный баланс доступных средств в программе
- Участник имеет положительный баланс доступных средств в программе
- Запрашиваемая сумма не превышает доступный баланс
<b>Механика возврата:</b>
@@ -72,7 +72,7 @@ sequenceDiagram
- Проверяется достаточность доступных средств
- Сумма резервируется для возврата, что уменьшает доступный баланс в кошельке программы
<b>Результат:</b> Заявление создано, средства зарезервированы для возврата. После применения возврата доступная сумма к возврату уменьшается, так как уменьшается сумма на кошельке вкладчика в программе.
<b>Результат:</b> Заявление создано, средства зарезервированы для возврата. После применения возврата доступная сумма к возврату уменьшается, так как уменьшается сумма на кошельке участника в программе.
## Авторизация возврата из программы
@ref capital::capauthwthd3 "Авторизация возврата из программы"
@@ -86,7 +86,7 @@ sequenceDiagram
@ref capital::capdeclwthd3 "Отклонение возврата из программы"
При отклонении заявления:
- Сумма возвращается в кошелек вкладчика в программе капитализации
- Сумма возвращается в кошелек участника в программе капитализации
- Заявление удаляется из системы
## Эффекты процесса
@@ -3,16 +3,16 @@
@defgroup public_capital_fundproj_process Фондирование членских взносов на проект
@ingroup public_capital_processes
Кооператив может направлять накопленные членские взносы на распределение между всеми вкладчиками конкретного проекта.
Кооператив может направлять накопленные членские взносы на распределение между всеми участниками конкретного проекта.
Источником для регистрации входящих членских взносов является кошелек накопленных членских взносов кооператива по конкретному проекту.
Распределяемые членские взносы на проект являются обеспечением для возврата паевых взносов вкладчиков, которые выбрали проектное направление при @ref public_capital_conversion_process "конвертации результата"
Распределяемые членские взносы на проект являются обеспечением для возврата паевых взносов участников, которые выбрали проектное направление при @ref public_capital_conversion_process "конвертации результата"
по процессу @ref public_capital_withdraw_from_project_process "возврата средств из кошелька проекта".
Процесс использует механизм CRPS - обновляет кумулятивный показатель на уровне проекта
без одновременного пересчета персональных кошельков вкладчиков. Расчёты долей по каждому вкладчику запрашиваются отдельно по @ref public_capital_refresh_project_process "процессу обновления кошелька проекта".
без одновременного пересчета персональных кошельков участников. Расчёты долей по каждому участнику запрашиваются отдельно по @ref public_capital_refresh_project_process "процессу обновления кошелька проекта".
@note CRPS помогает обойти ограничения блокчейна на количество одновременных математических вычислений, которые должны быть выполнены при приёме блока в цепочку каждым делегатом.
Алгоритм позволяет динамично распределять общий пул среди вкладчиков независимо друг от друга и производя вычисления только для одного вкладчика за раз.
Алгоритм позволяет динамично распределять общий пул среди участников независимо друг от друга и производя вычисления только для одного участника за раз.
Формула обновления кумулятивного показателя:
@@ -43,14 +43,14 @@ sequenceDiagram
### Шаг 1: Регистрация членских взносов проекта
@ref capital::fundproj "Регистрация входящих членских взносов по проекту"
Кооператив направляет накопленные членские взносы на распределение между вкладчиками конкретного проекта.
Кооператив направляет накопленные членские взносы на распределение между участниками конкретного проекта.
Для этого требуется вызов от авторизованного контракта (soviet/gateway) с указанием кооператива,
хеша проекта, суммы взноса и мемо. Метод валидирует сумму, проверяет существование проекта и наличие долей,
затем обновляет кумулятивный показатель CRPS для данного проекта. После регистрации взноса вкладчики могут самостоятельно обновить свои начисления через @ref public_capital_refresh_project_process "процесс обновления кошелька проекта". Или, кооператив может обновить эту информацию за них, но по одному.
затем обновляет кумулятивный показатель CRPS для данного проекта. После регистрации взноса участники могут самостоятельно обновить свои начисления через @ref public_capital_refresh_project_process "процесс обновления кошелька проекта". Или, кооператив может обновить эту информацию за них, но по одному.
@post Обновление показателя CRPS для конкретного проекта
@post Средства становятся доступны для распределения между вкладчиками проекта
@post Обеспечение формируется для последующего возврата паевых взносов вкладчиков
@post Средства становятся доступны для распределения между участниками проекта
@post Обеспечение формируется для последующего возврата паевых взносов участников
## Эффекты процесса
@include{doc} fundproj-effect.dox
@@ -3,12 +3,12 @@
@defgroup public_capital_refresh_project_process Обновления кошелька проекта
@ingroup public_capital_processes
Процесс обновления в кошельке вкладчика информации о накопленном обеспечении членскими взносами по конкретному проекту для возврата.
Процесс обновления в кошельке участника информации о накопленном обеспечении членскими взносами по конкретному проекту для возврата.
Использует алгоритм CRPS для расчёта персональных начислений на основе
кумулятивного показателя проекта и доли вкладчика.
кумулятивного показателя проекта и доли участника.
Процесс обновляет кошелёк проекта вкладчика на основе разности между
текущим кумулятивным показателем проекта и персональным слепком вкладчика.
Процесс обновляет кошелёк проекта участника на основе разности между
текущим кумулятивным показателем проекта и персональным слепком участника.
@note кошелёк проекта содержит информацию о накопленных членских взносах от конкретного проекта, доступных к возврату.
@@ -17,7 +17,7 @@
\htmlonly
<div class="mermaid">
sequenceDiagram
participant P as Вкладчик
participant P as Участник
participant C as Capital Contract
P->>C: 1. Обновление кошелька проекта
@@ -29,28 +29,28 @@ sequenceDiagram
</div>
\endhtmlonly
@pre Вкладчик обладает кошельком в конкретном проекте
@pre Участник обладает кошельком в конкретном проекте
## Пошаговое описание
### Шаг 1: Обновление кошелька проекта
@ref capital::refreshproj "Обновление кошелька проекта"
Вкладчик инициирует обновление своего кошелька проекта для получения
Участник инициирует обновление своего кошелька проекта для получения
накопленных доходов от проектных членских взносов.
Механика расчёта:
- доля участника равна количеству долей участника в конкретном проекте
- delta_crps равна разности кумулятивного показателя проекта и персонального слепка вкладчика
- delta_crps равна разности кумулятивного показателя проекта и персонального слепка участника
- новые начисления равны произведению delta_crps на долю участника
Вкладчик получает начисления пропорционально своей доле в проекте.
Участник получает начисления пропорционально своей доле в проекте.
Алгоритм CRPS обеспечивает справедливое распределение с учётом времени
вхождения в проект и исключает начисления задним числом.
@note Математический пример:
Вкладчик с долей 1000 рублей при кумулятивном показателе проекта равном 0.15
и персональном слепке вкладчика равном 0.05 получит: (0.15 - 0.05) * 1000 = 100 рублей.
Участник с долей 1000 рублей при кумулятивном показателе проекта равном 0.15
и персональном слепке участника равном 0.05 получит: (0.15 - 0.05) * 1000 = 100 рублей.
@post доступные средства в кошельке проекта увеличиваются на сумму новых начислений
@post персональный слепок CRPS в кошельке проекта устанавливается равным кумулятивному показателю проекта
@@ -3,20 +3,20 @@
@defgroup public_capital_withdraw_from_project_process Возврат паевого взноса из проекта
@ingroup public_capital_processes
Процесс возврата накопленных средств вкладчикам из конкретного проекта представляет
Процесс возврата накопленных средств участникам из конкретного проекта представляет
собой формализованную процедуру частичного или полного вывода членских взносов,
ранее внесенных вкладчиком в проект. Процесс включает подачу заявления вкладчиком,
ранее внесенных участником в проект. Процесс включает подачу заявления участником,
проверку достаточности накопленных средств, резервирование запрашиваемой суммы,
принятие решения советом кооператива и непосредственный перевод средств в
главный кошелёкек вкладчика. При отклонении заявления советом зарезервированная сумма возвращается
в кошелек вкладчика в проекте.
главный кошелёкек участника. При отклонении заявления советом зарезервированная сумма возвращается
в кошелек участника в проекте.
## Диаграмма процесса
\htmlonly
<div class="mermaid">
sequenceDiagram
participant P as Вкладчик
participant P as Участник
participant C as Capital Contract
participant S as Soviet Contract
@@ -36,14 +36,14 @@ sequenceDiagram
Note over C: Перевод средств в главный кошелёкёк
else Отклонение советом
S->>C: 5. Отклонение заявления
Note over C: Возврат зарезервированной суммы<br/>в кошелек вкладчика
Note over C: Возврат зарезервированной суммы<br/>в кошелек участника
end
</div>
\endhtmlonly
## Подача заявления вкладчиком
## Подача заявления участником
Вкладчик указывает сумму для возврата из конкретного проекта. Система проверяет достаточность накопленных средств в проекте. При успешной проверке запрашиваемая сумма резервируется (блокируется) в кошельке вкладчика в проекте.
Участник указывает сумму для возврата из конкретного проекта. Система проверяет достаточность накопленных средств в проекте. При успешной проверке запрашиваемая сумма резервируется (блокируется) в кошельке участника в проекте.
## Рассмотрение председателем
@@ -55,16 +55,16 @@ sequenceDiagram
## Исполнение решения
При одобрении средства переводятся в главный кошелёкек вкладчика. При отклонении зарезервированная сумма возвращается в кошелек вкладчика в проекте.
При одобрении средства переводятся в главный кошелёкек участника. При отклонении зарезервированная сумма возвращается в кошелек участника в проекте.
## Создание заявления на возврат из проекта
@ref capital::createwthd2 "Создание заявления на возврат из проекта"
Вкладчик подаёт заявление на возврат части накопленных членских взносов из конкретного проекта:
Участник подаёт заявление на возврат части накопленных членских взносов из конкретного проекта:
@pre <b>Входящий документ:</b> Заявление на возврат части паевого взноса из проекта
@pre <b>Предварительные условия:</b>
- Вкладчик имеет положительный баланс доступных средств в проекте
- Участник имеет положительный баланс доступных средств в проекте
- Запрашиваемая сумма не превышает доступный баланс
<b>Механика возврата:</b>
@@ -72,7 +72,7 @@ sequenceDiagram
- Проверяется достаточность доступных средств
- Сумма резервируется для возврата, что уменьшает доступный баланс в кошельке проекта
<b>Результат:</b> Заявление создано, средства зарезервированы для возврата. После применения возврата доступная сумма к возврату уменьшается, так как уменьшается сумма на кошельке вкладчика в проекте.
<b>Результат:</b> Заявление создано, средства зарезервированы для возврата. После применения возврата доступная сумма к возврату уменьшается, так как уменьшается сумма на кошельке участника в проекте.
## Авторизация возврата из проекта
@ref capital::capauthwthd2 "Авторизация возврата из проекта"
@@ -86,7 +86,7 @@ sequenceDiagram
@ref capital::capdeclwthd2 "Отклонение возврата из проекта"
При отклонении заявления:
- Сумма возвращается в кошелек вкладчика в проекте
- Сумма возвращается в кошелек участника в проекте
- Заявление удаляется из системы
## Эффекты процесса
@@ -3,7 +3,7 @@
* Одобряет расход в проекте и отправляет в совет:
* - Проверяет подлинность одобренного заявления
* - Валидирует статус расхода (должен быть created)
* - Проверяет что создатель является участником проекта
* - Проверяет что исполнитель является участником проекта
* - Одобряет расход (обновляет статус)
* - Отправляет в совет для рассмотрения
* @param coopname Наименование кооператива
@@ -24,7 +24,7 @@ void capital::approveexpns(name coopname, name approver, checksum256 expense_has
auto expense = Capital::Expenses::get_expense_or_fail(coopname, expense_hash);
eosio::check(expense.status == Capital::Expenses::Status::CREATED, "Расход должен быть в статусе 'created'");
// Проверяем что создатель является участником проекта
// Проверяем что исполнитель является участником проекта
auto contributor = Capital::Contributors::get_active_contributor_with_appendix_or_fail(coopname, expense.project_hash, expense.username);
// Одобряем расход (простое обновление статуса)
@@ -3,14 +3,14 @@
@defgroup public_capital_create_expense_process Списание расходов
@ingroup public_capital_processes
Процесс создания, одобрения, авторизации и оплаты операционных расходов проекта из накопленного пула расходов представляет собой формализованную процедуру, которая позволяет вкладчикам проекта запрашивать расходы на операционные нужды проекта. Процесс включает подачу заявления вкладчиком, проверку достаточности накопленных средств в пуле расходов, резервирование запрашиваемой суммы, одобрение председателем и авторизацию советом кооператива. После авторизации происходит перевод средств через платёжный шлюз для оплаты расходов проекта.
Процесс создания, одобрения, авторизации и оплаты операционных расходов проекта из накопленного пула расходов представляет собой формализованную процедуру, которая позволяет участникам проекта запрашивать расходы на операционные нужды проекта. Процесс включает подачу заявления участником, проверку достаточности накопленных средств в пуле расходов, резервирование запрашиваемой суммы, одобрение председателем и авторизацию советом кооператива. После авторизации происходит перевод средств через платёжный шлюз для оплаты расходов проекта.
## Диаграмма процесса
\htmlonly
<div class="mermaid">
sequenceDiagram
participant P as Вкладчик
participant P as Участник
participant C as Capital Contract
participant S as Soviet Contract
participant G as Gateway Contract
@@ -36,11 +36,11 @@ sequenceDiagram
## Подача заявления о расходе
Вкладчик проекта подает заявление о необходимости расхода с указанием суммы расхода, описания назначения и обоснования в заявлении. Система проверяет подлинность заявления и корректность данных.
Участник проекта подает заявление о необходимости расхода с указанием суммы расхода, описания назначения и обоснования в заявлении. Система проверяет подлинность заявления и корректность данных.
## Проверка участия в проекте
Система проверяет наличие активного договора УХД вкладчика в проекте. Только активные вкладчики с подписанными приложениями могут создавать расходы.
Система проверяет наличие активного договора УХД участника в проекте. Только активные участники с подписанными приложениями могут создавать расходы.
## Проверка уникальности расхода
@@ -72,11 +72,11 @@ sequenceDiagram
## Создание заявления о расходе
@ref capital::createexpnse "Создание расхода"
Вкладчик проекта подаёт заявление о необходимости операционного расхода:
Участник проекта подаёт заявление о необходимости операционного расхода:
@pre <b>Входящий документ:</b> Заявление о необходимости операционного расхода проекта
@pre <b>Предварительные условия:</b>
- Вкладчик имеет активный договор УХД в проекте
- Участник имеет активный договор УХД в проекте
- Накопленные средства пула расходов достаточны для покрытия расхода
- Сумма расхода положительная
@@ -3,7 +3,7 @@
* Создает расход в проекте с резервированием средств:
* - Проверяет подлинность заявления о расходе
* - Валидирует сумму расхода (положительная)
* - Проверяет что создатель является участником проекта
* - Проверяет что исполнитель является участником проекта
* - Валидирует уникальность расхода по хешу
* - Проверяет доступность средств в пуле расходов проекта
* - Резервирует средства в проекте
@@ -29,7 +29,7 @@ void capital::createexpnse(eosio::name coopname, checksum256 expense_hash, check
eosio::check(amount.amount > 0, "Сумма должна быть положительной");
// Проверяем что создатель является участником проекта
// Проверяем что исполнитель является участником проекта
auto contributor = Capital::Contributors::get_active_contributor_with_appendix_or_fail(coopname, project_hash, creator);
// Проверяем что расхода с таким хэшем нет
@@ -3,11 +3,11 @@
* Одобряет коммит от мастера проекта и обрабатывает все связанные операции:
* - Проверяет что одобрение идет от мастера проекта
* - Получает коммит
* - Добавляет коммит к проекту
* - Обновляет или создает сегмент создателя
* - Распределяет авторские средства между всеми авторами проекта
* - Удаляет коммит после обработки
* @param coopname Наименование кооператива
* @param username Наименование пользователя, одобрившего коммит
* @param master Мастер проекта, одобряющий коммит
* @param commit_hash Хеш коммита для одобрения
* @ingroup public_actions
@@ -23,21 +23,21 @@ void capital::approvecmmt(eosio::name coopname, eosio::name master, checksum256
// Получаем проект и проверяем что мастер является мастером этого проекта
auto project = Capital::Projects::get_project_or_fail(coopname, commit.project_hash);
eosio::check(project.master == master, "Только мастер проекта может одобрять коммиты");
// Добавляем коммит к проекту
Capital::Projects::add_commit(coopname, commit.project_hash, commit.amounts);
// Обновляем или создаем сегмент создателя
Capital::Core::upsert_creator_segment(coopname, commit.project_hash, commit.username, commit.amounts);
// Распределяем авторские средства между всеми авторами проекта
Capital::Core::increment_authors_crps_in_project(coopname, commit.project_hash,
commit.amounts.authors_base_pool,
commit.amounts.authors_bonus_pool);
// Распределяем премии вкладчиков между всеми вкладчиками проекта через CRPS
// Распределяем премии участников между всеми участниками проекта через CRPS
Capital::Core::increment_contributors_crps_in_project(coopname, commit.project_hash, commit.amounts.contributors_bonus_pool);
// Удаляем коммит после обработки
Capital::Commits::delete_commit(coopname, commit_hash);
};
};
@@ -3,18 +3,18 @@
@defgroup public_capital_commit_creation_process Создание коммита
@ingroup public_capital_processes
Процесс фиксации трудозатрат создателя на проекте через создание коммита с указанием потраченного времени. Коммит инициирует пересчет затрат авторов и расчет будущих взносов всех вкладчиков. Процесс включает фиксацию трудозатрат создателем, проверку прав, уникальности коммита, расчет затрат и взносов, создание коммита в статусе ожидания одобрения, и последующее одобрение или отклонение мастером проекта.
Процесс фиксации трудозатрат создателя на проекте через создание коммита с указанием потраченного времени. Коммит инициирует пересчет затрат авторов и расчет будущих взносов всех участников. Процесс включает фиксацию трудозатрат создателем, проверку прав, уникальности коммита, расчет затрат и взносов, создание коммита в статусе ожидания одобрения, и последующее одобрение или отклонение мастером проекта.
@pre Проект находится в активном состоянии
@pre Создатель имеет действующий договор УХД
@pre Создатель подписал приложение к проекту
@pre Исполнитель имеет действующий договор УХД
@pre Исполнитель подписал приложение к проекту
## Диаграмма процесса
\htmlonly
<div class="mermaid">
sequenceDiagram
participant С as Создатель
participant С as Исполнитель
participant C as Capital Contract
participant G as Core Generation
participant М as Мастер проекта
@@ -24,7 +24,7 @@ sequenceDiagram
Note over C: Валидация прав создателя
Note over C: Проверка уникальности коммита
C->>G: 2. Расчет затрат и взносов
Note over G: Пересчет авторских затрат<br/>Расчет долей вкладчиков программы
Note over G: Пересчет авторских затрат<br/>Расчет долей участников программы
G->>C: 3. Создание коммита в статусе ОЖИДАНИЕ
Note over C: Коммит создан, ожидает одобрения мастера
М->>C: 4. Одобрение коммита
@@ -39,7 +39,7 @@ sequenceDiagram
## Фиксация трудозатрат создателем
Создатель инициирует фиксацию трудозатрат после выполнения работы над проектом с указанием количества потраченных часов. Коммит представляет зафиксированные трудозатраты создателя и служит основой для пересчета затрат авторов проекта, расчета будущих взносов вкладчиков программы капитализации и определения экономических показателей проекта.
Исполнитель инициирует фиксацию трудозатрат после выполнения работы над проектом с указанием количества потраченных часов. Коммит представляет зафиксированные трудозатраты создателя и служит основой для пересчета затрат авторов проекта, расчета будущих взносов участников программы капитализации и определения экономических показателей проекта.
## Валидация прав создателя
@@ -51,7 +51,7 @@ sequenceDiagram
## Расчет затрат и взносов
Система выполняет автоматический расчет базового вознаграждения создателя, пересчета затрат авторов проекта на основе новых трудозатрат и расчета будущих взносов всех вкладчиков программы капитализации при их участии в проекте. Расчет учитывает индивидуальную почасовую ставку создателя и автоматически распределяет суммы по категориям участников.
Система выполняет автоматический расчет базового вознаграждения создателя, пересчета затрат авторов проекта на основе новых трудозатрат и расчета будущих взносов всех участников программы капитализации при их участии в проекте. Расчет учитывает индивидуальную почасовую ставку создателя и автоматически распределяет суммы по категориям участников.
## Создание коммита в ожидании одобрения
@@ -60,19 +60,19 @@ sequenceDiagram
## Создание коммита
@ref capital::createcmmt "Создание коммита"
Создатель инициирует фиксацию трудозатрат после выполнения работы над проектом:
Исполнитель инициирует фиксацию трудозатрат после выполнения работы над проектом:
@pre <b>Предварительные условия:</b>
- Проект находится в активном состоянии
- Создатель имеет действующий договор УХД
- Создатель подписал приложение к проекту
- Исполнитель имеет действующий договор УХД
- Исполнитель подписал приложение к проекту
<b>Механика создания коммита:</b>
- Выполняется проверка прав создателя
- Проверяется уникальность хеша коммита
- Рассчитываются затраты и будущие взносы
<b>Результат:</b> Коммит создан и ожидает одобрения от мастера проекта. При одобрении происходит пересчет затрат авторов проекта и расчет будущих взносов вкладчиков программы капитализации.
<b>Результат:</b> Коммит создан и ожидает одобрения от мастера проекта. При одобрении происходит пересчет затрат авторов проекта и расчет будущих взносов участников программы капитализации.
@post Требуется авторизация создателя
@post Создан коммит с зафиксированными трудозатратами
@@ -14,12 +14,14 @@
* @param project_hash Хеш проекта
* @param commit_hash Хеш коммита
* @param creator_hours Количество часов создателя
* @param description Описание коммита
* @param meta Метаданные коммита
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p coopname
*/
void capital::createcmmt(eosio::name coopname, eosio::name username, checksum256 project_hash, checksum256 commit_hash, uint64_t creator_hours){
void capital::createcmmt(eosio::name coopname, eosio::name username, checksum256 project_hash, checksum256 commit_hash, uint64_t creator_hours, std::string description, std::string meta){
require_auth(coopname);
// Проверяем существование проекта и получаем его
@@ -57,7 +59,8 @@ void capital::createcmmt(eosio::name coopname, eosio::name username, checksum256
username,
project_hash,
commit_hash,
description,
meta,
delta_amounts
);
}
};
@@ -10,7 +10,6 @@
* @param reason Причина отклонения коммита
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p coopname
*/
void capital::declinecmmt(eosio::name coopname, eosio::name master, checksum256 commit_hash, std::string reason) {
@@ -17,6 +17,13 @@ void capital::rfrshsegment(eosio::name coopname, checksum256 project_hash, eosio
// Проверяем существование проекта
auto project = Capital::Projects::get_project_or_fail(coopname, project_hash);
auto segment_opt = Capital::Segments::get_segment_or_fail(coopname, project_hash, username, "Сегмент пайщика не найден");
// Если проект завершен и сегмент еще в генерации, переводим в статус готовности к внесению результата
if (project.status == Capital::Projects::Status::RESULT && segment_opt.status == Capital::Segments::Status::GENERATION) {
Capital::Segments::update_segment_status(coopname, project_hash, username, Capital::Segments::Status::READY);
}
// Обновляем сегмент участника через CRPS систему
Capital::Core::refresh_segment(coopname, project_hash, username);
}
@@ -3,8 +3,8 @@
* @defgroup public_capital_segment_refresh_process Обновления сегмента участника
* @ingroup public_capital_processes
*
* Процесс пересчета стоимостей будущего взноса вкладчика и лимитов ссуд с учетом новых поступивших взносов.
* Метод актуализирует состояние сегмента вкладчика в проекте.
* Процесс пересчета стоимостей будущего взноса участника и лимитов ссуд с учетом новых поступивших взносов.
* Метод актуализирует состояние сегмента участника в проекте.
*
* \htmlonly
* <div class="mermaid">
@@ -26,7 +26,7 @@
*
* Кооператив инициирует обновление сегмента участника когда:
* - Необходимо пересчитать лимиты ссуд
* - Поступили новые вклады, которые могли повлиять на сегмент вкладчика
* - Поступили новые вклады, которые могли повлиять на сегмент участника
*
* ### Шаг 2: Проверка существования проекта
* <b>Действие:</b> Валидация целевого проекта
@@ -1,12 +1,12 @@
/**
* @brief Добавляет вкладчика в проект через CRPS систему
* Добавляет вкладчика в проект через систему CRPS с автоматическими проверками:
* @brief Добавляет участника в проект через CRPS систему
* Добавляет участника в проект через систему CRPS с автоматическими проверками:
* - Проверяет существование проекта
* - Выполняет проверки через CRPS систему (активный договор УХД, приложение к проекту, положительный баланс)
* - Добавляет вкладчика через CRPS систему
* - Добавляет участника через CRPS систему
* @param coopname Наименование кооператива
* @param project_hash Хеш проекта
* @param username Наименование пользователя-вкладчика
* @param username Наименование пользователя-участника
* @ingroup public_actions
* @ingroup public_capital_actions
@@ -24,10 +24,10 @@ void capital::regshare(eosio::name coopname, checksum256 project_hash, eosio::na
auto exist_segment = Capital::Segments::get_segment(coopname, project_hash, username);
if (exist_segment.has_value()) {
// Проверяем что пользователь не зарегистрирован в проекте как вкладчик
eosio::check(!exist_segment -> is_contributor, "Вкладчик уже зарегистрирован в проекте");
// Проверяем что пользователь не зарегистрирован в проекте как участник
eosio::check(!exist_segment -> is_contributor, "Участник уже зарегистрирован в проекте");
}
// Добавляем вкладчика
// Добавляем участника
Capital::Core::upsert_contributor_segment(coopname, project_hash, username);
}
@@ -1,9 +1,9 @@
/**
@defgroup public_capital_share_registration_process Регистрация доли вкладчика
@defgroup public_capital_share_registration_process Регистрация доли участника
@ingroup public_capital_processes
Процесс, при котором вкладчик, являющийся участником программы "Капитализация", регистрирует свою долю в конкретном проекте для получения премий из пула премий вкладчиков. Процесс позволяет вкладчику участвовать в распределении премий проекта пропорционально своему балансу в программе "Капитализация".
Процесс, при котором участник, являющийся участником программы "Капитализация", регистрирует свою долю в конкретном проекте для получения премий из пула премий участников. Процесс позволяет участнику участвовать в распределении премий проекта пропорционально своему балансу в программе "Капитализация".
@pre
- Активный договор УХД с кооперативом
@@ -16,43 +16,43 @@
\htmlonly
<div class="mermaid">
sequenceDiagram
participant В as Вкладчик
participant В as Участник
participant C as Capital Contract
В->>C: 1. Запрос регистрации доли
Note over C: Проверка существования проекта
Note over C: Проверка условий участия
Note over C: Регистрация доли вкладчика
Note over C: Регистрация доли участника
</div>
\endhtmlonly
## Запрос регистрации доли вкладчиком
## Запрос регистрации доли участником
Вкладчик, который уже участвует в программе "Капитализация", самостоятельно инициирует процесс регистрации своей доли в проекте. Это необходимо для получения премий вкладчиков проекта.
Участник, который уже участвует в программе "Капитализация", самостоятельно инициирует процесс регистрации своей доли в проекте. Это необходимо для получения премий участников проекта.
## Проверка существования проекта
Система проверяет, что проект существует и доступен для регистрации долей вкладчиков. Проект должен быть активным и принимать участников.
Система проверяет, что проект существует и доступен для регистрации долей участников. Проект должен быть активным и принимать участников.
## Проверка условий участия
Система проверяет выполнение всех требований для участия в проекте:
- Наличие активного договора УХД с кооперативом у вкладчика
- Наличие активного договора УХД с кооперативом у участника
- Наличие подписанного приложения к конкретному проекту
- Положительный баланс вкладчика в программе "Капитализация"
- Техническая возможность участия в распределении премий вкладчиков
- Положительный баланс участника в программе "Капитализация"
- Техническая возможность участия в распределении премий участников
## Регистрация доли вкладчика
## Регистрация доли участника
Система создает сегмент вкладчика в проекте для учета его доли:
Система создает сегмент участника в проекте для учета его доли:
- Регистрирует долю пропорционально балансу в программе капитализации
- Устанавливает связь между программой и проектом
- Активирует пересчет доли в премиях вкладчиков при следующем @ref public_capital_segment_refresh_process "обновлении сегмента"
- Активирует пересчет доли в премиях участников при следующем @ref public_capital_segment_refresh_process "обновлении сегмента"
## Регистрация доли вкладчика
@ref capital::regshare "Добавление вкладчика"
## Регистрация доли участника
@ref capital::regshare "Добавление участника"
Вкладчик, который уже участвует в программе "Капитализация", самостоятельно инициирует процесс регистрации своей доли в проекте:
Участник, который уже участвует в программе "Капитализация", самостоятельно инициирует процесс регистрации своей доли в проекте:
@pre <b>Предварительные условия:</b>
- Активный договор УХД с кооперативом
@@ -62,14 +62,14 @@ sequenceDiagram
<b>Механика регистрации:</b>
- Выполняется проверка существования проекта
- Проверяются условия участия вкладчика
- Создается сегмент вкладчика в проекте
- Проверяются условия участия участника
- Создается сегмент участника в проекте
<b>Результат:</b> Вкладчик зарегистрирован в проекте и имеет право на получение премий пропорционально своему балансу в программе "Капитализация".
<b>Результат:</b> Участник зарегистрирован в проекте и имеет право на получение премий пропорционально своему балансу в программе "Капитализация".
@post Требуется авторизация вкладчика
@post Создан сегмент вкладчика в проекте
@post Активирован автоматический расчет доли вкладчика
@post Требуется авторизация участника
@post Создан сегмент участника в проекте
@post Активирован автоматический расчет доли участника
## Связанные процессы
@@ -61,7 +61,7 @@
- Средства зачисляются в пул инвестиций проекта
- Обновляется баланс программы капитализации
@note Распределение аллоцированных средств между пулом расходов и инвестиционным пулом проекта определяется в конфигурации кооператива. Если у проекта есть плановые непокрытые расходы, то в накопительный пул расходов выделяется процент от аллоцированной суммы, который установлен в конфигурации контракта параметром @c expense_pool_percent. Например, если у кооператива установлено значение 20% для пула расходов, то при аллокации средств в размере 10000 руб, в пул расходов пойдет 2000 руб, а оставшиеся 8000 руб пойдут в инвестиционный пул для обеспечения себестоимости затрат вкладчиков. При этом, если плановый пул расходов уже достаточно покрыт, то вся сумма может пойти в инвестиционный пул.
@note Распределение аллоцированных средств между пулом расходов и инвестиционным пулом проекта определяется в конфигурации кооператива. Если у проекта есть плановые непокрытые расходы, то в накопительный пул расходов выделяется процент от аллоцированной суммы, который установлен в конфигурации контракта параметром @c expense_pool_percent. Например, если у кооператива установлено значение 20% для пула расходов, то при аллокации средств в размере 10000 руб, в пул расходов пойдет 2000 руб, а оставшиеся 8000 руб пойдут в инвестиционный пул для обеспечения себестоимости затрат участников. При этом, если плановый пул расходов уже достаточно покрыт, то вся сумма может пойти в инвестиционный пул.
* ### Шаг 5: Активация использования средств
* <b>Действие:</b> Интеграция в систему проекта
@@ -17,7 +17,7 @@ void capital::diallocate(eosio::name coopname, checksum256 project_hash) {
// Проверяем, что проект выполнен
auto project = Capital::Projects::get_project_or_fail(coopname, project_hash);
eosio::check(project.status == Capital::Projects::Status::COMPLETED, "Проект должен быть выполнен");
eosio::check(project.status == Capital::Projects::Status::RESULT, "Проект должен быть выполнен");
// Проверяем есть ли неиспользованные программные средства
eosio::check(project.fact.program_invest_pool.amount > 0, "Нет программных средств для возврата");
@@ -7,14 +7,15 @@
* - Добавляет средства в глобальный пул доступных инвестиций
* - Удаляет инвестицию после обработки
* @param coopname Наименование кооператива
* @param username Наименование пользователя, одобрившего программную инвестицию
* @param invest_hash Хеш программной инвестиции для одобрения
* @param approved_statement Одобренное заявление об инвестиции
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p _soviet
* @note Авторизация требуется от контракта совета
*/
void capital::apprvpinv(eosio::name coopname, checksum256 invest_hash, document2 approved_statement) {
void capital::apprvpinv(eosio::name coopname, eosio::name username, checksum256 invest_hash, document2 approved_statement) {
require_auth(_soviet);
// Получаем программную инвестицию
@@ -5,14 +5,15 @@
* - Разблокирует средства в кошельке
* - Удаляет инвестицию после отклонения
* @param coopname Наименование кооператива
* @param username Наименование пользователя, отклонившего программную инвестицию
* @param invest_hash Хеш программной инвестиции для отклонения
* @param declined_statement Отклоненное заявление об инвестиции
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p _soviet
* @note Авторизация требуется от контракта совета
*/
void capital::declpinv(eosio::name coopname, checksum256 invest_hash, document2 declined_statement) {
void capital::declpinv(eosio::name coopname, eosio::name username, checksum256 invest_hash, document2 declined_statement) {
require_auth(_soviet);
// Получаем программную инвестицию
@@ -4,7 +4,7 @@
* @ingroup public_capital_processes
*
* Процесс управления инвестициями в программу "Капитализация", позволяющий
* вкладчикам направлять средства в общую программу с последующим централизованным
* участникам направлять средства в общую программу с последующим централизованным
* распределением по проектам. Процесс включает создание заявки на инвестирование,
* блокировку средств, одобрение или отклонение советом кооператива, а также
* перевод средств в программу или возврат инвестору.
@@ -9,14 +9,15 @@
* - Пополняет кошелек договора УХД и блокирует средства
* - Удаляет инвестицию после обработки
* @param coopname Наименование кооператива
* @param username Наименование пользователя, одобрившего инвестицию
* @param invest_hash Хеш инвестиции для одобрения
* @param approved_statement Одобренное заявление об инвестиции
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p _soviet
* @note Авторизация требуется от контракта совета
*/
void capital::approveinvst(eosio::name coopname, checksum256 invest_hash, document2 approved_statement) {
void capital::approveinvst(eosio::name coopname, eosio::name username, checksum256 invest_hash, document2 approved_statement) {
require_auth(_soviet);
// Получаем инвестицию
@@ -5,14 +5,15 @@
* - Разблокирует средства в программе кошелька
* - Удаляет инвестицию из базы данных
* @param coopname Наименование кооператива
* @param username Наименование пользователя, отклонившего инвестицию
* @param invest_hash Хеш инвестиции для отклонения
* @param decline_statement Отклоненное заявление об инвестиции
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p _soviet
* @note Авторизация требуется от контракта совета
*/
void capital::declineinvst(eosio::name coopname, checksum256 invest_hash, document2 decline_statement) {
void capital::declineinvst(eosio::name coopname, eosio::name username, checksum256 invest_hash, document2 decline_statement) {
require_auth(_soviet);
// Получаем инвестицию
@@ -3,12 +3,15 @@
* @defgroup public_capital_project_investment_process Инвестиции в проект
* @ingroup public_capital_processes
*
* Процесс привлечения денежных средств от вкладчиков в конкретный проект.
* Процесс привлечения денежных средств от участников в конкретный проект.
* Инвестиции распределяются между инвестиционным пулом и пулом расходов
* в соответствии с настройками кооператива. Процесс включает создание заявки
* на инвестицию, блокировку средств, одобрение или отклонение советом кооператива,
* а также распределение средств по пулам проекта при одобрении.
*
* @note КРИТИЧЕСКИ ВАЖНО: Чистые инвесторы (только роль инвестора) НЕ вносят результат через pushrslt.
* После завершения проекта они конвертируют свой сегмент напрямую через convertsegm.
*
* ## Диаграмма процесса
*
* \htmlonly
@@ -26,12 +29,14 @@
*
* alt Одобрение председателем и советом
* Контракт совета->>Контракт капитализации: 3. Одобрение инвестиции
* Контракт капитализации->>Контракт кошелька: 4. Перевод из главного кошелька в кошелек проекта
* Контракт капитализации->>Контракт кошелька: 4. Перевод из главного кошелька в кошелек проекта (source_program)
* Note over Контракт капитализации: Распределение по пулам:
* Note over Контракт капитализации: - Часть на расходы (expense_pool_percent)
* Note over Контракт капитализации: - Остаток в инвестиционный пул
* Note over Контракт капитализации: Расчёт координаторской премии
* Note over Контракт капитализации: Обновление коэффициентов проекта
* Note over Контракт капитализации: ВЗНОС ИНВЕСТОРА ЗАВЕРШЕН
* Note over Инвестор: Чистый инвестор НЕ вносит результат через pushrslt
* else Отклонение
* Контракт совета->>Контракт капитализации: 3. Отклонение инвестиции
* Контракт капитализации->>Контракт кошелька: 4. Разблокировка средств в главном кошельке
@@ -73,7 +78,7 @@
* - <b>На расходы:</b> часть средств направляется в пул расходов проекта
* - <b>В инвестиционный пул:</b> остаток средств направляется в инвестиционный пул
@note Распределение инвестиций между пулом расходов и инвестиционным пулом определяется в конфигурации кооператива. Если у проекта есть плановые непокрытые расходы, то в накопительный пул расходов выделяется процент от инвестиции, который установлен в конфигурации контракта параметром @c expense_pool_percent. Например, если у кооператива установлено значение 20% для пула расходов, то при поступлении инвестиции в размере 10000 руб, в пул расходов пойдет 2000 руб, а оставшиеся 8000 руб пойдут в инвестиционный пул для обеспечения себестоимости затрат вкладчиков. При этом, если плановый пул расходов уже достаточно покрыт, то вся инвестиция может пойти в инвестиционный пул.
@note Распределение инвестиций между пулом расходов и инвестиционным пулом определяется в конфигурации кооператива. Если у проекта есть плановые непокрытые расходы, то в накопительный пул расходов выделяется процент от инвестиции, который установлен в конфигурации контракта параметром @c expense_pool_percent. Например, если у кооператива установлено значение 20% для пула расходов, то при поступлении инвестиции в размере 10000 руб, в пул расходов пойдет 2000 руб, а оставшиеся 8000 руб пойдут в инвестиционный пул для обеспечения себестоимости затрат участников. При этом, если плановый пул расходов уже достаточно покрыт, то вся инвестиция может пойти в инвестиционный пул.
* <b>Обновление показателей проекта:</b>
* @post увеличение накопленного пула расходов проекта
@@ -85,9 +90,13 @@
* @post пересчет процента использования инвестиций
*
* <b>Обновление сегментов:</b>
* - Инвестор: увеличение суммы инвестиций, пересчёт предварительной суммы
* - Инвестор: увеличение суммы инвестиций, пересчёт предварительной суммы, установка флага is_investor
* - Координатор (если есть): увеличение базовой суммы координатора, пересчёт предварительной суммы
*
* @note ВАЖНО: Инвестиция является ПОЛНЫМ взносом инвестора в проект. Чистые инвесторы (без других ролей)
* НЕ должны вносить результат через pushrslt, так как их взнос уже учтен. После завершения проекта
* чистый инвестор может сразу конвертировать свой сегмент через convertsegm.
*
* ### Шаг 3: Отклонение инвестиции (альтернативный путь)
* @ref capital::declineinvst "Отклонение инвестиции"
*
@@ -20,7 +20,7 @@ void capital::returnunused(name coopname, checksum256 project_hash, name usernam
// Проверяем, что проект выполнен
auto project = Capital::Projects::get_project_or_fail(coopname, project_hash);
eosio::check(project.status == Capital::Projects::Status::COMPLETED, "Проект должен быть выполнен");
eosio::check(project.status == Capital::Projects::Status::RESULT, "Проект должен быть выполнен");
// Получаем сегмент инвестора
auto segment = Capital::Segments::get_segment_or_fail(coopname, project_hash, username, "Сегмент инвестора не найден");
@@ -0,0 +1,50 @@
/**
@defgroup public_capital_edit_contributor_process Редактирование параметров участника
@ingroup public_capital_processes
Процесс обновления параметров существующего участника кооператива.
Позволяет изменить количество рабочих часов в день.
\htmlonly
<div class="mermaid">
sequenceDiagram
participant К as Кооператив
participant Capital as Capital Contract
К->>Capital: 1. Запрос на редактирование параметров
Note over Capital: Проверка существования участника
Note over Capital: Проверка статуса ACTIVE
Capital->>Capital: 2. Обновление параметров участника
Note over Capital: hours_per_day обновлен
</div>
\endhtmlonly
## Пошаговое описание процесса
### Шаг 1: Запрос на редактирование
<b>Действие:</b> @ref capital::editcontrib "редактирование параметров участника"
Кооператив отправляет запрос на обновление параметров участника с новыми значениями
hours_per_day. Система проверяет существование участника и его активный статус.
@post Проверено существование активного участника
### Шаг 2: Обновление параметров
<b>Действие:</b> @ref capital::editcontrib "обновление записи участника"
Система обновляет поле hours_per_day в записи участника новым значением.
@post Обновлен параметр hours_per_day участника
## Результат процесса
После успешного завершения:
1. Обновлен параметр hours_per_day участника
2. Участник может продолжать участие в проектах с новыми параметрами
## Связанные процессы
- @ref public_capital_registration_process "Регистрация участников"
- @ref public_capital_joining_process "Получение допуска к проекту"
*/}
@@ -0,0 +1,27 @@
/**
* @brief Редактирование параметров участника
* Обновляет поля hours_per_day и about для существующего участника
* @param coopname Наименование кооператива
* @param username Наименование пользователя-участника
* @param hours_per_day Количество часов в день
* @param about Информация о себе
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p coopname
*/
void capital::editcontrib(eosio::name coopname, eosio::name username, eosio::asset rate_per_hour, uint64_t hours_per_day) {
require_auth(coopname);
// Проверяем существование активного участника
Capital::Contributors::get_active_contributor_or_fail(coopname, username);
Wallet::validate_asset(rate_per_hour);
eosio::check(hours_per_day >= 0, "Количество часов в день должно быть неотрицательным");
eosio::check(rate_per_hour.amount >= 0, "Ставка за час должна быть неотрицательной");
eosio::check(rate_per_hour.amount <= 30000000, "Ставка за час должна быть не более 30000000");
eosio::check(hours_per_day <= 8, "Количество часов в день должно быть не более 8");
// Обновляем параметры участника
Capital::Contributors::edit_contributor(coopname, username, rate_per_hour, hours_per_day);
};
@@ -7,14 +7,15 @@
* - Добавляет проект в вектор приложений пайщика
* - Удаляет приложение из базы
* @param coopname Наименование кооператива
* @param username Наименование пользователя, одобрившего приложение
* @param appendix_hash Хеш приложения к договору
* @param approved_document Одобренный документ приложения
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p _soviet
* @note Авторизация требуется от контракта совета
*/
void capital::apprvappndx(eosio::name coopname, checksum256 appendix_hash, document2 approved_document) {
void capital::apprvappndx(eosio::name coopname, eosio::name username, checksum256 appendix_hash, document2 approved_document) {
require_auth(_soviet);
// Находим приложение
@@ -4,14 +4,15 @@
* - Проверяет существование приложения
* - Удаляет приложение из базы данных с указанием причины
* @param coopname Наименование кооператива
* @param username Наименование пользователя, отклонившего приложение
* @param appendix_hash Хеш приложения к договору
* @param reason Причина отклонения приложения
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p _soviet
* @note Авторизация требуется от контракта совета
*/
void capital::dclineappndx(eosio::name coopname, checksum256 appendix_hash, std::string reason) {
void capital::dclineappndx(eosio::name coopname, eosio::name username, checksum256 appendix_hash, std::string reason) {
require_auth(_soviet);
// Находим приложение
@@ -22,7 +22,6 @@ void capital::getclearance(eosio::name coopname, eosio::name username, checksum2
// Проверяем что пользователь подписал общий договор УХД
auto contributor = Capital::Contributors::get_contributor(coopname, username);
eosio::check(contributor.has_value(), "Пайщик не подписывал основной договор УХД");
eosio::check(contributor -> status == Capital::Contributors::Status::ACTIVE, "Основной договор УХД не активен");
// Проверяем что приложение с таким хэшем не существует
auto exist_appendix = Capital::Appendix::get_appendix(coopname, appendix_hash);
@@ -3,15 +3,15 @@
@defgroup public_capital_joining_process Допуск к проекту
@ingroup public_capital_processes
@pre Пайщик имеет активный договор УХД и статус вкладчика
@pre Пайщик имеет активный договор УХД и статус участника
Процесс подписания приложений к договору УХД для участия вкладчика в конкретном проекте.
Процесс подписания приложений к договору УХД для участия участника в конкретном проекте.
Приложение к договору УХД определяет проект, по которому ведется участие в хозяйственной деятельности.
\htmlonly
<div class="mermaid">
sequenceDiagram
participant V as Вкладчик
participant V as Участник
participant C as Capital Contract
participant S as Soviet Contract
@@ -32,7 +32,7 @@
### Шаг 1: Подача заявки на допуск к проекту
@ref capital::getclearance "подача заявки на допуск к проекту"
Вкладчик с активным договором УХД подает заявку для участия в конкретном проекте.
Участник с активным договором УХД подает заявку для участия в конкретном проекте.
Необходимо предоставить подписанное приложение к договору УХД с указанием хеша проекта.
@post создается запись в таблице допуска со статусом PENDING
@@ -45,7 +45,7 @@
приложение к договору УХД своей подписью на документе.
@post статус допуска изменяется с PENDING на ACTIVE
@post вкладчик получает право участвовать в проекте
@post участник получает право участвовать в проекте
@post становится возможным создание коммитов и инвестиций в проект
### Шаг 3: Отклонение заявки (альтернативный путь)
@@ -54,7 +54,7 @@
При отклонении заявки председателем или советом запись удаляется
с указанием причины отказа.
@post вкладчик не получает доступ к участию в проекте
@post участник не получает доступ к участию в проекте
## Документы процесса
@include{doc} joining-process-docs.dox
@@ -1,8 +1,8 @@
/**
@defgroup public_capital_import_contributor_process Импорт вкладчиков
@defgroup public_capital_import_contributor_process Импорт участников
@ingroup public_capital_processes
Процесс импорта внешних вкладчиков с автоматическим созданием записи в системе,
Процесс импорта внешних участников с автоматическим созданием записи в системе,
открытием программного кошелька и внесением первоначальных взносов.
Используется для добавления существующего распределения вкладов пайщиков кооператива в цифровую систему.
@@ -13,11 +13,11 @@
participant К as Capital Contract
participant С as Soviet Contract
А->>К: 1. Импорт вкладчика с взносами
А->>К: 1. Импорт участника с взносами
Note over К: Проверка отсутствия конфигурации кооператива
Note over К: Валидация суммы взносов
Note over К: Проверка уникальности вкладчика
К->>К: 2. Создание записи вкладчика
Note over К: Проверка уникальности участника
К->>К: 2. Создание записи участника
Note over К: Статус ACTIVE, внешний договор
К->>С: 3. Открытие программного кошелька
Note over С: Создание кошелька в программе капитализации
@@ -28,31 +28,31 @@
## Пошаговое описание процесса
### Шаг 1: Импорт вкладчика с взносами
<b>Действие:</b> @ref capital::importcontrib "импорт вкладчика"
### Шаг 1: Импорт участника с взносами
<b>Действие:</b> @ref capital::importcontrib "импорт участника"
Администратор кооператива инициирует импорт внешнего вкладчика с указанием суммы первоначальных взносов.
Администратор кооператива инициирует импорт внешнего участника с указанием суммы первоначальных взносов.
Система проверяет, что кооператив еще не имеет установленной конфигурации, валидирует сумму взносов
и проверяет уникальность вкладчика по имени и хешу.
и проверяет уникальность участника по имени и хешу.
@post Проверяется отсутствие конфигурации кооператива
@post Валидируется сумма взносов
@post Проверяется уникальность вкладчика
@post Проверяется уникальность участника
### Шаг 2: Создание записи вкладчика
<b>Действие:</b> @ref capital::importcontrib "создание записи вкладчика"
### Шаг 2: Создание записи участника
<b>Действие:</b> @ref capital::importcontrib "создание записи участника"
Система создает запись вкладчика со статусом ACTIVE, помечая его как импортированного
Система создает запись участника со статусом ACTIVE, помечая его как импортированного
с внешним договором УХД и фиксированной почасовой ставкой.
@post Создается запись вкладчика со статусом ACTIVE
@post Создается запись участника со статусом ACTIVE
@post Устанавливается флаг внешнего договора УХД
@post Фиксируется почасовая ставка для импортированного вкладчика
@post Фиксируется почасовая ставка для импортированного участника
### Шаг 3: Открытие программного кошелька
<b>Действие:</b> @ref soviet::openprogwall "открытие кошелька программы"
Система открывает программный кошелек вкладчика в программе капитализации для учета
Система открывает программный кошелек участника в программе капитализации для учета
его членских взносов и участия в распределении доходов.
@post Создается программный кошелек в программе капитализации
@@ -61,7 +61,7 @@
### Шаг 4: Зачисление первоначальных взносов
<b>Действие:</b> @ref capital::importcontrib "зачисление взносов"
Система зачисляет указанную сумму первоначальных взносов в программный кошелек вкладчика,
Система зачисляет указанную сумму первоначальных взносов в программный кошелек участника,
блокируя средства для участия в программе капитализации.
@post Зачисляются первоначальные взносы в программный кошелек
@@ -71,7 +71,7 @@
## Результат процесса
После успешного завершения:
1. Внешний вкладчик становится полноценным участником системы капитализации
1. Внешний участник становится полноценным участником системы капитализации
2. Открыт программный кошелек для участии в программе капитализации
3. Внесены первоначальные взносы в программу капитализации
@@ -80,7 +80,7 @@
## Связанные процессы
- @ref public_capital_registration_process "Регистрация новых вкладчиков"
- @ref public_capital_registration_process "Регистрация новых участников"
- @ref public_capital_joining_process "Получение допуска к проекту"
*/
@@ -1,23 +1,23 @@
/**
* @brief Импорт внешнего вкладчика с автоматическим созданием записи и внесением взносов
* Создает запись вкладчика в системе капитализации для внешних участников кооператива:
* @brief Импорт внешнего участника с автоматическим созданием записи и внесением взносов
* Создает запись участника в системе капитализации для внешних участников кооператива:
* - Проверяет отсутствие конфигурации кооператива для возможности импорта
* - Валидирует сумму первоначальных взносов
* - Создает запись вкладчика со статусом ACTIVE и внешним договором УХД
* - Создает запись участника со статусом ACTIVE и внешним договором УХД
* - Открывает программный кошелек в программе капитализации
* - Зачисляет первоначальные взносы с блокировкой средств
* @param coopname Наименование кооператива
* @param username Наименование импортируемого вкладчика
* @param contributor_hash Уникальный хеш для идентификации вкладчика
* @param username Наименование импортируемого участника
* @param contributor_hash Уникальный хеш для идентификации участника
* @param contribution_amount Сумма первоначальных взносов в программу капитализации
* @param memo Мемо для импортированных вкладчиков
* @param memo Мемо для импортированных участников
* @ingroup public_actions
* @ingroup public_capital_actions
*
* @note Авторизация требуется от аккаунта: @p coopname
* @note Импорт возможен только до установки конфигурации кооператива
*
* @post Создается запись вкладчика со статусом ACTIVE
* @post Создается запись участника со статусом ACTIVE
* @post Открывается программный кошелек в программе капитализации
* @post Зачисляются первоначальные взносы с блокировкой средств
*/
@@ -27,27 +27,26 @@ void capital::importcontrib(eosio::name coopname, eosio::name username, checksum
// Проверка, что конфиг кооператива еще не установлен
Capital::global_state_table global_state_inst(_self, _self.value);
auto global_state_itr = global_state_inst.find(coopname.value);
eosio::check(global_state_itr == global_state_inst.end(), "Невозможно импортировать вкладчика: кооператив уже имеет установленную конфигурацию");
eosio::check(global_state_itr != global_state_inst.end(), "Невозможно импортировать участника: кооператив не активировал контракт");
// Проверка суммы взносов
Wallet::validate_asset(contribution_amount);
eosio::check(contribution_amount.amount > 0, "Сумма взносов должна быть положительной");
// Проверка, что вкладчик еще не существует
// Проверка, что участник еще не существует
auto existing_contributor = Capital::Contributors::get_contributor(coopname, username);
eosio::check(!existing_contributor.has_value(), "Вкладчик уже существует");
eosio::check(!existing_contributor.has_value(), "Участник уже существует");
// Проверка, что contributor_hash уникален
auto existing_by_hash = Capital::Contributors::get_contributor_by_hash(coopname, contributor_hash);
eosio::check(!existing_by_hash.has_value(), "Хэш вкладчика не уникален");
eosio::check(!existing_by_hash.has_value(), "Хэш участника не уникален");
// Создание вкладчика
// Создание участника
Capital::Contributors::import_contributor(
coopname,
username,
contributor_hash,
memo,
asset(20000000, _root_govern_symbol) // rate_per_hour = 2000 RUB / за час для импортированных вкладчиков
memo
);
// Открытие кошелька в программе капитализации
@@ -0,0 +1,130 @@
/**
* @defgroup public_capital_level_up_notification_process Уведомление о переходе на новый уровень
* @ingroup public_capital_processes
*
* Процесс автоматического уведомления системы о достижении участником
* нового уровня в системе геймификации.
*
* ## Назначение процесса
*
* Когда энергия участника достигает 100%, происходит автоматический переход
* на следующий уровень. Система отправляет inline action уведомление, которое:
* - Фиксирует факт перехода в истории блокчейна
* - Может быть перехвачено контроллером для отправки push-уведомлений
* - Содержит информацию о предыдущем и новом уровне для аналитики
*
* \htmlonly
* <div class="mermaid">
* sequenceDiagram
* participant Contributor
* participant Capital_Contract
* participant External_System
*
* Note over Contributor: Вносит вклад в проект
* Contributor->>Capital_Contract: Действие приема результата
* Capital_Contract->>Capital_Contract: Обновление энергии
*
* alt Энергия >= 100%
* Capital_Contract->>Capital_Contract: level += 1<br/>energy = 0
* Capital_Contract->>Capital_Contract: inline action: lvlnotify
* Capital_Contract->>External_System: Уведомление о переходе уровня
* External_System->>Contributor: Push-уведомление<br/>"Поздравляем! Новый уровень!"
* end
* </div>
* \endhtmlonly
*
* ## Пошаговое описание процесса
*
* ### Шаг 1: Обнаружение перехода уровня
* <b>Триггер:</b> Функция @ref Capital::Contributors::add_energy_and_check_levelup
*
* При добавлении энергии система проверяет условие перехода:
* ```cpp
* if (energy >= 100.0) {
* level += 1;
* energy = 0.0;
* }
* ```
*
* ### Шаг 2: Отправка inline action
* <b>Действие:</b> @ref capital::lvlnotify "Уведомление о переходе уровня"
*
* Система автоматически вызывает inline action с параметрами:
* - `coopname` - кооператив участника
* - `username` - имя участника
* - `prev_level` - предыдущий уровень
* - `new_level` - новый уровень
*
* ### Шаг 3: Обработка внешними системами
* <b>Интеграция:</b> Контроллер и система уведомлений
*
* Внешние системы могут:
* 1. Слушать действие `lvlnotify` в истории блокчейна
* 2. Отправлять push-уведомления пользователям
* 3. Обновлять статистику и достижения в интерфейсе
* 4. Начислять дополнительные бонусы или награды
*
* ## Данные уведомления
*
* | Параметр | Тип | Описание |
* |----------|-----|----------|
* | `coopname` | name | Кооператив, в котором произошел переход |
* | `username` | name | Участник, достигший нового уровня |
* | `prev_level` | uint32_t | Предыдущий уровень участника |
* | `new_level` | uint32_t | Новый достигнутый уровень |
*
* ## Пример использования в контроллере
*
* Контроллер может обрабатывать это событие следующим образом:
*
* ```typescript
* // Подписка на действие lvlnotify
* contract.on('lvlnotify', async (data) => {
* const { coopname, username, prev_level, new_level } = data;
*
* // Отправка push-уведомления
* await notificationService.send(username, {
* title: '🎉 Поздравляем!',
* message: `Вы достигли ${new_level} уровня!`,
* type: 'level_up',
* data: { prev_level, new_level }
* });
*
* // Обновление достижений
* await achievementService.unlock(username, `level_${new_level}`);
* });
* ```
*
* ## Когда происходит уведомление
*
* Уведомление отправляется автоматически в следующих случаях:
*
* 1. **При приеме результата проекта:**
* - Участник вносит результат интеллектуальной деятельности
* - Обновляются его рейтинги и вклады
* - Рассчитывается прирост энергии
* - Если энергия >= 100%, происходит переход уровня
*
* ## Особенности реализации
*
* 1. **Inline action:** Вызывается автоматически из контракта,
* не требует отдельной транзакции.
*
* 2. **Авторизация:** Требуется от аккаунта контракта (_capital),
* не может быть вызвано извне напрямую.
*
* 3. **Логирование:** Информация записывается в историю блокчейна
* и доступна для аудита.
*
* 4. **Асинхронность:** Обработка уведомления внешними системами
* происходит асинхронно и не влияет на выполнение основного действия.
*
* @post
* - Отправлено уведомление о переходе уровня
* - Информация записана в историю блокчейна
* - Внешние системы могут обработать событие
*
* @see Capital::Contributors::add_energy_and_check_levelup
* @see Capital::Contributors::update_gamification_from_segment
*/
@@ -0,0 +1,26 @@
/**
* @brief Отправляет уведомление о переходе участника на новый уровень
* Inline action для уведомления системы о достижении участником нового уровня:
* - Вызывается автоматически при достижении энергии 100%
* - Содержит информацию о предыдущем и новом уровне
* - Может использоваться внешними системами для отправки уведомлений
* @param coopname Имя кооператива
* @param username Имя участника, достигшего нового уровня
* @param prev_level Предыдущий уровень участника
* @param new_level Новый уровень участника
* @ingroup public_actions
* @ingroup public_capital_actions
*
* @note Авторизация требуется от аккаунта: @p _capital (вызывается inline action)
*/
void capital::lvlnotify(eosio::name coopname, eosio::name username, uint32_t prev_level, uint32_t new_level) {
require_auth(_capital);
// Это уведомление может быть перехвачено внешними системами
// Контроллер может слушать это действие и отправлять уведомления пользователям
// Логирование для истории
eosio::print("Участник ", username, " кооператива ", coopname,
" перешел с уровня ", prev_level, " на уровень ", new_level);
}
@@ -0,0 +1,123 @@
/**
* @defgroup public_capital_refresh_contributor_process Обновление энергии участника
* @ingroup public_capital_processes
*
* Процесс обновления энергии участника с учетом естественного снижения (decay)
* в системе геймификации "Уровень и Энергия".
*
* ## Назначение процесса
*
* Энергия участника естественным образом снижается со временем, стимулируя
* регулярную активность в кооперативе. Данный процесс обновляет текущее значение
* энергии участника на основе:
* - Времени с последнего обновления
* - Настроенной скорости снижения энергии (energy_decay_rate_per_day)
*
* Процесс не добавляет энергию - прирост энергии происходит автоматически
* при внесении вкладов через другие операции контракта.
*
* \htmlonly
* <div class="mermaid">
* sequenceDiagram
* participant Кооператив
* participant Capital_Contract
* participant Contributor_Table
*
* Кооператив->>Capital_Contract: 1. Запрос обновления энергии
* Note over Capital_Contract: Проверка авторизации
* Capital_Contract->>Contributor_Table: 2. Получение данных участника
* Capital_Contract->>Capital_Contract: 3. Расчет decay
* Note right of Capital_Contract: days_passed = (current_time - last_update) / 86400<br/>decay = days_passed × decay_rate_per_day
* Capital_Contract->>Contributor_Table: 4. Обновление энергии
* Note right of Contributor_Table: energy = max(0, energy - decay)<br/>last_energy_update = current_time
* Capital_Contract-->>Кооператив: Энергия обновлена
* </div>
* \endhtmlonly
*
* ## Пошаговое описание процесса
*
* ### Шаг 1: Авторизация кооператива
* <b>Действие:</b> Проверка авторизации от имени кооператива
*
* Только кооператив может обновлять энергию участников. Это централизованная
* операция обслуживания системы геймификации.
*
* ### Шаг 2: Получение данных участника
* <b>Действие:</b> @ref capital::refreshcontr "Обновление энергии участника"
*
* Система загружает текущее состояние участника из таблицы contributors,
* включая:
* - Текущий уровень энергии (energy)
* - Время последнего обновления (last_energy_update)
*
* ### Шаг 3: Расчет естественного снижения (decay)
* <b>Формула расчета:</b>
*
* 1. Рассчитывается количество прошедших дней:
* \f[
* days\_passed = \frac{current\_time - last\_energy\_update}{86400}
* \f]
*
* 2. Применяется decay на основе настроенной скорости:
* \f[
* decay = days\_passed \times energy\_decay\_rate\_per\_day
* \f]
*
* 3. Обновляется энергия:
* \f[
* new\_energy = max(0.0, current\_energy - decay)
* \f]
*
* ### Шаг 4: Сохранение обновленного состояния
* <b>Действие:</b> Запись в таблицу @ref Capital::contributor
*
* Система сохраняет:
* - Новое значение энергии
* - Текущее время как last_energy_update
*
* ## Параметры геймификации
*
* Процесс использует следующие параметры из конфигурации:
*
* | Параметр | По умолчанию | Описание |
* |----------|--------------|----------|
* | `energy_decay_rate_per_day` | 1.11% | Скорость снижения энергии в день |
*
* **Примеры настройки:**
* - **1.11%** - энергия снизится до 0 за 90 дней (3 месяца) без активности
* - **2.0%** - более агрессивное снижение за 50 дней
* - **0.5%** - мягкое снижение за 200 дней
*
* ## Взаимосвязь с другими процессами
*
* **Прирост энергии:**
* Энергия увеличивается автоматически при:
* - @ref public_capital_result_process "Приёме результата в кооператив"
*
* В этих процессах после обновления рейтингов вызывается
* @ref Capital::Contributors::update_gamification_from_segment,
* который рассчитывает прирост энергии от вкладов.
*
* **Переход на новый уровень:**
* Когда энергия достигает 100%, участник автоматически переходит
* на следующий уровень и получает уведомление через действие
* @ref capital::lvlnotify "lvlnotify".
*
* ## Примечания по использованию
*
* 1. **Регулярность обновления:** Рекомендуется вызывать это действие
* периодически (например, раз в день) для всех активных участников.
*
* 2. **Автоматизация:** Может быть реализовано через планировщик задач
* на стороне контроллера.
*
* 3. **Оптимизация:** Обновление не требуется, если участник недавно
* вносил вклады - в этом случае энергия уже актуальна.
*
* @post
* - Энергия участника обновлена с учетом прошедшего времени
* - Время последнего обновления установлено в текущее время
* - Энергия не может быть меньше 0
*
*/
@@ -0,0 +1,25 @@
/**
* @brief Обновляет энергию участника с учетом естественного снижения
* Применяет decay к энергии участника на основе прошедшего времени:
* - Проверяет авторизацию кооператива
* - Получает текущее состояние участника
* - Рассчитывает количество дней с последнего обновления
* - Применяет decay согласно настроенной скорости
* - Обновляет энергию и время последнего обновления
* @param coopname Имя кооператива
* @param username Имя участника для обновления
* @ingroup public_actions
* @ingroup public_capital_actions
*
* @note Авторизация требуется от аккаунта: @p coopname
*/
void capital::refreshcontr(eosio::name coopname, eosio::name username) {
require_auth(coopname);
// Проверяем существование активного участника
Capital::Contributors::get_active_contributor_or_fail(coopname, username);
// Обновляем энергию с учетом decay
Capital::Gamification::update_energy_with_decay(coopname, username);
}
@@ -1,21 +1,21 @@
/**
* @brief Принимает принятый председателем договор УХД и активирует вкладчика по нему
* @brief Принимает принятый председателем договор УХД и активирует участника по нему
* Активирует пайщика в системе кооператива после одобрения договора УХД:
* - Проверяет подлинность договора УХД
* - Валидирует статус пайщика (должен быть PENDING)
* - Активирует пайщика и устанавливает принятый договор
* - Создает программный кошелек для пайщика если необходимо
* @param coopname Имя кооператива
* @param username Наименование пользователя, одобрившего регистрацию
* @param contributor_hash Хэш контрибьютора
* @param contract Договор УХД
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p coopname
* @note Авторизация требуется от контракта совета
*/
void capital::approvereg(eosio::name coopname, checksum256 contributor_hash, document2 contract) {
void capital::approvereg(eosio::name coopname, eosio::name username, checksum256 contributor_hash, document2 contract) {
name payer = check_auth_and_get_payer_or_fail(contracts_whitelist);
verify_document_or_fail(contract);
auto exist = Capital::Contributors::get_contributor_by_hash(coopname, contributor_hash);
@@ -28,7 +28,7 @@ void capital::approvereg(eosio::name coopname, checksum256 contributor_hash, doc
eosio::check(contributor != contributors.end(), "Пайщик не зарегистрирован в контракте");
// Обновляем пайщика и устанавливаем принятый договор УХД
contributors.modify(contributor, coopname, [&](auto &c){
contributors.modify(contributor, payer, [&](auto &c){
c.status = Capital::Contributors::Status::ACTIVE;
c.contract = contract;
});
@@ -1,19 +1,20 @@
/**
* @brief Отклоняет председателем договор УХД и удаляет вкладчика из базы
* Отклоняет регистрацию вкладчика и удаляет его из системы кооператива:
* - Проверяет существование вкладчика по хешу
* - Валидирует статус вкладчика (должен быть PENDING)
* - Удаляет вкладчика из базы данных с указанием причины
* @brief Отклоняет председателем договор УХД и удаляет участника из базы
* Отклоняет регистрацию участника и удаляет его из системы кооператива:
* - Проверяет существование участника по хешу
* - Валидирует статус участника (должен быть PENDING)
* - Удаляет участника из базы данных с указанием причины
* @param coopname Имя кооператива
* @param username Наименование пользователя, отклонившего регистрацию
* @param contributor_hash Хэш контрибьютора
* @param reason Причина отклонения
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p coopname
* @note Авторизация требуется от контракта совета
*/
void capital::declinereg(eosio::name coopname, checksum256 contributor_hash, std::string reason) {
name payer = check_auth_and_get_payer_or_fail(contracts_whitelist);
void capital::declinereg(eosio::name coopname, eosio::name username, checksum256 contributor_hash, std::string reason) {
require_auth(_soviet);
auto exist = Capital::Contributors::get_contributor_by_hash(coopname, contributor_hash);
eosio::check(exist.has_value(), "Пайщик не обладает подписанным договором УХД");
@@ -16,7 +16,7 @@
* @note Авторизация требуется от аккаунта: @p coopname
*/
void capital::regcontrib(eosio::name coopname, eosio::name username, checksum256 contributor_hash, eosio::asset rate_per_hour, bool is_external_contract, document2 contract) {
void capital::regcontrib(eosio::name coopname, eosio::name username, checksum256 contributor_hash, eosio::asset rate_per_hour, uint64_t hours_per_day, bool is_external_contract, document2 contract) {
require_auth(coopname);
// если договор не внешний, то проверяем его на корректность
@@ -26,6 +26,10 @@ void capital::regcontrib(eosio::name coopname, eosio::name username, checksum256
}
Wallet::validate_asset(rate_per_hour);
eosio::check(hours_per_day >= 0, "Количество часов в день должно быть неотрицательным");
eosio::check(rate_per_hour.amount >= 0, "Ставка за час должна быть неотрицательной");
eosio::check(rate_per_hour.amount <= 30000000, "Ставка за час должна быть не более 30000000");
eosio::check(hours_per_day <= 12, "Количество часов в день должно быть не более 12");
auto exist_by_username = Capital::Contributors::get_contributor(coopname, username);
eosio::check(!exist_by_username.has_value(), "Пайщик уже обладает подписанным договором УХД");
@@ -33,7 +37,7 @@ void capital::regcontrib(eosio::name coopname, eosio::name username, checksum256
auto exist_by_hash = Capital::Contributors::get_contributor_by_hash(coopname, contributor_hash);
eosio::check(!exist_by_hash.has_value(), "Контрибьютор с данным хэшем уже зарегистрирован");
Capital::Contributors::create_contributor(coopname, username, contributor_hash, is_external_contract, contract, rate_per_hour);
Capital::Contributors::create_contributor(coopname, username, contributor_hash, is_external_contract, contract, rate_per_hour, hours_per_day);
std::string memo = "";
@@ -1,9 +1,9 @@
/**
@defgroup public_capital_registration_process Регистрация вкладчиков
@defgroup public_capital_registration_process Регистрация участников
@ingroup public_capital_processes
Процесс приёма договора УХД от пайщика, смены его статуса с кандидата в вкладчики на активного вкладчика
Процесс приёма договора УХД от пайщика, смены его статуса с кандидата в участники на активного участника
и обеспечения технической возможности участвовать в проектах и программе капитализации.
\htmlonly
@@ -16,11 +16,11 @@
П->>К: 1. Подача договора УХД
Note over К: Проверка уникальности кандидата
Note over К: Валидация договора УХД
К->>К: 2. Создание записи кандидата в вкладчики
К->>К: 2. Создание записи кандидата в участники
К->>С: 3. Направление на одобрение
alt Одобрение
С->>К: 4. Авторизация регистрации
Note over К: Смена статуса: кандидат → вкладчик
Note over К: Смена статуса: кандидат → участник
Note over К: Создание программного кошелька
else Отклонение
С->>К: 4. Отклонение регистрации
@@ -39,16 +39,16 @@
Система проверяет уникальность кандидата и хеша контрибьютора, валидирует договор УХД.
@post Передан договор УХД
@post Создается запись кандидата в вкладчики
@post Создается запись кандидата в участники
@post Создается заявка на одобрение
### Шаг 2: Создание записи кандидата в вкладчики
### Шаг 2: Создание записи кандидата в участники
<b>Действие:</b> @ref capital::regcontrib "создание записи кандидата"
Система создает запись кандидата в вкладчики со статусом PENDING с зафиксированными параметрами:
Система создает запись кандидата в участники со статусом PENDING с зафиксированными параметрами:
почасовой ставкой, договором УХД и уникальным хешем.
@post Создается запись кандидата в вкладчики со статусом PENDING
@post Создается запись кандидата в участники со статусом PENDING
### Шаг 3: Направление на одобрение
<b>Действие:</b> @ref Soviet::create_approval "направление заявки на рассмотрение"
@@ -59,24 +59,24 @@
@post Создается заявка на одобрение
### Шаг 4: Авторизация регистрации
<b>Действие:</b> @ref capital::approvereg "одобрение регистрации вкладчика"
<b>Действие:</b> @ref capital::approvereg "одобрение регистрации участника"
Председатель одобряет регистрацию вкладчика. Система меняет статус кандидата с PENDING на ACTIVE,
превращая его в полноправного вкладчика, и создает программный кошелек для участия в проектах.
Председатель одобряет регистрацию участника. Система меняет статус кандидата с PENDING на ACTIVE,
превращая его в полноправного участника, и создает программный кошелек для участия в проектах.
@post Изменяется статус кандидата на ACTIVE (кандидат становится вкладчиком)
@post Создается программный кошелек для вкладчика
@post Изменяется статус кандидата на ACTIVE (кандидат становится участником)
@post Создается программный кошелек для участника
<b>Альтернатива:</b> @ref capital::declinereg "отклонение регистрации"
При отклонении система удаляет запись кандидата в вкладчики из базы данных с указанием причины отказа.
При отклонении система удаляет запись кандидата в участники из базы данных с указанием причины отказа.
@post Удаляется запись кандидата в вкладчики
@post Удаляется запись кандидата в участники
## Результат процесса
После успешного завершения:
1. Пайщик-кандидат становится полноправным вкладчиком со статусом ACTIVE
1. Пайщик-кандидат становится полноправным участником со статусом ACTIVE
2. Зафиксированы условия оценки трудового вклада
3. Создана правовая основа для участия в проектах через договор УХД
4. Открыт программный кошелек для операций по проектам
@@ -3,12 +3,12 @@
@defgroup public_capital_add_author_process Добавления соавтора проекта
@ingroup public_capital_processes
@pre Вкладчик имеет активное приложение к договору УХД для данного проекта
@pre Вкладчик еще не является автором проекта
@pre Участник имеет активное приложение к договору УХД для данного проекта
@pre Участник еще не является автором проекта
@pre Не превышен лимит авторов проекта
Процесс назначения мастером проекта соавторов из числа вкладчиков, обладающих экспертизой
и видением для планирования результата интеллектуальной деятельности, а также, вкладчиков, исторически причастных к рождению идею. Соавторы участвуют в планировании проекта
Процесс назначения мастером проекта соавторов из числа участников, обладающих экспертизой
и видением для планирования результата интеллектуальной деятельности, а также, участников, исторически причастных к рождению идею. Соавторы участвуют в планировании проекта
и определении требований к результату. Авторы могут быть и создателями одновременно, фиксируя свой вклад коммитами.
\htmlonly
@@ -18,7 +18,7 @@
participant C as Capital Contract
M->>C: 1. Добавление соавтора проекта
Note over C: Проверка статуса вкладчика
Note over C: Проверка статуса участника
Note over C: Валидация лимитов авторов
Note over C: Создание авторского сегмента
</div>
@@ -27,13 +27,13 @@
### Шаг 1: Добавление соавтора проекта
Действие: @ref capital::addauthor "добавление соавтора проекта"
Мастер добавляет вкладчика в роли соавтора к проекту для участия в планировании
Мастер добавляет участника в роли соавтора к проекту для участия в планировании
и определении требований к будущему результату. Соавторы обладают экспертизой
и видением того, что должно быть создано, участвуют в формировании концепции проекта
на этапе планирования, в отличие от создателей, которые фиксируют трудозатраты
коммитами на этапе генерации.
@post вкладчик получает право на авторские доли в результате проекта
@post участник получает право на авторские доли в результате проекта
@post активируется участие в авторском распределении премий
@post предоставляется право голоса на голосовании за пул премий по системе Водянова
*/
@@ -0,0 +1,25 @@
/**
* @brief Закрывает проект от приёма инвестиций
* Переводит проект в статус закрытого для приема инвестиций:
* - Проверяет существование проекта
* - Валидирует что проект открыт для инвестиций
* - Закрывает проект через доменную логику
* @param coopname Наименование кооператива
* @param project_hash Хеш проекта для закрытия
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p coopname
*/
void capital::closeproject(name coopname, checksum256 project_hash) {
require_auth(coopname);
// Проверяем существование проекта и получаем его
auto project = Capital::Projects::get_project_or_fail(coopname, project_hash);
// Проверяем, что проект открыт для инвестиций
eosio::check(project.is_opened == true, "Проект уже закрыт или не был открыт для инвестиций");
// Закрываем проект
Capital::Projects::close_project(coopname, project_hash);
}
@@ -0,0 +1,92 @@
/**
* @defgroup public_capital_project_close_process Закрытие проекта от инвестиций
* @ingroup public_capital_processes
* Процесс перевода открытого проекта в статус закрытого
* для прекращения привлечения инвестиций от участников кооператива.
* ## Назначение процесса
* Закрытие проекта от инвестиций обеспечивает:
* - Прекращение фазы привлечения средств
* - Блокировку возможности инвестирования для участников
* - Завершение формирования финансовой базы проекта
* - Подготовку к переходу на следующий этап жизненного цикла
* \htmlonly
* <div class="mermaid">
* sequenceDiagram
* participant К as Кооператив
* participant ПК as Контракт Capital
* participant П as Проект
* К->>ПК: 1. Инициация закрытия проекта
* Note over ПК: Проверка возможности закрытия
* ПК->>П: 2. Проверка статуса проекта
* alt Проект открыт для инвестиций
* П->>ПК: 3. Подтверждение статуса
* ПК->>П: 4. Закрытие проекта от инвестиций
* П->>К: 5. Проект закрыт от инвестиций
* else Проект уже закрыт
* ПК->>К: Ошибка: проект уже закрыт или не был открыт
* end
* </div>
* \endhtmlonly
* ## Пошаговое описание процесса
* ### Шаг 1: Инициация закрытия проекта
* <b>Действие:</b> @ref capital::closeproject "Закрытие проекта"
* Кооператив инициирует закрытие проекта от инвестиций после
* достижения необходимого уровня финансирования или по другим
* организационным причинам.
* ### Шаг 2: Проверка возможности закрытия
* <b>Действие:</b> Валидация предварительных условий
* Система проверяет возможность закрытия проекта:
* - Проект должен быть открыт для инвестиций (is_opened = true)
* - Проект должен существовать
* @post Подтвержден статус открытого проекта
* ### Шаг 3: Закрытие проекта
* <b>Действие:</b> Деактивация инвестиционной фазы
* Система переводит проект в статус закрытого для инвестиций:
* - Устанавливает флаг is_opened = false
* - Блокирует возможность операций инвестирования
* - Сохраняет все ранее привлеченные средства
* @post Проект закрыт для приема инвестиций
* @post Флаг is_opened установлен в false
* ## Условия для закрытия
* <b>Обязательные требования:</b>
* - Проект должен быть открыт для инвестиций (is_opened = true)
* <b>Результат закрытия:</b>
* - Флаг is_opened устанавливается в false
* - Блокируются операции инвестирования
* - Сохраняются все ранее привлеченные инвестиции
* ## Результат процесса
* После завершения процесса:
* 1. Проект переведен в статус закрытого для инвестиций
* 2. Деактивированы механизмы привлечения средств
* 3. Сохранена финансовая основа проекта
* 4. Подготовлен переход к следующим этапам жизненного цикла
* ## Связанные процессы
* - @ref public_capital_project_opening_process "Открытие проекта для инвестиций" - обратная операция
* - @ref public_capital_project_investment_process "Инвестирование в проект" - завершаемый этап
* - @ref public_capital_project_start_process "Запуск генерации проекта" - возможный следующий этап
* @see capital::closeproject
* @see Capital::Projects::close_project
* @see Capital::Projects::get_project_or_fail
*/
@@ -21,7 +21,7 @@ void capital::cmpltvoting(name coopname, checksum256 project_hash) {
// Проверяем, что голосование завершено
eosio::check(Capital::Core::Voting::is_voting_completed(project), "Голосование еще не завершено");
// Обновляем статус проекта на "completed"
Capital::Projects::update_status(coopname, project_hash, Capital::Projects::Status::COMPLETED);
// Обновляем статус проекта на "result"
Capital::Projects::update_status(coopname, project_hash, Capital::Projects::Status::RESULT);
}
@@ -9,7 +9,9 @@
* @param parent_hash Хэш родителя или пустой хэш, если проект корневой
* @param title Название проекта
* @param description Описание проекта
* @param invite Приглашение к проекту
* @param meta Дополнительные метаданные проекта
* @param data Данные/шаблон проекта
* @param can_convert_to_project Разрешена ли конвертация в кошелек данного проекта
* @ingroup public_actions
* @ingroup public_capital_actions
@@ -17,21 +19,37 @@
* @note Авторизация требуется от аккаунта: @p coopname
*/
void capital::createproj (
eosio::name coopname,
eosio::name coopname,
checksum256 project_hash,
checksum256 parent_hash,
std::string title,
std::string title,
std::string description,
std::string invite,
std::string meta,
std::string data,
bool can_convert_to_project
) {
require_auth(coopname);
// Проверяем что контракт инициализирован
Capital::State::is_initialized(coopname);
// Проверяем что проекта с таким хэшем еще не существует
auto exist = Capital::Projects::get_project(coopname, project_hash);
eosio::check(!exist.has_value(), "Проект с указанным хэшем уже существует");
// Валидируем parent_hash согласно правилам проектов
Capital::Projects::validate_parent_hash(coopname, parent_hash);
Capital::Projects::create_project(coopname, project_hash, parent_hash, title, description, meta, can_convert_to_project);
Capital::Projects::create_project(coopname, project_hash, parent_hash, title, description, invite, meta, data, can_convert_to_project);
// Копируем соавторов с родительского проекта, если он существует
checksum256 empty_hash = checksum256();
if (parent_hash != empty_hash) {
auto parent_authors = Capital::Segments::get_project_authors(coopname, parent_hash);
for (const auto& author_segment : parent_authors) {
// Создаем сегмент автора в новом проекте с нулевым состоянием
Capital::Core::upsert_author_segment(coopname, project_hash, author_segment.username);
}
}
}
@@ -22,25 +22,29 @@
Note over C: Проверка уникальности хеша
Note over C: Валидация родительского проекта
C->>C: Создание записи проекта
Note over C: Копирование соавторов (если есть родитель)
Note over C: Статус: CREATED, готов к планированию
</div>
\endhtmlonly
## Пошаговое описание процесса
@note При создании проекта возможно указать родительский проект, который станет мета-проектом.
Подробнее о мета-проектах см. @ref capital_meta_projects "Мета-проекты".
### Шаг 1: Создание проекта
<b>Действие:</b> @ref capital::createproj "создание проекта"
Кооператив создает проект в системе после прохождения отбора в банке идей.
Система проверяет уникальность хеша проекта и валидирует родительский проект,
затем создает запись со статусом CREATED.
@post создается запись проекта в таблице projects
@post статус проекта устанавливается в CREATED
@post проект готов к переходу в фазу планирования
## Пошаговое описание процесса
@note При создании проекта возможно указать родительский проект, который станет мета-проектом.
Подробнее о мета-проектах см. @ref capital_meta_projects "Мета-проекты".
### Шаг 1: Создание проекта
<b>Действие:</b> @ref capital::createproj "создание проекта"
Кооператив создает проект в системе после прохождения отбора в банке идей.
Система проверяет уникальность хеша проекта и валидирует родительский проект,
затем создает запись со статусом CREATED. Если указан родительский проект,
автоматически копируются все соавторы родительского проекта в новый проект
с нулевым состоянием вкладов.
@post создается запись проекта в таблице projects
@post статус проекта устанавливается в CREATED
@post если указан родительский проект, копируются его соавторы в новый проект
@post проект готов к переходу в фазу планирования
## Документы процесса
@include{doc} project-creation-docs.dox
@@ -17,7 +17,7 @@ void capital::delproject(name coopname, checksum256 project_hash) {
require_auth(coopname);
auto project = Capital::Projects::get_project_or_fail(coopname, project_hash);
eosio::check(project.status == Capital::Projects::Status::COMPLETED, "Проект должен быть в статусе 'completed'");
eosio::check(project.status == Capital::Projects::Status::RESULT, "Проект должен быть в статусе 'result'");
// Проверяем что все сегменты сконвертированы (удалены)
eosio::check(!Capital::Segments::has_project_segments(coopname, project_hash),
@@ -0,0 +1,42 @@
/**
* @brief Редактирует проект
* Выполняет проверки и редактирует существующий проект в системе кооператива:
* - Проверяет существование проекта с указанным хэшем
* - Проверяет что проект не завершен
* - Обновляет указанные поля проекта
* @param coopname Имя кооператива (scope таблицы)
* @param project_hash Уникальный хэш проекта для редактирования
* @param title Новое название проекта
* @param description Новое описание проекта
* @param invite Новое приглашение к проекту
* @param meta Новые метаданные проекта
* @param data Новые данные/шаблон проекта
* @param can_convert_to_project Разрешена ли конвертация в кошелек данного проекта
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p coopname
*/
void capital::editproj (
eosio::name coopname,
checksum256 project_hash,
std::string title,
std::string description,
std::string invite,
std::string meta,
std::string data,
bool can_convert_to_project
) {
require_auth(coopname);
// Проверяем что проект существует
auto exist = Capital::Projects::get_project(coopname, project_hash);
eosio::check(exist.has_value(), "Проект с указанным хэшем не найден.");
// Проверяем что проект не завершен
eosio::check(exist->status != Capital::Projects::Status::RESULT &&
exist->status != Capital::Projects::Status::CANCELLED,
"Нельзя редактировать завершенный проект");
Capital::Projects::edit_project(coopname, project_hash, title, description, invite, meta, data, can_convert_to_project);
}
@@ -0,0 +1 @@
- 📄 Шаблонизированная часть приложения к договору УХД образуется предметом проекта, которая устанавливается при редактировании проекта
@@ -0,0 +1,49 @@
/**
@defgroup public_capital_project_editing_process Редактировать проект
@ingroup public_capital_processes
@pre Проект должен существовать в системе кооператива
@pre Проект не должен быть завершен (COMPLETED или CLOSED)
Процесс редактирования существующего проекта в системе кооператива для
обновления его параметров. Процесс позволяет изменять основные поля проекта
без нарушения его работоспособности и связей.
\htmlonly
<div class="mermaid">
sequenceDiagram
participant К as Кооператив
participant C as Capital Contract
participant П as Проект
Note over П: Проект существует
К->>C: Редактирование проекта
Note over C: Проверка существования проекта
Note over C: Проверка статуса проекта
C->>C: Обновление полей проекта
Note over C: Поля обновлены, связи сохранены
</div>
\endhtmlonly
## Пошаговое описание процесса
@note При редактировании проекта можно изменять следующие поля: название, описание, приглашение, метаданные, настройку конвертации.
@note Пустые строки в параметрах означают что поле не нужно изменять.
@note Нельзя редактировать завершенные проекты (со статусом COMPLETED или CLOSED).
### Шаг 1: Редактирование проекта
<b>Действие:</b> @ref capital::editproj "редактирование проекта"
Кооператив редактирует проект в системе после получения соответствующих прав.
Система проверяет существование проекта и его статус, затем обновляет
указанные поля без изменения связей и зависимостей.
@post обновляются только указанные непустые поля проекта
@post связи и зависимости проекта остаются неизменными
@post статус и идентификаторы проекта не изменяются
## Документы процесса
@include{doc} project-editing-docs.dox
*/
@@ -10,7 +10,7 @@
* Установка мастера проекта обеспечивает назначение ответственного за управление проектом,
* который будет осуществлять централизованную координацию работы команды, контролировать
* качество и сроки выполнения задач, а также выступать в роли связующего звена между
* вкладчиками проекта и кооперативом. Мастер играет ключевую роль в успешной реализации
* участниками проекта и кооперативом. Мастер играет ключевую роль в успешной реализации
* проекта и несет персональную ответственность за достижение поставленных целей и результатов.
* Мастер при добавлении к проекту становится его соавтором.
*
@@ -20,7 +20,7 @@
* participant К as Кооператив
* participant ПК as Контракт Capital
* participant П as Проект
* participant В as Вкладчик
* participant В as Участник
*
* К->>ПК: 1. Инициация назначения мастера
* Note over ПК: Проверка существования проекта
@@ -30,12 +30,12 @@
* ПК->>В: 4. Проверка договора УХД
* В->>ПК: 5. Подтверждение активного договора
* ПК->>П: 6. Проверка участия в проекте
* alt Вкладчик - участник проекта
* alt Участник - участник проекта
* П->>ПК: 7. Подтверждение участия
* ПК->>П: 8. Назначение мастера
* П->>К: 9. Мастер назначен
* else Вкладчик не участник
* ПК->>К: Ошибка: вкладчик не участник проекта
* else Участник не участник
* ПК->>К: Ошибка: участник не участник проекта
* end
* else Проект не существует
* ПК->>К: Ошибка: проект не найден
@@ -15,27 +15,33 @@
*/
void capital::setmaster(name coopname, checksum256 project_hash, name master) {
require_auth(coopname);
// Проверяем что проект существует
auto project = Capital::Projects::get_project(coopname, project_hash);
eosio::check(project.has_value(), "Проект не найден");
// Если мастер не указан (пустая строка), просто снимаем назначение мастера
if (master == name()) {
Capital::Projects::set_master(coopname, project -> id, name());
return;
}
// Проверяем что пользователь подписал основной договор УХД
auto contributor = Capital::Contributors::get_contributor(coopname, master);
eosio::check(contributor.has_value(), "Мастер должен подписать основной договор УХД");
eosio::check(contributor -> status == Capital::Contributors::Status::ACTIVE, "Основной договор УХД не активен");
// Проверяем что пользователь является участником проекта
eosio::check(Capital::Contributors::is_contributor_has_appendix_in_project(coopname, project_hash, master),
eosio::check(Capital::Contributors::is_contributor_has_appendix_in_project(coopname, project_hash, master),
"Мастер должен быть участником проекта");
// Назначаем мастера проекта
Capital::Projects::set_master(coopname, project -> id, master);
// Проверяем лимит количества авторов
uint64_t current_authors_count = Capital::Segments::count_project_authors(coopname, project_hash);
eosio::check(current_authors_count < MAX_PROJECT_AUTHORS, "Превышено максимальное количество соавторов в проекте");
// Добавляем мастера как соавтора в проект
Capital::Core::upsert_author_segment(coopname, project_hash, master);
@@ -102,7 +102,7 @@
* 2. Себестоимость авторов составляет 61.8% от себестоимости создателей (золотое сечение)
* 3. Координаторские премии рассчитываются как процент от общей суммы (настраивается в конфиге контракта кооператива, 4% по дефолту)
* 4. Премии создателей и авторов составляют 100% от их себестоимости
* 5. Премии вкладчиков составляют 161.8% от себестоимости вкладов авторов, создателей, координаторов
* 5. Премии участников составляют 161.8% от себестоимости вкладов авторов, создателей, координаторов
*
* ### Пример расчёта (500 часов, 2000 RUB/час, 4% координаторам)
*
@@ -26,7 +26,7 @@ void capital::setplan(name coopname, name master, checksum256 project_hash, uint
eosio::check(project.master == master, "Мастер проекта не совпадает с мастером, который устанавливает план");
// Проверяем, что проект в статусе "pending"
eosio::check(project.status == Capital::Projects::Status::PENDING, "Проект должен быть в статусе 'pending'");
eosio::check(project.status == Capital::Projects::Status::PENDING || project.status == Capital::Projects::Status::ACTIVE || project.status == Capital::Projects::Status::VOTING, "Проект должен быть в статусе 'pending' или 'planned'");
Wallet::validate_asset(plan_expenses);
Wallet::validate_asset(plan_hour_cost);
@@ -20,6 +20,7 @@ void capital::startvoting(name coopname, checksum256 project_hash) {
// Проверяем, что проект в статусе "active"
eosio::check(project.status == Capital::Projects::Status::ACTIVE, "Проект должен быть в статусе 'active'");
eosio::check(project.counts.total_commits > 0, "Проект без коммитов не может быть поставлен на голосование");
// Обновляем статус проекта на "voting"
Capital::Projects::update_status(coopname, project_hash, Capital::Projects::Status::VOTING);
@@ -0,0 +1,93 @@
/**
* @defgroup public_capital_project_stop_process Остановка проекта
* @ingroup public_capital_processes
* Остановка проекта обеспечивает переход от активной фазы обратно к подготовительной,
* временно запрещает создание коммитов участниками, приостанавливает фиксацию трудозатрат
* и генерацию результата, а также деактивирует основные операции по созданию интеллектуального
* результата проекта до момента возобновления работы.
* \htmlonly
* <div class="mermaid">
* sequenceDiagram
* participant К as Кооператив
* participant ПК as Контракт Capital
* participant П as Проект
* К->>ПК: 1. Инициация остановки проекта
* Note over ПК: Проверка возможности остановки
* ПК->>П: 2. Проверка статуса проекта
* alt Проект в статусе ACTIVE
* П->>ПК: 3. Подтверждение статуса
* ПК->>П: 4. Перевод в статус ожидания
* П->>К: 5. Проект остановлен
* else Проект не в статусе ACTIVE
* ПК->>К: Ошибка: проект не в активном статусе
* end
* </div>
* \endhtmlonly
* ## Пошаговое описание процесса
* ### Шаг 1: Инициация остановки проекта
* <b>Действие:</b> @ref capital::pauseproject "Приостановка проекта"
* Кооператив инициирует остановку проекта в случае необходимости временного
* прекращения работ по проекту для решения организационных вопросов,
* перераспределения ресурсов или других причин.
* @post Проверка авторизации кооператива
* ### Шаг 2: Проверка возможности остановки
* <b>Действие:</b> Валидация предварительных условий
* Система проверяет возможность остановки проекта, подтверждая что проект
* находится в статусе ACTIVE и может быть переведен обратно в подготовительную фазу.
* @post Подтвержден статус ACTIVE проекта
* ### Шаг 3: Перевод в статус ожидания
* <b>Действие:</b> Деактивация рабочей фазы
* Система переводит проект в статус PENDING, что временно запрещает создание коммитов
* участниками, приостанавливает операции генерации результата, блокирует выдачу ссуд
* авторам/создателям/координаторам и ограничивает доступ к операционным функциям.
* @post Статус проекта изменен на PENDING
* ## Особенности остановки проекта
* Приостановка проекта может быть использована для временного прекращения работ
* без потери накопленных результатов и данных. После возобновления работы все
* ранее созданные коммиты, инвестиции и другие данные остаются доступными.
* ## Операции, недоступные после остановки
* После перевода в статус PENDING становятся недоступными:
* - @ref public_capital_commit_creation_process "Создание коммитов"
* - @ref public_capital_debt_process "Выдача ссуд участникам"
* - @ref public_capital_create_expense_process "Создание расходов"
* - @ref public_capital_project_property_process "Имущественные взносы"
* ## Возобновление работы
* Для возобновления работы над проектом необходимо выполнить действие
* @ref public_capital_project_start_process "запуска проекта", которое
* вернет проект в активный статус.
* ## Критерии возобновления работы
* Работа над проектом может быть возобновлена когда устранены причины остановки,
* ресурсы перераспределены и команда готова к продолжению работ.
* @post
* 1. Проект переведен в статус ожидания
* 2. Запрещено создание коммитов участниками
* 3. Деактивированы основные операции генерации
* ## Связанные процессы
* - @ref public_capital_project_start_process "Запуск проекта" - возобновление работы
* - @ref public_capital_commit_creation_process "Создание коммитов" - основная деятельность
* - @ref public_capital_voting_start_process "Начало голосования" - следующий этап после возобновления
*/
@@ -0,0 +1,25 @@
/**
* @brief Останавливает проект
* Переводит проект из активного статуса обратно в статус ожидания:
* - Проверяет существование проекта
* - Валидирует что проект в статусе active
* - Обновляет статус проекта на pending
* @param coopname Наименование кооператива
* @param project_hash Хеш проекта для остановки
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p coopname
*/
void capital::stopproject(name coopname, checksum256 project_hash) {
require_auth(coopname);
// Проверяем существование проекта и получаем его
auto project = Capital::Projects::get_project_or_fail(coopname, project_hash);
// Проверяем, что проект в статусе "active"
eosio::check(project.status == Capital::Projects::Status::ACTIVE, "Проект должен быть в статусе 'active'");
// Обновляем статус проекта на "pending"
Capital::Projects::update_status(coopname, project_hash, Capital::Projects::Status::PENDING);
}
@@ -7,14 +7,15 @@
* - Обновляет статус на approved
* - Отправляет на рассмотрение совета
* @param coopname Наименование кооператива
* @param username Наименование пользователя, одобрившего программный имущественный взнос
* @param property_hash Хеш программного имущественного взноса для принятия
* @param approved_statement Одобренное заявление председателя
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p _soviet
* @note Авторизация требуется от контракта совета
*/
void capital::approvepgprp(eosio::name coopname, checksum256 property_hash, document2 approved_statement) {
void capital::approvepgprp(eosio::name coopname, eosio::name username, checksum256 property_hash, document2 approved_statement) {
require_auth(_soviet);
auto soviet = get_board_by_type_or_fail(coopname, "soviet"_n);
@@ -7,7 +7,7 @@
* - Валидирует сумму и описание имущества
* - Создает предложение и отправляет на одобрение
* @param coopname Наименование кооператива
* @param username Наименование пользователя-вкладчика
* @param username Наименование пользователя-участника
* @param property_hash Хеш программного имущественного взноса
* @param property_amount Стоимость имущества
* @param property_description Описание имущества
@@ -4,14 +4,15 @@
* - Получает предложение по программному имущественному взносу
* - Удаляет предложение из базы данных с указанием причины
* @param coopname Наименование кооператива
* @param username Наименование пользователя, отклонившего программный имущественный взнос
* @param property_hash Хеш программного имущественного взноса для отклонения
* @param reason Причина отклонения предложения
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p _soviet
* @note Авторизация требуется от контракта совета
*/
void capital::declinepgprp(eosio::name coopname, checksum256 property_hash, std::string reason) {
void capital::declinepgprp(eosio::name coopname, eosio::name username, checksum256 property_hash, std::string reason) {
require_auth(_soviet);
auto property = Capital::ProgramProperties::get_program_property_or_fail(coopname, property_hash);
@@ -12,7 +12,7 @@
* \htmlonly
* <div class="mermaid">
* sequenceDiagram
* participant P as Собственник
* participant P as Пропертор
* participant C as Capital Contract
* participant S as Soviet Contract
* participant W as Кошелек программы
@@ -42,13 +42,13 @@
* ### Шаг 1: Создание заявления на программный имущественный взнос
* @ref capital::createpgprp "Создание имущественного взноса в программу"
*
* Собственник подаёт заявление на внесение имущества в программу "Капитализации":
* Пропертор подаёт заявление на внесение имущества в программу "Капитализации":
*
* <b>Входящий документ:</b> Заявление на паевой взнос "Исключительные права на имущество" (подписано участником)
*
* <b>Предварительные условия:</b>
* - Собственник имеет активный договор УХД
* - Собственник подписал соглашение об условиях ЦПП "Капитализация"
* - Пропертор имеет активный договор УХД
* - Пропертор подписал соглашение об условиях ЦПП "Капитализация"
* - Имущество соответствует требованиям кооператива
*
* <b>Входящие параметры:</b>
@@ -88,7 +88,7 @@
* ### Шаг 4: Подписание акта №1 участником
* @ref capital::act1pgprp "Подписание акта №1 участником"
*
* Собственник подписывает акт приёма-передачи имущества:
* Пропертор подписывает акт приёма-передачи имущества:
*
* <b>Входящий документ:</b> Акт приёма-передачи доли в имуществе (подпись участника)
*
@@ -132,7 +132,7 @@
*
* ## Связанные процессы
*
* - @ref public_capital_registration_process "Регистрация вкладчиков" - требуется активный договор УХД
* - @ref public_capital_registration_process "Регистрация участников" - требуется активный договор УХД
* - @ref public_capital_project_property_process "Имущественные взносы в проект" - альтернативное направление
* - @ref public_capital_membership_process "Распределение членских взносов" - получение доходов
* - @ref public_capital_conversion_process "Конвертация взносов" - имущественные взносы направляются в программу
@@ -6,14 +6,15 @@
* - Обновляет или создает сегмент пропертора с имущественным взносом
* - Удаляет предложение после обработки
* @param coopname Наименование кооператива
* @param username Наименование пользователя, одобрившего имущественный взнос
* @param property_hash Хеш имущественного взноса для принятия
* @param empty_document Пустой документ (не используется)
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p _soviet
* @note Авторизация требуется от контракта совета
*/
void capital::approvepjprp(eosio::name coopname, checksum256 property_hash, document2 empty_document) {
void capital::approvepjprp(eosio::name coopname, eosio::name username, checksum256 property_hash, document2 empty_document) {
require_auth(_soviet);
// Получаем предложение
@@ -8,7 +8,7 @@
* - Валидирует сумму и описание имущества
* - Создает предложение и отправляет на одобрение
* @param coopname Наименование кооператива
* @param username Наименование пользователя-вкладчика
* @param username Наименование пользователя-участника
* @param project_hash Хеш проекта
* @param property_hash Хеш имущественного взноса
* @param property_amount Стоимость имущества
@@ -4,14 +4,15 @@
* - Получает предложение по имущественному взносу
* - Удаляет предложение из базы данных с указанием причины
* @param coopname Наименование кооператива
* @param username Наименование пользователя, отклонившего имущественный взнос
* @param property_hash Хеш имущественного взноса для отклонения
* @param reason Причина отклонения предложения
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p _soviet
* @note Авторизация требуется от контракта совета
*/
void capital::declinepjprp(eosio::name coopname, checksum256 property_hash, std::string reason) {
void capital::declinepjprp(eosio::name coopname, eosio::name username, checksum256 property_hash, std::string reason) {
require_auth(_soviet);
auto property = Capital::ProjectProperties::get_property_or_fail(coopname, property_hash);
@@ -12,7 +12,7 @@
* \htmlonly
* <div class="mermaid">
* sequenceDiagram
* participant O as Собственник
* participant O as Пропертор
* participant C as Capital Contract
* participant S as Soviet Contract
*
@@ -37,14 +37,14 @@
* ### Шаг 1: Создание заявления на паевой взнос имуществом
* @ref capital::createpjprp "Создание имущественного взноса в проект"
*
* Собственник подает заявление на внесение имущества в активный проект:
* Пропертор подает заявление на внесение имущества в активный проект:
*
* <b>Входящий документ:</b> Заявление на паевой взнос имуществом
*
* <b>Предварительные условия:</b>
* - Проект в статусе `active`
* - Собственник имеет активный договор УХД
* - Собственник подписал приложение к договору для данного проекта
* - Пропертор имеет активный договор УХД
* - Пропертор подписал приложение к договору для данного проекта
*
* <b>Входящие параметры:</b>
* - property_amount - оценочная стоимость имущества
@@ -60,7 +60,7 @@
*
* <b>Результат:</b> Создана заявка на имущественный взнос
*
* <b>Важно:</b> На этом этапе создается только предварительное предложение по имущественному взносу. Фактическое внесение имущества происходит на стадии приёма результата проекта, когда проект проходит стадию генерации и формирует готовый результат. В этот момент имущество передается наравне с другими вкладчиками проекта с подписанием акта приёма-передачи.
* <b>Важно:</b> На этом этапе создается только предварительное предложение по имущественному взносу. Фактическое внесение имущества происходит на стадии приёма результата проекта, когда проект проходит стадию генерации и формирует готовый результат. В этот момент имущество передается наравне с другими участниками проекта с подписанием акта приёма-передачи.
*
* ### Шаг 2: Принятие имущественного взноса
* @ref capital::approvepjprp "Принятие имущественного взноса в проект"
@@ -3,9 +3,11 @@
*
* @brief Конвертирует сегмент участника в различные типы кошельков
* Конвертирует сегмент участника в кошелек, капитал и кошелек проекта:
* - Проверяет статус сегмента (должен быть contributed)
* - Проверяет статус сегмента:
* * Для чистых инвесторов: READY или CONTRIBUTED (не требуется внесение через pushrslt)
* * Для участников с интеллектуальными ролями: CONTRIBUTED (результат внесён через pushrslt)
* - Валидирует актуальность сегмента
* - Проверяет что долг уже погашен после pushrslt
* - Проверяет что долг уже погашен (если был)
* - Проверяет наличие средств для конвертации (с учетом погашенного долга)
* - Валидирует корректность сумм конвертации
* - Выполняет операции с балансами (кошелек, капитал, проект)
@@ -21,6 +23,7 @@
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p coopname
* @note Чистые инвесторы могут конвертировать сегмент БЕЗ внесения результата через pushrslt
*/
void capital::convertsegm(eosio::name coopname, eosio::name username,
checksum256 project_hash, checksum256 convert_hash,
@@ -32,8 +35,25 @@ void capital::convertsegm(eosio::name coopname, eosio::name username,
auto segment = Capital::Segments::get_segment_or_fail(coopname, project_hash, username,
"Сегмент пайщика не найден");
// Проверяем статус сегмента - результат должен быть внесён после pushrslt
eosio::check(segment.status == Capital::Segments::Status::ACCEPTED, "Результат не внесён. Сначала внесите результат через pushrslt");
// Проверяем статус сегмента
// Чистые инвесторы могут конвертировать в статусе READY (они не вносят результат через pushrslt)
// Все остальные должны внести результат (статус CONTRIBUTED)
bool is_pure_inv = Capital::Segments::is_pure_investor(segment);
if (is_pure_inv) {
// Чистые инвесторы могут конвертировать уже в статусе READY
eosio::check(segment.status == Capital::Segments::Status::READY ||
segment.status == Capital::Segments::Status::CONTRIBUTED,
"Чистые инвесторы могут конвертировать сегмент в статусе READY или CONTRIBUTED");
// Чистые инвесторы не могут погашать долг через pushrslt, поэтому у них не должно быть долга
eosio::check(segment.debt_amount.amount == 0,
"Чистые инвесторы не могут иметь непогашенный долг. Сначала погасите долг.");
} else {
// Участники с интеллектуальными ролями должны сначала внести результат
eosio::check(segment.status == Capital::Segments::Status::CONTRIBUTED,
"Результат не внесён. Сначала внесите результат через pushrslt");
}
// Проверяем актуальность сегмента (включая синхронизацию с инвестициями)
Capital::Segments::check_segment_is_updated(coopname, project_hash, username, "Сегмент не обновлен. Выполните rfrshsegment перед конвертацией");
@@ -69,7 +89,9 @@ void capital::convertsegm(eosio::name coopname, eosio::name username,
eosio::check(capital_amount <= available_for_program, "Сумма конвертации в программу превышает сумму себестоимости и премий за вычетом суммы выданных ссуд");
eosio::check(capital_amount == (available_for_program - wallet_amount - project_amount), "В программу должно быть сконвертировано всё доступное, что не конвертируется в проект или кошелёк");
// Списываем средства с кошелька генерации, которые уходят из проекта
// Списываем средства с кошелька source_program, которые уходят из проекта
// Для чистых инвесторов: средства были заблокированы при инвестировании (approveinvst)
// Для участников с интеллектуальными ролями: средства были начислены при внесении результата (signact2)
Wallet::sub_blocked_funds(_capital, coopname, username, total_convert - project_amount, _source_program, Capital::Memo::get_convert_segment_to_wallet_memo(convert_hash));
// Выполняем операции с балансами
@@ -20,7 +20,7 @@
\htmlonly
<div class="mermaid">
sequenceDiagram
participant В as Вкладчик
participant В as Участник
participant C as Capital Contract
participant W as Wallet Contract
@@ -57,7 +57,7 @@
### Шаг 1: Конвертация сегмента
<b>Действие:</b> @ref capital::convertsegm "конвертация сегмента участника"
Вкладчик распределяет свои доступные средства между тремя направлениями согласно
Участник распределяет свои доступные средства между тремя направлениями согласно
выбранной стратегии. Система проверяет соблюдение всех ограничений:
- Долг должен быть погашен (debt_settled >= debt_amount)
- Общая сумма конвертации равна всем взносам участника минус погашенный долг
@@ -1,20 +1,22 @@
/**
* @brief Одобряет результат участника
* @brief Одобряет результат участника председателем
* Одобряет результат участника и отправляет в совет:
* - Проверяет подлинность одобренного заявления
* - Валидирует статус результата (должен быть created)
* - Валидирует статус результата (должен быть created) и статус сегмента (должен быть statement)
* - Устанавливает одобренное заявление
* - Обновляет статус на approved
* - Обновляет статус результата на approved
* - Обновляет статус сегмента на approved
* - Отправляет результат в совет
* @param coopname Наименование кооператива
* @param username Наименование пользователя, одобрившего результат
* @param result_hash Хеш результата для одобрения
* @param approved_statement Одобренное заявление о результате
* @ingroup public_actions
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p coopname
* @note Авторизация требуется от контракта совета
*/
void capital::approverslt(eosio::name coopname, checksum256 result_hash, document2 approved_statement){
void capital::approverslt(eosio::name coopname, eosio::name username, checksum256 result_hash, document2 approved_statement){
require_auth(_soviet);
// Проверяем заявление
@@ -25,12 +27,19 @@ void capital::approverslt(eosio::name coopname, checksum256 result_hash, documen
eosio::check(exist_result.has_value(), "Результат пользователя не существует");
eosio::check(exist_result->status == Capital::Results::Status::CREATED, "Неверный статус результата");
// Проверяем статус сегмента
auto segment = Capital::Segments::get_segment_or_fail(coopname, exist_result->project_hash, exist_result->username, "Сегмент участника не найден");
eosio::check(segment.status == Capital::Segments::Status::STATEMENT, "Неверный статус сегмента. Ожидается статус 'statement'");
// Устанавливаем одобренное заявление
Capital::Results::set_result_approved_statement(coopname, result_hash, approved_statement);
// Обновляем статус
// Обновляем статус результата
Capital::Results::update_result_status(coopname, result_hash, Capital::Results::Status::APPROVED);
// Обновляем статус сегмента
Capital::Segments::update_segment_status(coopname, exist_result->project_hash, exist_result->username, Capital::Segments::Status::APPROVED);
// Отправляем в совет
Capital::Results::send_result_to_soviet(coopname, exist_result->username, result_hash, approved_statement);
};
@@ -2,9 +2,10 @@
* @brief Авторизует результат участника советом
* Авторизует результат участника советом:
* - Проверяет подлинность документа решения совета
* - Валидирует статус результата (должен быть approved)
* - Валидирует статус результата (должен быть approved) и статус сегмента (должен быть approved)
* - Устанавливает документ авторизации
* - Обновляет статус на authorized
* - Обновляет статус результата на authorized
* - Обновляет статус сегмента на authorized
* @param coopname Наименование кооператива
* @param result_hash Хеш результата для авторизации
* @param decision Документ решения совета
@@ -24,9 +25,16 @@ void capital::authrslt(eosio::name coopname, checksum256 result_hash, document2
eosio::check(exist_result.has_value(), "Объект результата не найден");
eosio::check(exist_result->status == Capital::Results::Status::APPROVED, "Неверный статус. Результат должен быть одобрен председателем");
// Проверяем статус сегмента
auto segment = Capital::Segments::get_segment_or_fail(coopname, exist_result->project_hash, exist_result->username, "Сегмент участника не найден");
eosio::check(segment.status == Capital::Segments::Status::APPROVED, "Неверный статус сегмента. Ожидается статус 'approved'");
// Устанавливаем документ авторизации
Capital::Results::set_result_authorization(coopname, result_hash, decision);
// Обновляем статус
// Обновляем статус результата
Capital::Results::update_result_status(coopname, result_hash, Capital::Results::Status::AUTHORIZED);
// Обновляем статус сегмента
Capital::Segments::update_segment_status(coopname, exist_result->project_hash, exist_result->username, Capital::Segments::Status::AUTHORIZED);
};
@@ -1,9 +1,10 @@
/**
* @brief Отклоняет результат участника советом
* Отклоняет результат участника советом и возвращает статус сегмента:
* - Проверяет подлинность документа решения совета
* - Валидирует статус результата (должен быть approved)
* - Удаляет объект результата и возвращает статус сегмента в ready
* - Валидирует статус результата (должен быть created, approved или authorized)
* - Валидирует статус сегмента (должен быть statement, approved или authorized)
* - Удаляет объект результата
* - Возвращает статус сегмента в ready для возможности повторного внесения результата
* @param coopname Наименование кооператива
* @param result_hash Хеш результата для отклонения
* @param reason Причина отклонения
@@ -18,11 +19,21 @@ void capital::declrslt(eosio::name coopname, checksum256 result_hash, std::strin
// Получаем результат и проверяем статус
auto exist_result = Capital::Results::get_result(coopname, result_hash);
eosio::check(exist_result.has_value(), "Объект результата не найден");
eosio::check(exist_result->status == Capital::Results::Status::APPROVED || exist_result -> status == Capital::Results::Status::CREATED, "Неверный статус результата");
eosio::check(exist_result->status == Capital::Results::Status::CREATED ||
exist_result->status == Capital::Results::Status::APPROVED ||
exist_result->status == Capital::Results::Status::AUTHORIZED,
"Результат можно отклонить только в статусах: created, approved или authorized");
// Проверяем статус сегмента соответствует статусу результата
auto segment = Capital::Segments::get_segment_or_fail(coopname, exist_result->project_hash, exist_result->username, "Сегмент участника не найден");
eosio::check(segment.status == Capital::Segments::Status::STATEMENT ||
segment.status == Capital::Segments::Status::APPROVED ||
segment.status == Capital::Segments::Status::AUTHORIZED,
"Неверный статус сегмента для отклонения");
// Удаляем объект результата
Capital::Results::delete_result(coopname, exist_result->project_hash, exist_result->username);
// Возвращаем статус сегмента в GENERATION
Capital::Segments::update_segment_status(coopname, exist_result->project_hash, exist_result->username, Capital::Segments::Status::GENERATION);
// Возвращаем статус сегмента в READY для возможности повторного внесения результата
Capital::Segments::update_segment_status(coopname, exist_result->project_hash, exist_result->username, Capital::Segments::Status::READY);
};
@@ -5,6 +5,8 @@
* - Валидирует входные параметры (суммы взноса и долга)
* - Проверяет завершенность проекта и актуальность сегмента
* - Валидирует сегмент участника и его статус
* - БЛОКИРУЕТ внесение результата для чистых инвесторов (они уже внесли средства при инвестировании)
* - Для участников с ролями инвестор+создатель/автор/координатор вычитает инвестиционную часть
* - Проверяет соответствие сумм взноса и долга
* - Создает объект результата
* - Обновляет сегмент после принятия результата и пересчитывает доли
@@ -13,7 +15,7 @@
* @param username Наименование пользователя-участника
* @param project_hash Хеш проекта
* @param result_hash Хеш результата
* @param contribution_amount Сумма взноса в результат
* @param contribution_amount Сумма взноса в результат (БЕЗ инвестиционной части для инвесторов)
* @param debt_amount Сумма долга для погашения
* @param statement Заявление о результате
* @param debt_hashes Вектор хэшей долгов для погашения (опционально)
@@ -21,6 +23,7 @@
* @ingroup public_capital_actions
* @note Авторизация требуется от аккаунта: @p coopname
* @note Чистые инвесторы НЕ вносят результат через pushrslt - их средства уже внесены при инвестировании
*/
void capital::pushrslt(name coopname, name username, checksum256 project_hash, checksum256 result_hash,
eosio::asset contribution_amount, eosio::asset debt_amount, document2 statement,
@@ -38,17 +41,23 @@ void capital::pushrslt(name coopname, name username, checksum256 project_hash, c
auto existing_result = Capital::Results::get_result(coopname, result_hash);
eosio::check(!existing_result.has_value(), "Результат с таким хэшем уже существует");
// Проверяем, что проект завершен
auto project = Capital::Projects::get_project_or_fail(coopname, project_hash);
eosio::check(project.status == Capital::Projects::Status::COMPLETED, "Проект должен быть завершен");
// Проверяем актуальность сегмента (включая синхронизацию с инвестициями)
Capital::Segments::check_segment_is_updated(coopname, project_hash, username,
"Сегмент не обновлен. Выполните rfrshsegment перед внесением результата");
// Проверяем сегмент участника и его статус
auto segment = Capital::Segments::get_segment_or_fail(coopname, project_hash, username, "Сегмент участника не найден");
eosio::check(segment.status == Capital::Segments::Status::GENERATION, "Участник уже подавал результат или результат уже принят");
eosio::check(segment.status == Capital::Segments::Status::READY, "Участник уже подавал результат или результат уже принят");
// Проверяем, что проект завершен
auto project = Capital::Projects::get_project_or_fail(coopname, project_hash);
eosio::check(project.status == Capital::Projects::Status::RESULT, "Проект должен быть завершен");
// КРИТИЧЕСКАЯ ПРОВЕРКА: чистые инвесторы НЕ должны вносить результат
// Инвесторы уже внесли свои средства при инвестировании (средства в source_program)
eosio::check(!Capital::Segments::is_pure_investor(segment),
"Чистые инвесторы не должны вносить результат через pushrslt. Инвестиция уже внесена при инвестировании. Используйте convertsegm для конвертации сегмента.");
// Проверяем, что у участника есть интеллектуальные роли для внесения результата
eosio::check(Capital::Segments::has_intellectual_contribution_roles(segment),
"У участника нет ролей, требующих внесения интеллектуального результата");
eosio::check(segment.total_segment_cost.amount > 0, "У участника нет вкладов для приема результата");
eosio::check(segment.username == username, "Неверный участник");
@@ -58,8 +67,18 @@ void capital::pushrslt(name coopname, name username, checksum256 project_hash, c
// Получаем обновленный сегмент
segment = Capital::Segments::get_segment_or_fail(coopname, project_hash, username, "Сегмент участника не найден");
// Проверяем, что сумма взноса равна общей стоимости сегмента
eosio::check(contribution_amount == segment.total_segment_cost, "Сумма взноса должна равняться общей стоимости сегмента");
// Рассчитываем требуемую сумму взноса (без инвестиционной части, если участник также инвестор)
eosio::asset expected_contribution = segment.total_segment_cost;
// Если участник также инвестор, вычитаем инвестиционную часть (она уже внесена)
if (segment.is_investor && segment.investor_base.amount > 0) {
expected_contribution -= segment.investor_base;
print("Участник также является инвестором. Инвестиционная часть (", segment.investor_base, ") исключена из суммы взноса результата.");
}
// Проверяем, что сумма взноса соответствует ожидаемой (без инвестиционной части)
eosio::check(contribution_amount == expected_contribution,
"Сумма взноса должна равняться общей стоимости сегмента за вычетом инвестиционной части (если есть)");
// Если есть долг, проверяем что взнос достаточен для его покрытия
if (segment.debt_amount.amount > 0) {
@@ -116,10 +135,7 @@ void capital::pushrslt(name coopname, name username, checksum256 project_hash, c
// Обновляем сегмент
Capital::Segments::update_segment_after_result_contribution(coopname, project_hash, username,
debt_amount);
// Обновляем накопительные показатели контрибьютора на основе его ролей в сегменте
Capital::Contributors::update_contributor_ratings_from_segment(coopname, segment);
// Отправляем результат на одобрение председателем
Capital::Results::send_result_for_approval(coopname, username, result_hash, statement);
}
@@ -1,7 +1,6 @@
- 📄 Заявление на внесение паевого взноса с опциональным погашением ссуды (если брал)
- 📄 Заявление на взнос доли в результате интеллектуальной деятельности
- 📄 Заявление на внесение паевого взноса доли в результате интеллектуальной деятельности с опциональным погашением ссуды (если брал)
- 📄 Визирующая подпись председателя на заявл. на паевой взнос результатом
- 📄 Решение совета о приёме паевого взноса результатом
- 📄 Подписаный акт приёма-передачи от вкладчика
- 📄 Подписаный акт приёма-передачи от участника
- 📄 Подписаный акт приёма-передачи от председателя
@note здесь при взносе результата собственники имущества должны одновременно внести своё имущество
@@ -4,48 +4,62 @@
* @ingroup public_capital_processes
*
* Процесс приёма паевого взноса результатом интеллектуальной деятельности
* после завершения проекта. Фиксирует доли вкладчиков для последующей конвертации.
* после завершения проекта. Фиксирует доли участников для последующей конвертации.
*
* @note КРИТИЧЕСКИ ВАЖНО: Этот процесс НЕ применяется к чистым инвесторам.
* Чистые инвесторы (только роль is_investor) уже внесли свой вклад при инвестировании.
* Они НЕ проходят через pushrslt и переходят напрямую к конвертации через convertsegm.
* Участники со смешанными ролями (инвестор + создатель/автор/координатор) вносят
* результат только по интеллектуальной части, инвестиционная часть исключается.
*
* ## Диаграмма процесса
*
* @note Чистые инвесторы НЕ участвуют в этом процессе и пропускают его полностью.
*
* \htmlonly
* <div class="mermaid">
* sequenceDiagram
* participant P as Вкладчик
* participant P as Участник с интеллектуальными ролями
* participant C as Capital Contract
* participant S as Soviet Contract
* participant L as Loan Contract
*
*
* Note over P: ТОЛЬКО для участников с ролями<br/>автор/создатель/координатор/пропертор<br/>Чистые инвесторы не участвуют!
* P->>C: 1. pushrslt(заявление на взнос результатом)
* Note over C: Проверка готовности сегмента
* Note over C: Блокировка чистых инвесторов
* Note over C: Проверка наличия интеллектуальных ролей
* Note over C: Исключение investor_base из contribution_amount
* Note over C: Расчёт итоговых сумм
* Note over C: Статус сегмента = CONTRIBUTED
* Note over C: Статус сегмента = STATEMENT
* C->>L: 2. Погашение долгов (если есть)
*
*
* C->>S: 3. soviet::create_approval
*
*
* S->>C: 4. approverslt(одобрение председателем)
* Note over C: Статус сегмента = APPROVED
* C->>S: 5. soviet::create_agenda
*
*
* alt Авторизация советом
* S->>C: 6. authrslt(решение совета)
*
* P->>C: 7. signact1(акт №1 от вкладчика)
* Note over C: Подпись вкладчика на акте
*
* Note over C: Статус сегмента = AUTHORIZED
*
* P->>C: 7. signact1(акт №1 от участника)
* Note over C: Статус сегмента = ACT1
* Note over C: Подпись участника на акте
*
* alt Принятие председателем
* S->>C: 8. signact2(акт №2 от председателя)
* Note over C: Статус сегмента = ACCEPTED
* Note over C: Статус сегмента = CONTRIBUTED
* Note over C: Удаление временного объекта результата
* Note over C: Готовность к конвертации
* else Отклонение до совета
* S->>C: 8. declineapprv(отклонение)
* Note over C: Возврат к статусу GENERATION
* Note over C: Возврат к статусу READY
* end
*
*
* else Отклонение советом
* S->>C: 6. declrslt(отклонение советом)
* Note over C: Возврат к статусу GENERATION
* Note over C: Возврат к статусу READY
* end
* </div>
* \endhtmlonly
@@ -55,126 +69,144 @@
* ### Шаг 1: Подача заявления на взнос результатом
* Подача заявления на паевой взнос результатом
*
* Вкладчик подаёт итоговое заявление на взнос результатом интеллектуальной деятельности:
* Участник подаёт итоговое заявление на взнос результатом интеллектуальной деятельности:
*
* <b>Входящий документ:</b> Заявление на паевой взнос результатом (подписано вкладчиком)
* <b>Входящий документ:</b> Заявление на паевой взнос результатом (подписано участником)
*
* <b>Предварительные условия:</b>
* - Проект в статусе `completed` (голосование завершено)
* - Сегмент вкладчика в статусе `GENERATION`
* - Сегмент участника в статусе `READY`
* - Сегмент обновлён (выполнен rfrshsegment)
*
* - Участник имеет интеллектуальные роли (is_author, is_creator, is_coordinator, is_propertor)
* - Участник НЕ является чистым инвестором (is_pure_investor == false)
*
* <b>Входящие суммы должны соответствовать расчётам:</b>
* - contribution_amount == total_segment_cost (полная стоимость вклада вкладчика)
* - contribution_amount == total_segment_cost - investor_base (если участник также инвестор)
* - contribution_amount == total_segment_cost (если участник не инвестор)
* - debt_amount == segment.debt_amount (сумма к погашению)
*
* @note Инвестиционная часть (investor_base) НЕ включается в contribution_amount,
* так как она уже была внесена при инвестировании через approveinvst.
*
* <b>Расчёты и обновления:</b>
*
*
* @post Погашение ссуд через внешний контракт loan (если debt_amount > 0)
*
* <b>Результат:</b>
*
* <b>Результат:</b>
* - Создается временный объект `results`
* - Статус сегмента → `CONTRIBUTED`
* - Статус сегмента → `STATEMENT`
* - Заявка отправляется на рассмотрение председателем
*
* ### Шаг 2: Одобрение заявления председателем
* Одобрение заявления председателем
*
*
* Председатель рассматривает заявление и принимает решение:
* - Проверяет корректность расчётов
* - Оценивает соответствие результата проекту
* - Подтверждает готовность к рассмотрению советом
*
*
* <b>Входящий документ:</b> Принятое председателем заявление на взнос результатом
*
* При одобрении заявка передается в совет для финального решения.
*
*
* <b>Результат:</b>
* - Статус сегмента → `APPROVED`
* - Заявка передается в совет для финального решения
*
* ### Шаг 3: Авторизация советом
* Авторизация взноса результатом советом
*
*
* Совет принимает решение о принятии результата интеллектуальной деятельности:
* - Оценивает ценность результата для кооператива
* - Подтверждает справедливость распределения долей
* - Даёт согласие на приём паевого взноса
*
*
* <b>Входящий документ:</b> Решение совета о принятии взноса результатом
*
* После авторизации становится возможным подписание актов приёма-передачи.
*
* ### Шаг 4: Подписание акта №1 вкладчиком
* Подписание акта №1 вкладчиком
*
* Вкладчик подписывает акт приёма-передачи доли в результате:
*
* <b>Результат:</b>
* - Статус сегмента → `AUTHORIZED`
* - Становится возможным подписание актов приёма-передачи
*
* ### Шаг 4: Подписание акта №1 участником
* Подписание акта №1 участником
*
* Участник подписывает акт приёма-передачи доли в результате:
* - Подтверждает передачу своей доли кооперативу
* - Соглашается с расчётом вознаграждения
* - Фиксирует своё согласие на условия приёма
*
* <b>Входящий документ:</b> Акт приёма-передачи (подпись вкладчика)
*
*
* <b>Входящий документ:</b> Акт приёма-передачи (подпись участника)
*
* <b>Результат:</b>
* - Статус сегмента → `ACT1`
* - Акт готов к подписанию председателем
*
* ### Шаг 5: Подписание акта №2 председателем
* Подписание акта №2 председателем
*
*
* Председатель подписывает акт от имени кооператива:
* - Подтверждает приём доли в результате
* - Фиксирует обязательства кооператива по выплатам
* - Завершает процедуру приёма паевого взноса
*
* <b>Входящий документ:</b> Акт приёма-передачи (подписи вкладчика и председателя)
*
*
* <b>Входящий документ:</b> Акт приёма-передачи (подписи участника и председателя)
*
* <b>Финальные изменения:</b>
* - Статус сегмента → `ACCEPTED`
* - Статус сегмента → `CONTRIBUTED`
* - Удаление временного объекта `results`
* - Готовность сегмента к конвертации
*
* ### Альтернативные пути: Отклонение заявления
*
*
* #### Отклонение председателем
* - Заявление отклоняется до передачи в совет
* - Временный объект `results` удаляется
* - Статус сегмента возвращается к `GENERATION`
* - Вкладчик может подать исправленное заявление
*
* - Статус сегмента возвращается к `READY`
* - Участник может подать исправленное заявление
*
* #### Отклонение советом
* - Совет не принимает результат
* - Временный объект `results` удаляется
* - Статус сегмента возвращается к `GENERATION`
* - Совет не принимает результат на любом этапе (до авторизации или после)
* - Временный объект `results` удаляется
* - Статус сегмента возвращается к `READY`
* - Требуется доработка результата или условий
*
* ## Правовые аспекты взноса результатом
*
* ### Природа паевого взноса
* - Результат интеллектуальной деятельности передается как имущественный вклад
* - Вкладчик получает паевые права в кооперативе
* - Участник получает паевые права в кооперативе
* - Кооператив становится обладателем исключительных прав на результат
*
* ### Документооборот
* - <b>Заявление</b> - волеизъявление вкладчика о намерении совершить паевой взнос
* - <b>Заявление</b> - волеизъявление участника о намерении совершить паевой взнос
* - <b>Решение совета</b> - протокол собрания совета с решением и приёме взноса
* - <b>Акты приёма-передачи</b> - фиксация перехода прав
*
* ## Структура итогового вознаграждения
*
* После завершения процесса вкладчик получает:
* После завершения процесса участник получает:
*
* ### Базовая часть (себестоимость)
* - <b>Создатель:</b> creator_base (стоимость коммитов)
* - <b>Исполнитель:</b> creator_base (стоимость коммитов)
* - <b>Автор:</b> author_base (61.8% от создателей)
* - <b>Координатор:</b> coordinator_base (% от привлечённых инвестиций)
* - <b>Инвестор:</b> investor_base (использованная часть инвестиций)
* - <b>Собственник:</b> property_base (стоимость имущественного взноса)
* - <b>Инвестор:</b> investor_base (использованная часть инвестиций) - УЖЕ ВНЕСЕНА при инвестировании
* - <b>Пропертор:</b> property_base (стоимость имущественного взноса)
*
* @note investor_base НЕ включается в contribution_amount при pushrslt для участников
* со смешанными ролями, так как эта сумма уже внесена при approveinvst.
*
* ### Премиальная часть (бонусы)
* - <b>Создатели:</b> creator_bonus (100% от базы)
* - <b>Авторы:</b> author_bonus (равная часть + голосование)
* - <b>Вкладчики:</b> contributor_bonus (161.8% от генерации)
* - <b>Участники:</b> contributor_bonus (161.8% от генерации)
* - <b>Голосование:</b> voting_bonus (по методу Водянова)
*
* ## Результат процесса
*
* @post:
* 1. Результат интеллектуальной деятельности принят кооперативом как паевой взнос
* 2. Погашена ссуда вкладчика
* 3. Сегмент готов к конвертации в различные кошельки кооператива
* 2. Погашена ссуда участника (если была)
* 3. Сегмент в статусе CONTRIBUTED и готов к конвертации в различные кошельки кооператива
* 4. Статусы сегмента и результата синхронизированы на каждом этапе процесса
*
## Эффекты процесса
@@ -2,10 +2,11 @@
* @brief Подписывает акт 1 по результату участника
* Подписывает первый акт по результату участника:
* - Проверяет подлинность документа акта от участника
* - Валидирует статус результата (должен быть authorized)
* - Валидирует статус результата (должен быть authorized) и статус сегмента (должен быть authorized)
* - Проверяет права участника на подписание акта
* - Устанавливает первый акт
* - Обновляет статус на act1
* - Обновляет статус результата на act1
* - Обновляет статус сегмента на act1
* @param coopname Наименование кооператива
* @param username Наименование пользователя-участника
* @param result_hash Хеш результата
@@ -26,10 +27,17 @@ void capital::signact1(eosio::name coopname, eosio::name username, checksum256 r
eosio::check(exist_result.has_value(), "Объект результата не найден");
eosio::check(exist_result->status == Capital::Results::Status::AUTHORIZED, "Неверный статус. Результат должен быть авторизован советом");
eosio::check(exist_result->username == username, "Только участник может подписать акт для своего результата");
// Проверяем статус сегмента
auto segment = Capital::Segments::get_segment_or_fail(coopname, exist_result->project_hash, username, "Сегмент участника не найден");
eosio::check(segment.status == Capital::Segments::Status::AUTHORIZED, "Неверный статус сегмента. Ожидается статус 'authorized'");
// Устанавливаем первый акт
Capital::Results::set_result_act1(coopname, result_hash, act);
// Обновляем статус
// Обновляем статус результата
Capital::Results::update_result_status(coopname, result_hash, Capital::Results::Status::ACT1);
// Обновляем статус сегмента
Capital::Segments::update_segment_status(coopname, exist_result->project_hash, exist_result->username, Capital::Segments::Status::ACT1);
};
@@ -2,10 +2,12 @@
* @brief Подписывает акт 2 по результату участника
* Подписывает второй акт председателем и завершает процесс принятия результата:
* - Проверяет что подписывает председатель
* - Валидирует статус результата (должен быть act1)
* - Валидирует статус результата (должен быть act1) и статус сегмента (должен быть act1)
* - Проверяет подлинность документа акта от председателя и участника
* - Устанавливает второй акт
* - Обновляет статус сегмента на accepted
* - Начисляет заблокированные средства и обновляет учёт
* - Обновляет статус сегмента на contributed
* - Обновляет статус результата на act2
* - Удаляет объект результата после успешного принятия
* @param coopname Наименование кооператива
* @param username Наименование пользователя-председателя
@@ -30,6 +32,10 @@ void capital::signact2(eosio::name coopname, eosio::name chairman, checksum256 r
eosio::check(result.has_value(), "Объект результата не найден");
eosio::check(result->status == Capital::Results::Status::ACT1, "Неверный статус. Первый акт должен быть подписан");
// Проверяем статус сегмента
auto segment = Capital::Segments::get_segment_or_fail(coopname, result->project_hash, result->username, "Сегмент участника не найден");
eosio::check(segment.status == Capital::Segments::Status::ACT1, "Неверный статус сегмента. Ожидается статус 'act1'");
// Проверяем документ
verify_document_or_fail(act, { result->username, real_chairman });
@@ -50,11 +56,17 @@ void capital::signact2(eosio::name coopname, eosio::name chairman, checksum256 r
Ledger::sub(_capital, coopname, Ledger::accounts::LONG_TERM_LOANS, result -> debt_amount, memo);
}
// Обновляем накопительные показатели контрибьютора на основе его ролей в сегменте
Capital::Contributors::update_contributor_ratings_from_segment(coopname, segment);
//TODO: линковать документ акта
// Обновляем статус сегмента
Capital::Segments::update_segment_status(coopname, result->project_hash, result->username, Capital::Segments::Status::ACCEPTED);
Capital::Segments::update_segment_status(coopname, result->project_hash, result->username, Capital::Segments::Status::CONTRIBUTED);
// Изменяем статус результата на act2 перед удалением
Capital::Results::update_result_status(coopname, result_hash, Capital::Results::Status::ACT2);
// Удаляем объект результата после успешного принятия
Capital::Results::delete_result(coopname, result->project_hash, result->username);
};
@@ -2,32 +2,32 @@
* @defgroup public_capital_calculate_votes_process Подсчет голосов по методу Водянова
* @ingroup public_capital_processes
*
* Процесс завершения голосования для конкретного вкладчика с расчетом итоговых сумм
* Процесс завершения голосования для конкретного участника с расчетом итоговых сумм
* по методу Водянова.
*
* ## Назначение процесса
*
* Подсчет голосов по методу Водянова обеспечивает:
* - Расчет итоговых сумм вкладчика по результатам голосования
* - Расчет итоговых сумм участника по результатам голосования
* - Применение метода Водянова: (сумма голосов + средняя сумма распределения) / количество голосующих
* - Распределение фиксированных премий авторам и создателям
* - Обновление сегмента вкладчика с итоговыми суммами
* - Обновление сегмента участника с итоговыми суммами
*
* \htmlonly
* <div class="mermaid">
* sequenceDiagram
* participant У as Вкладчик
* participant У as Участник
* participant ПК as Контракт Capital
* participant П as Проект
*
* У->>ПК: 1. Завершение голосования вкладчика
* У->>ПК: 1. Завершение голосования участника
* Note over ПК: Проверка статуса проекта
* ПК->>П: 2. Проверка статуса и завершения голосования
* alt Проект завершен и голосование завершено
* П->>ПК: 3. Подтверждение статуса
* ПК->>ПК: 4. Получение сегмента вкладчика
* ПК->>ПК: 4. Получение сегмента участника
* ПК->>ПК: 5. Расчет итоговых сумм
* ПК->>ПК: 6. Обновление сегмента вкладчика
* ПК->>ПК: 6. Обновление сегмента участника
* else Проект или голосование не завершены
* ПК->>У: Ошибка: проект или голосование не завершены
* end
@@ -37,9 +37,9 @@
* ## Пошаговое описание процесса
*
* ### Шаг 1: Инициация подсчета голосов
* <b>Действие:</b> @ref capital::calcvotes "Завершение голосования вкладчика"
* <b>Действие:</b> @ref capital::calcvotes "Завершение голосования участника"
*
* Инициируется процесс подсчета голосов для конкретного вкладчика
* Инициируется процесс подсчета голосов для конкретного участника
* после завершения голосования по проекту.
*
* @post Проверка авторизации кооператива
@@ -50,18 +50,18 @@
* Система проверяет, что:
* - Проект находится в статусе завершенного голосования
* - Голосование по проекту завершено
* - Вкладчик является вкладчиком голосования
* - Участник является участником голосования
*
* @post Подтвержден статус проекта как "завершенное голосование"
* @post Подтверждено завершение голосования
* @post Подтверждено участие пользователя в голосовании
*
* ### Шаг 3: Получение сегмента вкладчика
* <b>Действие:</b> Загрузка данных вкладчика
* ### Шаг 3: Получение сегмента участника
* <b>Действие:</b> Загрузка данных участника
*
* Система получает сегмент вкладчика для расчета его итоговых сумм.
* Система получает сегмент участника для расчета его итоговых сумм.
*
* @post Получен сегмент вкладчика
* @post Получен сегмент участника
*
* ### Шаг 4: Расчет итоговых сумм
* <b>Действие:</b> Вычисление результатов голосования
@@ -69,21 +69,21 @@
* Система рассчитывает три типа итоговых сумм:
* - Результаты по методу Водянова: (сумма голосов + средняя сумма распределения) / количество голосующих
* - Равные распределения авторам: 61.8% авторских премий равномерно между авторами
* - Прямые распределения создателям: 61.8% создательских премий
* - Прямые распределения создателям: 61.8% исполнительских премий
*
* @post Рассчитаны все итоговые суммы вкладчика
* @post Рассчитаны все итоговые суммы участника
*
* ### Шаг 5: Обновление сегмента вкладчика
* ### Шаг 5: Обновление сегмента участника
* <b>Действие:</b> Сохранение результатов
*
* Система обновляет сегмент вкладчика с рассчитанными итоговыми суммами
* Система обновляет сегмент участника с рассчитанными итоговыми суммами
* раздельно по пулам для дальнейшего использования.
*
* @post Сегмент вкладчика обновлен с итоговыми суммами
* @post Сегмент участника обновлен с итоговыми суммами
*
* ## Метод расчета по Водянову
*
* Метод Водянова для расчета итоговой суммы вкладчика:
* Метод Водянова для расчета итоговой суммы участника:
* ```
* итоговая_сумма = (сумма_голосов + средняя_сумма_распределения) / количество_голосующих
* ```
@@ -92,14 +92,14 @@
*
* Система также рассчитывает фиксированные распределения:
* - 61.8% авторских премий распределяются равномерно между всеми авторами
* - 61.8% создательских премий распределяются напрямую создателям
* - 61.8% исполнительских премий распределяются напрямую создателям
*
* ## Результат процесса
*
* После завершения процесса:
* 1. Рассчитаны все итоговые суммы вкладчика
* 2. Сегмент вкладчика обновлен с результатами голосования
* 3. Вкладчик получил свою долю по результатам голосования
* 1. Рассчитаны все итоговые суммы участника
* 2. Сегмент участника обновлен с результатами голосования
* 3. Участник получил свою долю по результатам голосования
*
* ## Связанные процессы
*
@@ -2,7 +2,7 @@
* @brief Завершение голосования для конкретного участника по методу Водянова
* Рассчитывает полные итоговые суммы участника включая:
* - Результаты голосования по Водянову: (сумма голосов + средняя сумма распределения) / количество голосующих
* - Фиксированные распределения: 61.8% авторских премий равно между авторами, 61.8% создательских премий прямо создателям
* - Фиксированные распределения: 61.8% авторских премий равно между авторами, 61.8% исполнительских премий прямо создателям
* Обновляет сегмент участника с итоговыми суммами раздельно по пулам
* @param coopname Наименование кооператива
* @param username Наименование пользователя-участника голосования
@@ -17,13 +17,16 @@ void capital::calcvotes(name coopname, name username, checksum256 project_hash)
// Получаем проект и проверяем состояние
auto project = Capital::Projects::get_project_or_fail(coopname, project_hash);
eosio::check(project.status == Capital::Projects::Status::COMPLETED, "Проект не в статусе завершенного голосования");
eosio::check(project.status == Capital::Projects::Status::RESULT, "Проект не в статусе завершенного голосования");
eosio::check(Capital::Core::Voting::is_voting_completed(project), "Голосование еще не завершено");
eosio::check(Capital::Segments::is_voting_participant(coopname, project_hash, username), "Пользователь не является участником голосования");
// Получаем сегмент участника
auto segment = Capital::Segments::get_segment_or_fail(coopname, project_hash, username, "Сегмент участника не найден");
// Проверяем, что расчет голосования еще не выполнен
eosio::check(!segment.is_votes_calculated, "Расчет суммы голосования для данного участника уже выполнен");
// Рассчитываем все суммы через Core функции
auto vodyanov_amount = Capital::Core::Voting::calculate_voting_final_amount(coopname, project_hash, username);
@@ -2,21 +2,21 @@
* @defgroup public_capital_submit_vote_process Голосование по методу Водянова
* @ingroup public_capital_processes
*
* Процесс распределения голосующей суммы вкладчиком между другими вкладчиками проекта
* Процесс распределения голосующей суммы участником между другими участниками проекта
* по методу Водянова и сохранения результатов голосования в системе.
*
* ## Назначение процесса
*
* Подача голоса по методу Водянова обеспечивает:
* - Распределение голосующей суммы вкладчика между другими вкладчиками проекта
* - Распределение голосующей суммы участника между другими участниками проекта
* - Валидацию корректности распределения голосов
* - Сохранение голосов в системе для последующего подсчета
* - Учет голоса в общем количестве полученных голосов вкладчиками
* - Учет голоса в общем количестве полученных голосов участниками
*
* \htmlonly
* <div class="mermaid">
* sequenceDiagram
* participant У as Вкладчик
* participant У as Участник
* participant ПК as Контракт Capital
* participant П as Проект
*
@@ -25,7 +25,7 @@
* ПК->>П: 2. Проверка статуса и срока голосования
* alt Проект в статусе голосования
* П->>ПК: 3. Подтверждение статуса
* ПК->>ПК: 4. Валидация вкладчика голосования
* ПК->>ПК: 4. Валидация участника голосования
* ПК->>ПК: 5. Проверка корректности голосов
* ПК->>ПК: 6. Сохранение голосов
* ПК->>П: 7. Обновление счетчика голосов
@@ -40,7 +40,7 @@
* ### Шаг 1: Инициация подачи голоса
* <b>Действие:</b> @ref capital::submitvote "Подача голоса по методу Водянова"
*
* Вкладчик распределяет свою голосующую сумму между другими вкладчиками проекта
* Участник распределяет свою голосующую сумму между другими участниками проекта
* в рамках голосования по методу Водянова.
*
* @post Проверка авторизации кооператива
@@ -55,12 +55,12 @@
* @post Подтвержден статус проекта как "голосование"
* @post Подтверждено, что срок голосования не истек
*
* ### Шаг 3: Валидация вкладчика голосования
* <b>Действие:</b> Проверка прав вкладчика
* ### Шаг 3: Валидация участника голосования
* <b>Действие:</b> Проверка прав участника
*
* Система проверяет, что:
* - Вкладчик является вкладчиком голосования по проекту (автор или создатель)
* - Вкладчик еще не голосовал по данному проекту
* - Участник является участником голосования по проекту (автор или исполнитель)
* - Участник еще не голосовал по данному проекту
*
* @post Подтверждено участие пользователя в голосовании
* @post Подтверждено, что пользователь еще не голосовал
@@ -69,11 +69,11 @@
* <b>Действие:</b> Валидация распределения голосов
*
* Система проверяет корректность распределения голосов:
* - Вкладчик не голосует за себя
* - Все получатели голосов являются вкладчиками голосования
* - Участник не голосует за себя
* - Все получатели голосов являются участниками голосования
* - Нет повторяющихся получателей голосов
* - Все суммы голосов положительные
* - Количество получателей равно общему количеству вкладчиков минус один (сам вкладчик)
* - Количество получателей равно общему количеству участников минус один (сам участник)
* - Общая сумма голосов равна активной голосующей сумме
* - Сумма голосов плюс равная не голосующая сумма равна общей сумме на распределении
*
@@ -100,16 +100,16 @@
* <b>Обязательные требования:</b>
* - Проект должен быть в статусе голосования
* - Срок голосования не должен быть истекшим
* - Вкладчик должен быть вкладчиком голосования
* - Вкладчик еще не голосовал по данному проекту
* - Участник должен быть участником голосования
* - Участник еще не голосовал по данному проекту
* - Распределение голосов должно соответствовать правилам метода Водянова
*
* ## Результат процесса
*
* post"
* 1. Голоса вкладчика сохранены в системе
* 1. Голоса участника сохранены в системе
* 2. Счетчик полученных голосов обновлен
* 3. Вкладчик больше не может голосовать по данному проекту
* 3. Участник больше не может голосовать по данному проекту
*
* ## Связанные процессы
*

Some files were not shown because too many files have changed in this diff Show More