Compare commits
102 Commits
v2.0.7
...
v2.1.4-alpha.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 6345c2d414 | |||
| 87930cad75 | |||
| 3ab2232121 | |||
| 9719e25421 | |||
| 8e1f998c39 | |||
| deb1c224f8 | |||
| b2fa79898a | |||
| da2759a3c6 | |||
| f6bc696426 | |||
| da653e9b32 | |||
| 227e153bde | |||
| 12f906b9b0 | |||
| c8236d4d10 | |||
| e2006da50d | |||
| 433a7d3641 | |||
| 6b41c74b43 | |||
| cc3e7ff7c6 | |||
| a35a6bf642 | |||
| 9ecd523646 | |||
| e7f896c38e | |||
| 624ec743b1 | |||
| 553c5745ef | |||
| 3f2779ca3d | |||
| e51b962627 | |||
| f709e135b6 | |||
| 50b48aa247 | |||
| 508f2abc82 | |||
| 42ec56e578 | |||
| 92673dac6e | |||
| daf57aba35 | |||
| dee629c429 | |||
| 67f9092350 | |||
| 88691d47a5 | |||
| 0fdd9bc803 | |||
| 8452c607b4 | |||
| 4fc57c2d57 | |||
| 9f0b707a30 | |||
| 511bc351d5 | |||
| 56ee3e962c | |||
| 2781e8519d | |||
| 46575348fe | |||
| bae2ca646b | |||
| 0686c6ab00 | |||
| db04b66ce5 | |||
| c43c8a29af | |||
| aaea18abe1 | |||
| 0b6076cb61 | |||
| 3b6d02f02c | |||
| 625a0586a3 | |||
| 10d63ca586 | |||
| d2697bf9de | |||
| fa8c8843e2 | |||
| 7b59ea4b96 | |||
| 058215934e | |||
| 1d724d841f | |||
| 32db2100de | |||
| 095c77b65b | |||
| c1c07bff8f | |||
| 1206bd0e98 | |||
| 67bcd1b307 | |||
| 31ef70e433 | |||
| afb12961d2 | |||
| 3dbd40e334 | |||
| bc5d6e38c8 | |||
| 5a39143051 | |||
| 18e9571877 | |||
| a828f4c831 | |||
| 54ac12f250 | |||
| 9a6a72f605 | |||
| 03949489e8 | |||
| 8ebd735e7e | |||
| 39246da73f | |||
| bf33f60368 | |||
| 492a613769 | |||
| 2c02c3434e | |||
| a186ddd9d2 | |||
| 4b0c7a5e4e | |||
| 54cfbe3ab6 | |||
| 02015cf0b8 | |||
| 416e4d3598 | |||
| e0d9c4b0ea | |||
| 2659e3bc09 | |||
| d296167b6a | |||
| 89b0aa7fec | |||
| 787aadf444 | |||
| d67161a29b | |||
| 7f4777ead4 | |||
| 1e2147b143 | |||
| 9f0a2fbf63 | |||
| 7804851bc9 | |||
| adc50dd89e | |||
| 5378cf5ddc | |||
| a733bb605f | |||
| aaa1b5a264 | |||
| 5855cdee65 | |||
| c0d584e644 | |||
| 955f0f473e | |||
| 9ceb888124 | |||
| e902933693 | |||
| e07b47fb10 | |||
| 5bf08d9701 | |||
| 597fa1e6fa |
@@ -3,6 +3,53 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.1.3](https://github.com/coopenomics/monocoop/compare/v2.1.2-alpha.10...v2.1.3) (2024-10-26)
|
||||
|
||||
|
||||
|
||||
## [2.1.2](https://github.com/coopenomics/monocoop/compare/v2.1.1...v2.1.2) (2024-10-19)
|
||||
|
||||
**Note:** Version bump only for package monocoop
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.1.2](https://github.com/coopenomics/monocoop/compare/v2.1.1...v2.1.2) (2024-10-19)
|
||||
|
||||
**Note:** Version bump only for package monocoop
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [2.1.0](https://github.com/coopenomics/monocoop/compare/v2.0.10-alpha.3...v2.1.0) (2024-10-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* запрос соглашений ([9a6a72f](https://github.com/coopenomics/monocoop/commit/9a6a72f605ba52eef2ed6f18ccee6fbed287ea00))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.0.9](https://github.com/coopenomics/monocoop/compare/v2.0.8...v2.0.9) (2024-10-10)
|
||||
|
||||
**Note:** Version bump only for package monocoop
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.0.8](https://github.com/coopenomics/monocoop/compare/v2.0.7...v2.0.8) (2024-10-09)
|
||||
|
||||
**Note:** Version bump only for package monocoop
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.0.7](https://github.com/coopenomics/monocoop/compare/v2.0.6...v2.0.7) (2024-09-30)
|
||||
|
||||
**Note:** Version bump only for package monocoop
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
k# Conventional Commits
|
||||
|
||||
### Основные типы коммитов:
|
||||
|
||||
- **`feat`**: Добавление новой функциональности (feature).
|
||||
- Пример: `feat: добавлена возможность загрузки файлов`
|
||||
|
||||
- **`fix`**: Исправление бага.
|
||||
- Пример: `fix: исправлена ошибка отображения кнопки на мобильных устройствах`
|
||||
|
||||
- **`chore`**: Изменения, не влияющие на исходный код (например, обновление зависимостей или инструментария).
|
||||
- Пример: `chore: обновление зависимостей`
|
||||
|
||||
- **`docs`**: Изменения в документации.
|
||||
- Пример: `docs: обновлено руководство пользователя`
|
||||
|
||||
- **`style`**: Изменения стиля кода, не влияющие на его функциональность (форматирование, пробелы, и т.д.).
|
||||
- Пример: `style: исправлены отступы в коде`
|
||||
|
||||
- **`refactor`**: Изменения в коде, которые не исправляют баги и не добавляют новую функциональность.
|
||||
- Пример: `refactor: улучшена структура класса`
|
||||
|
||||
- **`perf`**: Изменения, направленные на улучшение производительности.
|
||||
- Пример: `perf: оптимизирована работа с массивами`
|
||||
|
||||
- **`test`**: Добавление или изменение тестов.
|
||||
- Пример: `test: добавлен тест для проверки функции отправки сообщений`
|
||||
|
||||
### Дополнительные типы коммитов:
|
||||
|
||||
- **`build`**: Изменения, связанные с процессом сборки или зависимостями.
|
||||
- Пример: `build: обновление конфигурации Webpack`
|
||||
|
||||
- **`ci`**: Изменения, касающиеся настроек непрерывной интеграции (например, Travis, Jenkins).
|
||||
- Пример: `ci: настройка Travis для автоматических сборок`
|
||||
|
||||
- **`revert`**: Откат на предыдущие изменения.
|
||||
- Пример: `revert: откат коммита e0b5107`
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
# MONOCOOP
|
||||
|
||||
Моно-репозиторий компонент Цифрового Кооператива.
|
||||
Моно-репозиторий компонент клиента системы электронного документооборота для потребительских и производственных кооперативов.
|
||||
|
||||
## Инициализация
|
||||
```
|
||||
curl -X POST http://127.0.0.1:2998/v1/system/init \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "server-secret: SECRET" \
|
||||
-d @init-cooperative1.json
|
||||
```
|
||||
|
||||
## Лицензия
|
||||
Продукт Потребительского Кооператива "ВОСХОД" распространяется по лицензии BY-NC-SA 4.0.
|
||||
|
||||
Разрешено делиться, копировать и распространять материал на любом носителе и форме, адаптировать, делать ремиксы, видоизменять и создавать новое, опираясь на этот материал. При использовании, Вы должны обеспечить указание авторства, предоставить ссылку, и обозначить изменения, если таковые были сделаны. Если вы перерабатываете, преобразовываете материал или берёте его за основу для производного произведения, вы должны распространять переделанные вами части материала на условиях той же лицензии , в соответствии с которой распространяется оригинал. Запрещено коммерческое использование материала. Использование в коммерческих целях – это использование, в первую очередь направленное на получение коммерческого преимущества или денежного вознаграждения.
|
||||
|
||||
Юридический текст лицензии: https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.ru
|
||||
|
||||
Vendored
BIN
Binary file not shown.
@@ -3,6 +3,50 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.1.3](https://github.com/copenomics/cooparser/compare/v2.1.2-alpha.10...v2.1.3) (2024-10-26)
|
||||
|
||||
|
||||
|
||||
## [2.1.2](https://github.com/copenomics/cooparser/compare/v2.1.1...v2.1.2) (2024-10-19)
|
||||
|
||||
**Note:** Version bump only for package cooparser-ts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.1.2](https://github.com/copenomics/cooparser/compare/v2.1.1...v2.1.2) (2024-10-19)
|
||||
|
||||
**Note:** Version bump only for package cooparser-ts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [2.1.0](https://github.com/copenomics/cooparser/compare/v2.0.10-alpha.3...v2.1.0) (2024-10-13)
|
||||
|
||||
**Note:** Version bump only for package cooparser-ts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.0.9](https://github.com/copenomics/cooparser/compare/v2.0.8...v2.0.9) (2024-10-10)
|
||||
|
||||
**Note:** Version bump only for package cooparser-ts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.0.8](https://github.com/copenomics/cooparser/compare/v2.0.7...v2.0.8) (2024-10-09)
|
||||
|
||||
**Note:** Version bump only for package cooparser-ts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.0.2](https://github.com/copenomics/cooparser/compare/v2.0.2-alpha.1...v2.0.2) (2024-09-29)
|
||||
|
||||
**Note:** Version bump only for package cooparser-ts
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "pkg-placeholder",
|
||||
"version": "2.0.2",
|
||||
"version": "2.1.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "pkg-placeholder",
|
||||
"version": "2.0.2",
|
||||
"version": "2.1.3",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^2.16.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "cooparser-ts",
|
||||
"type": "module",
|
||||
"version": "2.0.2",
|
||||
"version": "2.1.3",
|
||||
"private": false,
|
||||
"packageManager": "pnpm@9.0.6",
|
||||
"description": "",
|
||||
@@ -82,5 +82,6 @@
|
||||
"unbuild": "^2.0.0",
|
||||
"vite": "^5.2.10",
|
||||
"vitest": "^1.5.2"
|
||||
}
|
||||
},
|
||||
"gitHead": "7b59ea4b96991ed06abdc92e6d7835632845e3a5"
|
||||
}
|
||||
|
||||
@@ -14,12 +14,10 @@ export async function BlockParser(db: Database, reader: EosioShipReaderResolved)
|
||||
setTimeout(() => process.exit(1), 10000)
|
||||
})
|
||||
|
||||
|
||||
blocks$.subscribe(async (block: IBlock) => {
|
||||
// console.log('new block: ', block)
|
||||
// process.stdout.write('\r') // Возврат каретки в начало строки
|
||||
// process.stdout.write(`Блок: ${block.block_num}`) // Ваш текст
|
||||
|
||||
db.updateCurrentBlock(block.last_irreversible_block_num)
|
||||
db.updateCurrentBlock(block.block_num)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -51,18 +51,15 @@ export class Database {
|
||||
|
||||
const pipeline = [
|
||||
{ $match: filter },
|
||||
{ $sort: { block_num: -1, _id: -1 } },
|
||||
{ $sort: { block_num: -1 } }, // Сортировка по primary_key и block_num
|
||||
{ $group: { _id: '$primary_key', doc: { $first: '$$ROOT' } } },
|
||||
// { $match: { 'doc.present': true } },
|
||||
{ $replaceRoot: { newRoot: '$doc' } },
|
||||
{ $sort: { block_num: -1 } },
|
||||
{ $skip: (page - 1) * limit }, // Применяется внутри пайплайна
|
||||
{ $limit: limit }, // Применяется внутри пайплайна
|
||||
]
|
||||
|
||||
const [result] = await Promise.all([
|
||||
this.deltas.aggregate(pipeline)
|
||||
.skip((page - 1) * limit)
|
||||
.limit(limit)
|
||||
.toArray(),
|
||||
])
|
||||
const result = await this.deltas.aggregate(pipeline).toArray()
|
||||
|
||||
return {
|
||||
results: result as IDelta[],
|
||||
@@ -79,9 +76,10 @@ export class Database {
|
||||
|
||||
const result = await this.actions.aggregate([
|
||||
{ $match: query },
|
||||
{ $sort: { block_num: -1, _id: -1 } },
|
||||
{ $sort: { block_num: -1 } }, // Сортировка по primary_key и block_num
|
||||
{ $group: { _id: '$global_sequence', doc: { $first: '$$ROOT' } } },
|
||||
{ $replaceRoot: { newRoot: '$doc' } },
|
||||
{ $sort: { block_num: -1 } },
|
||||
{ $skip: (page - 1) * limit },
|
||||
{ $limit: limit },
|
||||
]).toArray()
|
||||
|
||||
@@ -54,6 +54,7 @@ export const subsribedActions: IActionConfig[] = [
|
||||
{ code: 'soviet', action: 'joincoopdec' },
|
||||
|
||||
{ code: 'soviet', action: 'updateboard', notify: true },
|
||||
{ code: 'soviet', action: 'createboard', notify: true },
|
||||
]
|
||||
|
||||
// --------------------------
|
||||
|
||||
@@ -3,6 +3,42 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.1.3](https://github.com/hagopj13/node-express-boilerplate/compare/v2.1.2-alpha.10...v2.1.3) (2024-10-26)
|
||||
|
||||
|
||||
|
||||
## [2.1.2](https://github.com/hagopj13/node-express-boilerplate/compare/v2.1.1...v2.1.2) (2024-10-19)
|
||||
|
||||
**Note:** Version bump only for package @coopenomics/controller
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.1.2](https://github.com/hagopj13/node-express-boilerplate/compare/v2.1.1...v2.1.2) (2024-10-19)
|
||||
|
||||
**Note:** Version bump only for package coopback
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [2.1.0](https://github.com/hagopj13/node-express-boilerplate/compare/v2.0.10-alpha.3...v2.1.0) (2024-10-13)
|
||||
|
||||
**Note:** Version bump only for package coopback
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.0.8](https://github.com/hagopj13/node-express-boilerplate/compare/v2.0.7...v2.0.8) (2024-10-09)
|
||||
|
||||
**Note:** Version bump only for package coopback
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.0.7](https://github.com/hagopj13/node-express-boilerplate/compare/v2.0.6...v2.0.7) (2024-09-30)
|
||||
|
||||
**Note:** Version bump only for package coopback
|
||||
|
||||
@@ -1,47 +1,30 @@
|
||||
FROM node:alpine AS base
|
||||
# Базовый образ Ubuntu для лучшей совместимости с WeasyPrint
|
||||
FROM ubuntu:20.04 AS base
|
||||
|
||||
# ENV PNPM_HOME="/pnpm"
|
||||
# ENV PATH="$PNPM_HOME:$PATH"
|
||||
# Обновление и установка необходимых пакетов для Node.js и WeasyPrint
|
||||
RUN apt-get update && \
|
||||
apt-get install -y curl gnupg python3 python3-pip && \
|
||||
curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \
|
||||
apt-get install -y nodejs
|
||||
|
||||
# Включение pnpm
|
||||
RUN corepack enable pnpm \
|
||||
&& corepack prepare pnpm@latest --activate
|
||||
|
||||
|
||||
# Устанавливаем рабочую директорию
|
||||
WORKDIR /app
|
||||
|
||||
# Копируем package.json
|
||||
COPY package.json ./
|
||||
|
||||
# Install dependencies for Puppeteer
|
||||
RUN apk add --no-cache \
|
||||
chromium \
|
||||
nss \
|
||||
freetype \
|
||||
freetype-dev \
|
||||
harfbuzz \
|
||||
ca-certificates \
|
||||
ttf-freefont \
|
||||
&& apk add --no-cache --virtual .build-deps \
|
||||
curl \
|
||||
&& rm -rf /var/cache/*
|
||||
|
||||
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
|
||||
|
||||
# RUN mkdir -p /usr/src/node-app && chown -R node:node /usr/src/node-app
|
||||
|
||||
# WORKDIR /usr/src/node-app
|
||||
|
||||
# COPY package.json pnpm-lock.yaml ./
|
||||
|
||||
# USER node
|
||||
|
||||
# FROM base AS prod-deps
|
||||
# RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile
|
||||
|
||||
# FROM base AS build
|
||||
# RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
|
||||
|
||||
# COPY --chown=node:node . .
|
||||
|
||||
# EXPOSE 3000
|
||||
|
||||
# CMD ["npx", "ts-node", "src/index.ts"]
|
||||
# Установка зависимостей для WeasyPrint
|
||||
RUN apt-get install -y \
|
||||
libpango-1.0-0 \
|
||||
libharfbuzz0b \
|
||||
libpangoft2-1.0-0 \
|
||||
libharfbuzz-subset0 \
|
||||
libffi-dev \
|
||||
libjpeg-dev \
|
||||
libopenjp2-7-dev \
|
||||
&& pip3 install WeasyPrint==62.3 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# COOPERATIVE CONTROLLER
|
||||
# COOPERATIVE CONTROLLER.
|
||||
|
||||
[](https://travis-ci.org/hagopj13/node-express-boilerplate)
|
||||
[](https://coveralls.io/github/hagopj13/node-express-boilerplate?branch=master)
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "create-nodejs-express-app",
|
||||
"version": "2.0.7",
|
||||
"version": "2.1.4-alpha.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "create-nodejs-express-app",
|
||||
"version": "2.0.7",
|
||||
"version": "2.1.4-alpha.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@a2seven/yoo-checkout": "^1.1.4",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "coopback",
|
||||
"version": "2.0.7",
|
||||
"name": "@coopenomics/controller",
|
||||
"version": "2.1.4-alpha.0",
|
||||
"description": "",
|
||||
"private": true,
|
||||
"private": false,
|
||||
"bin": "bin/createNodejsApp.js",
|
||||
"main": "src/index.ts",
|
||||
"repository": "https://github.com/hagopj13/node-express-boilerplate.git",
|
||||
@@ -12,6 +12,9 @@
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"deploy-testnet": "git checkout testnet && git merge main && git push origin testnet && git checkout main",
|
||||
"deploy-production": "git checkout production && git merge testnet && git push origin production && git checkout main",
|
||||
@@ -86,6 +89,7 @@
|
||||
"isomorphic-fetch": "^3.0.0",
|
||||
"jest": "^29.7.0",
|
||||
"joi": "^17.13.1",
|
||||
"joi-to-json": "^4.3.0",
|
||||
"joi-to-typescript": "^4.13.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"jspdf": "^2.5.1",
|
||||
@@ -94,6 +98,7 @@
|
||||
"mongoose": "^8.5.2",
|
||||
"mongoose-sequence": "^6.0.1",
|
||||
"morgan": "^1.9.1",
|
||||
"node-cron": "^3.0.3",
|
||||
"nodemailer": "^6.3.1",
|
||||
"nunjucks": "^3.2.4",
|
||||
"passport": "^0.4.0",
|
||||
@@ -103,9 +108,11 @@
|
||||
"socket.io-client": "^4.7.5",
|
||||
"swagger-jsdoc": "^6.0.8",
|
||||
"swagger-ui-express": "^4.1.6",
|
||||
"threads": "^1.7.0",
|
||||
"ts-jest": "^29.1.3",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsd": "^0.31.0",
|
||||
"tsoa": "^6.4.0",
|
||||
"validator": "^13.0.0",
|
||||
"winston": "^3.2.1",
|
||||
"winston-daily-rotate-file": "^5.0.0",
|
||||
|
||||
@@ -9,8 +9,6 @@ const envVarsSchema = Joi.object()
|
||||
NODE_ENV: Joi.string().valid('production', 'development', 'test').required(),
|
||||
BASE_URL: Joi.string().required(),
|
||||
SERVER_SECRET: Joi.string().required(),
|
||||
SERVICE_USERNAME: Joi.string().required(),
|
||||
SERVICE_WIF: Joi.string().required(),
|
||||
PORT: Joi.number().default(3000),
|
||||
MONGODB_URL: Joi.string().required().description('Mongo DB url'),
|
||||
JWT_SECRET: Joi.string().required().description('JWT secret key'),
|
||||
@@ -46,8 +44,6 @@ export default {
|
||||
base_url: envVars.BASE_URL,
|
||||
port: envVars.PORT,
|
||||
server_secret: envVars.SERVER_SECRET,
|
||||
service_wif: envVars.SERVICE_WIF,
|
||||
service_username: envVars.SERVICE_USERNAME,
|
||||
mongoose: {
|
||||
url: envVars.MONGODB_URL + (envVars.NODE_ENV === 'test' ? '-test' : ''),
|
||||
options: {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const user = [
|
||||
'getSelf',
|
||||
'initialPayment',
|
||||
'generateDocument',
|
||||
'getMyDocuments',
|
||||
'getMyOrders',
|
||||
'sendVerificationEmail',
|
||||
@@ -11,9 +10,19 @@ const user = [
|
||||
'getVars',
|
||||
];
|
||||
|
||||
const member = ['getUsers', 'manageUsers', 'loadAgenda', 'loadStaff', 'getDocuments', 'loadInfo', 'manageOrders'];
|
||||
const member = [
|
||||
...user,
|
||||
'getUsers',
|
||||
'manageUsers',
|
||||
'loadAgenda',
|
||||
'loadStaff',
|
||||
'getDocuments',
|
||||
'loadInfo',
|
||||
'manageOrders',
|
||||
'regenerateDocument',
|
||||
];
|
||||
|
||||
const chairman = [...user, ...member, 'addUser', 'setVars', 'manageSettings'];
|
||||
const chairman = [...user, ...member, 'addUser', 'setVars', 'manageSettings', 'setWif', 'setPlugin'];
|
||||
|
||||
const allRoles = {
|
||||
user,
|
||||
|
||||
@@ -14,8 +14,8 @@ export const getDocuments = catchAsync(async (req: RGetDocuments, res) => {
|
||||
const filter = req.query?.filter;
|
||||
const limit = req.query?.limit as number;
|
||||
const page = req.query?.page as number;
|
||||
|
||||
const documents = await documentService.queryDocuments(filter, page, limit);
|
||||
const type = req.query?.type as string;
|
||||
const documents = await documentService.queryDocuments(type, filter, page, limit);
|
||||
|
||||
res.status(httpStatus.OK).send(documents);
|
||||
});
|
||||
|
||||
@@ -8,3 +8,4 @@ export * as systemController from './system.controller';
|
||||
export * as participantController from './participant.controller';
|
||||
export * as methodController from './method.controller';
|
||||
export * as settingController from './setting.controller';
|
||||
export * as pluginController from './plugin.controller';
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { Request, Response } from 'express';
|
||||
import { pluginService } from '../services';
|
||||
import httpStatus from 'http-status';
|
||||
import type { RGetPluginConfig, RGetPluginList, RGetPluginSchema, RSetPlugin } from '../types';
|
||||
import ApiError from '../utils/ApiError';
|
||||
import catchAsync from '../utils/catchAsync';
|
||||
import { restartWorker, terminateWorker } from '../factories/pluginFactory';
|
||||
import pick from '../utils/pick';
|
||||
|
||||
export const getPluginList = catchAsync(async (req: RGetPluginList, res: Response) => {
|
||||
const filter = pick(req.query, ['name']);
|
||||
const options = pick(req.query, ['sortBy', 'limit', 'page']);
|
||||
|
||||
const plugins = await pluginService.queryPlugins(filter, options);
|
||||
|
||||
res.send(plugins);
|
||||
});
|
||||
|
||||
// Контроллер для обновления параметров плагинов
|
||||
export const setPluginConfig = catchAsync(async (req: RSetPlugin, res: Response) => {
|
||||
const { name, config, enabled } = req.body;
|
||||
try {
|
||||
const updatedConfig = await pluginService.updatePluginConfig(name, enabled, config);
|
||||
|
||||
if (enabled == false) await terminateWorker(name);
|
||||
else await restartWorker(name);
|
||||
|
||||
res.status(httpStatus.OK).json({
|
||||
message: `Конфигурация плагина ${name} успешно обновлена`,
|
||||
config: updatedConfig,
|
||||
});
|
||||
} catch (e: any) {
|
||||
throw new ApiError(httpStatus.BAD_REQUEST, e.message);
|
||||
}
|
||||
});
|
||||
|
||||
// Контроллер для обновления параметров плагинов
|
||||
export const getPluginSchema = catchAsync(async (req: RGetPluginSchema, res: Response) => {
|
||||
const { name } = req.query;
|
||||
try {
|
||||
const schema = pluginService.getPluginSchema(name);
|
||||
res.status(httpStatus.OK).json(schema);
|
||||
} catch (e: any) {
|
||||
throw new ApiError(httpStatus.BAD_REQUEST, e.message);
|
||||
}
|
||||
});
|
||||
|
||||
// Контроллер для обновления параметров плагинов
|
||||
export const getPluginConfig = catchAsync(async (req: RGetPluginConfig, res: Response) => {
|
||||
const { name } = req.query;
|
||||
console.log('plugin', name);
|
||||
const config = await pluginService.getPluginConfig(name);
|
||||
|
||||
res.status(httpStatus.OK).json(config);
|
||||
});
|
||||
@@ -5,18 +5,30 @@ import { IHealthResponse, IInstall, RInstall } from '../types';
|
||||
import { Request, Response } from 'express';
|
||||
import catchAsync from '../utils/catchAsync';
|
||||
import { systemService } from '../services';
|
||||
import type { ISetVars, RSetVars } from '../types/auto-generated/system.validation';
|
||||
import type { IInit, ISetVars, RInit, RSetVars, RSetWif } from '../types/auto-generated/system.validation';
|
||||
import logger from '../config/logger';
|
||||
|
||||
export const init = catchAsync(async (req: RInit, res: Response) => {
|
||||
const { body } = req;
|
||||
await systemService.init(body as IInit);
|
||||
|
||||
res.status(httpStatus.OK).send();
|
||||
});
|
||||
|
||||
export const install = catchAsync(async (req: RInstall, res: Response) => {
|
||||
const { body } = req;
|
||||
await systemService.install(body as IInstall);
|
||||
|
||||
logger.info('System installed', { source: 'install', vars: req.body });
|
||||
logger.info('System installed');
|
||||
|
||||
res.status(httpStatus.OK).send();
|
||||
});
|
||||
|
||||
export const setWif = catchAsync(async (req: RSetWif, res: Response) => {
|
||||
await systemService.setWif(req.body);
|
||||
res.status(httpStatus.OK).send();
|
||||
});
|
||||
|
||||
export const getHealth = catchAsync(async (req: Request, res: Response) => {
|
||||
const status = await getMonoStatus();
|
||||
const blockchain = await getBlockchainInfo();
|
||||
@@ -31,7 +43,6 @@ export const getHealth = catchAsync(async (req: Request, res: Response) => {
|
||||
|
||||
export const setVars = catchAsync(async (req: RSetVars, res: Response) => {
|
||||
await systemService.setVars(req.body as ISetVars);
|
||||
logger.info('New vars installed', { source: 'setVars', vars: req.body });
|
||||
res.status(httpStatus.OK).send();
|
||||
});
|
||||
|
||||
@@ -39,3 +50,8 @@ export const getVarsSchema = catchAsync(async (req: RSetVars, res: Response) =>
|
||||
const schema = await systemService.getVarsSchema();
|
||||
res.status(httpStatus.OK).send(schema);
|
||||
});
|
||||
|
||||
export const getVars = catchAsync(async (req: RSetVars, res: Response) => {
|
||||
const vars = await systemService.getVars();
|
||||
res.status(httpStatus.OK).send(vars);
|
||||
});
|
||||
|
||||
@@ -5,12 +5,26 @@ import { userService, tokenService, emailService, blockchainService } from '../s
|
||||
import { IAddUser, ICreateUser, RCreateUser } from '../types';
|
||||
import httpStatus from 'http-status';
|
||||
import pick from '../utils/pick';
|
||||
import { IGetResponse } from '../types/common';
|
||||
// import { IGetResponse } from '../types/common';
|
||||
import { IUser, userStatus } from '../types';
|
||||
import { Request, Response } from 'express';
|
||||
import { generateUsername } from '../../tests/utils/generateUsername';
|
||||
import config from '../config/config';
|
||||
import logger from '../config/logger';
|
||||
// import { Body, Controller, Get, Path, Post, Query, Route, SuccessResponse } from 'tsoa';
|
||||
|
||||
// @Route('users')
|
||||
// export default class UsersController extends Controller {
|
||||
// @SuccessResponse(201, 'Created') // Указываем статус 201 и описание
|
||||
// @Post()
|
||||
// public async createUser(@Body() req: RCreateUser): Promise<{ user: IUser; tokens: any }> {
|
||||
// const user = await userService.createUser(req.body);
|
||||
// const tokens = await tokenService.generateAuthTokens(user);
|
||||
|
||||
// this.setStatus(201); // Устанавливаем статус 201 Created
|
||||
// return { user, tokens }; // Возвращаем объект в ответ
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Порядок регистрации:
|
||||
@@ -27,6 +41,7 @@ import logger from '../config/logger';
|
||||
* 11. (trx confirmpay) Пользователь подписывает велком-письмо с подтверждением собственноручности оплаты (транзакция в блокчейне для активации)
|
||||
* 12. Регистрация продолжается ожиданием решения совета
|
||||
*/
|
||||
|
||||
export const createUser = catchAsync(async (req: RCreateUser, res) => {
|
||||
const user = await userService.createUser(req.body);
|
||||
const tokens = await tokenService.generateAuthTokens(user);
|
||||
@@ -36,7 +51,7 @@ export const createUser = catchAsync(async (req: RCreateUser, res) => {
|
||||
|
||||
export const addUser = catchAsync(async (req: Request, res: Response) => {
|
||||
const body: IAddUser = req.body;
|
||||
|
||||
console.log('body: ', body);
|
||||
const newUser: ICreateUser = {
|
||||
...body,
|
||||
public_key: '',
|
||||
@@ -47,13 +62,15 @@ export const addUser = catchAsync(async (req: Request, res: Response) => {
|
||||
const user = await userService.createUser(newUser);
|
||||
user.status = userStatus['4_Registered'];
|
||||
user.is_registered = true;
|
||||
user.has_account = true;
|
||||
|
||||
await user.save();
|
||||
|
||||
try {
|
||||
await blockchainService.addUser({
|
||||
...body,
|
||||
...newUser,
|
||||
registrator: config.service_username,
|
||||
registrator: config.coopname,
|
||||
referer: body.referer ? body.referer : '',
|
||||
coopname: config.coopname,
|
||||
meta: '',
|
||||
|
||||
@@ -3,6 +3,7 @@ import { IAction } from '../types/common';
|
||||
import { SovietContract } from 'cooptypes';
|
||||
import { wsService } from '../services';
|
||||
import logger from '../config/logger';
|
||||
import config from '../config/config';
|
||||
|
||||
let clientSocket: Socket | undefined;
|
||||
|
||||
@@ -33,7 +34,13 @@ export const closeSocketConnection = (): void => {
|
||||
};
|
||||
|
||||
async function processEvent(event: IAction) {
|
||||
if (event.receiver === SovietContract.contractName.production && event.name === 'updateboard') {
|
||||
wsService.updateBoard(event.data);
|
||||
if (event.receiver === config.coopname) {
|
||||
if (event.name === 'updateboard') {
|
||||
wsService.updateBoard(event.data);
|
||||
}
|
||||
|
||||
if (event.name === 'createboard') {
|
||||
wsService.updateBoard(event.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,78 +14,22 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/auth/register": {
|
||||
"post": {
|
||||
"summary": "Register as user",
|
||||
"tags": ["Auth"],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["name", "email", "password"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"format": "email",
|
||||
"description": "must be unique"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"format": "password",
|
||||
"minLength": 8,
|
||||
"description": "At least one number and one letter"
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"name": "fake name",
|
||||
"email": "fake@example.com",
|
||||
"password": "password1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Created",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"user": {
|
||||
"$ref": "#/components/schemas/User"
|
||||
},
|
||||
"tokens": {
|
||||
"$ref": "#/components/schemas/AuthTokens"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"$ref": "#/components/responses/DuplicateEmail"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/auth/login": {
|
||||
"post": {
|
||||
"summary": "Login",
|
||||
"tags": ["Auth"],
|
||||
"tags": [
|
||||
"Auth"
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["email", "password"],
|
||||
"required": [
|
||||
"email",
|
||||
"password"
|
||||
],
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
@@ -143,14 +87,18 @@
|
||||
"/auth/logout": {
|
||||
"post": {
|
||||
"summary": "Logout",
|
||||
"tags": ["Auth"],
|
||||
"tags": [
|
||||
"Auth"
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["refreshToken"],
|
||||
"required": [
|
||||
"refreshToken"
|
||||
],
|
||||
"properties": {
|
||||
"refreshToken": {
|
||||
"type": "string"
|
||||
@@ -176,14 +124,18 @@
|
||||
"/auth/refresh-tokens": {
|
||||
"post": {
|
||||
"summary": "Refresh auth tokens",
|
||||
"tags": ["Auth"],
|
||||
"tags": [
|
||||
"Auth"
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["refreshToken"],
|
||||
"required": [
|
||||
"refreshToken"
|
||||
],
|
||||
"properties": {
|
||||
"refreshToken": {
|
||||
"type": "string"
|
||||
@@ -217,14 +169,18 @@
|
||||
"post": {
|
||||
"summary": "Forgot password",
|
||||
"description": "An email will be sent to reset password.",
|
||||
"tags": ["Auth"],
|
||||
"tags": [
|
||||
"Auth"
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["email"],
|
||||
"required": [
|
||||
"email"
|
||||
],
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
@@ -251,7 +207,9 @@
|
||||
"/auth/reset-password": {
|
||||
"post": {
|
||||
"summary": "Reset password",
|
||||
"tags": ["Auth"],
|
||||
"tags": [
|
||||
"Auth"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
@@ -269,7 +227,9 @@
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["password"],
|
||||
"required": [
|
||||
"password"
|
||||
],
|
||||
"properties": {
|
||||
"password": {
|
||||
"type": "string",
|
||||
@@ -310,7 +270,9 @@
|
||||
"post": {
|
||||
"summary": "Send verification email",
|
||||
"description": "An email will be sent to verify email.",
|
||||
"tags": ["Auth"],
|
||||
"tags": [
|
||||
"Auth"
|
||||
],
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
@@ -329,7 +291,9 @@
|
||||
"/auth/verify-email": {
|
||||
"post": {
|
||||
"summary": "verify email",
|
||||
"tags": ["Auth"],
|
||||
"tags": [
|
||||
"Auth"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
@@ -364,7 +328,9 @@
|
||||
},
|
||||
"/orders/ipn": {
|
||||
"post": {
|
||||
"tags": ["Orders"],
|
||||
"tags": [
|
||||
"Orders"
|
||||
],
|
||||
"summary": "Обработка IPN уведомления",
|
||||
"description": "Маршрут для обработки IPN уведомления.",
|
||||
"responses": {
|
||||
@@ -376,7 +342,9 @@
|
||||
},
|
||||
"/orders/initial": {
|
||||
"post": {
|
||||
"tags": ["Orders"],
|
||||
"tags": [
|
||||
"Orders"
|
||||
],
|
||||
"summary": "Создание регистрационного платежа",
|
||||
"description": "Маршрут для создания регистрационного платежа.",
|
||||
"security": [
|
||||
@@ -410,7 +378,9 @@
|
||||
},
|
||||
"/orders/deposit": {
|
||||
"post": {
|
||||
"tags": ["Orders"],
|
||||
"tags": [
|
||||
"Orders"
|
||||
],
|
||||
"summary": "Создание депозита в кошелёк",
|
||||
"description": "Маршрут для создания депозита.",
|
||||
"security": [
|
||||
@@ -446,7 +416,9 @@
|
||||
"post": {
|
||||
"summary": "Создать пользователя",
|
||||
"description": "Только администраторы могут создавать новых пользователей.",
|
||||
"tags": ["Users"],
|
||||
"tags": [
|
||||
"Users"
|
||||
],
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
@@ -487,7 +459,9 @@
|
||||
"get": {
|
||||
"summary": "Получить всех пользователей",
|
||||
"description": "Только администратор может получить всех пользователей",
|
||||
"tags": ["Users"],
|
||||
"tags": [
|
||||
"Users"
|
||||
],
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
@@ -587,7 +561,9 @@
|
||||
"get": {
|
||||
"summary": "Получить пользователя",
|
||||
"description": "Авторизованные пользователи могут получать только свою собственную информацию. Только администраторы могут получать информацию о других пользователях.",
|
||||
"tags": ["Users"],
|
||||
"tags": [
|
||||
"Users"
|
||||
],
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
@@ -629,7 +605,9 @@
|
||||
"patch": {
|
||||
"summary": "Обновить пользователя",
|
||||
"description": "Только администраторы могут обновлять информацию о других пользователях.",
|
||||
"tags": ["Users"],
|
||||
"tags": [
|
||||
"Users"
|
||||
],
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
@@ -744,14 +722,25 @@
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["created", "joined", "payed", "registered", "active", "blocked"]
|
||||
"enum": [
|
||||
"created",
|
||||
"joined",
|
||||
"payed",
|
||||
"registered",
|
||||
"active",
|
||||
"blocked"
|
||||
]
|
||||
},
|
||||
"is_registered": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["individual", "entrepreneur", "organization"]
|
||||
"enum": [
|
||||
"individual",
|
||||
"entrepreneur",
|
||||
"organization"
|
||||
]
|
||||
},
|
||||
"public_key": {
|
||||
"type": "string"
|
||||
@@ -787,7 +776,10 @@
|
||||
},
|
||||
"ICreatedPayment": {
|
||||
"type": "object",
|
||||
"required": ["order_num", "confirmation_token"],
|
||||
"required": [
|
||||
"order_num",
|
||||
"confirmation_token"
|
||||
],
|
||||
"properties": {
|
||||
"order_num": {
|
||||
"type": "number"
|
||||
@@ -799,7 +791,10 @@
|
||||
},
|
||||
"ICreateDeposit": {
|
||||
"type": "object",
|
||||
"required": ["username", "quantity"],
|
||||
"required": [
|
||||
"username",
|
||||
"quantity"
|
||||
],
|
||||
"properties": {
|
||||
"username": {
|
||||
"type": "string"
|
||||
@@ -811,7 +806,9 @@
|
||||
},
|
||||
"ICreateInitialPayment": {
|
||||
"type": "object",
|
||||
"required": ["username"],
|
||||
"required": [
|
||||
"username"
|
||||
],
|
||||
"properties": {
|
||||
"username": {
|
||||
"type": "string"
|
||||
@@ -844,7 +841,15 @@
|
||||
"format": "email"
|
||||
}
|
||||
},
|
||||
"required": ["first_name", "last_name", "middle_name", "birthdate", "full_address", "phone", "email"]
|
||||
"required": [
|
||||
"first_name",
|
||||
"last_name",
|
||||
"middle_name",
|
||||
"birthdate",
|
||||
"full_address",
|
||||
"phone",
|
||||
"email"
|
||||
]
|
||||
},
|
||||
"RepresentedBySchema": {
|
||||
"type": "object",
|
||||
@@ -865,7 +870,13 @@
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["first_name", "last_name", "middle_name", "position", "based_on"]
|
||||
"required": [
|
||||
"first_name",
|
||||
"last_name",
|
||||
"middle_name",
|
||||
"position",
|
||||
"based_on"
|
||||
]
|
||||
},
|
||||
"RussiaDetailsSchema": {
|
||||
"type": "object",
|
||||
@@ -877,7 +888,10 @@
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["inn", "ogrn"]
|
||||
"required": [
|
||||
"inn",
|
||||
"ogrn"
|
||||
]
|
||||
},
|
||||
"RussianBankDetailsSchema": {
|
||||
"type": "object",
|
||||
@@ -895,14 +909,22 @@
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["bik", "inn", "corr", "kpp"]
|
||||
"required": [
|
||||
"bik",
|
||||
"inn",
|
||||
"corr",
|
||||
"kpp"
|
||||
]
|
||||
},
|
||||
"IBankAccount": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"currency": {
|
||||
"type": "string",
|
||||
"enum": ["RUB", "Other"]
|
||||
"enum": [
|
||||
"RUB",
|
||||
"Other"
|
||||
]
|
||||
},
|
||||
"card_number": {
|
||||
"type": "string"
|
||||
@@ -917,7 +939,13 @@
|
||||
"$ref": "#/components/schemas/RussianBankDetailsSchema"
|
||||
}
|
||||
},
|
||||
"required": ["currency", "card_number", "bank_name", "account_number", "details"]
|
||||
"required": [
|
||||
"currency",
|
||||
"card_number",
|
||||
"bank_name",
|
||||
"account_number",
|
||||
"details"
|
||||
]
|
||||
},
|
||||
"IOrganizationData": {
|
||||
"type": "object",
|
||||
@@ -937,7 +965,10 @@
|
||||
},
|
||||
"country": {
|
||||
"type": "string",
|
||||
"enum": ["Russia", "Other"]
|
||||
"enum": [
|
||||
"Russia",
|
||||
"Other"
|
||||
]
|
||||
},
|
||||
"city": {
|
||||
"type": "string"
|
||||
@@ -997,7 +1028,10 @@
|
||||
},
|
||||
"country": {
|
||||
"type": "string",
|
||||
"enum": ["Russia", "Other"]
|
||||
"enum": [
|
||||
"Russia",
|
||||
"Other"
|
||||
]
|
||||
},
|
||||
"city": {
|
||||
"type": "string"
|
||||
@@ -1038,7 +1072,10 @@
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
"enum": ["user", "admin"]
|
||||
"enum": [
|
||||
"user",
|
||||
"admin"
|
||||
]
|
||||
},
|
||||
"public_key": {
|
||||
"type": "string"
|
||||
@@ -1053,7 +1090,11 @@
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["individual", "entrepreneur", "organization"]
|
||||
"enum": [
|
||||
"individual",
|
||||
"entrepreneur",
|
||||
"organization"
|
||||
]
|
||||
},
|
||||
"individual_data": {
|
||||
"$ref": "#/components/schemas/IIndividualData"
|
||||
@@ -1065,7 +1106,14 @@
|
||||
"$ref": "#/components/schemas/IEntrepreneurData"
|
||||
}
|
||||
},
|
||||
"required": ["email", "password", "role", "public_key", "username", "type"]
|
||||
"required": [
|
||||
"email",
|
||||
"password",
|
||||
"role",
|
||||
"public_key",
|
||||
"username",
|
||||
"type"
|
||||
]
|
||||
},
|
||||
"IDocument": {
|
||||
"type": "object",
|
||||
@@ -1083,7 +1131,12 @@
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": ["hash", "signature", "public_key", "meta"]
|
||||
"required": [
|
||||
"hash",
|
||||
"signature",
|
||||
"public_key",
|
||||
"meta"
|
||||
]
|
||||
},
|
||||
"IJoinCooperative": {
|
||||
"type": "object",
|
||||
@@ -1095,7 +1148,10 @@
|
||||
"$ref": "#/components/schemas/IDocument"
|
||||
}
|
||||
},
|
||||
"required": ["username", "document"]
|
||||
"required": [
|
||||
"username",
|
||||
"document"
|
||||
]
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
@@ -1167,7 +1223,7 @@
|
||||
"tags": [
|
||||
{
|
||||
"name": "Auth",
|
||||
"description": "Authentication"
|
||||
"description": "Управление аудентификацией"
|
||||
},
|
||||
{
|
||||
"name": "Orders",
|
||||
@@ -1178,4 +1234,4 @@
|
||||
"description": "Управление пользователями"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import config from '../config/config';
|
||||
const swaggerDef = {
|
||||
openapi: '3.0.0',
|
||||
info: {
|
||||
title: "API Цифрового Кооператива",
|
||||
title: 'API Цифрового Кооператива',
|
||||
// description: `Модуль предоставляет:
|
||||
|
||||
// - API для хранения персональных данных пользователей
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
import { spawn, Thread, Worker } from 'threads';
|
||||
import { PluginConfig } from '../models/pluginConfig.model';
|
||||
|
||||
// Объект для хранения запущенных воркеров
|
||||
const workerMap: { [key: string]: { worker: any; thread: Worker } } = {};
|
||||
|
||||
export const initializeDefaultPlugins = async () => {
|
||||
const defaultPlugins = [
|
||||
{
|
||||
name: 'powerup',
|
||||
enabled: true,
|
||||
config: {
|
||||
dailyPackageSize: 5, // Размер ежедневного пакета в AXON
|
||||
topUpAmount: 5, // Сумма пополнения при достижении порога (в AXON)
|
||||
systemSymbol: 'AXON',
|
||||
systemPrecision: 4,
|
||||
thresholds: {
|
||||
cpu: 5000, // Порог CPU в микросекундах
|
||||
net: 1024, // Порог NET в байтах
|
||||
ram: 10240, // Порог RAM в байтах
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
for (const plugin of defaultPlugins) {
|
||||
const existingPlugin = await PluginConfig.findOne({ name: plugin.name });
|
||||
if (!existingPlugin) {
|
||||
await PluginConfig.create(plugin);
|
||||
console.log(`Дефолтный плагин ${plugin.name} добавлен в базу.`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const pluginFactory = async () => {
|
||||
const plugins = await PluginConfig.find({ enabled: true });
|
||||
|
||||
for (const pluginData of plugins) {
|
||||
await initializeWorkerByName(pluginData.name);
|
||||
}
|
||||
};
|
||||
|
||||
// Функция для завершения воркера по имени плагина
|
||||
export const terminateWorker = async (pluginName: string) => {
|
||||
const workerData = workerMap[pluginName];
|
||||
if (workerData) {
|
||||
await workerData.thread.terminate();
|
||||
delete workerMap[pluginName]; // Удаляем воркер из карты
|
||||
console.log(`Воркер для плагина ${pluginName} завершен.`);
|
||||
} else {
|
||||
console.log(`Воркер для плагина ${pluginName} не найден.`);
|
||||
}
|
||||
};
|
||||
|
||||
// Функция для инициализации воркера по имени плагина
|
||||
export const initializeWorkerByName = async (pluginName: string) => {
|
||||
// Проверяем, запущен ли уже воркер
|
||||
if (workerMap[pluginName]) {
|
||||
console.log(`Воркер для плагина ${pluginName} уже запущен.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Получаем данные плагина из базы
|
||||
const pluginData = await PluginConfig.findOne({ name: pluginName });
|
||||
if (!pluginData || !pluginData.enabled) {
|
||||
console.log(`Плагин ${pluginName} не найден или отключен.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Запускаем новый воркер
|
||||
const thread = new Worker('../workers/plugin.worker.ts');
|
||||
const worker = spawn(thread, { timeout: 30000 }); // Не используем await, чтобы не блокировать основной поток
|
||||
//таймаут выше для локальных машин
|
||||
|
||||
// Сохраняем воркера и поток в объекте по имени плагина
|
||||
workerMap[pluginName] = { worker, thread };
|
||||
|
||||
// Воркеры работают в фоне
|
||||
worker.then(async (workerInstance) => {
|
||||
try {
|
||||
const result = await workerInstance.initializePlugin(pluginName);
|
||||
console.log(result); // Плагин инициализирован успешно
|
||||
} catch (err) {
|
||||
console.error(err); // Обработка ошибки
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`Воркер для плагина ${pluginName} успешно запущен.`);
|
||||
};
|
||||
|
||||
// Функция для перезагрузки воркера по имени плагина
|
||||
export const restartWorker = async (pluginName: string) => {
|
||||
const workerData = workerMap[pluginName];
|
||||
|
||||
if (workerData) {
|
||||
// Если воркер уже запущен, сначала завершаем его
|
||||
console.log(`Перезагрузка воркера для плагина ${pluginName}...`);
|
||||
await terminateWorker(pluginName);
|
||||
}
|
||||
|
||||
// Затем запускаем воркер заново
|
||||
await initializeWorkerByName(pluginName);
|
||||
console.log(`Воркер для плагина ${pluginName} перезагружен.`);
|
||||
};
|
||||
@@ -4,9 +4,10 @@ import mongoose from 'mongoose';
|
||||
import app from './app';
|
||||
import config from './config/config';
|
||||
import logger from './config/logger';
|
||||
import { connectGenerator } from './services/document.service';
|
||||
import { connectGenerator, diconnectGenerator } from './services/document.service';
|
||||
import { initSocketConnection } from './controllers/ws.controller';
|
||||
import { systemService } from './services';
|
||||
import { initializeDefaultPlugins, pluginFactory } from './factories/pluginFactory';
|
||||
import { paymentService } from './services';
|
||||
|
||||
const SERVER_URL: string = process.env.SOCKET_SERVER || 'http://localhost:2222';
|
||||
|
||||
@@ -15,20 +16,27 @@ let server: any;
|
||||
mongoose.connect(config.mongoose.url).then(async () => {
|
||||
logger.info('Connected to MongoDB');
|
||||
|
||||
await systemService.init();
|
||||
|
||||
// подключаемся к хранилищу приватных данных
|
||||
await connectGenerator();
|
||||
|
||||
// подключаемся к ws-серверу
|
||||
await initSocketConnection(SERVER_URL);
|
||||
|
||||
// Запуск фабрики платежей
|
||||
await paymentService.init();
|
||||
|
||||
// Инициализация дефолтных плагинов
|
||||
await initializeDefaultPlugins();
|
||||
|
||||
// // Запуск плагинов
|
||||
await pluginFactory();
|
||||
|
||||
server = app.listen(config.port, () => {
|
||||
logger.info(`Listening to port ${config.port}`);
|
||||
});
|
||||
});
|
||||
|
||||
const exitHandler = () => {
|
||||
const exitHandler = async () => {
|
||||
if (server) {
|
||||
server.close(() => {
|
||||
logger.info('Server closed');
|
||||
@@ -39,16 +47,20 @@ const exitHandler = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const unexpectedErrorHandler = (error: any) => {
|
||||
const unexpectedErrorHandler = async (error: any) => {
|
||||
console.log(error);
|
||||
await diconnectGenerator();
|
||||
await mongoose.disconnect();
|
||||
logger.error(error, { source: 'unexpectedErrorHandler' });
|
||||
exitHandler();
|
||||
await exitHandler();
|
||||
};
|
||||
|
||||
process.on('uncaughtException', unexpectedErrorHandler);
|
||||
process.on('unhandledRejection', unexpectedErrorHandler);
|
||||
|
||||
process.on('SIGTERM', () => {
|
||||
process.on('SIGTERM', async () => {
|
||||
logger.info('SIGTERM received');
|
||||
await mongoose.disconnect();
|
||||
if (server) {
|
||||
server.close();
|
||||
}
|
||||
|
||||
@@ -25,18 +25,12 @@ const verifyCallback = (req, resolve, reject, requiredRights) => async (err, use
|
||||
const hasRequiredRights = requiredRights.every((requiredRight) => userRights.includes(requiredRight));
|
||||
|
||||
// Check if user is accessing their own resource
|
||||
const isOwnResource = req.params.username === user.username;
|
||||
const isOwnResource =
|
||||
(req.params.username && req.params.username === user.username) ||
|
||||
(req.body.username && req.body.username === user.username);
|
||||
|
||||
if (requiredRights.length) {
|
||||
// If rights are required but user doesn't have them, deny access
|
||||
if (!hasRequiredRights) {
|
||||
return reject(new ApiError(FORBIDDEN, 'Недостаточно прав доступа'));
|
||||
}
|
||||
} else {
|
||||
// If no rights are required, ensure user is accessing their own resource
|
||||
if (!isOwnResource) {
|
||||
return reject(new ApiError(FORBIDDEN, 'Недостаточно прав доступа'));
|
||||
}
|
||||
if (!isOwnResource && (!hasRequiredRights || !requiredRights.length)) {
|
||||
return reject(new ApiError(FORBIDDEN, 'Недостаточно прав доступа'));
|
||||
}
|
||||
|
||||
resolve();
|
||||
|
||||
@@ -7,7 +7,6 @@ import { RpcError } from 'eosjs';
|
||||
|
||||
export const errorConverter = (err, req, res, next) => {
|
||||
let error = err;
|
||||
console.log(error);
|
||||
if (!(error instanceof ApiError)) {
|
||||
if (error instanceof RpcError) {
|
||||
const message = error.json.error.details[0].message.replace('assertion failure with message: ', ''); // Получаем первую строку ошибки
|
||||
@@ -27,7 +26,6 @@ export const errorConverter = (err, req, res, next) => {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
export const errorHandler = (err, req, res, next?) => {
|
||||
let { statusCode, message } = err;
|
||||
console.error(err);
|
||||
if (config.env === 'production' && !err.isOperational) {
|
||||
statusCode = httpStatus.INTERNAL_SERVER_ERROR;
|
||||
message = httpStatus[httpStatus.INTERNAL_SERVER_ERROR];
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Schema, model, type Model } from 'mongoose';
|
||||
import type { IPluginSchema } from '../types/plugin.types';
|
||||
import { paginate, toJSON } from './plugins';
|
||||
|
||||
interface IPaginate extends Model<IPluginSchema<any>> {
|
||||
paginate(filter, options): any;
|
||||
}
|
||||
|
||||
export const pluginSchema = new Schema<IPluginSchema<any>, IPaginate>(
|
||||
{
|
||||
name: { type: String, required: true },
|
||||
enabled: { type: Boolean, default: true },
|
||||
config: { type: Schema.Types.Mixed }, // Своя конфигурация для каждого плагина
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
// add plugin that converts mongoose to json
|
||||
pluginSchema.plugin(toJSON);
|
||||
pluginSchema.plugin(paginate);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const PluginConfig = model<IPluginSchema<any>, IPaginate>('Plugins', pluginSchema);
|
||||
@@ -0,0 +1,24 @@
|
||||
import { Schema, model, type Model } from 'mongoose';
|
||||
import type { IPluginLog } from '../types/plugin.types';
|
||||
import { paginate, toJSON } from './plugins';
|
||||
|
||||
interface IPaginate extends Model<IPluginLog<any>> {
|
||||
paginate(filter, options): any;
|
||||
}
|
||||
|
||||
export const pluginLog = new Schema<IPluginLog<any>, IPaginate>(
|
||||
{
|
||||
name: { type: String, required: true },
|
||||
log: { type: Schema.Types.Mixed }, // Своя конфигурация для каждого плагина
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
// add plugin that converts mongoose to json
|
||||
pluginLog.plugin(toJSON);
|
||||
pluginLog.plugin(paginate);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const PluginLog = model<IPluginLog<any>, IPaginate>('PluginLogs', pluginLog);
|
||||
@@ -0,0 +1,65 @@
|
||||
import mongoose, { Schema, type Model } from 'mongoose';
|
||||
import { paginate, toJSON } from './plugins';
|
||||
import { decrypt, encrypt } from '../utils/aes';
|
||||
|
||||
export interface IVault {
|
||||
username: string;
|
||||
permission: wifPermissions;
|
||||
wif: string;
|
||||
}
|
||||
|
||||
export enum wifPermissions {
|
||||
'Active' = 'active',
|
||||
}
|
||||
|
||||
interface IVaultActions extends Model<IVault> {
|
||||
getWif(username: string, permission?: wifPermissions): Promise<string | null>;
|
||||
setWif(username: string, wif: string, permission?: wifPermissions): Promise<boolean>;
|
||||
}
|
||||
|
||||
const VaultSchema = new Schema<IVault, IVaultActions>({
|
||||
username: { type: String, required: true },
|
||||
permission: { type: String, required: true, enum: Object.values(wifPermissions) },
|
||||
wif: { type: String, required: true, private: true },
|
||||
});
|
||||
|
||||
// Метод для извлечения WIF с дефолтным значением permission
|
||||
VaultSchema.statics.getWif = async function (
|
||||
username: string,
|
||||
permission: wifPermissions = wifPermissions.Active
|
||||
): Promise<string | null> {
|
||||
const vault = await this.findOne({ username, permission });
|
||||
if (vault) {
|
||||
try {
|
||||
return decrypt(vault.wif); // Расшифровываем WIF перед возвратом
|
||||
} catch (error) {
|
||||
console.error('Ошибка при расшифровке WIF:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// Метод для обновления или создания WIF с дефолтным значением permission
|
||||
VaultSchema.statics.setWif = async function (
|
||||
username: string,
|
||||
wif: string,
|
||||
permission: wifPermissions = wifPermissions.Active
|
||||
): Promise<boolean> {
|
||||
const encryptedWif = encrypt(wif); // Шифруем WIF перед сохранением
|
||||
|
||||
const result = await this.findOneAndUpdate(
|
||||
{ username, permission },
|
||||
{ wif: encryptedWif },
|
||||
{ new: true, upsert: true } // upsert создает новую запись, если не существует
|
||||
);
|
||||
|
||||
return result !== null;
|
||||
};
|
||||
|
||||
VaultSchema.plugin(toJSON);
|
||||
VaultSchema.plugin(paginate);
|
||||
|
||||
const Vault = mongoose.model<IVault, IVaultActions>('Vault', VaultSchema);
|
||||
|
||||
export default Vault;
|
||||
@@ -0,0 +1,5 @@
|
||||
import * as powerup from './powerup/powerup.plugin';
|
||||
|
||||
export const PluginRegistry = {
|
||||
powerup,
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.1.3](https://github.com/coopenomics/monocoop/compare/v2.1.2-alpha.10...v2.1.3) (2024-10-26)
|
||||
|
||||
|
||||
|
||||
## [2.1.2](https://github.com/coopenomics/monocoop/compare/v2.1.1...v2.1.2) (2024-10-19)
|
||||
|
||||
**Note:** Version bump only for package powerup
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.1.2](https://github.com/coopenomics/monocoop/compare/v2.1.1...v2.1.2) (2024-10-19)
|
||||
|
||||
**Note:** Version bump only for package powerup
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "powerup",
|
||||
"version": "2.1.3",
|
||||
"description": "",
|
||||
"private": true,
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"gitHead": "7b59ea4b96991ed06abdc92e6d7835632845e3a5"
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
import { IPlugin, type IPluginLog, type IPluginSchema } from '../../types/plugin.types';
|
||||
import Joi from 'joi';
|
||||
import cron from 'node-cron';
|
||||
import { blockchainService } from '../../services';
|
||||
import logger from '../../config/logger';
|
||||
import { default as coopConfig } from '../../config/config';
|
||||
import { PluginConfig } from '../../models/pluginConfig.model';
|
||||
import { PluginLog } from '../../models/pluginLog.model';
|
||||
import type { IGetPluginConfig } from '../../types';
|
||||
import type { Document, Types } from 'mongoose';
|
||||
|
||||
// Интерфейс для параметров конфигурации плагина powerup
|
||||
export interface IConfig {
|
||||
dailyPackageSize: number; // Размер ежедневного пакета в AXON
|
||||
topUpAmount: number; // Сумма пополнения при достижении порога (в AXON)
|
||||
systemSymbol: string;
|
||||
systemPrecision: number;
|
||||
lastDailyReplenishmentDate: Date;
|
||||
thresholds: {
|
||||
cpu: number; // Порог CPU в микросекундах
|
||||
net: number; // Порог NET в байтах
|
||||
ram: number; // Порог RAM в байтах
|
||||
};
|
||||
}
|
||||
|
||||
export interface ILog {
|
||||
type: 'daily' | 'now';
|
||||
amount: string;
|
||||
resources: {
|
||||
username: string;
|
||||
ram_usage: any;
|
||||
ram_quota: any;
|
||||
net_limit: any;
|
||||
cpu_limit: any;
|
||||
};
|
||||
}
|
||||
|
||||
export class Plugin implements IPlugin {
|
||||
name = 'powerup';
|
||||
data!: IPluginSchema<IConfig>;
|
||||
|
||||
public pluginSchema = Joi.object<IConfig>({
|
||||
dailyPackageSize: Joi.number().required(),
|
||||
topUpAmount: Joi.number().required(),
|
||||
thresholds: Joi.object({
|
||||
cpu: Joi.number().required(),
|
||||
net: Joi.number().required(),
|
||||
ram: Joi.number().required(),
|
||||
}).required(),
|
||||
});
|
||||
|
||||
async initialize() {
|
||||
const pluginData = await PluginConfig.findOne({ name: this.name });
|
||||
if (!pluginData) throw new Error('Конфиг не найден');
|
||||
|
||||
this.data = pluginData;
|
||||
|
||||
logger.info(`Инициализация ${this.name} с конфигурацией`, this.data);
|
||||
|
||||
// Проверяем, было ли ежедневное пополнение в последние 24 часа
|
||||
const lastDate = this.data.config.lastDailyReplenishmentDate;
|
||||
const now = new Date();
|
||||
|
||||
if (lastDate) {
|
||||
const diffInHours = Math.abs(now.getTime() - lastDate.getTime()) / 36e5; // Разница во времени в часах
|
||||
if (diffInHours < 24) {
|
||||
logger.info('Ежедневное пополнение уже выполнялось в последние 24 часа. Повторное пополнение не требуется.');
|
||||
} else {
|
||||
logger.info('Ежедневное пополнение не выполнялось в последние 24 часа. Выполняем пополнение...');
|
||||
await this.runDailyTask();
|
||||
}
|
||||
} else {
|
||||
logger.info('Дата последнего пополнения отсутствует. Выполняем пополнение...');
|
||||
await this.runDailyTask();
|
||||
}
|
||||
|
||||
// Регистрация cron-задачи для ежедневного пополнения
|
||||
cron.schedule('0 0 * * *', () => {
|
||||
logger.info('Запуск ежедневной задачи пополнения');
|
||||
this.runDailyTask();
|
||||
});
|
||||
|
||||
// Регистрация cron-задачи для проверки ресурсов каждую минуту
|
||||
cron.schedule('* * * * *', () => {
|
||||
logger.info('Запуск задачи проверки ресурсов');
|
||||
this.runTask();
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
await new Promise(() => {});
|
||||
}
|
||||
|
||||
private getQuantity(amount: number): string {
|
||||
return `${amount.toFixed(this.data.config.systemPrecision)} ${this.data.config.systemSymbol}`;
|
||||
}
|
||||
|
||||
// Ежедневная задача пополнения
|
||||
private async runDailyTask() {
|
||||
const quantity = this.getQuantity(this.data.config.dailyPackageSize);
|
||||
|
||||
logger.info(`Выполнение ежедневного пополнения на сумму ${quantity}`);
|
||||
|
||||
try {
|
||||
// Получаем имя пользователя из окружения или другой конфигурации
|
||||
const username = coopConfig.coopname;
|
||||
const account = await blockchainService.getBlockchainAccount(username);
|
||||
|
||||
await blockchainService.powerUp(username, quantity);
|
||||
|
||||
this.data.config.lastDailyReplenishmentDate = new Date();
|
||||
this.data.markModified('config'); // Помечаем config как измененное поле
|
||||
|
||||
await this.data.save();
|
||||
|
||||
await this.log({
|
||||
type: 'daily',
|
||||
amount: quantity,
|
||||
resources: {
|
||||
username: account.account_name,
|
||||
ram_usage: account.ram_usage,
|
||||
ram_quota: account.ram_quota,
|
||||
net_limit: account.net_limit,
|
||||
cpu_limit: account.cpu_limit,
|
||||
},
|
||||
});
|
||||
|
||||
logger.info('Ежедневное пополнение выполнено успешно');
|
||||
} catch (error) {
|
||||
console.error('Ошибка при выполнении ежедневного пополнения:', error);
|
||||
}
|
||||
}
|
||||
|
||||
private async log(action: ILog) {
|
||||
await PluginLog.create({ name: this.name, log: action });
|
||||
}
|
||||
|
||||
// Задача проверки и пополнения ресурсов
|
||||
private async runTask() {
|
||||
logger.info(`Задача плагина ${this.name} выполняется...`);
|
||||
|
||||
try {
|
||||
// Получаем имя пользователя из окружения или другой конфигурации
|
||||
const username = coopConfig.coopname;
|
||||
|
||||
const account = await blockchainService.getBlockchainAccount(username);
|
||||
|
||||
// Получаем текущие значения квот
|
||||
const cpuLimit = account.cpu_limit;
|
||||
const netLimit = account.net_limit;
|
||||
const ramQuota = account.ram_quota;
|
||||
const ramUsage = account.ram_usage;
|
||||
const availableRam = ramQuota - ramUsage;
|
||||
|
||||
// Проверяем пороги и пополняем при необходимости
|
||||
let needPowerUp = false;
|
||||
|
||||
if (cpuLimit.available <= this.data.config.thresholds.cpu) {
|
||||
logger.info(`CPU квота ниже порога (${cpuLimit.available} µs).`);
|
||||
needPowerUp = true;
|
||||
}
|
||||
|
||||
if (netLimit.available <= this.data.config.thresholds.net) {
|
||||
logger.info(`NET квота ниже порога (${netLimit.available} bytes).`);
|
||||
needPowerUp = true;
|
||||
}
|
||||
|
||||
if (availableRam <= this.data.config.thresholds.ram) {
|
||||
logger.info(`RAM квота ниже порога (${availableRam} bytes).`);
|
||||
needPowerUp = true;
|
||||
}
|
||||
|
||||
if (needPowerUp) {
|
||||
// Выполняем пополнение ресурсов
|
||||
const quantity = this.getQuantity(this.data.config.topUpAmount);
|
||||
await blockchainService.powerUp(username, quantity);
|
||||
logger.info(`Пополнение выполнено на сумму ${quantity}.`);
|
||||
|
||||
await this.log({
|
||||
type: 'now',
|
||||
amount: quantity,
|
||||
resources: {
|
||||
username: account.account_name,
|
||||
ram_usage: account.ram_usage,
|
||||
ram_quota: account.ram_quota,
|
||||
net_limit: account.net_limit,
|
||||
cpu_limit: account.cpu_limit,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
logger.info('Квоты ресурсов в норме, пополнение не требуется.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Ошибка при проверке и пополнении ресурсов:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,55 +21,7 @@ export default router;
|
||||
* @swagger
|
||||
* tags:
|
||||
* name: Auth
|
||||
* description: Authentication
|
||||
*/
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /auth/register:
|
||||
* post:
|
||||
* summary: Register as user
|
||||
* tags: [Auth]
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - name
|
||||
* - email
|
||||
* - password
|
||||
* properties:
|
||||
* name:
|
||||
* type: string
|
||||
* email:
|
||||
* type: string
|
||||
* format: email
|
||||
* description: must be unique
|
||||
* password:
|
||||
* type: string
|
||||
* format: password
|
||||
* minLength: 8
|
||||
* description: At least one number and one letter
|
||||
* example:
|
||||
* name: fake name
|
||||
* email: fake@example.com
|
||||
* password: password1
|
||||
* responses:
|
||||
* "201":
|
||||
* description: Created
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* user:
|
||||
* $ref: '#/components/schemas/User'
|
||||
* tokens:
|
||||
* $ref: '#/components/schemas/AuthTokens'
|
||||
* "400":
|
||||
* $ref: '#/components/responses/DuplicateEmail'
|
||||
* description: Управление аудентификацией
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,14 +8,14 @@ const router = express.Router();
|
||||
|
||||
router
|
||||
.route('/generate')
|
||||
.post(auth('generateDocument'), validate(documentValidation.RGenerate), documentController.generateDocument);
|
||||
.post(auth('regenerateDocument'), validate(documentValidation.RGenerate), documentController.generateDocument);
|
||||
|
||||
router
|
||||
.route('/get-documents')
|
||||
.get(auth('getDocuments'), validate(documentValidation.RGetDocuments), documentController.getDocuments);
|
||||
|
||||
router
|
||||
.route('/get-my-documents')
|
||||
.get(auth('getMyDocuments'), validate(documentValidation.RGetDocuments), documentController.getDocuments);
|
||||
// router
|
||||
// .route('/get-my-documents')
|
||||
// .get(auth('getMyDocuments'), validate(documentValidation.RGetDocuments), documentController.getDocuments);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -9,6 +9,7 @@ import dataRoute from './document.route';
|
||||
import notifyRoute from './notify.route';
|
||||
import participantsRoute from './participant.route';
|
||||
import methodRoute from './method.route';
|
||||
import pluginRoute from './plugin.route';
|
||||
|
||||
import config from '../../config/config';
|
||||
|
||||
@@ -51,6 +52,10 @@ const defaultRoutes = [
|
||||
path: '/notify',
|
||||
route: notifyRoute,
|
||||
},
|
||||
{
|
||||
path: '/plugins',
|
||||
route: pluginRoute,
|
||||
},
|
||||
];
|
||||
|
||||
const devRoutes = [
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { Router } from 'express';
|
||||
import { pluginController } from '../../controllers';
|
||||
import auth from '../../middlewares/auth';
|
||||
import validate from '../../middlewares/validate';
|
||||
import { pluginValidation } from '../../validations';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.route('/').post(auth('setPlugin'), validate(pluginValidation.RSetPlugin), pluginController.setPluginConfig);
|
||||
router.route('/').get(auth('setPlugin'), validate(pluginValidation.RGetPluginList), pluginController.getPluginList);
|
||||
|
||||
router
|
||||
.route('/schema')
|
||||
.get(auth('setPlugin'), validate(pluginValidation.RGetPluginSchema), pluginController.getPluginSchema);
|
||||
|
||||
router
|
||||
.route('/config')
|
||||
.get(auth('setPlugin'), validate(pluginValidation.RGetPluginConfig), pluginController.getPluginConfig);
|
||||
|
||||
export default router;
|
||||
@@ -6,12 +6,18 @@ import { systemValidation } from '../../validations';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.route('/install').post(auth('install'), validate(systemValidation.RInstall), systemController.install);
|
||||
//init - устанавливает данные организации кооператива
|
||||
router.route('/init').post(auth('init'), validate(systemValidation.RInit), systemController.init);
|
||||
|
||||
router.route('/get-vars-schema').post(auth('getVars'), systemController.getVarsSchema);
|
||||
router.route('/get-vars').post(auth('getVars'), systemController.setVars);
|
||||
router.route('/install').post(validate(systemValidation.RInstall), systemController.install);
|
||||
|
||||
router.route('/set-vars').post(auth('setVars'), validate(systemValidation.RSetVars), systemController.setVars);
|
||||
router.route('/wif').post(auth('setWif'), validate(systemValidation.RSetWif), systemController.setWif);
|
||||
|
||||
//wif
|
||||
|
||||
router.route('/vars/schema').get(auth('getVars'), systemController.getVarsSchema);
|
||||
router.route('/vars').get(auth('getVars'), systemController.getVars);
|
||||
router.route('/vars').post(auth('setVars'), validate(systemValidation.RSetVars), systemController.setVars);
|
||||
|
||||
router.route('/health').get(systemController.getHealth);
|
||||
|
||||
|
||||
@@ -198,3 +198,33 @@ export default router;
|
||||
* $ref: '#/components/responses/NotFound'
|
||||
*
|
||||
*/
|
||||
|
||||
// /**
|
||||
// * @swagger
|
||||
// * /users/add:
|
||||
// * post:
|
||||
// * summary: Добавить пользователя без заявления
|
||||
// * description: Только администраторы могут добавлять новых пользователей без прохождения процедуры подачи заявления. Это используется для добавления действующих пайщиков.
|
||||
// * tags: [Users]
|
||||
// * security:
|
||||
// * - bearerAuth: []
|
||||
// * requestBody:
|
||||
// * required: true
|
||||
// * content:
|
||||
// * application/json:
|
||||
// * schema:
|
||||
// * "$ref": '#/components/schemas/IAddUser'
|
||||
// * responses:
|
||||
// * "201":
|
||||
// * description: Пользователь успешно добавлен
|
||||
// * content:
|
||||
// * application/json:
|
||||
// * schema:
|
||||
// * $ref: '#/components/schemas/User'
|
||||
// * "400":
|
||||
// * $ref: '#/components/responses/BadRequest'
|
||||
// * "401":
|
||||
// * $ref: '#/components/responses/Unauthorized'
|
||||
// * "403":
|
||||
// * $ref: '#/components/responses/Forbidden'
|
||||
// */
|
||||
|
||||
@@ -98,7 +98,7 @@ export const resetKey = async (resetKeyToken, publicKey) => {
|
||||
if (config.env !== 'test')
|
||||
await blockchainService.changeKey({
|
||||
coopname: config.coopname,
|
||||
changer: config.service_username,
|
||||
changer: config.coopname,
|
||||
username: user.username,
|
||||
public_key: publicKey,
|
||||
});
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { Api, JsonRpc } from 'eosjs';
|
||||
import { JsSignatureProvider } from 'eosjs/dist/eosjs-jssig';
|
||||
import { TextEncoder, TextDecoder } from 'util';
|
||||
import fetch from 'isomorphic-fetch';
|
||||
import EosApi from 'eosjs-api';
|
||||
import getInternalAction from '../utils/getInternalAction';
|
||||
import { GatewayContract, RegistratorContract, SovietContract } from 'cooptypes';
|
||||
import { GatewayContract, RegistratorContract, SovietContract, type SystemContract } from 'cooptypes';
|
||||
import { IUser } from '../types/user.types';
|
||||
import { GetAccountResult, GetInfoResult } from 'eosjs/dist/eosjs-rpc-interfaces';
|
||||
import config from '../config/config';
|
||||
@@ -13,6 +12,7 @@ import ApiError from '../utils/ApiError';
|
||||
import httpStatus from 'http-status';
|
||||
import type { IOrder } from '../types/order.types';
|
||||
import type { IBCAction } from '../types';
|
||||
import Vault from '../models/vault.model';
|
||||
|
||||
const rpc = new JsonRpc(process.env.BLOCKCHAIN_RPC as string, { fetch });
|
||||
|
||||
@@ -36,7 +36,7 @@ async function getBlockchainAccount(username): Promise<GetAccountResult> {
|
||||
}
|
||||
|
||||
export async function transact(actions: any): Promise<any> {
|
||||
const instance = await getInstance(config.service_wif);
|
||||
const instance = await getInstance(config.coopname);
|
||||
const result = await instance.transact(
|
||||
{
|
||||
actions,
|
||||
@@ -57,15 +57,19 @@ export async function transact(actions: any): Promise<any> {
|
||||
* @returns {eosjs-api}
|
||||
*/
|
||||
|
||||
async function getInstance(wif) {
|
||||
async function getInstance(username: string) {
|
||||
const wif = await Vault.getWif(username);
|
||||
|
||||
if (!wif) throw new ApiError(httpStatus.BAD_GATEWAY, 'Не найден приватный ключ для совершения операции');
|
||||
|
||||
const signatureProvider = new JsSignatureProvider([wif]);
|
||||
const api = new Api({ rpc, signatureProvider, textDecoder: new TextDecoder(), textEncoder: new TextEncoder() });
|
||||
const api = new Api({ rpc, signatureProvider });
|
||||
return api;
|
||||
}
|
||||
|
||||
function getApi() {
|
||||
const options = {
|
||||
httpEndpoint: process.env.BLOCKCHAIN_RPC, // default, null for cold-storage
|
||||
httpEndpoint: process.env.BLOCKCHAIN_RPC, //
|
||||
verbose: false, // API logging
|
||||
fetchConfiguration: {},
|
||||
};
|
||||
@@ -115,7 +119,7 @@ async function getCooperative(coopname) {
|
||||
}
|
||||
|
||||
async function registerBlockchainAccount(user: IUser, order: IOrder) {
|
||||
const eos = await getInstance(config.service_wif);
|
||||
const eos = await getInstance(config.coopname);
|
||||
const actions = [] as any;
|
||||
|
||||
// Создаем newaccount
|
||||
@@ -133,7 +137,7 @@ async function registerBlockchainAccount(user: IUser, order: IOrder) {
|
||||
name: RegistratorContract.Actions.CreateAccount.actionName,
|
||||
authorization: [
|
||||
{
|
||||
actor: config.service_username,
|
||||
actor: config.coopname,
|
||||
permission: 'active',
|
||||
},
|
||||
],
|
||||
@@ -156,7 +160,7 @@ async function registerBlockchainAccount(user: IUser, order: IOrder) {
|
||||
name: RegistratorContract.Actions.RegisterUser.actionName,
|
||||
authorization: [
|
||||
{
|
||||
actor: config.service_username,
|
||||
actor: config.coopname,
|
||||
permission: 'active',
|
||||
},
|
||||
],
|
||||
@@ -178,7 +182,7 @@ async function registerBlockchainAccount(user: IUser, order: IOrder) {
|
||||
name: RegistratorContract.Actions.JoinCooperative.actionName,
|
||||
authorization: [
|
||||
{
|
||||
actor: config.service_username,
|
||||
actor: config.coopname,
|
||||
permission: 'active',
|
||||
},
|
||||
],
|
||||
@@ -198,7 +202,7 @@ async function registerBlockchainAccount(user: IUser, order: IOrder) {
|
||||
name: GatewayContract.Actions.CreateDeposit.actionName,
|
||||
authorization: [
|
||||
{
|
||||
actor: config.service_username,
|
||||
actor: config.coopname,
|
||||
permission: 'active',
|
||||
},
|
||||
],
|
||||
@@ -208,7 +212,7 @@ async function registerBlockchainAccount(user: IUser, order: IOrder) {
|
||||
// Создаем completeDeposit
|
||||
const completeDeposit: GatewayContract.Actions.CompleteDeposit.ICompleteDeposit = {
|
||||
coopname: config.coopname,
|
||||
admin: config.service_username,
|
||||
admin: config.coopname,
|
||||
deposit_id: order.order_num as number,
|
||||
memo: '',
|
||||
};
|
||||
@@ -217,7 +221,7 @@ async function registerBlockchainAccount(user: IUser, order: IOrder) {
|
||||
name: GatewayContract.Actions.CompleteDeposit.actionName,
|
||||
authorization: [
|
||||
{
|
||||
actor: config.service_username,
|
||||
actor: config.coopname,
|
||||
permission: 'active',
|
||||
},
|
||||
],
|
||||
@@ -240,7 +244,7 @@ async function registerBlockchainAccount(user: IUser, order: IOrder) {
|
||||
name: SovietContract.Actions.Agreements.SendAgreement.actionName,
|
||||
authorization: [
|
||||
{
|
||||
actor: config.service_username,
|
||||
actor: config.coopname,
|
||||
permission: 'active',
|
||||
},
|
||||
],
|
||||
@@ -263,7 +267,7 @@ async function registerBlockchainAccount(user: IUser, order: IOrder) {
|
||||
name: SovietContract.Actions.Agreements.SendAgreement.actionName,
|
||||
authorization: [
|
||||
{
|
||||
actor: config.service_username,
|
||||
actor: config.coopname,
|
||||
permission: 'active',
|
||||
},
|
||||
],
|
||||
@@ -286,7 +290,7 @@ async function registerBlockchainAccount(user: IUser, order: IOrder) {
|
||||
name: SovietContract.Actions.Agreements.SendAgreement.actionName,
|
||||
authorization: [
|
||||
{
|
||||
actor: config.service_username,
|
||||
actor: config.coopname,
|
||||
permission: 'active',
|
||||
},
|
||||
],
|
||||
@@ -309,7 +313,7 @@ async function registerBlockchainAccount(user: IUser, order: IOrder) {
|
||||
name: SovietContract.Actions.Agreements.SendAgreement.actionName,
|
||||
authorization: [
|
||||
{
|
||||
actor: config.service_username,
|
||||
actor: config.coopname,
|
||||
permission: 'active',
|
||||
},
|
||||
],
|
||||
@@ -330,7 +334,7 @@ async function registerBlockchainAccount(user: IUser, order: IOrder) {
|
||||
}
|
||||
|
||||
async function createBoard(data: SovietContract.Actions.Boards.CreateBoard.ICreateboard) {
|
||||
const eos = await getInstance(config.service_wif);
|
||||
const eos = await getInstance(config.coopname);
|
||||
|
||||
// console.log('data: ', data);
|
||||
|
||||
@@ -340,7 +344,7 @@ async function createBoard(data: SovietContract.Actions.Boards.CreateBoard.ICrea
|
||||
name: SovietContract.Actions.Boards.CreateBoard.actionName,
|
||||
authorization: [
|
||||
{
|
||||
actor: config.service_username,
|
||||
actor: config.coopname,
|
||||
permission: 'active',
|
||||
},
|
||||
],
|
||||
@@ -360,7 +364,7 @@ async function createBoard(data: SovietContract.Actions.Boards.CreateBoard.ICrea
|
||||
}
|
||||
|
||||
async function createOrder(data) {
|
||||
const eos = await getInstance(config.service_wif);
|
||||
const eos = await getInstance(config.coopname);
|
||||
|
||||
const actions = [
|
||||
{
|
||||
@@ -392,7 +396,7 @@ async function createOrder(data) {
|
||||
}
|
||||
|
||||
async function completeDeposit(order: IOrder) {
|
||||
const eos = await getInstance(config.service_wif);
|
||||
const eos = await getInstance(config.coopname);
|
||||
|
||||
const createDeposit: GatewayContract.Actions.CreateDeposit.ICreateDeposit = {
|
||||
coopname: config.coopname,
|
||||
@@ -404,7 +408,7 @@ async function completeDeposit(order: IOrder) {
|
||||
|
||||
const completeDeposit: GatewayContract.Actions.CompleteDeposit.ICompleteDeposit = {
|
||||
coopname: config.coopname,
|
||||
admin: config.service_username,
|
||||
admin: config.coopname,
|
||||
deposit_id: order.order_num as number,
|
||||
memo: '',
|
||||
};
|
||||
@@ -415,7 +419,7 @@ async function completeDeposit(order: IOrder) {
|
||||
name: GatewayContract.Actions.CreateDeposit.actionName,
|
||||
authorization: [
|
||||
{
|
||||
actor: config.service_username,
|
||||
actor: config.coopname,
|
||||
permission: 'active',
|
||||
},
|
||||
],
|
||||
@@ -426,7 +430,7 @@ async function completeDeposit(order: IOrder) {
|
||||
name: GatewayContract.Actions.CompleteDeposit.actionName,
|
||||
authorization: [
|
||||
{
|
||||
actor: config.service_username,
|
||||
actor: config.coopname,
|
||||
permission: 'active',
|
||||
},
|
||||
],
|
||||
@@ -446,7 +450,7 @@ async function completeDeposit(order: IOrder) {
|
||||
}
|
||||
|
||||
async function failOrder(data) {
|
||||
const eos = await getInstance(config.service_wif);
|
||||
const eos = await getInstance(config.coopname);
|
||||
|
||||
const actions = [
|
||||
{
|
||||
@@ -474,15 +478,15 @@ async function failOrder(data) {
|
||||
}
|
||||
|
||||
export async function addUser(data: RegistratorContract.Actions.AddUser.IAddUser) {
|
||||
const eos = await getInstance(config.service_wif);
|
||||
|
||||
const eos = await getInstance(config.coopname);
|
||||
console.log('data:', data);
|
||||
const actions = [
|
||||
{
|
||||
account: RegistratorContract.contractName.production,
|
||||
name: RegistratorContract.Actions.AddUser.actionName,
|
||||
authorization: [
|
||||
{
|
||||
actor: config.service_username,
|
||||
actor: config.coopname,
|
||||
permission: 'active',
|
||||
},
|
||||
],
|
||||
@@ -502,7 +506,7 @@ export async function addUser(data: RegistratorContract.Actions.AddUser.IAddUser
|
||||
}
|
||||
|
||||
export async function changeKey(data: RegistratorContract.Actions.ChangeKey.IChangeKey) {
|
||||
const eos = await getInstance(config.service_wif);
|
||||
const eos = await getInstance(config.coopname);
|
||||
|
||||
const actions = [
|
||||
{
|
||||
@@ -510,7 +514,7 @@ export async function changeKey(data: RegistratorContract.Actions.ChangeKey.ICha
|
||||
name: RegistratorContract.Actions.ChangeKey.actionName,
|
||||
authorization: [
|
||||
{
|
||||
actor: config.service_username,
|
||||
actor: config.coopname,
|
||||
permission: 'active',
|
||||
},
|
||||
],
|
||||
@@ -535,7 +539,7 @@ export async function cancelOrder(data: GatewayContract.Actions.RefundDeposit.IR
|
||||
name: GatewayContract.Actions.RefundDeposit.actionName,
|
||||
authorization: [
|
||||
{
|
||||
actor: config.service_username,
|
||||
actor: config.coopname,
|
||||
permission: 'active',
|
||||
},
|
||||
],
|
||||
@@ -545,6 +549,38 @@ export async function cancelOrder(data: GatewayContract.Actions.RefundDeposit.IR
|
||||
return await transact([action]);
|
||||
}
|
||||
|
||||
export async function powerUp(username: string, quantity: string): Promise<void> {
|
||||
const data: SystemContract.Actions.Powerup.IPowerup = {
|
||||
payer: username,
|
||||
receiver: username,
|
||||
days: 1,
|
||||
payment: quantity,
|
||||
transfer: false,
|
||||
};
|
||||
|
||||
const actions = [
|
||||
{
|
||||
account: 'eosio',
|
||||
name: 'powerup',
|
||||
authorization: [
|
||||
{
|
||||
actor: username,
|
||||
permission: 'active',
|
||||
},
|
||||
],
|
||||
data,
|
||||
},
|
||||
];
|
||||
|
||||
try {
|
||||
const result = await transact(actions);
|
||||
console.log('Транзакция powerup выполнена:', result);
|
||||
} catch (error) {
|
||||
console.error('Ошибка при выполнении транзакции powerup:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function getSoviet(coopname) {
|
||||
const api = await getApi();
|
||||
|
||||
|
||||
@@ -11,6 +11,10 @@ export const connectGenerator = async () => {
|
||||
await generator.connect(config.mongoose.url);
|
||||
};
|
||||
|
||||
export const diconnectGenerator = async () => {
|
||||
await generator.disconnect();
|
||||
};
|
||||
|
||||
export const generateDocument = async (options: IGenerate) => {
|
||||
return await generator.generate(options);
|
||||
};
|
||||
@@ -30,7 +34,7 @@ export async function buildComplexDocument(
|
||||
{
|
||||
const document = await generator.getDocument({ hash: raw_document.document.hash });
|
||||
|
||||
if (document)
|
||||
if (document && document.meta.links && Array.isArray(document.meta.links))
|
||||
for (const link of document.meta.links) {
|
||||
const linked_document = await generator.getDocument({ hash: link });
|
||||
links.push(linked_document);
|
||||
@@ -78,7 +82,7 @@ export async function buildComplexDocument(
|
||||
|
||||
const document = await generator.getDocument({ hash: decision_action?.data?.document?.hash });
|
||||
|
||||
if (document)
|
||||
if (document && document.meta.links && Array.isArray(document.meta.links))
|
||||
for (const link of document.meta.links) {
|
||||
const linked_document = await generator.getDocument({ hash: link });
|
||||
links.push(linked_document);
|
||||
@@ -102,7 +106,23 @@ export async function buildComplexDocument(
|
||||
return { statement, decision, acts, links };
|
||||
}
|
||||
|
||||
function toDotNotation(obj, prefix = '') {
|
||||
return Object.keys(obj).reduce((acc, key) => {
|
||||
const value = obj[key];
|
||||
const newKey = prefix ? `${prefix}.${key}` : key;
|
||||
|
||||
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
||||
Object.assign(acc, toDotNotation(value, newKey));
|
||||
} else {
|
||||
acc[newKey] = value;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
export const queryDocuments = async (
|
||||
type: string,
|
||||
filter: any,
|
||||
page = 1,
|
||||
limit = 100
|
||||
@@ -112,9 +132,8 @@ export const queryDocuments = async (
|
||||
{
|
||||
filter: JSON.stringify({
|
||||
account: SovietContract.contractName.production,
|
||||
name: SovietContract.Actions.Registry.NewResolved.actionName,
|
||||
receiver: process.env.COOPNAME,
|
||||
...filter,
|
||||
name: type, //< newresolved | newsubmitted
|
||||
...toDotNotation(filter),
|
||||
}),
|
||||
page,
|
||||
limit,
|
||||
@@ -130,7 +149,7 @@ export const queryDocuments = async (
|
||||
for (const raw_action_document of actions.results) {
|
||||
const complexDocument = await buildComplexDocument(raw_action_document);
|
||||
|
||||
if (complexDocument.decision.action) response.results.push(complexDocument);
|
||||
if (complexDocument.statement.action) response.results.push(complexDocument);
|
||||
}
|
||||
|
||||
return response;
|
||||
|
||||
@@ -11,5 +11,6 @@ export * as systemService from './system.service';
|
||||
export * as participantService from './participant.service';
|
||||
export * as redisService from './redis.service';
|
||||
export * as methodService from './method.service';
|
||||
export * as payEffectService from './payEffect.service';
|
||||
export * as paymentService from './payment.service';
|
||||
export * as settingService from './setting.service';
|
||||
export * as pluginService from './plugin.service';
|
||||
|
||||
@@ -69,8 +69,8 @@ export async function createOrder(
|
||||
amount,
|
||||
symbol,
|
||||
type === 'deposit'
|
||||
? `Добровольный паевый взнос №${db_order.order_num}`
|
||||
: `Добровольный вступительный взнос №${db_order.order_num}`,
|
||||
? `Паевый взнос №${db_order.order_num}`
|
||||
: `Вступительный и минимальный паевый взносы №${secret.slice(0, 10)}`,
|
||||
db_order.order_num as number,
|
||||
secret
|
||||
);
|
||||
@@ -168,7 +168,7 @@ export async function setStatus(id: string, status: string) {
|
||||
if (status == 'refunded') {
|
||||
await blockchainService.cancelOrder({
|
||||
coopname: config.coopname,
|
||||
admin: config.service_username,
|
||||
admin: config.coopname,
|
||||
deposit_id: order.order_num as number,
|
||||
memo: '',
|
||||
});
|
||||
|
||||
+15
-13
@@ -8,7 +8,7 @@ import { redisSubscriber } from './redis.service';
|
||||
import config from '../config/config';
|
||||
|
||||
export class PaymentEffectProcessor {
|
||||
static async processPaymentEffect(id: string, status: string) {
|
||||
public async processPaymentEffect(id: string, status: string) {
|
||||
const order = await Order.findById(id);
|
||||
|
||||
if (!order) {
|
||||
@@ -18,7 +18,7 @@ export class PaymentEffectProcessor {
|
||||
|
||||
switch (status) {
|
||||
case 'paid':
|
||||
if (order.status != 'completed') await PaymentEffectProcessor.process(order);
|
||||
if (order.status != 'completed') await this.process(order);
|
||||
break;
|
||||
|
||||
case 'failed':
|
||||
@@ -31,7 +31,7 @@ export class PaymentEffectProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private static async process(order: IOrder) {
|
||||
private async process(order: IOrder) {
|
||||
logger.info(`Processing blockchain data for order ${order.id}`, { source: 'process' });
|
||||
|
||||
try {
|
||||
@@ -62,15 +62,17 @@ export class PaymentEffectProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
redisSubscriber.subscribe(`${config.coopname}:orderStatusUpdate`);
|
||||
export const init = () => {
|
||||
redisSubscriber.subscribe(`${config.coopname}:orderStatusUpdate`);
|
||||
|
||||
redisSubscriber.on('message', async (channel, message) => {
|
||||
if (channel === `${config.coopname}:orderStatusUpdate`) {
|
||||
try {
|
||||
const { id, status } = JSON.parse(message);
|
||||
await PaymentEffectProcessor.processPaymentEffect(id, status);
|
||||
} catch (error) {
|
||||
logger.error('Error processing Redis message:', error);
|
||||
redisSubscriber.on('message', async (channel, message) => {
|
||||
if (channel === `${config.coopname}:orderStatusUpdate`) {
|
||||
try {
|
||||
const { id, status } = JSON.parse(message);
|
||||
await new PaymentEffectProcessor().processPaymentEffect(id, status);
|
||||
} catch (error) {
|
||||
logger.error('Error processing Redis message:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -78,7 +78,7 @@ class SberbankPollingProvider implements PollingProvider {
|
||||
cooperative?.bank_account.details.corr
|
||||
}|Sum=${parseInt(amount)}00|Purpose=${description}. Без НДС.|PayeeINN=${cooperative?.details.inn}|KPP=${
|
||||
cooperative?.details.kpp
|
||||
};`;
|
||||
}`;
|
||||
|
||||
const result: PaymentDetails = {
|
||||
data: invoice,
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import { PluginConfig } from '../models/pluginConfig.model';
|
||||
import Joi from 'joi';
|
||||
import { PluginRegistry } from '../plugins';
|
||||
import parse from 'joi-to-json';
|
||||
|
||||
import ApiError from '../utils/ApiError';
|
||||
import httpStatus from 'http-status';
|
||||
|
||||
// Динамическое создание объектов и сбор схем
|
||||
const getPluginSchemasInternal = () => {
|
||||
const pluginSchemas = Object.entries(PluginRegistry).reduce((schemas, [key, PluginModule]) => {
|
||||
const pluginInstance = new PluginModule.Plugin();
|
||||
schemas[pluginInstance.name] = pluginInstance.pluginSchema;
|
||||
return schemas;
|
||||
}, {} as { [key: string]: Joi.ObjectSchema });
|
||||
return pluginSchemas;
|
||||
};
|
||||
|
||||
// Функция для обновления конфигурации плагина
|
||||
export const updatePluginConfig = async (pluginName: string, enabled: boolean, config: any) => {
|
||||
const schema = getPluginSchemasInternal()[pluginName];
|
||||
if (!schema) {
|
||||
throw new ApiError(httpStatus.BAD_REQUEST, `Схема для плагина ${pluginName} не найдена.`);
|
||||
}
|
||||
|
||||
// Валидация переданных параметров
|
||||
const { error } = schema.validate(config);
|
||||
|
||||
if (error) {
|
||||
throw new ApiError(httpStatus.BAD_REQUEST, `Ошибка валидации конфигурации плагина ${pluginName}: ${error.message}`);
|
||||
}
|
||||
|
||||
// Обновление конфигурации в базе данных
|
||||
const pluginConfig = await PluginConfig.findOneAndUpdate(
|
||||
{ name: pluginName },
|
||||
{ enabled, config },
|
||||
{ new: true, upsert: true }
|
||||
);
|
||||
|
||||
return pluginConfig;
|
||||
};
|
||||
|
||||
// Метод для извлечения Joi схемы
|
||||
export const getPluginSchema = (pluginName: string) => {
|
||||
const pluginInstance = getPluginSchemasInternal()[pluginName];
|
||||
|
||||
if (!pluginInstance) {
|
||||
throw new ApiError(httpStatus.BAD_REQUEST, 'Плагин не найден');
|
||||
}
|
||||
// Преобразование Joi схемы в JSON
|
||||
try {
|
||||
const jsonSchema = parse(pluginInstance);
|
||||
return jsonSchema;
|
||||
} catch (e: any) {
|
||||
console.log('on error');
|
||||
throw new ApiError(httpStatus.BAD_REQUEST, e.message);
|
||||
}
|
||||
};
|
||||
|
||||
// Метод для извлечения Joi схемы
|
||||
export const getPluginConfig = async (pluginName: string): Promise<any> => {
|
||||
const config = await PluginConfig.findOne({ name: pluginName });
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
export const queryPlugins = async (filter, options) => {
|
||||
const plugins = await PluginConfig.paginate(filter, options);
|
||||
|
||||
return plugins;
|
||||
};
|
||||
@@ -9,12 +9,28 @@ import { generator } from './document.service';
|
||||
import { blockchainService, emailService, tokenService, userService } from '.';
|
||||
import { IUser, userStatus } from '../types/user.types';
|
||||
import axios from 'axios';
|
||||
import { getBlockchainInfo } from './blockchain.service';
|
||||
import { getBlockchainAccount, getBlockchainInfo, hasActiveKey } from './blockchain.service';
|
||||
import { RegistratorContract, type Cooperative } from 'cooptypes';
|
||||
import type { ISetVars } from '../types/auto-generated/system.validation';
|
||||
import type { IInit, ISetVars, ISetWif } from '../types/auto-generated/system.validation';
|
||||
import { VarsSchema } from 'coopdoc-generator-ts';
|
||||
import Vault, { type wifPermissions } from '../models/vault.model';
|
||||
import { PrivateKey } from '@wharfkit/antelope';
|
||||
import { createUser } from './user.service';
|
||||
|
||||
export const install = async (soviet: IInstall): Promise<void> => {
|
||||
export const setWif = async (params: ISetWif): Promise<void> => {
|
||||
//check auth
|
||||
const blockchainAccount = await getBlockchainAccount(params.username);
|
||||
|
||||
const publicKey = PrivateKey.fromString(params.wif).toPublic().toLegacyString();
|
||||
|
||||
const hasKey = hasActiveKey(blockchainAccount, publicKey);
|
||||
|
||||
if (!hasKey) throw new ApiError(httpStatus.UNAUTHORIZED, 'Неверный приватный ключ');
|
||||
|
||||
await Vault.setWif(params.username, params.wif, params.permission as wifPermissions);
|
||||
};
|
||||
|
||||
export const install = async (data: IInstall): Promise<void> => {
|
||||
const mono = await Mono.findOne({ coopname: config.coopname });
|
||||
const info = await getBlockchainInfo();
|
||||
const coop = await blockchainService.getCooperative(config.coopname);
|
||||
@@ -25,9 +41,16 @@ export const install = async (soviet: IInstall): Promise<void> => {
|
||||
throw new ApiError(httpStatus.BAD_REQUEST, 'Установка уже выполнена');
|
||||
}
|
||||
|
||||
await setWif({
|
||||
permission: 'active',
|
||||
username: config.coopname,
|
||||
wif: data.wif,
|
||||
});
|
||||
|
||||
const users = [] as IUser[];
|
||||
const members = [] as any;
|
||||
const sovietExt = [] as any;
|
||||
const soviet = data.soviet;
|
||||
|
||||
try {
|
||||
for (const member of soviet) {
|
||||
@@ -35,7 +58,7 @@ export const install = async (soviet: IInstall): Promise<void> => {
|
||||
sovietExt.push({ ...member, username });
|
||||
|
||||
const addUser: RegistratorContract.Actions.AddUser.IAddUser = {
|
||||
registrator: config.service_username,
|
||||
registrator: config.coopname,
|
||||
coopname: config.coopname,
|
||||
referer: '',
|
||||
username,
|
||||
@@ -83,7 +106,7 @@ export const install = async (soviet: IInstall): Promise<void> => {
|
||||
//TODO создаёт доску совета
|
||||
await blockchainService.createBoard({
|
||||
coopname: config.coopname,
|
||||
username: config.service_username,
|
||||
username: config.coopname,
|
||||
type: 'soviet',
|
||||
members: members,
|
||||
name: 'Совет',
|
||||
@@ -105,33 +128,41 @@ export const install = async (soviet: IInstall): Promise<void> => {
|
||||
}
|
||||
);
|
||||
|
||||
logger.info('MONO активирован');
|
||||
logger.info('Система установлена');
|
||||
};
|
||||
|
||||
export const init = async (): Promise<void> => {
|
||||
export const init = async (data: IInit): Promise<void> => {
|
||||
const mono = await Mono.findOne({ coopname: config.coopname });
|
||||
|
||||
if (!mono)
|
||||
await Mono.create({
|
||||
coopname: config.coopname,
|
||||
status: 'install',
|
||||
});
|
||||
if (mono) throw new ApiError(httpStatus.BAD_REQUEST, 'MONO уже инициализирован');
|
||||
|
||||
logger.info('MONO инициализирован');
|
||||
await Mono.create({
|
||||
coopname: config.coopname,
|
||||
status: 'install',
|
||||
});
|
||||
|
||||
await setVars(data.vars);
|
||||
|
||||
await generator.save('organization', { username: config.coopname, ...data.organization_data });
|
||||
|
||||
logger.info('Система инициализирована');
|
||||
};
|
||||
|
||||
export const getMonoStatus = async (): Promise<IHealthStatus> => {
|
||||
const mono = await Mono.findOne({ coopname: config.coopname });
|
||||
|
||||
if (!mono) throw new ApiError(httpStatus.BAD_REQUEST, 'Установщик не найден');
|
||||
|
||||
return mono.status;
|
||||
if (!mono) return 'maintenance';
|
||||
else return mono.status;
|
||||
};
|
||||
|
||||
export const setVars = async (vars: ISetVars): Promise<void> => {
|
||||
await generator.save('vars', vars);
|
||||
};
|
||||
|
||||
export const getVars = async (): Promise<Cooperative.Model.IVars> => {
|
||||
return (await generator.get('vars', {})) as Cooperative.Model.IVars;
|
||||
};
|
||||
|
||||
export const getVarsSchema = async (): Promise<unknown> => {
|
||||
return VarsSchema;
|
||||
};
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { SovietContract } from 'cooptypes';
|
||||
import { userService } from '.';
|
||||
import { User } from '../models';
|
||||
import config from '../config/config';
|
||||
|
||||
export const updateBoard = async (action: SovietContract.Actions.Boards.UpdateBoard.IUpdateBoard): Promise<void> => {
|
||||
//сброс всех прав
|
||||
if (action.coopname != config.coopname) return;
|
||||
|
||||
const users = await User.find({ role: { $in: ['member', 'chairman'] } }).exec();
|
||||
for (const user of users) {
|
||||
user.role = 'user';
|
||||
|
||||
@@ -25,12 +25,17 @@ export interface IGetDocuments {
|
||||
* Unknown Property
|
||||
*/
|
||||
[x: string]: unknown;
|
||||
filter?: {
|
||||
receiver?: string;
|
||||
filter: {
|
||||
/**
|
||||
* Unknown Property
|
||||
*/
|
||||
[x: string]: unknown;
|
||||
receiver: string;
|
||||
};
|
||||
limit?: number;
|
||||
page?: number;
|
||||
sortBy?: string;
|
||||
type?: 'newsubmitted' | 'newresolved';
|
||||
}
|
||||
|
||||
export interface RGenerate {
|
||||
@@ -58,12 +63,17 @@ export interface RGetDocuments {
|
||||
* Unknown Property
|
||||
*/
|
||||
[x: string]: unknown;
|
||||
filter?: {
|
||||
receiver?: string;
|
||||
filter: {
|
||||
/**
|
||||
* Unknown Property
|
||||
*/
|
||||
[x: string]: unknown;
|
||||
receiver: string;
|
||||
};
|
||||
limit?: number;
|
||||
page?: number;
|
||||
sortBy?: string;
|
||||
type?: 'newsubmitted' | 'newresolved';
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -10,5 +10,6 @@ export * from './method.validation';
|
||||
export * from './notify.validation';
|
||||
export * from './order.validation';
|
||||
export * from './participant.validation';
|
||||
export * from './plugin.validation';
|
||||
export * from './system.validation';
|
||||
export * from './user.validation';
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* This file was automatically generated by joi-to-typescript
|
||||
* Do not modify this file manually
|
||||
*/
|
||||
|
||||
export interface IGetPluginConfig {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface IGetPluginList {
|
||||
limit?: number;
|
||||
name: string;
|
||||
page?: number;
|
||||
}
|
||||
|
||||
export interface IGetPluginSchema {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface ISetPlugin {
|
||||
config?: object;
|
||||
enabled: boolean;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface RGetPluginConfig {
|
||||
query: {
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface RGetPluginList {
|
||||
query: {
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface RGetPluginSchema {
|
||||
query: {
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface RSetPlugin {
|
||||
body: {
|
||||
config?: object;
|
||||
enabled: boolean;
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
@@ -3,25 +3,102 @@
|
||||
* Do not modify this file manually
|
||||
*/
|
||||
|
||||
export type IInstall = ({
|
||||
individual_data: {
|
||||
birthdate: string;
|
||||
email: string;
|
||||
first_name: string;
|
||||
full_address: string;
|
||||
last_name: string;
|
||||
middle_name: string;
|
||||
passport?: {
|
||||
code: string;
|
||||
issued_at: string;
|
||||
issued_by: string;
|
||||
number: number;
|
||||
series: number;
|
||||
export interface IInit {
|
||||
organization_data: {
|
||||
bank_account: {
|
||||
account_number: string;
|
||||
bank_name: string;
|
||||
card_number?: string;
|
||||
currency: 'RUB' | 'Other';
|
||||
details: {
|
||||
bik: string;
|
||||
corr: string;
|
||||
kpp: string;
|
||||
};
|
||||
};
|
||||
city: string;
|
||||
country: 'Russia' | 'Other';
|
||||
details: {
|
||||
inn: string;
|
||||
kpp: string;
|
||||
ogrn: string;
|
||||
};
|
||||
email: string;
|
||||
full_address: string;
|
||||
full_name: string;
|
||||
is_cooperative: boolean;
|
||||
phone: string;
|
||||
represented_by: {
|
||||
based_on: string;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
middle_name: string;
|
||||
position: string;
|
||||
};
|
||||
short_name: string;
|
||||
type: 'coop' | 'ooo' | 'oao' | 'zao' | 'pao' | 'ao';
|
||||
};
|
||||
role: 'chairman' | 'member';
|
||||
})[];
|
||||
vars: {
|
||||
/**
|
||||
* Unknown Property
|
||||
*/
|
||||
[x: string]: unknown;
|
||||
confidential_email: string;
|
||||
confidential_link: string;
|
||||
contact_email: string;
|
||||
coopname: string;
|
||||
full_abbr: string;
|
||||
full_abbr_dative: string;
|
||||
full_abbr_genitive: string;
|
||||
name: string;
|
||||
participant_application: {
|
||||
protocol_day_month_year: string;
|
||||
protocol_number: string;
|
||||
};
|
||||
passport_request: 'yes' | 'no';
|
||||
privacy_agreement: {
|
||||
protocol_day_month_year: string;
|
||||
protocol_number: string;
|
||||
};
|
||||
short_abbr: string;
|
||||
signature_agreement: {
|
||||
protocol_day_month_year: string;
|
||||
protocol_number: string;
|
||||
};
|
||||
user_agreement: {
|
||||
protocol_day_month_year: string;
|
||||
protocol_number: string;
|
||||
};
|
||||
wallet_agreement: {
|
||||
protocol_day_month_year: string;
|
||||
protocol_number: string;
|
||||
};
|
||||
website: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IInstall {
|
||||
soviet: ({
|
||||
individual_data: {
|
||||
birthdate: string;
|
||||
email: string;
|
||||
first_name: string;
|
||||
full_address: string;
|
||||
last_name: string;
|
||||
middle_name: string;
|
||||
passport?: {
|
||||
code: string;
|
||||
issued_at: string;
|
||||
issued_by: string;
|
||||
number: number;
|
||||
series: number;
|
||||
};
|
||||
phone: string;
|
||||
};
|
||||
role: 'chairman' | 'member';
|
||||
})[];
|
||||
wif: string;
|
||||
}
|
||||
|
||||
export interface ISetVars {
|
||||
/**
|
||||
@@ -61,26 +138,111 @@ export interface ISetVars {
|
||||
website: string;
|
||||
}
|
||||
|
||||
export interface RInstall {
|
||||
body: ({
|
||||
individual_data: {
|
||||
birthdate: string;
|
||||
email: string;
|
||||
first_name: string;
|
||||
full_address: string;
|
||||
last_name: string;
|
||||
middle_name: string;
|
||||
passport?: {
|
||||
code: string;
|
||||
issued_at: string;
|
||||
issued_by: string;
|
||||
number: number;
|
||||
series: number;
|
||||
export interface ISetWif {
|
||||
permission: 'active';
|
||||
username: string;
|
||||
wif: string;
|
||||
}
|
||||
|
||||
export interface RInit {
|
||||
body: {
|
||||
organization_data: {
|
||||
bank_account: {
|
||||
account_number: string;
|
||||
bank_name: string;
|
||||
card_number?: string;
|
||||
currency: 'RUB' | 'Other';
|
||||
details: {
|
||||
bik: string;
|
||||
corr: string;
|
||||
kpp: string;
|
||||
};
|
||||
};
|
||||
city: string;
|
||||
country: 'Russia' | 'Other';
|
||||
details: {
|
||||
inn: string;
|
||||
kpp: string;
|
||||
ogrn: string;
|
||||
};
|
||||
email: string;
|
||||
full_address: string;
|
||||
full_name: string;
|
||||
is_cooperative: boolean;
|
||||
phone: string;
|
||||
represented_by: {
|
||||
based_on: string;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
middle_name: string;
|
||||
position: string;
|
||||
};
|
||||
short_name: string;
|
||||
type: 'coop' | 'ooo' | 'oao' | 'zao' | 'pao' | 'ao';
|
||||
};
|
||||
role: 'chairman' | 'member';
|
||||
})[];
|
||||
vars: {
|
||||
/**
|
||||
* Unknown Property
|
||||
*/
|
||||
[x: string]: unknown;
|
||||
confidential_email: string;
|
||||
confidential_link: string;
|
||||
contact_email: string;
|
||||
coopname: string;
|
||||
full_abbr: string;
|
||||
full_abbr_dative: string;
|
||||
full_abbr_genitive: string;
|
||||
name: string;
|
||||
participant_application: {
|
||||
protocol_day_month_year: string;
|
||||
protocol_number: string;
|
||||
};
|
||||
passport_request: 'yes' | 'no';
|
||||
privacy_agreement: {
|
||||
protocol_day_month_year: string;
|
||||
protocol_number: string;
|
||||
};
|
||||
short_abbr: string;
|
||||
signature_agreement: {
|
||||
protocol_day_month_year: string;
|
||||
protocol_number: string;
|
||||
};
|
||||
user_agreement: {
|
||||
protocol_day_month_year: string;
|
||||
protocol_number: string;
|
||||
};
|
||||
wallet_agreement: {
|
||||
protocol_day_month_year: string;
|
||||
protocol_number: string;
|
||||
};
|
||||
website: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface RInstall {
|
||||
body: {
|
||||
soviet: ({
|
||||
individual_data: {
|
||||
birthdate: string;
|
||||
email: string;
|
||||
first_name: string;
|
||||
full_address: string;
|
||||
last_name: string;
|
||||
middle_name: string;
|
||||
passport?: {
|
||||
code: string;
|
||||
issued_at: string;
|
||||
issued_by: string;
|
||||
number: number;
|
||||
series: number;
|
||||
};
|
||||
phone: string;
|
||||
};
|
||||
role: 'chairman' | 'member';
|
||||
})[];
|
||||
wif: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface RSetVars {
|
||||
@@ -123,6 +285,14 @@ export interface RSetVars {
|
||||
};
|
||||
}
|
||||
|
||||
export interface RSetWif {
|
||||
body: {
|
||||
permission: 'active';
|
||||
username: string;
|
||||
wif: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface RUpdateSettings {
|
||||
body: {
|
||||
settings: object;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { Document } from 'mongoose';
|
||||
|
||||
export interface IPlugin {
|
||||
name: string;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
initialize(config: any): Promise<void>;
|
||||
}
|
||||
|
||||
export interface IPluginSchema<T> extends Document {
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
config: T;
|
||||
}
|
||||
|
||||
export interface IPluginLog<T> extends Document {
|
||||
name: string;
|
||||
log: T;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import * as crypto from 'crypto'; // Импорт crypto из Node.js
|
||||
import config from '../config/config';
|
||||
const ALGORITHM = 'aes-256-cbc'; // Алгоритм шифрования
|
||||
const SERVER_SECRET = config.server_secret; // Получаем секретный ключ из переменной окружения
|
||||
const IV_LENGTH = 16; // Длина вектора инициализации для AES
|
||||
|
||||
// Преобразуем ключ в 32 байта с использованием SHA-256
|
||||
const getKey = (secret: string) => crypto.createHash('sha256').update(secret).digest();
|
||||
|
||||
// Функция для шифрования
|
||||
export function encrypt(text: string): string {
|
||||
const iv = crypto.randomBytes(IV_LENGTH); // Генерация случайного вектора инициализации
|
||||
const cipher = crypto.createCipheriv(ALGORITHM, getKey(SERVER_SECRET), iv); // Используем ключ 32 байта
|
||||
let encrypted = cipher.update(text, 'utf8', 'hex');
|
||||
encrypted += cipher.final('hex');
|
||||
return iv.toString('hex') + ':' + encrypted; // Сохраняем вектор инициализации вместе с зашифрованным текстом
|
||||
}
|
||||
|
||||
// Функция для расшифровки
|
||||
export function decrypt(text: string): string {
|
||||
const [ivHex, encrypted] = text.split(':');
|
||||
const iv = Buffer.from(ivHex, 'hex'); // Преобразование вектора инициализации из строки обратно в Buffer
|
||||
const decipher = crypto.createDecipheriv(ALGORITHM, getKey(SERVER_SECRET), iv); // Используем тот же ключ 32 байта
|
||||
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
|
||||
decrypted += decipher.final('utf8');
|
||||
return decrypted;
|
||||
}
|
||||
@@ -19,8 +19,11 @@ export const RGenerate = Joi.object({
|
||||
|
||||
export const IGetDocuments = Joi.object({
|
||||
filter: Joi.object({
|
||||
receiver: Joi.string(),
|
||||
}),
|
||||
receiver: Joi.string().required(),
|
||||
})
|
||||
.required()
|
||||
.unknown(true),
|
||||
type: Joi.string().optional().valid('newsubmitted', 'newresolved').default('newresolved'),
|
||||
sortBy: Joi.string(),
|
||||
limit: Joi.number().integer(),
|
||||
page: Joi.number().integer(),
|
||||
|
||||
@@ -8,3 +8,4 @@ export * as notifyValidation from './notify.validation';
|
||||
export * as systemValidation from './system.validation';
|
||||
export * as participantValidation from './participant.validation';
|
||||
export * as methodValidation from './method.validation';
|
||||
export * as pluginValidation from './plugin.validation';
|
||||
|
||||
@@ -8,7 +8,7 @@ const RussianBankDetailsSchema = Joi.object({
|
||||
|
||||
export const IBankAccount = Joi.object({
|
||||
currency: Joi.string().required().valid('RUB', 'Other'),
|
||||
card_number: Joi.string().default(''),
|
||||
card_number: Joi.string().default('').optional().allow(''),
|
||||
bank_name: Joi.string().required(),
|
||||
account_number: Joi.string().required(),
|
||||
details: RussianBankDetailsSchema.required(),
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import * as Joi from 'joi';
|
||||
|
||||
export const ISetPlugin = Joi.object({
|
||||
name: Joi.string().required(),
|
||||
enabled: Joi.boolean().required(),
|
||||
config: Joi.object().optional(),
|
||||
});
|
||||
|
||||
export const RSetPlugin = Joi.object({
|
||||
body: ISetPlugin.required(),
|
||||
});
|
||||
|
||||
export const IGetPluginSchema = Joi.object({
|
||||
name: Joi.string().required(),
|
||||
});
|
||||
|
||||
export const RGetPluginSchema = Joi.object({
|
||||
query: IGetPluginSchema.required(),
|
||||
});
|
||||
|
||||
export const IGetPluginConfig = Joi.object({
|
||||
name: Joi.string().required(),
|
||||
});
|
||||
|
||||
export const RGetPluginConfig = Joi.object({
|
||||
query: IGetPluginConfig.required(),
|
||||
});
|
||||
|
||||
export const IGetPluginList = Joi.object({
|
||||
name: Joi.string().required(),
|
||||
limit: Joi.number().integer(),
|
||||
page: Joi.number().integer(),
|
||||
});
|
||||
|
||||
export const RGetPluginList = Joi.object({
|
||||
query: IGetPluginConfig,
|
||||
});
|
||||
@@ -1,17 +1,32 @@
|
||||
import * as Joi from 'joi';
|
||||
import { IIndividualData } from './user.validation';
|
||||
import { IIndividualData, IOrganizationData } from './user.validation';
|
||||
|
||||
export const IInstall = Joi.array().items(
|
||||
Joi.object({
|
||||
role: Joi.string().required().valid('chairman', 'member'),
|
||||
individual_data: IIndividualData.required(),
|
||||
})
|
||||
);
|
||||
export const IInstall = Joi.object({
|
||||
wif: Joi.string().required(), // поле wif - обязательная строка
|
||||
soviet: Joi.array()
|
||||
.items(
|
||||
Joi.object({
|
||||
role: Joi.string().required().valid('chairman', 'member'), // поле role - обязательная строка с валидными значениями
|
||||
individual_data: IIndividualData.required(), // поле individual_data - обязательное
|
||||
})
|
||||
)
|
||||
.required(), // массив soviet - обязателен
|
||||
});
|
||||
|
||||
export const RInstall = Joi.object({
|
||||
body: IInstall.required(),
|
||||
});
|
||||
|
||||
export const ISetWif = Joi.object({
|
||||
username: Joi.string().required(),
|
||||
permission: Joi.string().required().valid('active'),
|
||||
wif: Joi.string().required(),
|
||||
});
|
||||
|
||||
export const RSetWif = Joi.object({
|
||||
body: ISetWif.required(),
|
||||
});
|
||||
|
||||
export const ISetVars = Joi.object({
|
||||
coopname: Joi.string().required(),
|
||||
full_abbr: Joi.string().required(),
|
||||
@@ -55,3 +70,12 @@ export const RUpdateSettings = Joi.object({
|
||||
settings: Joi.object().required(),
|
||||
}).required(),
|
||||
});
|
||||
|
||||
export const IInit = Joi.object({
|
||||
organization_data: IOrganizationData.required(),
|
||||
vars: ISetVars.required(),
|
||||
});
|
||||
|
||||
export const RInit = Joi.object({
|
||||
body: IInit.required(),
|
||||
});
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { expose } from 'threads/worker';
|
||||
import mongoose from 'mongoose';
|
||||
import { PluginRegistry } from '../plugins';
|
||||
import rootConfig from '../config/config';
|
||||
|
||||
const initializePlugin = async (pluginName: string) => {
|
||||
try {
|
||||
// Устанавливаем соединение с базой данных
|
||||
await mongoose.connect(rootConfig.mongoose.url);
|
||||
|
||||
const plugin = new PluginRegistry[pluginName].Plugin();
|
||||
await plugin.initialize();
|
||||
|
||||
return `Плагин ${pluginName} инициализирован успешно.`;
|
||||
} catch (error: any) {
|
||||
throw new Error(`Ошибка при инициализации плагина ${pluginName}: ${error.message}`);
|
||||
} finally {
|
||||
// Закрываем соединение с базой данных
|
||||
await mongoose.disconnect();
|
||||
}
|
||||
};
|
||||
|
||||
// Экспортируем функцию для вызова из основного потока
|
||||
expose({
|
||||
initializePlugin,
|
||||
});
|
||||
@@ -0,0 +1,439 @@
|
||||
{
|
||||
"openapi": "3.0.0",
|
||||
"components": {
|
||||
"examples": {},
|
||||
"headers": {},
|
||||
"parameters": {},
|
||||
"requestBodies": {},
|
||||
"responses": {},
|
||||
"schemas": {
|
||||
"RCreateUser": {
|
||||
"properties": {
|
||||
"body": {
|
||||
"properties": {
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"individual",
|
||||
"entrepreneur",
|
||||
"organization"
|
||||
]
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"user"
|
||||
],
|
||||
"nullable": false
|
||||
},
|
||||
"referer": {
|
||||
"type": "string"
|
||||
},
|
||||
"public_key": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization_data": {
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"coop",
|
||||
"ooo",
|
||||
"oao",
|
||||
"zao",
|
||||
"pao",
|
||||
"ao"
|
||||
]
|
||||
},
|
||||
"short_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"represented_by": {
|
||||
"properties": {
|
||||
"position": {
|
||||
"type": "string"
|
||||
},
|
||||
"middle_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"last_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"first_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"based_on": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"position",
|
||||
"middle_name",
|
||||
"last_name",
|
||||
"first_name",
|
||||
"based_on"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"is_cooperative": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"full_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"full_address": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"properties": {
|
||||
"ogrn": {
|
||||
"type": "string"
|
||||
},
|
||||
"kpp": {
|
||||
"type": "string"
|
||||
},
|
||||
"inn": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"ogrn",
|
||||
"kpp",
|
||||
"inn"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"country": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Russia",
|
||||
"Other"
|
||||
]
|
||||
},
|
||||
"city": {
|
||||
"type": "string"
|
||||
},
|
||||
"bank_account": {
|
||||
"properties": {
|
||||
"details": {
|
||||
"properties": {
|
||||
"kpp": {
|
||||
"type": "string"
|
||||
},
|
||||
"corr": {
|
||||
"type": "string"
|
||||
},
|
||||
"bik": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kpp",
|
||||
"corr",
|
||||
"bik"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"currency": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"RUB",
|
||||
"Other"
|
||||
]
|
||||
},
|
||||
"card_number": {
|
||||
"type": "string"
|
||||
},
|
||||
"bank_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"account_number": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"details",
|
||||
"currency",
|
||||
"bank_name",
|
||||
"account_number"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"short_name",
|
||||
"represented_by",
|
||||
"phone",
|
||||
"is_cooperative",
|
||||
"full_name",
|
||||
"full_address",
|
||||
"email",
|
||||
"details",
|
||||
"country",
|
||||
"city",
|
||||
"bank_account"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"individual_data": {
|
||||
"properties": {
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"passport": {
|
||||
"properties": {
|
||||
"series": {
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
"number": {
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
"issued_by": {
|
||||
"type": "string"
|
||||
},
|
||||
"issued_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"code": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"series",
|
||||
"number",
|
||||
"issued_by",
|
||||
"issued_at",
|
||||
"code"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"middle_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"last_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"full_address": {
|
||||
"type": "string"
|
||||
},
|
||||
"first_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"birthdate": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"phone",
|
||||
"middle_name",
|
||||
"last_name",
|
||||
"full_address",
|
||||
"first_name",
|
||||
"email",
|
||||
"birthdate"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"entrepreneur_data": {
|
||||
"properties": {
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"middle_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"last_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"full_address": {
|
||||
"type": "string"
|
||||
},
|
||||
"first_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"properties": {
|
||||
"ogrn": {
|
||||
"type": "string"
|
||||
},
|
||||
"inn": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"ogrn",
|
||||
"inn"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"country": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Russia",
|
||||
"Other"
|
||||
]
|
||||
},
|
||||
"city": {
|
||||
"type": "string"
|
||||
},
|
||||
"birthdate": {
|
||||
"type": "string"
|
||||
},
|
||||
"bank_account": {
|
||||
"properties": {
|
||||
"details": {
|
||||
"properties": {
|
||||
"kpp": {
|
||||
"type": "string"
|
||||
},
|
||||
"corr": {
|
||||
"type": "string"
|
||||
},
|
||||
"bik": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kpp",
|
||||
"corr",
|
||||
"bik"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"currency": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"RUB",
|
||||
"Other"
|
||||
]
|
||||
},
|
||||
"card_number": {
|
||||
"type": "string"
|
||||
},
|
||||
"bank_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"account_number": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"details",
|
||||
"currency",
|
||||
"bank_name",
|
||||
"account_number"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"phone",
|
||||
"middle_name",
|
||||
"last_name",
|
||||
"full_address",
|
||||
"first_name",
|
||||
"email",
|
||||
"details",
|
||||
"country",
|
||||
"city",
|
||||
"birthdate",
|
||||
"bank_account"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"username",
|
||||
"type",
|
||||
"role",
|
||||
"email"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"body"
|
||||
],
|
||||
"type": "object",
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
||||
},
|
||||
"info": {
|
||||
"title": "coopback",
|
||||
"version": "2.0.7",
|
||||
"license": {
|
||||
"name": "MIT"
|
||||
},
|
||||
"contact": {
|
||||
"name": "Alex Ant ",
|
||||
"email": "dacom.dark.sun@gmail.com"
|
||||
}
|
||||
},
|
||||
"paths": {
|
||||
"/users": {
|
||||
"post": {
|
||||
"operationId": "CreateUser",
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Created",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"tokens": {},
|
||||
"user": {}
|
||||
},
|
||||
"required": [
|
||||
"tokens",
|
||||
"user"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [],
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/RCreateUser"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"entryFile": "src/index.ts",
|
||||
"noImplicitAdditionalProperties": "throw-on-extras",
|
||||
"controllerPathGlobs": ["src/controllers/*.ts"],
|
||||
"spec": {
|
||||
"outputDirectory": "./swagger",
|
||||
"specVersion": 3
|
||||
},
|
||||
"exclude": ["node_modules", "dist"],
|
||||
"tsNode": true,
|
||||
"ignore": ["**/dist/**/*"],
|
||||
"debug": true
|
||||
}
|
||||
@@ -11,3 +11,4 @@ node_modules
|
||||
temp
|
||||
documents/*
|
||||
.env
|
||||
src/Services/Generator/tmp
|
||||
|
||||
@@ -3,6 +3,42 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.1.3](https://github.com/copenomics/coopdoc-generator-ts/compare/v2.1.2-alpha.10...v2.1.3) (2024-10-26)
|
||||
|
||||
|
||||
|
||||
## [2.1.2](https://github.com/copenomics/coopdoc-generator-ts/compare/v2.1.1...v2.1.2) (2024-10-19)
|
||||
|
||||
**Note:** Version bump only for package coopdoc-generator-ts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.1.2](https://github.com/copenomics/coopdoc-generator-ts/compare/v2.1.1...v2.1.2) (2024-10-19)
|
||||
|
||||
**Note:** Version bump only for package coopdoc-generator-ts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [2.1.0](https://github.com/copenomics/coopdoc-generator-ts/compare/v2.0.10-alpha.3...v2.1.0) (2024-10-13)
|
||||
|
||||
**Note:** Version bump only for package coopdoc-generator-ts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.0.8](https://github.com/copenomics/coopdoc-generator-ts/compare/v2.0.7...v2.0.8) (2024-10-09)
|
||||
|
||||
**Note:** Version bump only for package coopdoc-generator-ts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.0.7](https://github.com/copenomics/coopdoc-generator-ts/compare/v2.0.6...v2.0.7) (2024-09-30)
|
||||
|
||||
**Note:** Version bump only for package coopdoc-generator-ts
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "coopdoc-generator-ts",
|
||||
"type": "module",
|
||||
"version": "2.0.7",
|
||||
"version": "2.1.4-alpha.0",
|
||||
"private": false,
|
||||
"packageManager": "pnpm@9.0.6",
|
||||
"description": "",
|
||||
@@ -50,7 +50,7 @@
|
||||
"ajv-formats": "^3.0.1",
|
||||
"ajv-i18n": "^4.2.0",
|
||||
"axios": "^1.7.2",
|
||||
"cooptypes": "workspace:*",
|
||||
"cooptypes": "2.1.2",
|
||||
"dotenv": "^16.4.5",
|
||||
"eosjs-ecc": "^4.0.7",
|
||||
"handlebars": "^4.7.8",
|
||||
@@ -61,7 +61,7 @@
|
||||
"nunjucks": "^3.2.4",
|
||||
"pdf-lib": "^1.17.1",
|
||||
"puppeteer": "^22.8.0",
|
||||
"uuid": "^10.0.0"
|
||||
"uuid": "^11.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^2.17.0",
|
||||
@@ -92,5 +92,5 @@
|
||||
"vite@>=5.1.0 <=5.1.6": ">=5.1.7"
|
||||
}
|
||||
},
|
||||
"gitHead": "5ba05409c4a208ba2004c3f0d1f14e993b5f63ae"
|
||||
"gitHead": "7b59ea4b96991ed06abdc92e6d7835632845e3a5"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DraftContract } from 'cooptypes'
|
||||
import { WalletAgreement } from '../templates'
|
||||
import { DocFactory } from '../Factory'
|
||||
import type { IGeneratedDocument, IMetaDocument, ITemplate } from '../Interfaces'
|
||||
import type { IGeneratedDocument, IGenerationOptions, IMetaDocument, ITemplate } from '../Interfaces'
|
||||
import type { MongoDBConnector } from '../Services/Databazor'
|
||||
|
||||
export { WalletAgreement as Template } from '../templates'
|
||||
@@ -11,19 +11,19 @@ export class Factory extends DocFactory<WalletAgreement.Action> {
|
||||
super(storage)
|
||||
}
|
||||
|
||||
async generateDocument(options: WalletAgreement.Action): Promise<IGeneratedDocument> {
|
||||
async generateDocument(data: WalletAgreement.Action, options?: IGenerationOptions): Promise<IGeneratedDocument> {
|
||||
let template: ITemplate<WalletAgreement.Model>
|
||||
|
||||
if (process.env.SOURCE === 'local') {
|
||||
template = WalletAgreement.Template
|
||||
}
|
||||
else {
|
||||
template = await this.getTemplate(DraftContract.contractName.production, WalletAgreement.registry_id, options.block_num)
|
||||
template = await this.getTemplate(DraftContract.contractName.production, WalletAgreement.registry_id, data.block_num)
|
||||
}
|
||||
|
||||
const meta: IMetaDocument = await super.getMeta({ title: template.title, ...options })
|
||||
const coop = await super.getCooperative(options.coopname, options.block_num)
|
||||
const vars = await super.getVars(options.coopname, options.block_num)
|
||||
const meta: IMetaDocument = await super.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 combinedData: WalletAgreement.Model = {
|
||||
meta,
|
||||
@@ -33,8 +33,8 @@ export class Factory extends DocFactory<WalletAgreement.Action> {
|
||||
|
||||
await super.validate(combinedData, template.model)
|
||||
const translation = template.translations[meta.lang]
|
||||
const document: IGeneratedDocument = await super.generatePDF(null, template.context, combinedData, translation, meta)
|
||||
await super.saveDraft(document)
|
||||
const document: IGeneratedDocument = await super.generatePDF(null, template.context, combinedData, translation, meta, options?.skip_save)
|
||||
|
||||
return document
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DraftContract } from 'cooptypes'
|
||||
import { DocFactory } from '../Factory'
|
||||
import type { IGeneratedDocument, IMetaDocument, ITemplate } from '../Interfaces'
|
||||
import type { IGeneratedDocument, IGenerationOptions, IMetaDocument, ITemplate } from '../Interfaces'
|
||||
import type { MongoDBConnector } from '../Services/Databazor'
|
||||
import DataService from '../Services/Databazor/DataService'
|
||||
import { ParticipantApplication } from '../templates'
|
||||
@@ -12,26 +12,28 @@ export class Factory extends DocFactory<ParticipantApplication.Action> {
|
||||
super(storage)
|
||||
}
|
||||
|
||||
async generateDocument(options: ParticipantApplication.Action): Promise<IGeneratedDocument> {
|
||||
async generateDocument(data: ParticipantApplication.Action, _options?: IGenerationOptions): Promise<IGeneratedDocument> {
|
||||
// TODO надо использовать skip_save из options вместо skip_save из data, для этого на фронте внести соответствующие правки
|
||||
|
||||
let template: ITemplate<ParticipantApplication.Model>
|
||||
|
||||
if (process.env.SOURCE === 'local') {
|
||||
template = ParticipantApplication.Template
|
||||
}
|
||||
else {
|
||||
template = await this.getTemplate(DraftContract.contractName.production, ParticipantApplication.registry_id, options.block_num)
|
||||
template = await this.getTemplate(DraftContract.contractName.production, ParticipantApplication.registry_id, data.block_num)
|
||||
}
|
||||
|
||||
const user = await super.getUser(options.username, options.block_num)
|
||||
const user = await super.getUser(data.username, data.block_num)
|
||||
|
||||
const userData = {
|
||||
[user.type]: user.data,
|
||||
}
|
||||
|
||||
const coop = await super.getCooperative(options.coopname, options.block_num)
|
||||
const coop = await super.getCooperative(data.coopname, data.block_num)
|
||||
|
||||
let { signature, ...modifiedOptions } = options
|
||||
const meta: IMetaDocument = await super.getMeta({ title: template.title, ...modifiedOptions }) // Генерируем мета-данные
|
||||
let { signature, ...modifieddata } = data
|
||||
const meta: IMetaDocument = await super.getMeta({ title: template.title, ...modifieddata }) // Генерируем мета-данные
|
||||
|
||||
interface SignatureData {
|
||||
username: string
|
||||
@@ -42,12 +44,12 @@ export class Factory extends DocFactory<ParticipantApplication.Action> {
|
||||
const data_service = new DataService<SignatureData>(this.storage, 'signatures')
|
||||
|
||||
// пропуск сохранения необходим при вступлении для того, чтобы подготовить документ только для отображения без сохранения
|
||||
if (!options.skip_save) {
|
||||
if (!data.skip_save) {
|
||||
// если подпись не указана, то проверяем на наличие в базе данных
|
||||
if (!signature) {
|
||||
if (options.block_num) {
|
||||
const block_filter = options.block_num ? { block_num: { $lte: options.block_num } } : {}
|
||||
const db_signature = await data_service.getOne({ username: options.username, ...block_filter }) as SignatureData
|
||||
if (data.block_num) {
|
||||
const block_filter = data.block_num ? { block_num: { $lte: data.block_num } } : {}
|
||||
const db_signature = await data_service.getOne({ username: data.username, ...block_filter }) as SignatureData
|
||||
|
||||
if (db_signature)
|
||||
signature = db_signature.signature
|
||||
@@ -58,11 +60,11 @@ export class Factory extends DocFactory<ParticipantApplication.Action> {
|
||||
else {
|
||||
// если подпись указана - сохраняем в хранилище
|
||||
const data_service = new DataService<SignatureData>(this.storage, 'signatures')
|
||||
await data_service.save({ username: options.username, block_num: meta.block_num, signature })
|
||||
await data_service.save({ username: data.username, block_num: meta.block_num, signature })
|
||||
}
|
||||
}
|
||||
|
||||
const vars = await super.getVars(options.coopname, options.block_num)
|
||||
const vars = await super.getVars(data.coopname, data.block_num)
|
||||
|
||||
const combinedData: ParticipantApplication.Model = { ...userData, meta, coop, type: user.type, vars, signature }
|
||||
|
||||
@@ -73,11 +75,7 @@ export class Factory extends DocFactory<ParticipantApplication.Action> {
|
||||
const translation = template.translations[meta.lang]
|
||||
|
||||
// генерируем документ
|
||||
const document: IGeneratedDocument = await super.generatePDF(user.data, template.context, combinedData, translation, meta)
|
||||
|
||||
// сохраняем его в бд
|
||||
if (!options.skip_save)
|
||||
await super.saveDraft(document)
|
||||
const document: IGeneratedDocument = await super.generatePDF(user.data, template.context, combinedData, translation, meta, data.skip_save)
|
||||
|
||||
return document
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DraftContract } from 'cooptypes'
|
||||
import { RegulationElectronicSignature } from '../templates'
|
||||
import { DocFactory } from '../Factory'
|
||||
import type { IGeneratedDocument, IMetaDocument, ITemplate } from '../Interfaces'
|
||||
import type { IGeneratedDocument, IGenerationOptions, IMetaDocument, ITemplate } from '../Interfaces'
|
||||
import type { MongoDBConnector } from '../Services/Databazor'
|
||||
|
||||
export { RegulationElectronicSignature as Template } from '../templates'
|
||||
@@ -11,19 +11,19 @@ export class Factory extends DocFactory<RegulationElectronicSignature.Action> {
|
||||
super(storage)
|
||||
}
|
||||
|
||||
async generateDocument(options: RegulationElectronicSignature.Action): Promise<IGeneratedDocument> {
|
||||
async generateDocument(data: RegulationElectronicSignature.Action, options?: IGenerationOptions): Promise<IGeneratedDocument> {
|
||||
let template: ITemplate<RegulationElectronicSignature.Model>
|
||||
|
||||
if (process.env.SOURCE === 'local') {
|
||||
template = RegulationElectronicSignature.Template
|
||||
}
|
||||
else {
|
||||
template = await this.getTemplate(DraftContract.contractName.production, RegulationElectronicSignature.registry_id, options.block_num)
|
||||
template = await this.getTemplate(DraftContract.contractName.production, RegulationElectronicSignature.registry_id, data.block_num)
|
||||
}
|
||||
|
||||
const meta: IMetaDocument = await super.getMeta({ title: template.title, ...options })
|
||||
const coop = await super.getCooperative(options.coopname, options.block_num)
|
||||
const vars = await super.getVars(options.coopname, options.block_num)
|
||||
const meta: IMetaDocument = await super.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 combinedData: RegulationElectronicSignature.Model = {
|
||||
meta,
|
||||
@@ -35,9 +35,7 @@ export class Factory extends DocFactory<RegulationElectronicSignature.Action> {
|
||||
|
||||
const translation = template.translations[meta.lang]
|
||||
|
||||
const document: IGeneratedDocument = await super.generatePDF(null, template.context, combinedData, translation, meta)
|
||||
|
||||
await super.saveDraft(document)
|
||||
const document: IGeneratedDocument = await super.generatePDF(null, template.context, combinedData, translation, meta, options?.skip_save)
|
||||
|
||||
return document
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DraftContract } from 'cooptypes'
|
||||
import { PrivacyPolicy } from '../templates'
|
||||
import { DocFactory } from '../Factory'
|
||||
import type { IGeneratedDocument, IMetaDocument, ITemplate } from '../Interfaces'
|
||||
import type { IGeneratedDocument, IGenerationOptions, IMetaDocument, ITemplate } from '../Interfaces'
|
||||
import type { MongoDBConnector } from '../Services/Databazor'
|
||||
|
||||
export { PrivacyPolicy as Template } from '../templates'
|
||||
@@ -11,19 +11,19 @@ export class Factory extends DocFactory<PrivacyPolicy.Action> {
|
||||
super(storage)
|
||||
}
|
||||
|
||||
async generateDocument(options: PrivacyPolicy.Action): Promise<IGeneratedDocument> {
|
||||
async generateDocument(data: PrivacyPolicy.Action, options?: IGenerationOptions): Promise<IGeneratedDocument> {
|
||||
let template: ITemplate<PrivacyPolicy.Model>
|
||||
|
||||
if (process.env.SOURCE === 'local') {
|
||||
template = PrivacyPolicy.Template
|
||||
}
|
||||
else {
|
||||
template = await this.getTemplate(DraftContract.contractName.production, PrivacyPolicy.registry_id, options.block_num)
|
||||
template = await this.getTemplate(DraftContract.contractName.production, PrivacyPolicy.registry_id, data.block_num)
|
||||
}
|
||||
|
||||
const meta: IMetaDocument = await super.getMeta({ title: template.title, ...options })
|
||||
const coop = await super.getCooperative(options.coopname, options.block_num)
|
||||
const vars = await super.getVars(options.coopname, options.block_num)
|
||||
const meta: IMetaDocument = await super.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 combinedData: PrivacyPolicy.Model = {
|
||||
meta,
|
||||
@@ -35,9 +35,7 @@ export class Factory extends DocFactory<PrivacyPolicy.Action> {
|
||||
|
||||
const translation = template.translations[meta.lang]
|
||||
|
||||
const document: IGeneratedDocument = await super.generatePDF(null, template.context, combinedData, translation, meta)
|
||||
|
||||
await super.saveDraft(document)
|
||||
const document: IGeneratedDocument = await super.generatePDF(null, template.context, combinedData, translation, meta, options?.skip_save)
|
||||
|
||||
return document
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DraftContract } from 'cooptypes'
|
||||
import { UserAgreement } from '../templates'
|
||||
import { DocFactory } from '../Factory'
|
||||
import type { IGeneratedDocument, IMetaDocument, ITemplate } from '../Interfaces'
|
||||
import type { IGeneratedDocument, IGenerationOptions, IMetaDocument, ITemplate } from '../Interfaces'
|
||||
import type { MongoDBConnector } from '../Services/Databazor'
|
||||
|
||||
export { UserAgreement as Template } from '../templates'
|
||||
@@ -11,20 +11,20 @@ export class Factory extends DocFactory<UserAgreement.Action> {
|
||||
super(storage)
|
||||
}
|
||||
|
||||
async generateDocument(options: UserAgreement.Action): Promise<IGeneratedDocument> {
|
||||
async generateDocument(data: UserAgreement.Action, options?: IGenerationOptions): Promise<IGeneratedDocument> {
|
||||
let template: ITemplate<UserAgreement.Model>
|
||||
|
||||
if (process.env.SOURCE === 'local') {
|
||||
template = UserAgreement.Template
|
||||
}
|
||||
else {
|
||||
template = await this.getTemplate(DraftContract.contractName.production, UserAgreement.registry_id, options.block_num)
|
||||
template = await this.getTemplate(DraftContract.contractName.production, UserAgreement.registry_id, data.block_num)
|
||||
}
|
||||
|
||||
const meta: IMetaDocument = await super.getMeta({ title: template.title, ...options })
|
||||
const coop = await super.getCooperative(options.coopname, options.block_num)
|
||||
const vars = await super.getVars(options.coopname, options.block_num)
|
||||
const user = await super.getUser(options.username, options.block_num)
|
||||
const meta: IMetaDocument = await super.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 user = await super.getUser(data.username, data.block_num)
|
||||
const full_name = super.getFullName(user.data)
|
||||
|
||||
const combinedData: UserAgreement.Model = {
|
||||
@@ -40,9 +40,7 @@ export class Factory extends DocFactory<UserAgreement.Action> {
|
||||
|
||||
const translation = template.translations[meta.lang]
|
||||
|
||||
const document: IGeneratedDocument = await super.generatePDF(null, template.context, combinedData, translation, meta)
|
||||
|
||||
await super.saveDraft(document)
|
||||
const document: IGeneratedDocument = await super.generatePDF(null, template.context, combinedData, translation, meta, options?.skip_save)
|
||||
|
||||
return document
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { DraftContract } from 'cooptypes'
|
||||
import { CoopenomicsAgreement } from '../templates'
|
||||
import { DocFactory } from '../Factory'
|
||||
import type { IGeneratedDocument, IMetaDocument, ITemplate } from '../Interfaces'
|
||||
import type { IGeneratedDocument, IGenerationOptions, IMetaDocument, ITemplate } from '../Interfaces'
|
||||
import type { MongoDBConnector } from '../Services/Databazor'
|
||||
|
||||
export { CoopenomicsAgreement as Template } from '../templates'
|
||||
@@ -10,20 +11,20 @@ export class Factory extends DocFactory<CoopenomicsAgreement.Action> {
|
||||
super(storage)
|
||||
}
|
||||
|
||||
async generateDocument(options: CoopenomicsAgreement.Action): Promise<IGeneratedDocument> {
|
||||
async generateDocument(data: CoopenomicsAgreement.Action, options?: IGenerationOptions): Promise<IGeneratedDocument> {
|
||||
let template: ITemplate<CoopenomicsAgreement.Model>
|
||||
|
||||
if (process.env.SOURCE === 'local') {
|
||||
template = CoopenomicsAgreement.Template
|
||||
}
|
||||
else {
|
||||
template = await this.getTemplate(options.coopname, CoopenomicsAgreement.registry_id, options.block_num)
|
||||
template = await this.getTemplate(DraftContract.contractName.production, CoopenomicsAgreement.registry_id, data.block_num)
|
||||
}
|
||||
const meta: IMetaDocument = await super.getMeta({ title: template.title, ...data })
|
||||
|
||||
const meta: IMetaDocument = await super.getMeta({ title: template.title, ...options })
|
||||
const coop = await super.getCooperative(options.coopname, options.block_num)
|
||||
const vars = await super.getVars(options.coopname, options.block_num)
|
||||
const partner = await super.getOrganization(options.coopname, options.block_num)
|
||||
const coop = await super.getCooperative(data.coopname, data.block_num)
|
||||
const vars = await super.getVars(data.coopname, data.block_num)
|
||||
const partner = await super.getOrganization(data.username, data.block_num)
|
||||
|
||||
const combinedData: CoopenomicsAgreement.Model = {
|
||||
meta,
|
||||
@@ -36,9 +37,7 @@ export class Factory extends DocFactory<CoopenomicsAgreement.Action> {
|
||||
|
||||
const translation = template.translations[meta.lang]
|
||||
|
||||
const document: IGeneratedDocument = await super.generatePDF(null, template.context, combinedData, translation, meta)
|
||||
|
||||
await super.saveDraft(document)
|
||||
const document: IGeneratedDocument = await super.generatePDF(null, template.context, combinedData, translation, meta, options?.skip_save)
|
||||
|
||||
return document
|
||||
}
|
||||
|
||||
+10
-10
@@ -2,6 +2,7 @@ import { type Cooperative, DraftContract } from 'cooptypes'
|
||||
import { DocFactory } from '../Factory'
|
||||
import type {
|
||||
IGeneratedDocument,
|
||||
IGenerationOptions,
|
||||
IMetaDocument,
|
||||
ITemplate,
|
||||
} from '../Interfaces'
|
||||
@@ -17,7 +18,8 @@ export class Factory extends DocFactory<DecisionOfParticipantApplication.Action>
|
||||
}
|
||||
|
||||
async generateDocument(
|
||||
options: DecisionOfParticipantApplication.Action,
|
||||
data: DecisionOfParticipantApplication.Action,
|
||||
options?: IGenerationOptions,
|
||||
): Promise<IGeneratedDocument> {
|
||||
let template: ITemplate<DecisionOfParticipantApplication.Model>
|
||||
|
||||
@@ -25,27 +27,27 @@ export class Factory extends DocFactory<DecisionOfParticipantApplication.Action>
|
||||
template = DecisionOfParticipantApplication.Template
|
||||
}
|
||||
else {
|
||||
template = await this.getTemplate(DraftContract.contractName.production, DecisionOfParticipantApplication.registry_id, options.block_num)
|
||||
template = await this.getTemplate(DraftContract.contractName.production, DecisionOfParticipantApplication.registry_id, data.block_num)
|
||||
}
|
||||
|
||||
const user = await super.getUser(options.username, options.block_num)
|
||||
const user = await super.getUser(data.username, data.block_num)
|
||||
|
||||
const userData = {
|
||||
[user.type]: user.data,
|
||||
}
|
||||
|
||||
const coop = await super.getCooperative(options.coopname, options.block_num)
|
||||
const coop = await super.getCooperative(data.coopname, data.block_num)
|
||||
|
||||
// TODO необходимо строго типизировать мета-данные документов друг под друга!
|
||||
const meta: IMetaDocument = await super.getMeta({
|
||||
title: template.title,
|
||||
...options,
|
||||
...data,
|
||||
}) // Генерируем мета-данные
|
||||
|
||||
const decision: Cooperative.Document.IDecisionData = await super.getDecision(
|
||||
coop,
|
||||
options.coopname,
|
||||
options.decision_id,
|
||||
data.coopname,
|
||||
data.decision_id,
|
||||
meta.created_at,
|
||||
)
|
||||
|
||||
@@ -70,11 +72,9 @@ export class Factory extends DocFactory<DecisionOfParticipantApplication.Action>
|
||||
combinedData,
|
||||
translation,
|
||||
meta,
|
||||
options?.skip_save,
|
||||
)
|
||||
|
||||
// сохраняем его в бд
|
||||
await super.saveDraft(document)
|
||||
|
||||
// возвращаем
|
||||
return document
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { DraftContract, SovietContract } from 'cooptypes'
|
||||
import type { ICombinedData, IGeneratedDocument, IMetaDocument, IMetaDocumentPartial, ITemplate, ITranslations, externalDataTypes } from '../Interfaces'
|
||||
import type { MongoDBConnector } from '../Services/Databazor'
|
||||
import { type IVars, Individual, Organization, Vars } from '../Models'
|
||||
import type { IGenerate } from '../Interfaces/Documents'
|
||||
import type { IGenerate, IGenerationOptions } from '../Interfaces/Documents'
|
||||
import { PDFService } from '../Services/Generator'
|
||||
import packageJson from '../../package.json'
|
||||
import { Validator } from '../Services/Validator'
|
||||
@@ -20,7 +20,7 @@ import type { IOrganizationData } from '..'
|
||||
const packageVersion = packageJson.version
|
||||
|
||||
export abstract class DocFactory<T extends IGenerate> {
|
||||
abstract generateDocument(options: T): Promise<IGeneratedDocument>
|
||||
abstract generateDocument(data: T, options?: IGenerationOptions): Promise<IGeneratedDocument>
|
||||
|
||||
public storage: MongoDBConnector
|
||||
|
||||
@@ -216,6 +216,7 @@ export abstract class DocFactory<T extends IGenerate> {
|
||||
vars: ICombinedData,
|
||||
translation: ITranslations,
|
||||
meta: IMetaDocument,
|
||||
skip_save: boolean = false,
|
||||
): Promise<IGeneratedDocument> {
|
||||
const pdfService = new PDFService()
|
||||
const document: IGeneratedDocument = await pdfService.generateDocument(context, vars, translation, meta)
|
||||
@@ -223,6 +224,9 @@ export abstract class DocFactory<T extends IGenerate> {
|
||||
|
||||
document.full_title = `${document.meta.title} - ${full_name} - ${document.meta.created_at}.pdf`
|
||||
|
||||
if (!skip_save)
|
||||
await this.saveDraft(document)
|
||||
|
||||
return document
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -48,3 +48,7 @@ export interface IMetaDocumentPartial extends Partial<IMetaDocument> {
|
||||
}
|
||||
|
||||
export type IGenerate = Cooperative.Document.IGenerate
|
||||
|
||||
export interface IGenerationOptions {
|
||||
skip_save: boolean
|
||||
}
|
||||
|
||||
@@ -36,9 +36,10 @@ export class Cooperative {
|
||||
|
||||
const cooperative_response = await getFetch(`${getEnvVar('SIMPLE_EXPLORER_API')}/get-tables`, new URLSearchParams({
|
||||
filter: JSON.stringify({
|
||||
code: RegistratorContract.contractName.production,
|
||||
scope: RegistratorContract.contractName.production,
|
||||
table: RegistratorContract.Tables.Cooperatives.tableName,
|
||||
'code': RegistratorContract.contractName.production,
|
||||
'scope': RegistratorContract.contractName.production,
|
||||
'table': RegistratorContract.Tables.Cooperatives.tableName,
|
||||
'value.username': username,
|
||||
}),
|
||||
}))
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ class DataService<T extends IDocument> {
|
||||
private collection: Collection<T>
|
||||
private state: Collection
|
||||
|
||||
constructor(private dbConnector: MongoDBConnector, collectionName: string) {
|
||||
this.collection = this.dbConnector.getCollection<T>(collectionName)
|
||||
this.state = this.dbConnector.getCollection('sync')
|
||||
constructor(dbConnector: MongoDBConnector, collectionName: string) {
|
||||
this.collection = dbConnector.getCollection<T>(collectionName)
|
||||
this.state = dbConnector.getCollection('sync')
|
||||
}
|
||||
|
||||
async getOne(filter: Filter<T>): Promise<T | null> {
|
||||
|
||||
@@ -52,6 +52,7 @@ export class MongoDBConnector {
|
||||
if (!this.documents)
|
||||
throw new Error('Database not connected')
|
||||
|
||||
// await this.documents.insertOne({ hash: document.hash, document })
|
||||
await this.documents.updateOne({ hash: document.hash }, { $set: { ...document } }, { upsert: true })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { exec } from 'node:child_process'
|
||||
import puppeteer from 'puppeteer'
|
||||
import { PDFDocument } from 'pdf-lib'
|
||||
import moment from 'moment-timezone'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import type { IGeneratedDocument, IMetaDocument, ITranslations } from '../../Interfaces'
|
||||
import { TemplateEngine } from '../Templator'
|
||||
import { calculateSha256 } from '../../Utils/calculateSHA'
|
||||
import { ArialBase64 } from '../../Fonts/arial'
|
||||
|
||||
const weasyPrintVersion = '62.3'
|
||||
|
||||
export interface IPDFService {
|
||||
generateDocument: (
|
||||
@@ -39,35 +46,55 @@ export class PDFService implements IPDFService {
|
||||
}
|
||||
|
||||
private static async generatePDFBuffer(htmlContent: string): Promise<Uint8Array> {
|
||||
const browser = await puppeteer.launch({
|
||||
args: [
|
||||
'--no-sandbox',
|
||||
'--disable-setuid-sandbox',
|
||||
'--disable-dev-shm-usage',
|
||||
'--disable-gpu',
|
||||
'--disable-extensions',
|
||||
'--disable-software-rasterizer',
|
||||
],
|
||||
timeout: 120000, // увеличиваем общее время ожидания до 2 минут
|
||||
protocolTimeout: 120000, // увеличиваем время ожидания протокола до 2 минут
|
||||
const tempId = uuidv4() // Генерируем уникальный ID для временных файлов
|
||||
const tempDir = path.join(__dirname, 'tmp')
|
||||
|
||||
// Создаем папку tmp, если её нет
|
||||
if (!fs.existsSync(tempDir)) {
|
||||
fs.mkdirSync(tempDir)
|
||||
}
|
||||
|
||||
const tempHtmlPath = path.join(tempDir, `${tempId}.html`)
|
||||
const tempPdfPath = path.join(tempDir, `${tempId}.pdf`)
|
||||
|
||||
// CSS с указанием кодировки и шрифтом для кириллицы
|
||||
const fontStyle = `
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'Arial';
|
||||
src: url(data:font/ttf;base64,${ArialBase64}) format('truetype');
|
||||
}
|
||||
* {
|
||||
font-family: 'Arial', sans-serif;
|
||||
}
|
||||
</style>
|
||||
<meta charset="UTF-8">
|
||||
`
|
||||
|
||||
// Объединяем CSS и HTML-контент
|
||||
const htmlWithFontStyle = fontStyle + htmlContent
|
||||
|
||||
// Сохраняем HTML-контент во временный файл
|
||||
fs.writeFileSync(tempHtmlPath, htmlWithFontStyle, { encoding: 'utf8' })
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
// Запускаем WeasyPrint для конвертации HTML в PDF
|
||||
exec(`SOURCE_DATE_EPOCH=0 weasyprint ${tempHtmlPath} ${tempPdfPath}`, (error) => {
|
||||
if (error) {
|
||||
// Удаляем временные файлы при ошибке
|
||||
fs.unlinkSync(tempHtmlPath)
|
||||
reject(error)
|
||||
}
|
||||
else {
|
||||
// Читаем PDF-файл и возвращаем его как Uint8Array
|
||||
const pdfBuffer = fs.readFileSync(tempPdfPath)
|
||||
// Удаляем временные файлы после завершения
|
||||
fs.unlinkSync(tempHtmlPath)
|
||||
fs.unlinkSync(tempPdfPath)
|
||||
resolve(new Uint8Array(pdfBuffer))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const page = await browser.newPage()
|
||||
|
||||
// const data = await inlineCss(htmlContent, { url: 'about:blank' })
|
||||
// const template = hb.compile(htmlContent, { strict: true })
|
||||
// const result = template({})
|
||||
|
||||
await page.setContent(htmlContent, {
|
||||
waitUntil: 'networkidle0',
|
||||
})
|
||||
|
||||
// Добавьте задержку перед созданием PDF
|
||||
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||
|
||||
const pdfBuffer = await page.pdf({ format: 'A4' })
|
||||
await browser.close()
|
||||
return new Uint8Array(pdfBuffer)
|
||||
}
|
||||
|
||||
private static async updateMetadata(pdfBuffer: ArrayBuffer, meta: IMetaDocument): Promise<Uint8Array> {
|
||||
@@ -76,11 +103,12 @@ export class PDFService implements IPDFService {
|
||||
const pdfDoc = await PDFDocument.load(pdfBuffer)
|
||||
pdfDoc.setTitle(meta.title)
|
||||
pdfDoc.setLanguage(meta.lang)
|
||||
pdfDoc.setProducer(meta.version)
|
||||
pdfDoc.setSubject(`Шаблона документа по реестру №${meta.registry_id}`)
|
||||
pdfDoc.setCreator(meta.generator)
|
||||
pdfDoc.setCreator(`${meta.generator}-${meta.version}`)
|
||||
pdfDoc.setCreationDate(dateWithTimezone)
|
||||
pdfDoc.setModificationDate(dateWithTimezone)
|
||||
return pdfDoc.save()
|
||||
pdfDoc.setProducer(`weasyprint-v${weasyPrintVersion}`)
|
||||
|
||||
return pdfDoc.save({ useObjectStreams: false })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ export * from './Schema'
|
||||
import type { Filter, InsertOneResult, UpdateResult } from 'mongodb'
|
||||
import type { Cooperative as CooperativeModel } from 'cooptypes'
|
||||
import type { IFilterDocuments, IGeneratedDocument, Numbers, externalDataTypes, externalDataTypesArrays, internalFilterTypes } from './Interfaces'
|
||||
import type { IGenerate } from './Interfaces/Documents'
|
||||
import type { IGenerate, IGenerationOptions } from './Interfaces/Documents'
|
||||
import * as Actions from './Actions'
|
||||
|
||||
import { MongoDBConnector } from './Services/Databazor'
|
||||
@@ -30,7 +30,7 @@ export type { CooperativeData as ICooperativeData } from './Models'
|
||||
export interface IGenerator {
|
||||
connect: (mongoUri: string) => Promise<void>
|
||||
disconnect: () => Promise<void>
|
||||
generate: (options: IGenerate) => Promise<IGeneratedDocument>
|
||||
generate: (data: IGenerate, options?: IGenerationOptions) => Promise<IGeneratedDocument>
|
||||
getDocument: (filter: Filter<IFilterDocuments>) => Promise<IGeneratedDocument>
|
||||
|
||||
constructCooperative: (username: string, block_num?: number) => Promise<CooperativeData | null>
|
||||
@@ -62,7 +62,7 @@ export class Generator implements IGenerator {
|
||||
[Actions.RegulationElectronicSignature.Template.registry_id]: new Actions.RegulationElectronicSignature.Factory(this.storage), // 2
|
||||
[Actions.PrivacyPolicy.Template.registry_id]: new Actions.PrivacyPolicy.Factory(this.storage), // 3
|
||||
[Actions.UserAgreement.Template.registry_id]: new Actions.UserAgreement.Factory(this.storage), // 4
|
||||
[Actions.CoopenomicsAgreement.Template.registry_id]: new Actions.UserAgreement.Factory(this.storage), // 50
|
||||
[Actions.CoopenomicsAgreement.Template.registry_id]: new Actions.CoopenomicsAgreement.Factory(this.storage), // 50
|
||||
[Actions.ParticipantApplication.Template.registry_id]: new Actions.ParticipantApplication.Factory(this.storage), // 100
|
||||
[Actions.DecisionOfParticipantApplication.Template.registry_id]: new Actions.DecisionOfParticipantApplication.Factory(this.storage), // 501
|
||||
}
|
||||
@@ -75,14 +75,14 @@ export class Generator implements IGenerator {
|
||||
}
|
||||
|
||||
// Метод генерации документа
|
||||
async generate(options: IGenerate): Promise<IGeneratedDocument> {
|
||||
const factory = this.factories[options.registry_id as Numbers] // Get the factory
|
||||
async generate(data: IGenerate, options?: IGenerationOptions): Promise<IGeneratedDocument> {
|
||||
const factory = this.factories[data.registry_id as Numbers] // Get the factory
|
||||
|
||||
if (!factory)
|
||||
throw new Error(`Фабрика для документа #${options.registry_id} не найдена.`)
|
||||
throw new Error(`Фабрика для документа #${data.registry_id} не найдена.`)
|
||||
|
||||
// синтезируем документ
|
||||
return await factory.generateDocument(options)
|
||||
return await factory.generateDocument(data, options)
|
||||
}
|
||||
|
||||
async getDocument(filter: Filter<IFilterDocuments>): Promise<IGeneratedDocument> {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import path from 'node:path'
|
||||
import { beforeAll, beforeEach, describe, expect, it } from 'vitest'
|
||||
import type { RegistratorContract, SovietContract } from 'cooptypes'
|
||||
import { Generator } from '../src'
|
||||
@@ -12,14 +13,13 @@ const coopname = 'voskhod'
|
||||
|
||||
import type { ExternalEntrepreneurData, ExternalIndividualData, ExternalOrganizationData, IVars } from '../src/Models'
|
||||
import type { PaymentData } from '../src/Models/PaymentMethod'
|
||||
import { CoopenomicsAgreement, PrivacyPolicy, Registry, RegulationElectronicSignature, UserAgreement, WalletAgreement } from '../src/templates'
|
||||
import type { CoopenomicsAgreement } from '../src/templates'
|
||||
import { PrivacyPolicy, Registry, RegulationElectronicSignature, UserAgreement, WalletAgreement } from '../src/templates'
|
||||
import { signatureExample } from './signatureExample'
|
||||
|
||||
// eslint-disable-next-line ts/no-require-imports
|
||||
const fs = require('node:fs').promises
|
||||
|
||||
import path from 'node:path'
|
||||
|
||||
async function deleteAllFiles(folderPath: string) {
|
||||
try {
|
||||
const absolutePath = path.resolve(folderPath)
|
||||
@@ -551,49 +551,6 @@ describe('тест генератора документов', async () => {
|
||||
expect(hash1).toEqual(hash2)
|
||||
})
|
||||
|
||||
it('генерируем согласие с пользовательским соглашением платформы "Кооперативная Экономика"', async () => {
|
||||
const params: CoopenomicsAgreement.Action = {
|
||||
coopname: 'voskhod',
|
||||
username: 'ant',
|
||||
lang: 'ru',
|
||||
registry_id: CoopenomicsAgreement.registry_id,
|
||||
protocol_number: '01-01-2024',
|
||||
protocol_day_month_year: '1 января 2024 г.',
|
||||
}
|
||||
|
||||
const document: IGeneratedDocument = await generator.generate(params)
|
||||
|
||||
const filename1 = `${document.meta.title}-${document.meta.username}.pdf`
|
||||
await saveBufferToDisk(document.binary, filename1)
|
||||
|
||||
const regenerated_document: IGeneratedDocument = await generator.generate({
|
||||
...document.meta,
|
||||
})
|
||||
|
||||
const filename2 = `regenerated-${document.meta.title}-${document.meta.username}.pdf`
|
||||
await saveBufferToDisk(regenerated_document.binary, filename2)
|
||||
|
||||
expect(document.meta).toEqual(regenerated_document.meta)
|
||||
expect(document.hash).toEqual(regenerated_document.hash)
|
||||
|
||||
const document_from_disk1 = await loadBufferFromDisk(filename1)
|
||||
const document_from_disk2 = await loadBufferFromDisk(filename2)
|
||||
|
||||
const hash1 = calculateSha256(document_from_disk1)
|
||||
const hash2 = calculateSha256(document_from_disk2)
|
||||
|
||||
const getted_document = await generator.getDocument({ hash: regenerated_document.hash })
|
||||
|
||||
expect(getted_document).toBeDefined()
|
||||
expect(getted_document.hash).toEqual(document.hash)
|
||||
|
||||
console.log('hash1: ', hash1)
|
||||
console.log('hash2: ', hash2)
|
||||
console.log(document.meta)
|
||||
|
||||
expect(hash1).toEqual(hash2)
|
||||
})
|
||||
|
||||
it('генерируем заявление на вступление физического лица', async () => {
|
||||
const document: IGeneratedDocument = await generator.generate({
|
||||
registry_id: 100,
|
||||
@@ -823,4 +780,137 @@ describe('тест генератора документов', async () => {
|
||||
const filename3 = `${decision_document.meta.title}-${decision_document.meta.username}.pdf`
|
||||
await saveBufferToDisk(decision_document.binary, filename3)
|
||||
})
|
||||
|
||||
it('#1', async () => {
|
||||
const voskhodData: ExternalOrganizationData = {
|
||||
username: 'voskhod',
|
||||
type: 'coop',
|
||||
is_cooperative: true,
|
||||
short_name: '"ПК Восход"',
|
||||
full_name: 'Потребительский Кооператив "ВОСХОД"',
|
||||
represented_by: {
|
||||
first_name: 'Алексей',
|
||||
last_name: 'Муравьев',
|
||||
middle_name: 'Николаевич',
|
||||
position: 'Председатель',
|
||||
based_on: 'Решение общего собрания №1',
|
||||
},
|
||||
country: 'Russia',
|
||||
city: 'Москва',
|
||||
full_address: '117593 г. Москва, муниципальный округ Ясенево, проезд Соловьиный, дом 1, помещение 1/1',
|
||||
email: 'copenomics@yandex.ru',
|
||||
phone: '+71234567890',
|
||||
details: {
|
||||
inn: '9728130611',
|
||||
ogrn: '1247700283346',
|
||||
kpp: '772801001',
|
||||
},
|
||||
bank_account: {
|
||||
account_number: '40703810038000110117',
|
||||
currency: 'RUB',
|
||||
card_number: '',
|
||||
bank_name: 'ПАО Сбербанк',
|
||||
details: {
|
||||
bik: '044525225',
|
||||
corr: '30101810400000000225',
|
||||
kpp: '773643001',
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
await generator.save('organization', voskhodData)
|
||||
|
||||
const vars: IVars = {
|
||||
coopname: 'voskhod',
|
||||
full_abbr: 'потребительский кооператив',
|
||||
full_abbr_genitive: 'потребительского кооператива',
|
||||
full_abbr_dative: 'потребительскому кооперативу',
|
||||
short_abbr: 'ПК',
|
||||
website: 'цифровой-кооператив.рф',
|
||||
name: 'Восход',
|
||||
confidential_link: 'coopenomics.world/privacy',
|
||||
confidential_email: 'privacy@coopenomics.world',
|
||||
contact_email: 'contact@coopenomics.world',
|
||||
passport_request: 'no',
|
||||
wallet_agreement: {
|
||||
protocol_number: '10-04-2024',
|
||||
protocol_day_month_year: '10 апреля 2024 г.',
|
||||
},
|
||||
signature_agreement: {
|
||||
protocol_number: '10-04-2024',
|
||||
protocol_day_month_year: '10 апреля 2024 г.',
|
||||
},
|
||||
privacy_agreement: {
|
||||
protocol_number: '10-04-2024',
|
||||
protocol_day_month_year: '10 апреля 2024 г.',
|
||||
},
|
||||
user_agreement: {
|
||||
protocol_number: '10-04-2024',
|
||||
protocol_day_month_year: '10 апреля 2024 г.',
|
||||
},
|
||||
participant_application: {
|
||||
protocol_number: '10-04-2024',
|
||||
protocol_day_month_year: '10 апреля 2024 г.',
|
||||
},
|
||||
coopenomics_agreement: {
|
||||
protocol_number: '10-04-2024',
|
||||
protocol_day_month_year: '10 апреля 2024 г.',
|
||||
},
|
||||
}
|
||||
|
||||
await generator.save('vars', vars)
|
||||
|
||||
const coopname = 'test'
|
||||
|
||||
const organizationData: ExternalOrganizationData = {
|
||||
username: coopname,
|
||||
type: 'coop',
|
||||
is_cooperative: true,
|
||||
short_name: 'Ромашка',
|
||||
full_name: 'Ромашка',
|
||||
represented_by: {
|
||||
first_name: 'Иван',
|
||||
last_name: 'Иванов',
|
||||
middle_name: 'Иванович',
|
||||
position: 'Директор',
|
||||
based_on: 'решения собрания учредителей №22',
|
||||
},
|
||||
country: 'Russia',
|
||||
city: 'Moscow',
|
||||
full_address: 'г. Москва, ул. Арбат д. 22, офис 306',
|
||||
email: 'contact@exampleorg.com',
|
||||
phone: '+71234567890',
|
||||
details: {
|
||||
kpp: '123456789',
|
||||
inn: '0987654321',
|
||||
ogrn: '0987654321098',
|
||||
},
|
||||
bank_account: {
|
||||
account_number: '40817810099910004312',
|
||||
currency: 'RUB',
|
||||
card_number: '0987654321098765',
|
||||
bank_name: 'ПАО СБЕРБАНК',
|
||||
details: {
|
||||
bik: '098765432',
|
||||
corr: '30101810400000000225',
|
||||
kpp: '098765432',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
await generator.save('organization', organizationData)
|
||||
|
||||
const act: CoopenomicsAgreement.Action = {
|
||||
registry_id: 50,
|
||||
coopname: 'voskhod',
|
||||
username: 'test',
|
||||
lang: 'ru',
|
||||
}
|
||||
|
||||
const document: IGeneratedDocument = await generator.generate(act)
|
||||
|
||||
const filename1 = `Соглашение_о_подключении_${coopname}.pdf`
|
||||
await saveBufferToDisk(document.binary, filename1)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -3,6 +3,42 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.1.3](https://github.com/coopenomics/cooptypes/compare/v2.1.2-alpha.10...v2.1.3) (2024-10-26)
|
||||
|
||||
|
||||
|
||||
## [2.1.2](https://github.com/coopenomics/cooptypes/compare/v2.1.1...v2.1.2) (2024-10-19)
|
||||
|
||||
**Note:** Version bump only for package cooptypes
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.1.2](https://github.com/coopenomics/cooptypes/compare/v2.1.1...v2.1.2) (2024-10-19)
|
||||
|
||||
**Note:** Version bump only for package cooptypes
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [2.1.0](https://github.com/coopenomics/cooptypes/compare/v2.0.10-alpha.3...v2.1.0) (2024-10-13)
|
||||
|
||||
**Note:** Version bump only for package cooptypes
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.0.8](https://github.com/coopenomics/cooptypes/compare/v2.0.7...v2.0.8) (2024-10-09)
|
||||
|
||||
**Note:** Version bump only for package cooptypes
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.0.2](https://github.com/coopenomics/cooptypes/compare/v2.0.2-alpha.1...v2.0.2) (2024-09-29)
|
||||
|
||||
**Note:** Version bump only for package cooptypes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "cooptypes",
|
||||
"type": "module",
|
||||
"version": "2.0.2",
|
||||
"version": "2.1.4-alpha.0",
|
||||
"description": "_description_",
|
||||
"author": "Alex Ant <dacom.dark.sun@gmail.com>",
|
||||
"license": "MIT",
|
||||
@@ -65,5 +65,5 @@
|
||||
"vite": "^5.2.11",
|
||||
"vitest": "^1.5.3"
|
||||
},
|
||||
"gitHead": "5ba05409c4a208ba2004c3f0d1f14e993b5f63ae"
|
||||
"gitHead": "7b59ea4b96991ed06abdc92e6d7835632845e3a5"
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ export const authorizations = [{ permissions: [Permissions.active], actor: Contr
|
||||
/**
|
||||
* Имя действия
|
||||
*/
|
||||
|
||||
export const actionName = 'init'
|
||||
/**
|
||||
* @interface
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import * as Permissions from '../../../common/permissions'
|
||||
import * as ContractNames from '../../../common/names'
|
||||
import type * as Registrator from '../../../interfaces/registrator'
|
||||
|
||||
/**
|
||||
* Требуется подпись контракта {@link ContractNames._soviet | совета}, которая поставляется автоматически в момент исполнения решения совета о приёме нового пайщика.
|
||||
*/
|
||||
export const authorizations = [{ permissions: [Permissions.active], actor: ContractNames._soviet }] as const
|
||||
|
||||
/**
|
||||
* Имя действия
|
||||
*/
|
||||
export const actionName = 'confirmreg'
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
export type IConfirmJoin = Registrator.IConfirmreg
|
||||
@@ -38,12 +38,6 @@ export * as ChangeKey from './changeKey'
|
||||
*/
|
||||
export * as JoinCooperative from './joinCooperative'
|
||||
|
||||
/**
|
||||
* Действие, которое вызывается контрактом _soviet для подтверждения заявки на вступление в кооператив после принятия советом решения.
|
||||
* @private
|
||||
*/
|
||||
export * as ConfirmJoin from './confirmJoin'
|
||||
|
||||
/**
|
||||
* Действие, которые вызывается системным контрактом для инициализации.
|
||||
* @private
|
||||
|
||||
@@ -121,3 +121,7 @@ export interface IDecisionData {
|
||||
votes_abstained: number
|
||||
voters_percent: number
|
||||
}
|
||||
|
||||
export interface IGenerationOptions {
|
||||
skip_save: boolean
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ export interface Model {
|
||||
|
||||
export const title = 'Согласие с условиями ЦПП «ЦИФРОВОЙ КОШЕЛЕК»'
|
||||
export const description = 'Форма присоединения к целевой потребительской программе «ЦИФРОВОЙ КОШЕЛЕК»'
|
||||
export const context = '<div class="digital-document"><div style="text-align: right; margin:">\n<p style="margin: 0px !important">{% trans \'APPROVED\' %}</p>\n<p style="margin: 0px !important">{% trans \'protocol\' %} {{ vars.wallet_agreement.protocol_number }}</p>\n<p style="margin: 0px !important">{{ coop.full_name }} </p>\n<p style="margin: 0px !important">{% trans \'from\' %} {{ vars.wallet_agreement.protocol_day_month_year }}</p>\n</div>\n<div style="text-align: center">\n<h1 class="header"> {% trans \'PROVISION\' %}</h1>\n{% trans \'consumer_program_title\' %}\n</div>\n<p>{% trans \'consumer_program_provision_intro\' %} {{ coop.short_name }} {% trans \'cooperative_hereto\' %}</p>\n<p>{% trans \'legal_basis\' %}</p>\n<p>{% trans \'program_duration\' %}</p>\n<p>{% trans \'program_provision_status\' %}</p>\n<div style="text-align: center">\n<h3>{% trans \'terms_program\' %}</h3>\n</div>\n<p>{% trans \'consumer_program_terms\' %}</p>\n<div style="text-align: center">\n<h3>{% trans \'program_goals\' %}</h3>\n</div>\n<p>{% trans \'goal_efficiency\' %}</p>\n<p>{% trans \'goal_transparency\' %}</p>\n<div style="text-align: center"><h3>{% trans \'program_participation_procedure\' %}</h3></div>\n<p>{% trans \'program_participation_terms\' %}</p>\n<p>{% trans \'offer_acceptance\' %}</p>\n<p>{% trans \'procedure_participation\' %}</p>\n<div style="text-align: center"><h3>{% trans \'user_cabinet\' %}</h3></div>\n<p>{% trans \'site_access\' %}</p>\n<p>{% trans \'unique_code\' %}</p>\n<p>{% trans \'digital_signature\' %}</p>\n<p>{% trans \'identification\' %}</p>\n<p>{% trans \'information_security\' %}</p>\n<div style="text-align: center"><h3>{% trans \'program_interaction_mechanism\' %}</h3></div>\n<p>{% trans \'program_share_contribution\' %}</p>\n<p>{% trans \'share_contribution_procedure\' %}</p>\n<p>{% trans \'fund_management\' %}</p>\n<p>{% trans \'application_to_council\' %}</p>\n<p>{% trans \'share_contribution_return\' %}</p>\n<p>{% trans \'claim_return\' %}</p>\n<p>{% trans \'payment_confirmation\' %}</p>\n<p>{% trans \'novation_agreement\' %}</p>\n<p>{% trans \'novation_agreement_terms\' %}</p>\n<div style="text-align: center"><h3>{% trans \'program_rights_obligations\' %}</h3></div>\n<p>{% trans \'participant_rights\' %}</p>\n<p>{% trans \'participant_obligations\' %}</p>\n<p>{% trans \'cooperative_obligations\' %}</p>\n<p>{% trans \'cooperative_rights\' %}</p>\n<div style="text-align: center"><h3>{% trans \'force_majeure\' %}</h3></div>\n<p>{% trans \'legal_changes\' %}</p>\n<p>{% trans \'program_modification\' %}</p>\n<p>{% trans \'force_majeure_cases\' %}</p>\n<div style="text-align: center"><h3>{% trans \'program_communication\' %}</h3></div>\n<p>{% trans \'communication_channels\' %}</p>\n<p>{% trans \'alternative_methods\' %}</p>\n<p>{% trans \'program_additional_conditions\' %}</p>\n<p>{% trans \'governing_documents\' %}</p>\n<p>{% trans \'changes_amendments\' %}</p>\n<div class="digital-signature">\n{% trans \'acceptance_agreement\' %}</div></div>\n\n<style>\n.digital-document {\npadding: 20px;\n}\n</style>'
|
||||
export const context = '<style>* { font-family: Arial, sans-serif;}</style><div class="digital-document"><div style="text-align: right; margin:">\n<p style="margin: 0px !important">{% trans \'APPROVED\' %}</p>\n<p style="margin: 0px !important">{% trans \'protocol\' %} {{ vars.wallet_agreement.protocol_number }}</p>\n<p style="margin: 0px !important">{{ coop.full_name }} </p>\n<p style="margin: 0px !important">{% trans \'from\' %} {{ vars.wallet_agreement.protocol_day_month_year }}</p>\n</div>\n<div style="text-align: center">\n<h1 class="header"> {% trans \'PROVISION\' %}</h1>\n<p class="subheader"> {% trans \'consumer_program_title\' %}</p>\n</div>\n<p>{% trans \'consumer_program_provision_intro\' %} {{ coop.short_name }} {% trans \'cooperative_hereto\' %}</p>\n<p>{% trans \'legal_basis\' %}</p>\n<p>{% trans \'program_duration\' %}</p>\n<p>{% trans \'program_provision_status\' %}</p>\n<div style="text-align: center">\n<h3>{% trans \'terms_program\' %}</h3>\n</div>\n<p>{% trans \'consumer_program_terms\' %}</p>\n<div style="text-align: center">\n<h3>{% trans \'program_goals\' %}</h3>\n</div>\n<p>{% trans \'goal_efficiency\' %}</p>\n<p>{% trans \'goal_transparency\' %}</p>\n<div style="text-align: center"><h3>{% trans \'program_participation_procedure\' %}</h3></div>\n<p>{% trans \'program_participation_terms\' %}</p>\n<p>{% trans \'offer_acceptance\' %}</p>\n<p>{% trans \'procedure_participation\' %}</p>\n<div style="text-align: center"><h3>{% trans \'user_cabinet\' %}</h3></div>\n<p>{% trans \'site_access\' %}</p>\n<p>{% trans \'unique_code\' %}</p>\n<p>{% trans \'digital_signature\' %}</p>\n<p>{% trans \'identification\' %}</p>\n<p>{% trans \'information_security\' %}</p>\n<div style="text-align: center"><h3>{% trans \'program_interaction_mechanism\' %}</h3></div>\n<p>{% trans \'program_share_contribution\' %}</p>\n<p>{% trans \'share_contribution_procedure\' %}</p>\n<p>{% trans \'fund_management\' %}</p>\n<p>{% trans \'application_to_council\' %}</p>\n<p>{% trans \'share_contribution_return\' %}</p>\n<p>{% trans \'claim_return\' %}</p>\n<p>{% trans \'payment_confirmation\' %}</p>\n<p>{% trans \'novation_agreement\' %}</p>\n<p>{% trans \'novation_agreement_terms\' %}</p>\n<div style="text-align: center"><h3>{% trans \'program_rights_obligations\' %}</h3></div>\n<p>{% trans \'participant_rights\' %}</p>\n<p>{% trans \'participant_obligations\' %}</p>\n<p>{% trans \'cooperative_obligations\' %}</p>\n<p>{% trans \'cooperative_rights\' %}</p>\n<div style="text-align: center"><h3>{% trans \'force_majeure\' %}</h3></div>\n<p>{% trans \'legal_changes\' %}</p>\n<p>{% trans \'program_modification\' %}</p>\n<p>{% trans \'force_majeure_cases\' %}</p>\n<div style="text-align: center"><h3>{% trans \'program_communication\' %}</h3></div>\n<p>{% trans \'communication_channels\' %}</p>\n<p>{% trans \'alternative_methods\' %}</p>\n<p>{% trans \'program_additional_conditions\' %}</p>\n<p>{% trans \'governing_documents\' %}</p>\n<p>{% trans \'changes_amendments\' %}</p>\n<div class="digital-signature">\n{% trans \'acceptance_agreement\' %}</div></div>\n\n<style>\n.digital-document {\npadding: 20px;\nwhite-space: pre-wrap;\n}\n.subheader{\npadding-bottom: 20px;\n}\n</style>'
|
||||
|
||||
export const translations = {
|
||||
ru: {
|
||||
|
||||
File diff suppressed because one or more lines are too long
+3
-2
@@ -18,14 +18,14 @@ export interface Model {
|
||||
export const title = 'Согласие с условиями положения о простой электронной подписи'
|
||||
export const description = 'Форма согласия с условиями положения о простой электронной подписи'
|
||||
|
||||
export const context = '<div class="digital-document"><div style="text-align: right; margin:">\n<p style="margin: 0px !important">{% trans \'APPROVED\' %}</p>\n<p style="margin: 0px !important">{% trans \'protocol\' %} {{ vars.signature_agreement.protocol_number }}</p>\n<p style="margin: 0px !important">{{ coop.full_name }} </p>\n<p style="margin: 0px !important">{% trans \'from\' %} {{ vars.signature_agreement.protocol_day_month_year }}</p>\n</div>\n<div style="text-align: center">\n<h1 class="header"> {% trans \'PROVISION\' %} {{vars.full_abbr_genitive}} "{{vars.name}}"</h1>\n</div>\n<div style="text-align: left">\n<h3>{% trans \'regulation_pep_title_1\' %}</h3>\n</div>\n<p> {% trans \'regulation_text_1_1\' %} {{vars.website}}. {% trans \'regulation_text_1_2\' %} {{vars.full_abbr_genitive}} "{{vars.name}}" {% trans \'regulation_text_1_4\' %} {{vars.short_abbr}} "{{vars.name}}" {% trans \'regulation_text_1_6\' %} {{vars.short_abbr}} "{{vars.name}}" {% trans \'regulation_text_1_8\' %} {{vars.short_abbr}} "{{vars.name}}".{% trans \'regulation_text_1_10\' %} </p>\n<div style="text-align: left">\n<h3>{% trans \'regulation_pep_title_2\' %}</h3>\n</div>\n<p>{% trans \'regulation_text_2_1\' %} {{vars.short_abbr}} "{{vars.name}}", {% trans \'regulation_text_2_3\' %}</p>\n<div style="text-align: left">\n<h3>{% trans \'regulation_pep_title_3\' %} </h3>\n</div>\n<p>{% trans \'regulation_text_3_1\' %} {{vars.website}} {% trans \'regulation_text_3_2\' %}</p>\n<div style="text-align: left">\n<h3>{% trans \'regulation_pep_title_4\' %}</h3>\n</div>\n<p>{% trans \'regulation_pep_text_4\' %} </p>\n<div style="text-align: left">\n<h3>{% trans \'regulation_pep_title_5\' %}</h3>\n</div>\n<p>{% trans \'regulation_pep_text_5\' %} </p>\n<div class="signature">\n{% trans \'acceptance_agreement\' %}</div>\n<div style="text-align: center">\n<h3 class="header"> {% trans \'PRIL_PROVISION\' %} </h3>\n</div>\n<p>{% trans \'PRIL_PROVISION_TEXT\' %}</p>\n</div>\n<style>.digital-document {padding: 10px;}</style>'
|
||||
export const context = '<div class="digital-document"><div style="text-align: right; margin:">\n<p style="margin: 0px !important">{% trans \'APPROVED\' %}</p>\n<p style="margin: 0px !important">{% trans \'protocol\' %} {{ vars.signature_agreement.protocol_number }}</p>\n<p style="margin: 0px !important">{{ coop.full_name }} </p>\n<p style="margin: 0px !important">{% trans \'from\' %} {{ vars.signature_agreement.protocol_day_month_year }}</p>\n</div>\n<div style="text-align: center">\n<h1 class="header"> {% trans \'PROVISION\' %}</h1>\n<p class="subheader">{% trans \'PROVISION2\' %} {{vars.full_abbr_genitive}} "{{vars.name}}"</p>\n</div>\n<div style="text-align: left">\n<h3>{% trans \'regulation_pep_title_1\' %}</h3>\n</div>\n<p> {% trans \'regulation_text_1_1\' %} {{vars.website}}. {% trans \'regulation_text_1_2\' %} {{vars.full_abbr_genitive}} "{{vars.name}}" {% trans \'regulation_text_1_4\' %} {{vars.short_abbr}} "{{vars.name}}" {% trans \'regulation_text_1_6\' %} {{vars.short_abbr}} "{{vars.name}}" {% trans \'regulation_text_1_8\' %} {{vars.short_abbr}} "{{vars.name}}".{% trans \'regulation_text_1_10\' %} </p>\n<div style="text-align: left">\n<h3>{% trans \'regulation_pep_title_2\' %}</h3>\n</div>\n<p>{% trans \'regulation_text_2_1\' %} {{vars.short_abbr}} "{{vars.name}}", {% trans \'regulation_text_2_3\' %}</p>\n<div style="text-align: left">\n<h3>{% trans \'regulation_pep_title_3\' %} </h3>\n</div>\n<p>{% trans \'regulation_text_3_1\' %} {{vars.website}} {% trans \'regulation_text_3_2\' %}</p>\n<div style="text-align: left">\n<h3>{% trans \'regulation_pep_title_4\' %}</h3>\n</div>\n<p>{% trans \'regulation_pep_text_4\' %} </p>\n<div style="text-align: left">\n<h3>{% trans \'regulation_pep_title_5\' %}</h3>\n</div>\n<p>{% trans \'regulation_pep_text_5\' %} </p>\n<div class="signature">\n{% trans \'acceptance_agreement\' %}</div>\n<div style="text-align: center">\n<h1 class="header"> {% trans \'PRIL_PROVISION\' %} </h1>\n</div>\n<p>{% trans \'PRIL_PROVISION_TEXT\' %}</p>\n</div>\n<style>.digital-document {\npadding: 20px;\nwhite-space: pre-wrap;\n}</style>'
|
||||
|
||||
export const translations = {
|
||||
ru: {
|
||||
APPROVED: 'УТВЕРЖДЕНО',
|
||||
protocol: 'Протоколом Совета № СС',
|
||||
from: 'от',
|
||||
PROVISION: 'ПОЛОЖЕНИЕ\nо порядке и правилах использования простой электронной подписи \n',
|
||||
PROVISION: 'ПОЛОЖЕНИЕ',
|
||||
regulation_pep_title_1: '1. ТЕРМИНЫ И ОПРЕДЕЛЕНИЯ',
|
||||
regulation_text_1_1: '1.1. «Правила» - настоящие правила об использовании простой электронной подписи.\n1.2. «Электронный документ» (ЭД) – документированная информация Общества, представленная в электронно-цифровой форме, то есть в виде, пригодном для восприятия пайщиком Общества с использованием электронных вычислительных машин, а также для передачи по информационно –телекоммуникационным сетям или обработки в информационных системах.\n1.3. «Электронная подпись» (ЭП) – информация в электронной форме, которая присоединена к другой информации в электронной форме (подписываемой информации) или иным образом связана с такой информацией и которая используется для однозначного определения лица, подписывающего информацию.\n1.4. «Простая электронная подпись» (ПЭП) – буквенно-цифровую строка, которая зашифрована стандартным алгоритмом, описанным в Приложении №1 к настоящему Положению. Электронная подпись позволяет идентифицировать пользователя, а также подписывать документы в электронном виде. \n1.5. «Электронный документооборот» (ЭД) – процесс обмена электронными документами, подписанными ПЭП, между Обществом и пайщиками Общества.\n1.6. «Интернет-Cайт» (Сайт) – сайт Общества в сети Интернет, доступ к которому осуществляется по адресу: ',
|
||||
regulation_text_1_2: '\n1.7. «Личный кабинет» (ЛК) - поддерживаемая Сервисом информационная подсистема Сайта, представляющая собой личную страницу Пользователя, позволяющая Сервису и Пользователю осуществлять индивидуальное дистанционное взаимодействие в электронной форме. Доступ к информации в ЛК происходит с помощью Логина и пароля, известного только Пользователю.\n1.8. «Пользователь» - пайщик ',
|
||||
@@ -46,6 +46,7 @@ export const translations = {
|
||||
acceptance_agreement: 'СОГЛАСЕН',
|
||||
PRIL_PROVISION: 'ПРИЛОЖЕНИЕ № 1 к Положению\nТехнические характеристики электронной подписи',
|
||||
PRIL_PROVISION_TEXT: 'Электронная подпись генерируется Пользователем в приложении и является и является математическим двухкаскадным прокурсором секретного ключа, для получения которого используется одна из эллиптических кривых - secp256k1 или p256. \n\nПриватный ключ генерируется случайным образом криптографической библиотекой на стороне клиента без передачи на сервер и конвертируется в массив байтов (Uint8Array) длиной 32 байта для дальнейшего использования. \n\nДля подписания документов используется алгоритм ECDSA (Elliptic Curve Digital Signature Algorithm) с SHA-256 в качестве хэш-функции. Процесс подписания включает:\n1.\tХэширование документа с использованием алгоритма SHA-256.\n2.\tПрименение приватного ключа пользователя для создания цифровой подписи на основе алгоритма эллиптической кривой ECDSA.\nВерификация подписи проводится с использованием публичного ключа, который генерируется одновременно с приватным и передается на сервер. Алгоритм верификации цифровой подписи включает:\n1.\tПолучение публичного ключа из подписи.\n2.\tСравнение результата с ранее сохраненным публичным ключом , чтобы подтвердить подлинность подписи.\nЭлектронная подпись соответствует стандартам безопасности и криптографическим требованиям, обеспечивая высокую степень защиты данных. Процесс полностью совместим с международными стандартами и большинством публичных сетей.\n',
|
||||
PROVISION2: 'о порядке и правилах использования простой электронной подписи ',
|
||||
},
|
||||
|
||||
// ... другие переводы
|
||||
|
||||
@@ -18,7 +18,7 @@ export interface Model {
|
||||
export const title = 'Согласие с условиями политики обработки конфиденциальных данных'
|
||||
export const description = 'Форма согласия с условиями политики обработки конфиденциальных данных'
|
||||
|
||||
export const context = '<div class="digital-document"><div style="text-align: right; margin:">\n<p style="margin: 0px !important">{% trans \'APPROVED\' %}</p>\n<p style="margin: 0px !important">{% trans \'protocol\' %} {{ vars.privacy_agreement.protocol_number }}</p>\n<p style="margin: 0px !important">{{ coop.full_name }} </p>\n<p style="margin: 0px !important">{% trans \'from\' %} {{ vars.privacy_agreement.protocol_day_month_year }}</p>\n</div>\n<div style="text-align: center">\n<h1 class="header"> {% trans \'PRIVACY_POLICY\' %}</h1>\n</div>\n<div style="text-align: left">\n<b>{% trans \'privacy_policy_title_1\' %}</b>\n</div>\n<p> {% trans \'privacy_policy_text_1_1\' %} {{vars.full_abbr_dative}} {% trans \'privacy_policy_text_1_2\' %} "{{ vars.name}}" {{vars.website}}.</p>\n<div style="text-align: left">\n<b>{% trans \'privacy_policy_title_2\' %}</b>\n</div>\n<p>{% trans \'privacy_policy_text_2_1\' %} {{vars.website}}; {% trans \'privacy_policy_text_2_2\' %} {{vars.website}}; {% trans \'privacy_policy_text_2_3\' %} {{vars.website}}; {% trans \'privacy_policy_text_2_4\' %}</p>\n<div style="text-align: left">\n<b>{% trans \'privacy_policy_title_3_1\' %} {{vars.short_abbr}} "{{vars.name}}":</b>\n</div>\n<p>{% trans \'privacy_policy_text_3\' %}</p>\n<div style="text-align: left">\n<b>{% trans \'privacy_policy_title_4\' %}</b>\n</div>\n<p>{% trans \'privacy_policy_text_4_1\' %} {{vars.short_abbr}} "{{vars.name}}"{% trans \'privacy_policy_text_4_2\' %} {{vars.confidential_email}} {% trans \'privacy_policy_text_4_3\' %}</p>\n<div style="text-align: left">\n<b>{% trans \'privacy_policy_title_5\' %}</b>\n</div>\n<p>{% trans \'privacy_policy_text_5_1\' %} {{vars.website}} {% trans \'privacy_policy_text_5_2\' %} </p>\n<div style="text-align: left">\n<b>{% trans \'privacy_policy_title_6\' %}</b>\n</div>\n<p>{% trans \'privacy_policy_text_6_1\' %} {{vars.confidential_email}} {% trans \'privacy_policy_text_6_2\' %} {{vars.confidential_email}} {% trans \'privacy_policy_text_6_3\' %}</p>\n<div style="text-align: left">\n<b>{% trans \'privacy_policy_title_7\' %}</b>\n</div>\n<p>{% trans \'privacy_policy_text_7\' %}</p>\n<div style="text-align: left">\n<b>{% trans \'privacy_policy_title_8\' %}</b>\n</div>\n<p>{% trans \'privacy_policy_text_8_1\' %} {{vars.confidential_email}}. {% trans \'privacy_policy_text_8_2\' %} {{vars.confidential_link}}.</p>\n</div>\n<style>\n.digital-document {\npadding: 20px;\n};\n</style>\n\n'
|
||||
export const context = '<div class="digital-document"><div style="text-align: right; margin:">\n<p style="margin: 0px !important">{% trans \'APPROVED\' %}</p>\n<p style="margin: 0px !important">{% trans \'protocol\' %} {{ vars.privacy_agreement.protocol_number }}</p>\n<p style="margin: 0px !important">{{ coop.full_name }} </p>\n<p style="margin: 0px !important">{% trans \'from\' %} {{ vars.privacy_agreement.protocol_day_month_year }}</p>\n</div>\n<div style="text-align: center">\n<h1 class="header"> {% trans \'PRIVACY_POLICY\' %}</h1>\n</div>\n<div style="text-align: left">\n<b>{% trans \'privacy_policy_title_1\' %}</b>\n</div>\n<p> {% trans \'privacy_policy_text_1_1\' %} {{vars.full_abbr_dative}} {% trans \'privacy_policy_text_1_2\' %} "{{ vars.name}}" {{vars.website}}.</p>\n<div style="text-align: left">\n<b>{% trans \'privacy_policy_title_2\' %}</b>\n</div>\n<p>{% trans \'privacy_policy_text_2_1\' %} {{vars.website}}; {% trans \'privacy_policy_text_2_2\' %} {{vars.website}}; {% trans \'privacy_policy_text_2_3\' %} {{vars.website}}; {% trans \'privacy_policy_text_2_4\' %}</p>\n<div style="text-align: left">\n<b>{% trans \'privacy_policy_title_3_1\' %} {{vars.short_abbr}} "{{vars.name}}":</b>\n</div>\n<p>{% trans \'privacy_policy_text_3\' %}</p>\n<div style="text-align: left">\n<b>{% trans \'privacy_policy_title_4\' %}</b>\n</div>\n<p>{% trans \'privacy_policy_text_4_1\' %} {{vars.short_abbr}} "{{vars.name}}"{% trans \'privacy_policy_text_4_2\' %} {{vars.confidential_email}} {% trans \'privacy_policy_text_4_3\' %}</p>\n<div style="text-align: left">\n<b>{% trans \'privacy_policy_title_5\' %}</b>\n</div>\n<p>{% trans \'privacy_policy_text_5_1\' %} {{vars.website}} {% trans \'privacy_policy_text_5_2\' %} </p>\n<div style="text-align: left">\n<b>{% trans \'privacy_policy_title_6\' %}</b>\n</div>\n<p>{% trans \'privacy_policy_text_6_1\' %} {{vars.confidential_email}} {% trans \'privacy_policy_text_6_2\' %} {{vars.confidential_email}} {% trans \'privacy_policy_text_6_3\' %}</p>\n<div style="text-align: left">\n<b>{% trans \'privacy_policy_title_7\' %}</b>\n</div>\n<p>{% trans \'privacy_policy_text_7\' %}</p>\n<div style="text-align: left">\n<b>{% trans \'privacy_policy_title_8\' %}</b>\n</div>\n<p>{% trans \'privacy_policy_text_8_1\' %} {{vars.confidential_email}}. {% trans \'privacy_policy_text_8_2\' %} {{vars.confidential_link}}.</p>\n</div>\n<style>\n.digital-document {\npadding: 20px;\nwhite-space: pre-wrap;\n};\n</style>\n\n'
|
||||
|
||||
export const translations = {
|
||||
ru: {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -20,7 +20,7 @@ export interface Model {
|
||||
export const title = 'Пользовательское соглашение (оферта) о присоединении к платформе "Кооперативная Экономика"'
|
||||
export const description = 'Форма пользовательского соглашения (оферта) о присоединении к платформе "Кооперативная Экономика"'
|
||||
|
||||
export const context = '<div class="digital-document"><div style="text-align: right; margin:">\n<p style="margin: 0px !important">{% trans \'APPROVED\' %}</p>\n<p style="margin: 0px !important">{% trans \'protocol\' %} {{ vars.coopenomics_agreement.protocol_number }}</p>\n<p style="margin: 0px !important">{{ coop.full_name }}</p>\n<p style="margin: 0px !important">{% trans \'from\' %} {{ vars.coopenomics_agreement.protocol_day_month_year }}</p>\n</div>\n<div style="text-align: center">\n<h1 class="header"> {% trans \'PROVISION\' %}</h1>\n<p>{% trans \'consumer_program_title\' %}</p>\n</div>\n<p> {% trans \'coop_agreement_intro_1\' %} {{coop.chairman.last_name}} {{coop.chairman.first_name}} {{coop.chairman.middle_name}} {% trans \'coop_agreement_intro_2\' %} {{ partner.short_name}} {% trans \'coop_agreement_intro_3\' %}{{partner.represented_by.last_name}} {{partner.represented_by.first_name}} {{partner.represented_by.middle_name}}{% trans \'coop_agreement_intro_4\' %} </p>\n<div style="text-align: left">\n<h3>{% trans \'coop_agreement_1\' %}</h3>\n</div>\n<p>{% trans \'coop_agreement_1_text\' %}</p>\n<div style="text-align: left">\n<h3>{% trans \'coop_agreement_2\' %}</h3>\n</div>\n<p>{% trans \'coop_agreement_2_text\' %}</p>\n<div style="text-align: left">\n<h3>{% trans \'coop_agreement_3\' %}</h3>\n</div>\n<p>{% trans \'coop_agreement_3_text\' %}</p>\n<div style="text-align: left">\n<h3>{% trans \'coop_agreement_4\' %}</h3>\n</div>\n<p>{% trans \'coop_agreement_4_text\' %}</p>\n<div style="text-align: left">\n<h3>{% trans \'coop_agreement_5\' %}</h3>\n</div>\n<p>{% trans \'coop_agreement_5_text\' %}</p>\n<div style="text-align: left">\n<h3>{% trans \'coop_agreement_6\' %}</h3>\n</div>\n<p>{% trans \'coop_agreement_6_text\' %}</p>\n<div style="text-align: left">\n<h3>{% trans \'coop_agreement_7\' %}</h3>\n</div>\n<p>{% trans \'coop_agreement_7_text\', vars.contact_email %}</p>\n<div class="signature">\n{% trans \'acceptance_agreement\' %}</div></div>\n<style>\n.digital-document {\npadding: 20px;\n}\n</style>\n'
|
||||
export const context = '<div class="digital-document"><div style="text-align: right; margin:">\n<p style="margin: 0px !important">{% trans \'APPROVED\' %}</p>\n<p style="margin: 0px !important">{% trans \'protocol\' %} {{ vars.coopenomics_agreement.protocol_number }}</p>\n<p style="margin: 0px !important">{{ coop.full_name }}</p>\n<p style="margin: 0px !important">{% trans \'from\' %} {{ vars.coopenomics_agreement.protocol_day_month_year }}</p>\n</div>\n<div style="text-align: center">\n<h1 class="header"> {% trans \'PROVISION\' %}</h1>\n<p class="subheader">{% trans \'consumer_program_title\' %}</p>\n</div>\n<p>{% trans \'coop_agreement_intro_1\' %} {{coop.chairman.last_name}} {{coop.chairman.first_name}} {{coop.chairman.middle_name}}{% trans \'coop_agreement_intro_2\' %} {{ partner.short_name}} {% trans \'coop_agreement_intro_3\' %}{{partner.represented_by.last_name}} {{partner.represented_by.first_name}} {{partner.represented_by.middle_name}}{% trans \'coop_agreement_intro_4\' %} </p>\n<div style="text-align: left">\n<h3>{% trans \'coop_agreement_1\' %}</h3>\n</div>\n<p>{% trans \'coop_agreement_1_text\' %}</p>\n<div style="text-align: left">\n<h3>{% trans \'coop_agreement_2\' %}</h3>\n</div>\n<p>{% trans \'coop_agreement_2_text\' %}</p>\n<div style="text-align: left">\n<h3>{% trans \'coop_agreement_3\' %}</h3>\n</div>\n<p>{% trans \'coop_agreement_3_text\' %}</p>\n<div style="text-align: left">\n<h3>{% trans \'coop_agreement_4\' %}</h3>\n</div>\n<p>{% trans \'coop_agreement_4_text\' %}</p>\n<div style="text-align: left">\n<h3>{% trans \'coop_agreement_5\' %}</h3>\n</div>\n<p>{% trans \'coop_agreement_5_text\' %}</p>\n<div style="text-align: left">\n<h3>{% trans \'coop_agreement_6\' %}</h3>\n</div>\n<p>{% trans \'coop_agreement_6_text\' %}</p>\n<div style="text-align: left">\n<h3>{% trans \'coop_agreement_7\' %}</h3>\n</div>\n<p>{% trans \'coop_agreement_7_text\', vars.contact_email %}</p>\n<div class="signature">\n{% trans \'acceptance_agreement\' %}</div></div>\n<style>\n.digital-document {\npadding: 20px;\nwhite-space: pre-wrap;\n}\n.subheader {padding-bottom: 20px;}\n</style>\n'
|
||||
|
||||
export const translations = {
|
||||
ru: {
|
||||
@@ -39,7 +39,7 @@ export const translations = {
|
||||
coop_agreement_2: '2.\tПРЕДМЕТ СОГЛАШЕНИЯ',
|
||||
coop_agreement_2_text: 'Настоящее Соглашение формулируют условия и регламент присоединения и осуществления деятельности Кооператива на Платформе в режиме натурного тестирования Платформы и MONOCOOP и является по отношению к Кооперативу Офертой от Общества, где Общество является Оферентом, а Кооператив является Акцептантом.\n',
|
||||
coop_agreement_3: '3.\tУСЛОВИЯ И РЕГЛАМЕНТ ПРИСОЕДИНЕНИЯ',
|
||||
coop_agreement_3_text: '3.1.\tФактическое присоединение Кооператива к Платформе осуществляется Обществом посредством запуска MONOCOOР на (под)домене Кооператива в соответствии с разделом 5 Инструкции в течение Пробного Периода, которая является неотъемлемым Приложением к настоящему Соглашению.\n3.2.\tДействия, которые Кооператив совершает на Платформе, измеряются в Квотах.\n3.3.\tКооператив выплачивает Обществу Членский Взнос Денежными средствами в размере 2500 (две тысячи пятьсот) рублей за использование одной Квоты.\n3.4.\tКооператив, в соответствии с п. 3.3 настоящего Соглашения, и по истечению Пробного Периода выплачивает Членский Взнос в Общество за 24 (двадцать четыре) часа до начала использования Квоты согласно реквизитов Общества, указанных на сайте https://цифровой-кооператив.рф. \n3.5.\tФактом оплаты Членского Взноса Кооператива в Общество признается время и дата начисления Членского Взноса, вносимого Кооперативом согласно п. 3.3 настоящего Соглашения на расчетный счет Общества. \n3.6.\tПри неоплате Членского Взноса в Общество с соответствии с п. 3.3 настоящего Соглашения, за исключением услови, изложенного в п. 4.6. настоящего Соглашения, подключение Кооператива к Платформе приостанавливается до момента осуществления оплаты Членского Взноса Кооперативом.\n',
|
||||
coop_agreement_3_text: '3.1.\tФактическое присоединение Кооператива к Платформе осуществляется Обществом посредством запуска MONOCOOР на (под)домене Кооператива в соответствии с разделом 5 Инструкции в течение Пробного Периода, которая является неотъемлемым Приложением к настоящему Соглашению.\n3.2.\tДействия, которые Кооператив совершает на Платформе, измеряются в Квотах.\n3.3.\tКооператив выплачивает Обществу Членский Взнос Денежными средствами в размере 1500 (полторы тысячи) рублей за использование одной Квоты.\n3.4.\tКооператив, в соответствии с п. 3.3 настоящего Соглашения, и по истечению Пробного Периода выплачивает Членский Взнос в Общество за 24 (двадцать четыре) часа до начала использования Квоты согласно реквизитов Общества, указанных на сайте https://цифровой-кооператив.рф. \n3.5.\tФактом оплаты Членского Взноса Кооператива в Общество признается время и дата начисления Членского Взноса, вносимого Кооперативом согласно п. 3.3 настоящего Соглашения на расчетный счет Общества. \n3.6.\tПри неоплате Членского Взноса в Общество с соответствии с п. 3.3 настоящего Соглашения, за исключением услови, изложенного в п. 4.6. настоящего Соглашения, подключение Кооператива к Платформе приостанавливается до момента осуществления оплаты Членского Взноса Кооперативом.\n',
|
||||
coop_agreement_4: '4.\tОБЯЗАТЕЛЬСТВА И ПРАВА',
|
||||
coop_agreement_4_text: '4.1.\tОбщество обязуется заблаговременно - за 3 (три) дня до предполагаемого истечения Квоты - известить Кооператив посредством направления уведомления или сообщения согласно реквизитов Кооператива, указанных в п.7.7. настоящего Соглашения. \n4.2.\tКооператив соглашается не предпринимать действий юридического характера с какими-то ни было претензиями или рекламациями в отношении Общества в связи с возможными сбоями и/или ошибками в функционировании Платформы и/или MONOCOOР в рамках срока действия настоящего Соглашения, ввиду проведения натурного тестирования Платформы с участием Кооператива.\n4.3.\tКооператив обязуется предоставлять Обществу информацию об ошибках и сбоях функционирования Платформы и MONOCOOР при наличии таковых согласно реквизитов Общества, указанных на сайте https://цифровой-кооператив.рф.\n4.4.\tКооператив обязуется сохранять в тайне передаваемую или создаваемую для него Обществом защищаемую информацию, в том числе, но не ограничиваясь: логины, пароли, коды доступа закрытые ключи электронной подписи и прочую информацию, имеющую пометку “конфиденциально”, а также обеспечить такую тайну со стороны своих пайщиков и аффилированных лиц, в соответствии с условиями, изложенными в разделе 5 настоящего Соглашения, в течение срока действия настоящего Соглашения, а в случае его расторжения в соответствии с п.7.5 или окончания срока действия настоящего Соглашения без заключения последующего договора или соглашения с Обществом по подключению к Платформе - в течение 2 (двух) лет с даты такого расторжения или окончания срока действия настоящего Соглашения.\n4.5.\tКооператив обязуется немедленно информировать Общество о факте доступа посторонних лиц к защищаемой Обществом информации, а также подозрении на него, направив сообщение согласно реквизитов Общества, указанных на сайте https://цифровой-кооператив.рф.\n4.6.\tКооператив имеет право запросить продление Пробного Периода у Общества на срок по согласованию с Обществом, направив соответствующее обращение по реквизитам Общества, указанных на сайте https://цифровой-кооператив.рф за 24 (двадцать четыре) часа до окончания срока Пробного Периода согласно п. 1.6. настоящего Соглашения.\n',
|
||||
coop_agreement_5: '5.\tКОНФИДЕНЦИАЛЬНОСТЬ',
|
||||
|
||||
+2
-1
@@ -25,7 +25,8 @@ export interface Model {
|
||||
|
||||
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 {padding: 20px;}\n</style>\n\n<div class="digital-document"><h1 class="header">{% trans \'protocol_number\', decision.id %}</h1>\n<p style="text-align:center">{% trans \'council_meeting_name\' %}\n{{ coop.full_name }}</p>\n<p style="text-align: right"> {{ meta.created_at }}, {{ coop.city }}</p>\n\n<div class="about">\n<p>{% trans \'meeting_format\' %}</p>\n<p>{% trans \'meeting_place\', coop.full_address %}</p>\n<p>{% trans \'meeting_date\', decision.date %}</p>\n<p>{% trans \'opening_time\', decision.time %}</p>\n</div>\n\n<h3>{% trans \'council_members\' %}</h3>\n<ol>{% for member in coop.members %}\n<li>{{ member.last_name }} {{ member.first_name }} {{ member.middle_name }}{% if member.is_chairman %} {% trans \'chairman_of_the_council\' %}{% endif %}</li>\n{% endfor %}\n</ol>\n\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\n<h3>{% trans \'agenda\' %}</h3>\n<ol><li> {% trans \'decision_joincoop1\' %}{% if type == \'individual\' %} {{individual.last_name}} {{individual.first_name}} {{individual.middle.name}} ({{individual.birthdate}} {% trans \'birthdate\' %}) {% endif %}{% if type == \'entrepreneur\' %} {% trans \'entrepreneur\' %} {{entrepreneur.last_name}} {{entrepreneur.first_name}} {{entrepreneur.middle.name}} ({% trans \'ogrnip\' %} {{entrepreneur.details.ogrn}}) {% endif %}{% if type == \'organization\' %} {{organization.short_name}} ({% trans \'ogrn\' %} {{organization.details.ogrn}}) {% endif %}{% trans \'in_participants\' %} {{ coop.short_name }}.\n</li></ol>\n\n<h3>{% trans \'voting\' %}</h3>\n<p>{% trans \'vote_results\', decision.votes_for, decision.votes_against, decision.votes_abstained %} </p>\n\n<h3>{% trans \'decision_made\' %}</h3>\n<p>{% trans \'decision_joincoop2\' %}{% if type == \'individual\' %} {{individual.last_name}} {{individual.first_name}} {{individual.middle.name}} {{individual.birthdate}} {% trans \'birthdate\' %}{% endif %} {% if type == \'entrepreneur\' %}{% trans \'entrepreneur\' %} {{entrepreneur.last_name}} {{entrepreneur.first_name}} {{entrepreneur.middle.name}}, {% trans \'ogrnip\' %} {{entrepreneur.details.ogrn}}{% endif %} {% if type == \'organization\' %} {{organization.short_name}}, {% trans \'ogrn\' %} {{organization.details.ogrn}} {% endif %}</p>\n<hr>\n<p>{% trans \'closing_time\', decision.time %}</p>\n\n<div class="signature"> \n<p>{% trans \'signature\' %}<p>\n<p style="text-align: right;">{% trans \'chairman\' %} {{ coop.chairman.last_name }} {{ coop.chairman.first_name }} {{ coop.chairman.middle_name }}</p></div></div>'
|
||||
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}\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\' %}\n{{ coop.full_name }}</p>\n<p style="text-align: right"> {{ meta.created_at }}, {{ coop.city }}</p>\n\n<div class="about">\n<p>{% trans \'meeting_format\' %}</p>\n<p>{% trans \'meeting_place\', coop.full_address %}</p>\n<p>{% trans \'meeting_date\', decision.date %}</p>\n<p>{% trans \'opening_time\', decision.time %}</p>\n</div>\n\n<h3>{% trans \'council_members\' %}</h3>\n<ol>{% for member in coop.members %}\n<li>{{ member.last_name }} {{ member.first_name }} {{ member.middle_name }}{% if member.is_chairman %} {% trans \'chairman_of_the_council\' %}{% endif %}</li>\n{% endfor %}\n</ol>\n\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\n<h3>{% trans \'agenda\' %}</h3>\n<ol><li> {% trans \'decision_joincoop1\' %}{% if type == \'individual\' %} {{individual.last_name}} {{individual.first_name}} {{individual.middle.name}} ({{individual.birthdate}} {% trans \'birthdate\' %}) {% endif %}{% if type == \'entrepreneur\' %} {% trans \'entrepreneur\' %} {{entrepreneur.last_name}} {{entrepreneur.first_name}} {{entrepreneur.middle.name}} ({% trans \'ogrnip\' %} {{entrepreneur.details.ogrn}}) {% endif %}{% if type == \'organization\' %} {{organization.short_name}} ({% trans \'ogrn\' %} {{organization.details.ogrn}}) {% endif %}{% trans \'in_participants\' %} {{ coop.short_name }}.\n</li></ol>\n\n<h3>{% trans \'voting\' %}</h3>\n<p>{% trans \'vote_results\', decision.votes_for, decision.votes_against, decision.votes_abstained %} </p>\n\n<h3>{% trans \'decision_made\' %}</h3>\n<p>{% trans \'decision_joincoop2\' %}{% if type == \'individual\' %} {{individual.last_name}} {{individual.first_name}} {{individual.middle.name}} {{individual.birthdate}} {% trans \'birthdate\' %}{% endif %} {% if type == \'entrepreneur\' %}{% trans \'entrepreneur\' %} {{entrepreneur.last_name}} {{entrepreneur.first_name}} {{entrepreneur.middle.name}}, {% trans \'ogrnip\' %} {{entrepreneur.details.ogrn}}{% endif %} {% if type == \'organization\' %} {{organization.short_name}}, {% trans \'ogrn\' %} {{organization.details.ogrn}} {% endif %}</p>\n<hr>\n<p>{% trans \'closing_time\', decision.time %}</p>\n\n<div class="signature"> \n<p>{% trans \'signature\' %}<p>\n<p style="text-align: right;">{% trans \'chairman\' %} {{ coop.chairman.last_name }} {{ coop.chairman.first_name }} {{ coop.chairman.middle_name }}</p></div></div>'
|
||||
|
||||
export const translations = {
|
||||
ru: {
|
||||
meeting_format: 'Форма проведения собрания совета: заочная',
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user