project & component initialization & InitProjectStatement & InitProjectDecision
This commit is contained in:
+2
-3
@@ -17,7 +17,7 @@
|
||||
* @ingroup public_capital_actions
|
||||
|
||||
* @note Авторизация требуется от аккаунта: @p coopname
|
||||
* @note Для корневых проектов требуется отдельная инициализация через @ref capital::initprj
|
||||
* @note Для всех проектов требуется отдельная инициализация через @ref capital::initprj
|
||||
*/
|
||||
void capital::createproj (
|
||||
eosio::name coopname,
|
||||
@@ -42,11 +42,10 @@ void capital::createproj (
|
||||
// Валидируем parent_hash согласно правилам проектов
|
||||
Capital::Projects::validate_parent_hash(coopname, parent_hash);
|
||||
|
||||
// Если указан родительский проект, проверяем что он авторизован
|
||||
// Если указан родительский проект, проверяем что он существует
|
||||
if (parent_hash != checksum256()) {
|
||||
auto parent_project = Capital::Projects::get_project(coopname, parent_hash);
|
||||
eosio::check(parent_project.has_value(), "Родительский проект не найден");
|
||||
eosio::check(parent_project -> is_authorized, "Родительский проект не авторизован советом");
|
||||
}
|
||||
|
||||
Capital::Projects::create_project(coopname, project_hash, parent_hash, title, description, invite, meta, data, can_convert_to_project);
|
||||
|
||||
+8
-18
@@ -8,8 +8,7 @@
|
||||
реализации и генерации интеллектуального результата. Процесс вызывается тогда и только тогда, когда проект готов идти в планирование.
|
||||
До этого идея проекта хранится в банке идей за пределами контракта.
|
||||
|
||||
Дочерние проекты (компоненты мета-проекта) автоматически авторизованы при создании на авторизованном родительском проекте.
|
||||
Корневые проекты (без родителя) требуют отдельной инициализации через процесс @ref public_capital_project_initialization_process.
|
||||
Все проекты (корневые и дочерние) требуют отдельной инициализации через процесс @ref public_capital_project_initialization_process.
|
||||
|
||||
|
||||
\htmlonly
|
||||
@@ -22,18 +21,11 @@
|
||||
Note over БИ: Идея прошла отбор
|
||||
БИ->>К: Идея готова к реализации
|
||||
|
||||
alt Корневой проект
|
||||
К->>C: Создание проекта
|
||||
Note over C: Проверка уникальности хеша
|
||||
Note over C: Валидация родительского проекта
|
||||
C->>C: Создание записи проекта
|
||||
Note over C: Проект создан, требуется инициализация
|
||||
else Дочерний проект
|
||||
К->>C: Создание компонента
|
||||
Note over C: Проверка авторизации родителя
|
||||
C->>C: Создание записи проекта
|
||||
Note over C: Компонент автоматически авторизован
|
||||
end
|
||||
К->>C: Создание проекта
|
||||
Note over C: Проверка уникальности хеша
|
||||
Note over C: Валидация родительского проекта
|
||||
C->>C: Создание записи проекта
|
||||
Note over C: Проект создан, требуется инициализация
|
||||
</div>
|
||||
\endhtmlonly
|
||||
|
||||
@@ -49,13 +41,11 @@
|
||||
Система проверяет уникальность хеша проекта и валидирует родительский проект,
|
||||
затем создает запись проекта.
|
||||
|
||||
Дочерние проекты (компоненты) автоматически авторизованы при создании на авторизованном родительском проекте.
|
||||
Корневые проекты (без родителя) создаются без авторизации и требуют отдельной инициализации.
|
||||
Все проекты (корневые и дочерние) создаются без авторизации и требуют отдельной инициализации.
|
||||
|
||||
@post создается запись проекта в таблице projects
|
||||
@post статус проекта устанавливается в PENDING
|
||||
@post для дочерних проектов: проект автоматически авторизован и готов к планированию
|
||||
@post для корневых проектов: проект создан и ожидает инициализации
|
||||
@post проект создан и ожидает инициализации
|
||||
|
||||
## Документы процесса
|
||||
@include{doc} project-creation-docs.dox
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Инициализирует проект для авторизации советом
|
||||
* Отправляет корневой проект на рассмотрение совета кооператива:
|
||||
* - Проверяет что проект существует и является корневым
|
||||
* Отправляет проект на рассмотрение совета кооператива:
|
||||
* - Проверяет что проект существует
|
||||
* - Проверяет что проект еще не инициализирован
|
||||
* - Отправляет проект на авторизацию с предоставленным документом
|
||||
* @param coopname Наименование кооператива
|
||||
@@ -11,7 +11,7 @@
|
||||
* @ingroup public_capital_actions
|
||||
|
||||
* @note Авторизация требуется от аккаунта: @p coopname
|
||||
* @note Доступно только для корневых проектов (без родителя)
|
||||
* @note Доступно для всех проектов (корневых и дочерних)
|
||||
*/
|
||||
void capital::initprj(eosio::name coopname, checksum256 project_hash, document2 document) {
|
||||
require_auth(coopname);
|
||||
@@ -22,9 +22,6 @@ void capital::initprj(eosio::name coopname, checksum256 project_hash, document2
|
||||
// Получаем проект для проверки
|
||||
auto project = Capital::Projects::get_project_or_fail(coopname, project_hash);
|
||||
|
||||
// Проверяем что это корневой проект (без родителя)
|
||||
eosio::check(project->parent_hash == checksum256(), "Инициализация требуется только для корневых проектов");
|
||||
|
||||
// Проверяем что проект еще не инициализирован
|
||||
eosio::check(!project->is_authorized, "Проект уже инициализирован");
|
||||
|
||||
|
||||
+4
-5
@@ -3,9 +3,8 @@
|
||||
@defgroup public_capital_project_initialization_process Инициализировать проект
|
||||
@ingroup public_capital_processes
|
||||
@pre Проект создан через @ref public_capital_project_creation_process
|
||||
@pre Проект является корневым (без родителя)
|
||||
|
||||
Процесс инициализации корневого проекта для получения авторизации совета кооператива.
|
||||
Процесс инициализации проекта для получения авторизации совета кооператива.
|
||||
Процесс включает отправку проекта на рассмотрение совета с предоставленным документом,
|
||||
рассмотрение советом и принятие решения об авторизации или отклонении проекта.
|
||||
|
||||
@@ -18,7 +17,7 @@
|
||||
participant С as Совет
|
||||
|
||||
К->>C: Инициализация проекта
|
||||
Note over C: Проверка что проект корневой
|
||||
Note over C: Проверка что проект существует
|
||||
Note over C: Проверка что проект не инициализирован
|
||||
C->>С: Отправка на авторизацию с документом
|
||||
Note over С: Рассмотрение проекта советом
|
||||
@@ -37,8 +36,8 @@
|
||||
### Шаг 1: Инициализация проекта
|
||||
<b>Действие:</b> @ref capital::initprj "инициализация проекта"
|
||||
|
||||
Кооператив отправляет корневой проект на рассмотрение совета кооператива с предоставленным документом.
|
||||
Система проверяет что проект существует, является корневым и еще не инициализирован,
|
||||
Кооператив отправляет проект на рассмотрение совета кооператива с предоставленным документом.
|
||||
Система проверяет что проект существует и еще не инициализирован,
|
||||
затем отправляет проект на авторизацию в совет.
|
||||
|
||||
@post проект отправлен на рассмотрение совета
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* - Проверяет существование проекта
|
||||
* - Валидирует что проект в статусе active
|
||||
* - Обновляет статус проекта на pending
|
||||
* - Сбрасывает авторизацию проекта (требуется повторная инициализация)
|
||||
* @param coopname Наименование кооператива
|
||||
* @param project_hash Хеш проекта для остановки
|
||||
* @ingroup public_actions
|
||||
@@ -25,4 +26,7 @@ void capital::stopproject(name coopname, checksum256 project_hash) {
|
||||
|
||||
// Обновляем статус проекта на "pending"
|
||||
Capital::Projects::update_status(coopname, project_hash, Capital::Projects::Status::PENDING);
|
||||
|
||||
// Сбрасываем авторизацию проекта (требуется повторная инициализация)
|
||||
Capital::Projects::revoke_authorization(coopname, project_hash);
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace Capital::Projects {
|
||||
row.data = data;
|
||||
row.is_planed = false; // Изначально проект не запланирован
|
||||
row.can_convert_to_project = can_convert_to_project; // Разрешена ли конвертация в кошелек проекта
|
||||
row.is_authorized = (parent_hash != checksum256()); // Дочерние проекты сразу авторизованы, корневые - нет
|
||||
row.is_authorized = false; // Все проекты требуют инициализации
|
||||
row.authorization = document2(); // Пустой документ авторизации
|
||||
});
|
||||
}
|
||||
@@ -845,5 +845,24 @@ namespace Capital::Projects {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Сбрасывает авторизацию проекта
|
||||
* Устанавливает флаг авторизации в false и очищает документ авторизации
|
||||
* @param coopname Наименование кооператива
|
||||
* @param project_hash Хеш проекта
|
||||
*/
|
||||
inline void revoke_authorization(eosio::name coopname, const checksum256 &project_hash) {
|
||||
project_index projects(_capital, coopname.value);
|
||||
auto project_hash_index = projects.get_index<"byhash"_n>();
|
||||
|
||||
auto project_itr = project_hash_index.find(project_hash);
|
||||
eosio::check(project_itr != project_hash_index.end(), "Проект не найден");
|
||||
|
||||
project_hash_index.modify(project_itr, coopname, [&](auto& row) {
|
||||
row.is_authorized = false;
|
||||
row.authorization = document2(); // Пустой документ авторизации
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}// namespace Project
|
||||
@@ -0,0 +1,113 @@
|
||||
import type { ICommonUser, ICooperativeData, IVars } from '../../model'
|
||||
import type { IGenerate, IMetaDocument } from '../../document'
|
||||
|
||||
export const registry_id = 1005
|
||||
|
||||
// Модель действия для генерации
|
||||
export interface Action extends IGenerate {
|
||||
registry_id: number
|
||||
project_name: string
|
||||
project_id: string
|
||||
component_name: string
|
||||
component_id: string
|
||||
is_component: boolean
|
||||
}
|
||||
|
||||
export type Meta = IMetaDocument & Action
|
||||
|
||||
// Модель данных документа
|
||||
export interface Model {
|
||||
meta: IMetaDocument
|
||||
coop: ICooperativeData
|
||||
vars: IVars
|
||||
user: ICommonUser
|
||||
project_name: string
|
||||
project_id: string
|
||||
component_name: string
|
||||
component_id: string
|
||||
is_component: boolean
|
||||
}
|
||||
|
||||
export const title = 'Заявление на инициализацию проекта'
|
||||
export const description = 'Заявление на инициализацию проекта или компонента'
|
||||
|
||||
export const context = `<div class="digital-document"><div style="text-align: center"><h1>ЗАЯВЛЕНИЕ</h1><h2>на инициализацию проекта</h2></div><p style="text-align: right">{{ meta.created_at }}, {{ coop.city }}</p><p>{% trans 'parties_intro' %} "{{ vars.name }}" {% trans 'in_face_of_chairman' %} {{ coop.chairman.last_name }} {{ coop.chairman.first_name }} {{ coop.chairman.middle_name }}, {% trans 'acting_on_basis_of_charter' %}, {% trans 'hereinafter_referred_to_as' %} "{% trans 'society' %}", {% trans 'and_participant' %} {{ user.full_name_or_short_name }}, {% trans 'hereinafter_referred_to_as' %} "{% trans 'participant' %}", {% trans 'jointly_referred_to_as' %} "{% trans 'parties' %}", {% trans 'have_concluded_this_statement' %} {% trans 'hereinafter_referred_to_as' %} "{% trans 'statement' %}" {% trans 'of_the_following' %}:</p><p>{% if is_component %}{% trans 'participant_requests_component_init' %} "{{ component_name }}" (№{{ component_id }}) {% trans 'as_part_of_project' %} "{{ project_name }}" (№{{ project_id }}).{% else %}{% trans 'participant_requests_project_init' %} "{{ project_name }}" (№{{ project_id }}).{% endif %}</p><h2>{% trans 'details_and_signatures_of_parties' %}</h2><p><strong>{% trans 'society' %}/{{ vars.full_abbr }} "{{ vars.name }}"/:</strong></p><p>ИНН {{ coop.details.inn }}, КПП {{ coop.details.kpp }}, ОГРН {{ coop.details.ogrn }}</p><p>{% trans 'legal_address' %}: {{ coop.full_address }}</p><p>{% trans 'contact_phone' %}: {{ coop.phone }}</p><p>{% trans 'email' %}: {{ coop.email }}</p><p>{% trans 'bank_account' %}: {{ coop.defaultBankAccount.account_number }}</p><p>{% trans 'bank_name' %}: {{ coop.defaultBankAccount.bank_name }}</p><p>{% trans 'bik' %}: {{ coop.defaultBankAccount.details.bik }}</p><p>{% trans 'correspondent_account' %}: {{ coop.defaultBankAccount.details.corr }}</p><p>{% trans 'chairman' %} {{ vars.full_abbr_genitive }} "{{ vars.name }}"</p><p>{{ coop.chairman.last_name }} {{ coop.chairman.first_name }} {{ coop.chairman.middle_name }}</p><p>{% trans 'signed_by_digital_signature' %}</p><p><strong>{% trans 'participant' %}:</strong></p><p>{{ user.full_name_or_short_name }}</p><p>{% trans 'contact_phone' %}: {{ user.phone }}</p><p>{% trans 'email' %}: {{ user.email }}</p><p>{% trans 'signed_by_digital_signature' %}</p></div><style>.digital-document {padding: 20px;white-space: pre-wrap;}</style>`
|
||||
|
||||
export const translations = {
|
||||
ru: {
|
||||
parties_intro: 'Потребительский Кооператив',
|
||||
in_face_of_chairman: 'в лице Председателя Совета',
|
||||
acting_on_basis_of_charter: 'действующего на основании Устава',
|
||||
hereinafter_referred_to_as: 'далее именуемый(-ая)',
|
||||
society: 'Общество',
|
||||
and_participant: 'и',
|
||||
participant: 'Пайщик',
|
||||
jointly_referred_to_as: 'совместно именуемые',
|
||||
parties: 'Стороны',
|
||||
have_concluded_this_statement: 'составили настоящее Заявление',
|
||||
statement: 'Заявление',
|
||||
of_the_following: 'о нижеследующем',
|
||||
participant_requests_component_init: 'Пайщик просит инициализировать Компонент',
|
||||
participant_requests_project_init: 'Пайщик просит инициализировать Проект',
|
||||
as_part_of_project: 'как составную часть Проекта',
|
||||
details_and_signatures_of_parties: 'РЕКВИЗИТЫ И ПОДПИСИ СТОРОН',
|
||||
legal_address: 'Юр. адрес',
|
||||
contact_phone: 'Контактный тел.',
|
||||
email: 'Электронная почта',
|
||||
bank_account: 'Р/с',
|
||||
bank_name: 'Банк',
|
||||
bik: 'БИК',
|
||||
correspondent_account: 'Корр/счет',
|
||||
chairman: 'Председатель Совета',
|
||||
signed_by_digital_signature: 'Подписано электронной подписью',
|
||||
},
|
||||
}
|
||||
|
||||
export const exampleData = {
|
||||
meta: {
|
||||
created_at: '11.04.2024 12:00',
|
||||
},
|
||||
project_name: 'Проект цифровой платформы',
|
||||
project_id: 'B2C3D4E5F6789ABC',
|
||||
component_name: 'Компонент разработки',
|
||||
component_id: 'A1B2C3D4E5F6789A',
|
||||
is_component: true,
|
||||
vars: {
|
||||
name: 'ВОСХОД',
|
||||
full_abbr_genitive: 'Потребительского Кооператива',
|
||||
full_abbr: 'Потребительский Кооператив',
|
||||
},
|
||||
user: {
|
||||
full_name_or_short_name: 'Иванов Иван Иванович',
|
||||
abbr_full_name: 'Иванов И.И.',
|
||||
email: 'ivanov@example.com',
|
||||
phone: '+7 999 123-45-67',
|
||||
},
|
||||
coop: {
|
||||
short_name: 'ПК "ВОСХОД"',
|
||||
details: {
|
||||
inn: '9728130611',
|
||||
kpp: '772801001',
|
||||
ogrn: '1247700283346',
|
||||
},
|
||||
full_address: '117593, г. МОСКВА, ВН.ТЕР.Г. МУНИЦИПАЛЬНЫЙ ОКРУГ ЯСЕНЕВО, ПРОЕЗД СОЛОВЬИНЫЙ, Д. 1, ПОМЕЩ. 1/1',
|
||||
phone: '+7 902 895-33-75',
|
||||
email: 'chairman.voskhod@gmail.com',
|
||||
defaultBankAccount: {
|
||||
currency: 'RUB',
|
||||
bank_name: 'ПАО Сбербанк',
|
||||
account_number: '40703810038000110117',
|
||||
details: {
|
||||
bik: '044525225',
|
||||
corr: '30101810400000000225',
|
||||
kpp: '772801001',
|
||||
},
|
||||
},
|
||||
chairman: {
|
||||
first_name: 'Алексей',
|
||||
last_name: 'Муравьев',
|
||||
middle_name: 'Николаевич',
|
||||
},
|
||||
city: 'Москва',
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
import type { IDecisionData, IGenerate, IMetaDocument } from '../../document'
|
||||
import type { ICooperativeData, IVars } from '../../model'
|
||||
|
||||
export const registry_id = 1006
|
||||
|
||||
/**
|
||||
* Интерфейс генерации решения совета по инициализации проекта
|
||||
*/
|
||||
export interface Action extends IGenerate {
|
||||
decision_id: number
|
||||
project_name: string
|
||||
project_id: string
|
||||
component_name: string
|
||||
component_id: string
|
||||
is_component: boolean
|
||||
}
|
||||
|
||||
export type Meta = IMetaDocument & Action
|
||||
|
||||
// Модель данных
|
||||
export interface Model {
|
||||
coop: ICooperativeData
|
||||
meta: IMetaDocument
|
||||
decision: IDecisionData
|
||||
vars: IVars
|
||||
project_name: string
|
||||
project_id: string
|
||||
component_name: string
|
||||
component_id: string
|
||||
is_component: boolean
|
||||
}
|
||||
|
||||
export const title = 'Протокол решения совета об инициализации проекта'
|
||||
export const description = 'Форма протокола решения совета об инициализации проекта или компонента'
|
||||
export const context = '<style> \nh1 {\nmargin: 0px; \ntext-align:center;\n}\nh3{\nmargin: 0px;\npadding-top: 15px;\n}\n.about {\npadding: 20px;\n}\n.about p{\nmargin: 0px;\n}\n.signature {\npadding-top: 20px;\n}\n.digital-document {\npadding: 20px;\nwhite-space: pre-wrap;\n}\n.subheader {\npadding-bottom: 20px; \n}\ntable {\n width: 100%;\n border-collapse: collapse;\n}\nth, td {\n border: 1px solid #ccc;\n padding: 8px;\n text-align: left;\n word-wrap: break-word; \n overflow-wrap: break-word; \n}\nth {\n background-color: #f4f4f4;\n width: 30%;\n}\n</style>\n\n<div class="digital-document"><h1 class="header">{% trans \'protocol_number\', decision.id %}</h1>\n<p style="text-align:center" class="subheader">{% trans \'council_meeting_name\' %} {{vars.full_abbr_genitive}} "{{vars.name}}"</p>\n<p style="text-align: right"> {{ meta.created_at }}, {{ coop.city }}</p>\n<table class="about">\n<tbody>\n<tr>\n<th>{% trans \'meeting_format\' %}</th>\n<td>{% trans \'meeting_format_value\' %}</td>\n</tr>\n<tr>\n<th>{% trans \'meeting_place\' %}</th>\n<td>{{ coop.full_address }}</td>\n</tr>\n<tr>\n<th>{% trans \'meeting_date\' %}</th>\n<td>{{ decision.date }}</td>\n</tr>\n<tr>\n<th>{% trans \'opening_time\' %}</th>\n<td>{{ decision.time }}</td>\n</tr>\n</tbody>\n</table>\n<h3>{% trans \'council_members\' %}</h3>\n<table>\n<tbody>\n{% for member in coop.members %}\n<tr>\n<th>{% if member.is_chairman %}{% trans \'chairman_of_the_council\' %}{% else %}{% trans \'member_of_the_council\' %}{% endif %}</th>\n<td>{{ member.last_name }} {{ member.first_name }} {{ member.middle_name }}</td>\n</tr>\n{% endfor %}\n</tbody>\n</table>\n<h3>{% trans \'meeting_legality\' %} </h3>\n<p>{% trans \'voting_results\', decision.voters_percent %} {% trans \'quorum\' %} {% trans \'chairman_of_the_meeting\', coop.chairman.last_name, coop.chairman.first_name, coop.chairman.middle_name %}.</p>\n<h3>{% trans \'agenda\' %}</h3>\n<table>\n<tbody>\n<tr>\n<th>№</th>\n<td>{% trans \'question\' %}</td>\n</tr>\n<tr>\n<th>1</th>\n<td>{% if is_component %}{% trans \'init_component_question\', component_name, component_id, project_name, project_id %}{% else %}{% trans \'init_project_question\', project_name, project_id %}{% endif %}</td>\n</tr>\n</tbody>\n</table>\n<h3>{% trans \'voting\' %}</h3>\n<p>{% trans \'vote_results\' %} </p><table>\n<tbody>\n<tr>\n<th>{% trans \'votes_for\' %}</th>\n<td>{{ decision.votes_for }}</td>\n</tr>\n<tr>\n<th>{% trans \'votes_against\' %}</th>\n<td>{{ decision.votes_against }}</td>\n</tr>\n<tr>\n<th>{% trans \'votes_abstained\' %}</th>\n<td>{{ decision.votes_abstained }}</td>\n</tr>\n</tbody>\n</table>\n<h3>{% trans \'decision_made\' %}</h3>\n<table>\n<tbody>\n<tr>\n<th>№</th>\n<td>{% trans \'decision\' %}</td>\n</tr>\n<tr>\n<th>1</th>\n<td>{% if is_component %}{% trans \'init_component_decision\', component_name, component_id, project_name, project_id %}{% else %}{% trans \'init_project_decision\', project_name, project_id %}{% endif %}</td>\n</tr>\n</tbody>\n</table>\n<hr>\n<p>{% trans \'closing_time\', decision.time %}</p>\n<div class="signature"><p>{% trans \'signature\' %}</p><p>{% trans \'chairman\' %} {{ coop.chairman.last_name }} {{ coop.chairman.first_name }} {{ coop.chairman.middle_name }}</p></div></div>\n'
|
||||
|
||||
export const translations = {
|
||||
ru: {
|
||||
meeting_format: 'Форма',
|
||||
meeting_date: 'Дата',
|
||||
meeting_place: 'Место',
|
||||
opening_time: 'Время открытия',
|
||||
council_members: 'ЧЛЕНЫ СОВЕТА',
|
||||
voting_results: 'Количество голосов составляет {0}% от общего числа членов Совета.',
|
||||
meeting_legality: 'СОБРАНИЕ ПРАВОМОЧНО',
|
||||
chairman_of_the_meeting: 'Председатель собрания совета: {0} {1} {2}',
|
||||
agenda: 'ПОВЕСТКА ДНЯ',
|
||||
vote_results: 'По первому вопросу повестки дня проголосовали:',
|
||||
decision_made: 'РЕШИЛИ',
|
||||
closing_time: 'Время закрытия собрания совета: {0}.',
|
||||
protocol_number: 'ПРОТОКОЛ № {0}',
|
||||
council_meeting_name: 'Собрания Совета',
|
||||
chairman_of_the_council: 'Председатель совета',
|
||||
signature: 'Документ подписан электронной подписью.',
|
||||
chairman: 'Председатель',
|
||||
quorum: 'Кворум для решения поставленных на повестку дня вопросов имеется.',
|
||||
voting: 'ГОЛОСОВАНИЕ',
|
||||
meeting_format_value: 'Заочная',
|
||||
member_of_the_council: 'Член совета',
|
||||
question: 'Вопрос',
|
||||
votes_for: 'ЗА',
|
||||
votes_against: 'ПРОТИВ',
|
||||
votes_abstained: 'ВОЗДЕРЖАЛСЯ',
|
||||
decision: 'Решение',
|
||||
init_component_question: 'Об инициализации компонента "{0}" (№{1}) как составной части проекта "{2}" (№{3})',
|
||||
init_project_question: 'Об инициализации проекта "{0}" (№{1})',
|
||||
init_component_decision: 'Инициализировать компонент "{0}" (№{1}) как составную часть проекта "{2}" (№{3})',
|
||||
init_project_decision: 'Инициализировать проект "{0}" (№{1})',
|
||||
},
|
||||
// ... другие переводы
|
||||
}
|
||||
|
||||
export const exampleData = {
|
||||
meta: {
|
||||
created_at: '12.02.2024 00:01',
|
||||
},
|
||||
project_name: 'Проект цифровой платформы',
|
||||
project_id: 'B2C3D4E5F6789ABC',
|
||||
component_name: 'Компонент разработки',
|
||||
component_id: 'A1B2C3D4E5F6789A',
|
||||
is_component: true,
|
||||
coop: {
|
||||
city: 'Москва',
|
||||
full_address: 'Смольная 3-84',
|
||||
chairman: {
|
||||
last_name: 'Муравьев',
|
||||
first_name: 'Алексей',
|
||||
middle_name: 'Николаевич',
|
||||
},
|
||||
},
|
||||
decision: {
|
||||
time: '00:01',
|
||||
date: '12.02.2024',
|
||||
votes_for: '3',
|
||||
votes_against: '0',
|
||||
votes_abstained: '0',
|
||||
voters_percent: '100',
|
||||
id: '1',
|
||||
},
|
||||
vars: {
|
||||
full_abbr_genitive: 'потребительского кооператива',
|
||||
name: 'ВОСХОД',
|
||||
},
|
||||
}
|
||||
@@ -29,6 +29,8 @@ export * as BlagorostOfferTemplate from './999.BlagorostOfferTemplate'
|
||||
export * as GenerationAgreementTemplate from './997.GenerationAgreementTemplate'
|
||||
export * as GenerationAgreement from './1001.GenerationAgreement'
|
||||
export * as AppendixGenerationAgreement from './1002.AppendixGenerationAgreement'
|
||||
export * as InitProjectStatement from './1005.InitProjectStatement'
|
||||
export * as InitProjectDecision from './1006.InitProjectDecision'
|
||||
|
||||
export * as ExpenseStatement from './1010.ExpenseStatement'
|
||||
export * as ExpenseDecision from './1011.ExpenseDecision'
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import { DraftContract } from 'cooptypes'
|
||||
import { InitProjectStatement } from '../Templates'
|
||||
import { DocFactory } from '../Factory'
|
||||
import type { IGeneratedDocument, IGenerationOptions, IMetaDocument, ITemplate } from '../Interfaces'
|
||||
import type { MongoDBConnector } from '../Services/Databazor'
|
||||
|
||||
export { InitProjectStatement as Template } from '../Templates'
|
||||
|
||||
export class Factory extends DocFactory<InitProjectStatement.Action> {
|
||||
constructor(storage: MongoDBConnector) {
|
||||
super(storage)
|
||||
}
|
||||
|
||||
async generateDocument(data: InitProjectStatement.Action, options?: IGenerationOptions): Promise<IGeneratedDocument> {
|
||||
let template: ITemplate<InitProjectStatement.Model>
|
||||
|
||||
if (process.env.SOURCE === 'local') {
|
||||
template = InitProjectStatement.Template
|
||||
}
|
||||
else {
|
||||
template = await this.getTemplate(DraftContract.contractName.production, InitProjectStatement.registry_id, data.block_num)
|
||||
}
|
||||
|
||||
const meta: IMetaDocument = await this.getMeta({ title: template.title, ...data })
|
||||
const coop = await super.getCooperative(data.coopname, data.block_num)
|
||||
const vars = await super.getVars(data.coopname, data.block_num)
|
||||
|
||||
const userData = await super.getUser(data.username, data.block_num)
|
||||
const user = super.getCommonUser(userData)
|
||||
|
||||
const combinedData: InitProjectStatement.Model = {
|
||||
meta,
|
||||
coop,
|
||||
vars,
|
||||
user,
|
||||
project_name: data.project_name,
|
||||
project_id: data.project_id,
|
||||
component_name: data.component_name,
|
||||
component_id: data.component_id,
|
||||
is_component: data.is_component,
|
||||
}
|
||||
|
||||
await this.validate(combinedData, template.model)
|
||||
|
||||
const translation = template.translations[meta.lang]
|
||||
const document: IGeneratedDocument = await this.generatePDF('', template.context, combinedData, translation, meta, options?.skip_save)
|
||||
|
||||
return document
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
import { type Cooperative, DraftContract } from 'cooptypes'
|
||||
import { DocFactory } from '../Factory'
|
||||
import type {
|
||||
IGeneratedDocument,
|
||||
IGenerationOptions,
|
||||
IMetaDocument,
|
||||
ITemplate,
|
||||
} from '../Interfaces'
|
||||
import type { MongoDBConnector } from '../Services/Databazor'
|
||||
|
||||
import { InitProjectDecision } from '../Templates'
|
||||
|
||||
export { InitProjectDecision as Template } from '../Templates'
|
||||
|
||||
export class Factory extends DocFactory<InitProjectDecision.Action> {
|
||||
constructor(storage: MongoDBConnector) {
|
||||
super(storage)
|
||||
}
|
||||
|
||||
async generateDocument(
|
||||
data: InitProjectDecision.Action,
|
||||
options?: IGenerationOptions,
|
||||
): Promise<IGeneratedDocument> {
|
||||
let template: ITemplate<InitProjectDecision.Model>
|
||||
|
||||
if (process.env.SOURCE === 'local') {
|
||||
template = InitProjectDecision.Template
|
||||
}
|
||||
else {
|
||||
template = await this.getTemplate(DraftContract.contractName.production, InitProjectDecision.registry_id, data.block_num)
|
||||
}
|
||||
|
||||
const user = await this.getUser(data.username, data.block_num)
|
||||
|
||||
const userData = {
|
||||
[user.type]: user.data,
|
||||
}
|
||||
|
||||
const coop = await this.getCooperative(data.coopname, data.block_num)
|
||||
|
||||
// TODO необходимо строго типизировать мета-данные документов друг под друга!
|
||||
const meta: IMetaDocument = await this.getMeta({
|
||||
title: template.title,
|
||||
...data,
|
||||
}) // Генерируем мета-данные
|
||||
|
||||
const decision: Cooperative.Document.IDecisionData = await this.getDecision(
|
||||
coop,
|
||||
data.coopname,
|
||||
data.decision_id,
|
||||
meta.created_at,
|
||||
)
|
||||
|
||||
const vars = await super.getVars(data.coopname, data.block_num)
|
||||
|
||||
const combinedData: InitProjectDecision.Model = {
|
||||
...userData,
|
||||
meta,
|
||||
coop,
|
||||
decision,
|
||||
project_name: data.project_name,
|
||||
project_id: data.project_id,
|
||||
component_name: data.component_name,
|
||||
component_id: data.component_id,
|
||||
is_component: data.is_component,
|
||||
vars,
|
||||
}
|
||||
|
||||
// валидируем скомбинированные данные
|
||||
await this.validate(combinedData, template.model)
|
||||
|
||||
// получаем комплекс перевода
|
||||
const translation = template.translations[meta.lang]
|
||||
|
||||
// генерируем документ
|
||||
const document: IGeneratedDocument = await this.generatePDF(
|
||||
'',
|
||||
template.context,
|
||||
combinedData,
|
||||
translation,
|
||||
meta,
|
||||
options?.skip_save,
|
||||
)
|
||||
|
||||
// возвращаем
|
||||
return document
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,8 @@ export * as ReturnByMoneyDecision from './901.ReturnByMoneyDecision'
|
||||
export * as BlagorostOffer from './1000.CapitalizationAgreement'
|
||||
export * as GenerationAgreement from './1001.GenerationAgreement'
|
||||
export * as AppendixGenerationAgreement from './1002.AppendixGenerationAgreement'
|
||||
export * as InitProjectStatement from './1005.InitProjectStatement'
|
||||
export * as InitProjectDecision from './1006.InitProjectDecision'
|
||||
|
||||
export * as ExpenseStatement from './1010.ExpenseStatement'
|
||||
export * as ExpenseDecision from './1011.ExpenseDecision'
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import type { JSONSchemaType } from 'ajv'
|
||||
import { Cooperative } from 'cooptypes'
|
||||
import type { ITemplate } from '../Interfaces'
|
||||
import { CooperativeSchema } from '../Schema'
|
||||
import { IMetaJSONSchema } from '../Schema/MetaSchema'
|
||||
import { VarsSchema } from '../Schema/VarsSchema'
|
||||
import { CommonUserSchema } from '../Schema/CommonUserSchema'
|
||||
|
||||
export const registry_id = Cooperative.Registry.InitProjectStatement.registry_id
|
||||
|
||||
// Модель действия для генерации
|
||||
export type Action = Cooperative.Registry.InitProjectStatement.Action
|
||||
|
||||
// Модель данных
|
||||
export type Model = Cooperative.Registry.InitProjectStatement.Model
|
||||
|
||||
// Схема для сверки
|
||||
export const Schema: JSONSchemaType<Model> = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
meta: IMetaJSONSchema,
|
||||
coop: CooperativeSchema,
|
||||
vars: VarsSchema,
|
||||
user: CommonUserSchema,
|
||||
project_name: { type: 'string' },
|
||||
project_id: { type: 'string' },
|
||||
component_name: { type: 'string' },
|
||||
component_id: { type: 'string' },
|
||||
is_component: { type: 'boolean' },
|
||||
},
|
||||
required: ['meta', 'coop', 'vars', 'user', 'project_name', 'project_id', 'component_name', 'component_id', 'is_component'],
|
||||
additionalProperties: true,
|
||||
}
|
||||
|
||||
export const Template: ITemplate<Model> = {
|
||||
title: Cooperative.Registry.InitProjectStatement.title,
|
||||
description: Cooperative.Registry.InitProjectStatement.description,
|
||||
model: Schema,
|
||||
context: Cooperative.Registry.InitProjectStatement.context,
|
||||
translations: Cooperative.Registry.InitProjectStatement.translations,
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import type { JSONSchemaType } from 'ajv'
|
||||
|
||||
import { Cooperative } from 'cooptypes'
|
||||
import type { ITemplate } from '../Interfaces'
|
||||
import { IMetaJSONSchema } from '../Schema/MetaSchema'
|
||||
import { CooperativeSchema } from '../Schema/CooperativeSchema'
|
||||
import { decisionSchema } from '../Schema/DecisionSchema'
|
||||
import { VarsSchema } from '../Schema'
|
||||
|
||||
export const registry_id = Cooperative.Registry.InitProjectDecision.registry_id
|
||||
|
||||
/**
|
||||
* Интерфейс генерации решения совета по инициализации проекта
|
||||
*/
|
||||
export type Action = Cooperative.Registry.InitProjectDecision.Action
|
||||
|
||||
export type Model = Cooperative.Registry.InitProjectDecision.Model
|
||||
|
||||
// Схема для сверки
|
||||
export const Schema: JSONSchemaType<Model> = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
coop: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
...CooperativeSchema.properties,
|
||||
},
|
||||
required: [...CooperativeSchema.required],
|
||||
additionalProperties: true,
|
||||
},
|
||||
decision: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
...decisionSchema.properties,
|
||||
},
|
||||
required: [...decisionSchema.required],
|
||||
additionalProperties: true,
|
||||
},
|
||||
meta: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
...IMetaJSONSchema.properties,
|
||||
},
|
||||
required: [...IMetaJSONSchema.required],
|
||||
additionalProperties: true,
|
||||
},
|
||||
vars: VarsSchema,
|
||||
project_name: { type: 'string' },
|
||||
project_id: { type: 'string' },
|
||||
component_name: { type: 'string' },
|
||||
component_id: { type: 'string' },
|
||||
is_component: { type: 'boolean' },
|
||||
},
|
||||
required: ['meta', 'coop', 'decision', 'project_name', 'project_id', 'component_name', 'component_id', 'is_component'],
|
||||
additionalProperties: true,
|
||||
}
|
||||
|
||||
export const Template: ITemplate<Model> = {
|
||||
title: Cooperative.Registry.InitProjectDecision.title,
|
||||
description: Cooperative.Registry.InitProjectDecision.description,
|
||||
model: Schema,
|
||||
context: Cooperative.Registry.InitProjectDecision.context,
|
||||
translations: Cooperative.Registry.InitProjectDecision.translations,
|
||||
}
|
||||
@@ -27,6 +27,8 @@ export * as BlagorostOfferTemplate from './999.BlagorostOfferTemplate'
|
||||
export * as BlagorostOffer from './1000.CapitalizationAgreement'
|
||||
export * as GenerationAgreement from './1001.GenerationAgreement'
|
||||
export * as AppendixGenerationAgreement from './1002.AppendixGenerationAgreement'
|
||||
export * as InitProjectStatement from './1005.InitProjectStatement'
|
||||
export * as InitProjectDecision from './1006.InitProjectDecision'
|
||||
|
||||
export * as ExpenseStatement from './1010.ExpenseStatement'
|
||||
export * as ExpenseDecision from './1011.ExpenseDecision'
|
||||
|
||||
@@ -20,6 +20,8 @@ import * as ReturnByMoney from './900.returnByMoney'
|
||||
import * as ReturnByMoneyDecision from './901.ReturnByMoneyDecision'
|
||||
import * as GenerationAgreement from './1001.GenerationAgreement'
|
||||
import * as AppendixGenerationAgreement from './1002.AppendixGenerationAgreement'
|
||||
import * as InitProjectStatement from './1005.InitProjectStatement'
|
||||
import * as InitProjectDecision from './1006.InitProjectDecision'
|
||||
|
||||
import * as ExpenseStatement from './1010.ExpenseStatement'
|
||||
import * as ExpenseDecision from './1011.ExpenseDecision'
|
||||
@@ -95,6 +97,8 @@ export const Registry = {
|
||||
1000: BlagorostOffer,
|
||||
1001: GenerationAgreement,
|
||||
1002: AppendixGenerationAgreement,
|
||||
1005: InitProjectStatement,
|
||||
1006: InitProjectDecision,
|
||||
1010: ExpenseStatement,
|
||||
1011: ExpenseDecision,
|
||||
1020: GenerationMoneyInvestStatement,
|
||||
|
||||
@@ -110,6 +110,8 @@ export class Generator implements IGenerator {
|
||||
[Actions.AssetContributionAct.Template.registry_id]: new Actions.AssetContributionAct.Factory(this.storage), // 702
|
||||
[Actions.GenerationAgreement.Template.registry_id]: new Actions.GenerationAgreement.Factory(this.storage), // 1001
|
||||
[Actions.AppendixGenerationAgreement.Template.registry_id]: new Actions.AppendixGenerationAgreement.Factory(this.storage), // 1002
|
||||
[Actions.InitProjectStatement.Template.registry_id]: new Actions.InitProjectStatement.Factory(this.storage), // 1005
|
||||
[Actions.InitProjectDecision.Template.registry_id]: new Actions.InitProjectDecision.Factory(this.storage), // 1006
|
||||
|
||||
[Actions.ExpenseStatement.Template.registry_id]: new Actions.ExpenseStatement.Factory(this.storage), // 1010
|
||||
[Actions.ExpenseDecision.Template.registry_id]: new Actions.ExpenseDecision.Factory(this.storage), // 1011
|
||||
|
||||
@@ -55,6 +55,35 @@ describe('тест генератора документов с registry_id >= 1
|
||||
})
|
||||
})
|
||||
|
||||
it('генерируем заявление на инициализацию проекта', async () => {
|
||||
await testDocumentGeneration({
|
||||
registry_id: 1005,
|
||||
coopname: 'voskhod',
|
||||
username: 'ant',
|
||||
project_name: 'Проект цифровой платформы',
|
||||
project_id: 'B2C3D4E5F6789ABC',
|
||||
component_name: 'Компонент разработки',
|
||||
component_id: 'A1B2C3D4E5F6789A',
|
||||
is_component: true,
|
||||
lang: 'ru',
|
||||
})
|
||||
})
|
||||
|
||||
it('генерируем решение об инициализации проекта', async () => {
|
||||
await testDocumentGeneration({
|
||||
registry_id: 1006,
|
||||
coopname: 'voskhod',
|
||||
username: 'ant',
|
||||
decision_id: 1,
|
||||
project_name: 'Проект цифровой платформы',
|
||||
project_id: 'B2C3D4E5F6789ABC',
|
||||
component_name: 'Компонент разработки',
|
||||
component_id: 'A1B2C3D4E5F6789A',
|
||||
is_component: true,
|
||||
lang: 'ru',
|
||||
})
|
||||
})
|
||||
|
||||
// Документы расходов
|
||||
it('генерируем заявление о расходах', async () => {
|
||||
await testDocumentGeneration({
|
||||
|
||||
Reference in New Issue
Block a user