Compare commits

...

13 Commits

Author SHA1 Message Date
Alex Ant 0cd1af0cf1 chore(release): publish
- cooparser-ts@1.0.16
 - coopback@1.7.26
 - coopdoc-generator-ts@1.0.71
 - cooptypes@1.0.16
 - coop-notificator@0.0.20
 - terminal@0.1.29
2024-07-15 18:51:34 +05:00
Alex Ant d786dbc095 chore(release): publish
- coop-notificator@0.0.20-alpha.1
2024-07-15 18:36:08 +05:00
Alex Ant 5b0581158a fix тип socketio 2024-07-15 18:30:36 +05:00
Alex Ant dced33c8e6 chore(release): publish
- cooparser-ts@1.0.16-alpha.0
 - coopback@1.7.26-alpha.0
 - coopdoc-generator-ts@1.0.71-alpha.0
 - cooptypes@1.0.16-alpha.0
 - coop-notificator@0.0.20-alpha.0
 - terminal@0.1.29-alpha.1
2024-07-15 17:44:30 +05:00
Alex Ant 1a9ab8d997 1. Введен WS-нотификатор, отправляющий анонимизированные оповещения всем подписанантам
2. Контроллер подключен к нотификатору для циркулярного обновления прав доступа членов совета
3. Введены настройки кооператива: управление советом и просмотр реквизитов.
2024-07-15 17:41:03 +05:00
Alex Ant 0f4da3ad18 chore(release): publish
- terminal@0.1.29-alpha.0
2024-07-14 14:31:43 +05:00
Alex Ant bba8a72eef update 2024-07-14 14:30:22 +05:00
Alex Ant 7f0a81a1bc chore(release): publish
- terminal@0.1.28
2024-07-14 14:18:54 +05:00
Alex Ant 38db03b4fc chore(release): publish
- terminal@0.1.28-alpha.0
2024-07-14 14:17:57 +05:00
Alex Ant 409ba6c104 update 2024-07-14 14:17:29 +05:00
Alex Ant e9c11a0866 chore(release): publish
- terminal@0.1.27
2024-07-14 13:01:51 +05:00
Alex Ant 8d3bf8c5b6 chore(release): publish
- terminal@0.1.27-alpha.0
2024-07-14 12:59:59 +05:00
Alex Ant 00d46e4b3a update 2024-07-14 12:57:01 +05:00
72 changed files with 12632 additions and 9655 deletions
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.0.16](https://github.com/copenomics/cooparser/compare/cooparser-ts@1.0.16-alpha.0...cooparser-ts@1.0.16) (2024-07-15)
**Note:** Version bump only for package cooparser-ts
## [1.0.15](https://github.com/copenomics/cooparser/compare/cooparser-ts@1.0.15-alpha.0...cooparser-ts@1.0.15) (2024-07-14)
**Note:** Version bump only for package cooparser-ts
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "pkg-placeholder",
"version": "1.0.15",
"version": "1.0.16",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "pkg-placeholder",
"version": "1.0.15",
"version": "1.0.16",
"license": "MIT",
"devDependencies": {
"@antfu/eslint-config": "^2.16.0",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "cooparser-ts",
"type": "module",
"version": "1.0.15",
"version": "1.0.16",
"private": true,
"packageManager": "pnpm@9.0.6",
"description": "",
+9 -3
View File
@@ -7,8 +7,14 @@ import { loadReader } from '../Reader'
export class Parser {
async start() {
const reader = await loadReader(db)
BlockParser(db, reader)
ActionsParser(db, reader)
DeltasParser(db, reader)
try {
BlockParser(db, reader)
ActionsParser(db, reader)
DeltasParser(db, reader)
}
catch (e) {
console.error('Ошибка: ', e)
this.start()
}
}
}
+1 -1
View File
@@ -49,11 +49,11 @@ export const subsribedActions: IActionConfig[] = [
{ code: 'soviet', action: 'newresolved' },
{ code: 'soviet', action: 'newdecision' },
// // registrator.joincoop
{ code: 'soviet', action: 'joincoop' },
{ code: 'soviet', action: 'joincoopdec' },
{ code: 'soviet', action: 'updateboard', notify: true },
]
// --------------------------
+1 -1
View File
@@ -45,6 +45,6 @@ app.get('/get-current-block', async (req: any, res: any) => {
// Глобальный обработчик ошибок
app.use((err: any, req: any, res: any, _next: any) => {
console.error(err)
console.error('глобальная ошибка: ', err)
res.status(500).send(err.message)
})
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.7.26](https://github.com/hagopj13/node-express-boilerplate/compare/coopback@1.7.26-alpha.0...coopback@1.7.26) (2024-07-15)
**Note:** Version bump only for package coopback
## [1.7.25](https://github.com/hagopj13/node-express-boilerplate/compare/coopback@1.7.25-alpha.0...coopback@1.7.25) (2024-07-14)
**Note:** Version bump only for package coopback
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "create-nodejs-express-app",
"version": "1.7.25",
"version": "1.7.26",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "create-nodejs-express-app",
"version": "1.7.25",
"version": "1.7.26",
"license": "MIT",
"dependencies": {
"@a2seven/yoo-checkout": "^1.1.4",
+2 -1
View File
@@ -1,6 +1,6 @@
{
"name": "coopback",
"version": "1.7.25",
"version": "1.7.26",
"description": "",
"private": true,
"bin": "bin/createNodejsApp.js",
@@ -94,6 +94,7 @@
"passport-jwt": "^4.0.0",
"pdf-lib": "^1.17.1",
"pm2": "^5.1.0",
"socket.io-client": "^4.7.5",
"swagger-jsdoc": "^6.0.8",
"swagger-ui-express": "^4.1.6",
"ts-jest": "^29.1.3",
+2 -2
View File
@@ -1,8 +1,8 @@
const allRoles = {
user: [''],
service: ['sendNotification'],
admin: ['getUsers', 'manageUsers', 'loadAgenda', 'loadStaff', 'loadMembers', 'getDocuments'],
chairman: ['getUsers', 'manageUsers', 'loadAgenda', 'loadStaff', 'loadMembers', 'getDocuments'],
chairman: ['getUsers', 'manageUsers', 'loadAgenda', 'loadStaff', 'getDocuments', 'loadInfo'],
member: ['getUsers', 'manageUsers', 'loadAgenda', 'loadStaff', 'getDocuments', 'loadInfo'],
};
export const roles = Object.keys(allRoles);
@@ -2,33 +2,18 @@ import catchAsync from '../utils/catchAsync';
import { coopService, dataService } from '../services';
import { Cooperative } from 'cooptypes';
import { generator } from '../services/data.service';
import ApiError from '../utils/ApiError';
import httpStatus from 'http-status';
export const loadInfo = catchAsync(async (req, res) => {
const cooperative: Cooperative.Model.ICooperativeData | null = await generator.constructCooperative(
String(process.env.COOPNAME)
);
const cooperative = await coopService.loadInfo(String(process.env.COOPNAME));
res.send(cooperative);
});
if (!cooperative) throw new Error('Кооператив не найден');
export const loadContacts = catchAsync(async (req, res) => {
const contacts = await coopService.loadContacts(String(process.env.COOPNAME));
const announce = cooperative?.announce
? JSON.parse(cooperative.announce)
: { phone: cooperative?.phone, email: cooperative?.email };
const result = {
full_name: cooperative?.full_name,
full_address: cooperative?.full_address,
details: cooperative?.details,
phone: announce.phone,
email: announce.email,
description: cooperative?.description,
chairman: {
first_name: cooperative?.chairman.first_name,
last_name: cooperative?.chairman.last_name,
middle_name: cooperative?.chairman.middle_name,
},
};
res.send(result);
res.send(contacts);
});
export const loadAgenda = catchAsync(async (req, res) => {
@@ -50,11 +35,3 @@ export const loadStaff = catchAsync(async (req, res) => {
const staff = await coopService.loadStaff(coopname);
res.send(staff);
});
export const loadMembers = catchAsync(async (req, res) => {
const { coopname } = req.query;
const members = await coopService.loadMembers(coopname);
res.send(members);
});
@@ -0,0 +1,38 @@
import { io, Socket } from 'socket.io-client';
import { IAction } from '../types/common';
import { SovietContract } from 'cooptypes';
import { wsService } from '../services';
let clientSocket: Socket | undefined;
// Инициация подключения
export const initSocketConnection = (serverUrl: string): void => {
clientSocket = io(serverUrl);
clientSocket.on('connect', () => {
console.log('Успешное подключение к серверу оповещений.');
});
clientSocket.on('event', (event: IAction) => {
processEvent(event);
});
clientSocket.on('connect_error', (error: Error) => {
console.error('Ошибка подключения к серверу оповещений:');
});
};
// Закрытие подключения
export const closeSocketConnection = (): void => {
if (clientSocket) {
clientSocket.disconnect();
console.log('Client disconnected from server');
clientSocket = undefined;
}
};
async function processEvent(event: IAction) {
if (event.receiver === SovietContract.contractName.production && event.name === 'updateboard') {
wsService.updateBoard(event.data);
}
}
+7 -4
View File
@@ -4,18 +4,21 @@ import config from './config/config';
import logger from './config/logger';
import { updateAuth } from './services/auth.service';
import { connectGenerator } from './services/data.service';
import { initSocketConnection } from './controllers/ws.controller';
const SERVER_URL: string = process.env.SOCKET_SERVER || 'http://localhost:2222';
let server: any;
mongoose.connect(config.mongoose.url, config.mongoose.options).then(async () => {
logger.info('Connected to MongoDB');
// logger.info('Update soviet auth');
// updateAuth();
// setInterval(() => updateAuth(), 60 * 1000);
//подключаемся к хранилищу приватных данных
await connectGenerator();
//подключаемся к ws-серверу
initSocketConnection(SERVER_URL);
server = app.listen(config.port, () => {
logger.info(`Listening to port ${config.port}`);
});
+3 -3
View File
@@ -16,9 +16,9 @@ const verifyCallback = (req, resolve, reject, requiredRights) => async (err, use
const hasRequiredRights = requiredRights.every((requiredRight) => userRights?.includes(requiredRight));
// if (process.env.IS_PRODUCTION) {
if (!hasRequiredRights && req.params.username !== user.username) {
return reject(new ApiError(FORBIDDEN, 'Недостаточно прав доступа'));
}
if (!hasRequiredRights && req.params.username !== user.username) {
return reject(new ApiError(FORBIDDEN, 'Недостаточно прав доступа'));
}
// }
}
@@ -2,15 +2,15 @@ import { Router } from 'express';
import auth from '../../middlewares/auth';
import validate from '../../middlewares/validate';
import * as coopValidation from '../../validations/coop.validation';
// import { loadAgenda, loadStaff, loadMembers } from '../../validations/coop.validation';
// import { loadAgenda, loadStaff, } from '../../validations/coop.validation';
import * as coopController from '../../controllers/coop.controller';
const router = Router();
router.route('/agenda').get(auth('loadAgenda'), validate(coopValidation.loadAgenda), coopController.loadAgenda);
router.route('/staff').get(auth('loadStaff'), validate(coopValidation.loadStaff), coopController.loadStaff);
router.route('/members').get(auth('loadMembers'), validate(coopValidation.loadMembers), coopController.loadMembers);
router.route('/info').get(coopController.loadInfo);
router.route('/contacts').get(coopController.loadContacts);
router.route('/info').get(auth('loadInfo'), coopController.loadInfo);
export default router;
@@ -83,23 +83,21 @@ async function registerBlockchainAccount(user: IUser, orderData: GatewayContract
username: user.username,
public_key: user.public_key,
meta: '',
signature_hash: '' // LEGACY - delete it later
}
};
const registerUserData: RegistratorContract.Actions.RegisterUser.IRegistrerUser = {
coopname: process.env.COOPNAME as string,
registrator: process.env.COOPNAME as string,
username: user.username,
}
type: user.type,
};
const joinCooperativeData: RegistratorContract.Actions.JoinCooperative.IJoinCooperative = {
coopname: process.env.COOPNAME as string,
registrator: process.env.COOPNAME as string,
username: user.username,
document: {...user.statement, meta: JSON.stringify(user.statement.meta)},
}
console.log("joinCooperativeData: ", joinCooperativeData)
document: { ...user.statement, meta: JSON.stringify(user.statement.meta) },
};
const actions = [
{
@@ -115,7 +113,7 @@ async function registerBlockchainAccount(user: IUser, orderData: GatewayContract
},
{
account: RegistratorContract.contractName.production,
name: RegistratorContract.Actions.RegisterUser.actionName,//reguser
name: RegistratorContract.Actions.RegisterUser.actionName, //reguser
authorization: [
{
actor: process.env.COOPNAME as string,
@@ -146,7 +144,6 @@ async function registerBlockchainAccount(user: IUser, orderData: GatewayContract
],
data: orderData,
},
];
const result = await eos.transact(
@@ -2,8 +2,10 @@ import { getActions } from '../utils/getFetch';
import { generator } from './data.service';
import { userService, blockchainService } from './index';
import { Cooperative, SovietContract } from 'cooptypes';
import ApiError from '../utils/ApiError';
import httpStatus from 'http-status';
const loadAgenda = async (coopname: string): Promise<Cooperative.Documents.IAgenda[]> => {
export const loadAgenda = async (coopname: string): Promise<Cooperative.Documents.IAgenda[]> => {
const api = await blockchainService.getApi();
const decisions = (await blockchainService.lazyFetch(
@@ -34,7 +36,7 @@ const loadAgenda = async (coopname: string): Promise<Cooperative.Documents.IAgen
return agenda;
};
const loadStaff = async (coopname) => {
export const loadStaff = async (coopname) => {
const api = await blockchainService.getApi();
const staff = await blockchainService.lazyFetch(api, process.env.SOVIET_CONTRACT, coopname, 'staff');
@@ -51,60 +53,33 @@ const loadStaff = async (coopname) => {
return staff;
};
const loadMembers = async (coopname) => {
// const api = await blockchainService.getApi()
// const soviet = (await blockchainService.lazyFetch(
// api,
// process.env.SOVIET_CONTRACT,
// coopname,
// 'boards',
// "soviet",
// "soviet",
// 1,
// 'i64',
// 2
// ))[0]
// for (const member of soviet.members) {
// const user = await userService.getUserByUsername(member.username)
// if (user) {
// member.is_organization = user.is_organization
// member.user_profile = user.user_profile
// member.org_profile = user.organization_profile
// }
// }
// return soviet.members
export const loadInfo = async (coopname: string) => {
const cooperative: Cooperative.Model.ICooperativeData | null = await generator.constructCooperative(coopname);
if (!cooperative) throw new ApiError(httpStatus.NO_CONTENT, 'Кооператив не найден');
else return cooperative;
};
const loadSoviet = async (api, coopname) => {
const [soviet] = await blockchainService.lazyFetch(
api,
process.env.SOVIET_CONTRACT,
coopname,
'boards',
'soviet',
'soviet',
1,
'i64',
2
);
export const loadContacts = async (coopname: string) => {
const cooperative: Cooperative.Model.ICooperativeData | null = await generator.constructCooperative(coopname);
soviet.chairman = soviet.members.find((el) => el.position == 'chairman').username;
if (!cooperative) throw new Error('Кооператив не найден');
return soviet;
const announce = cooperative?.announce
? JSON.parse(cooperative.announce)
: { phone: cooperative?.phone, email: cooperative?.email };
return {
full_name: cooperative?.full_name,
full_address: cooperative?.full_address,
details: cooperative?.details,
phone: announce.phone,
email: announce.email,
description: cooperative?.description,
chairman: {
first_name: cooperative?.chairman.first_name,
last_name: cooperative?.chairman.last_name,
middle_name: cooperative?.chairman.middle_name,
},
};
};
const getDecision = async (api, coopname, decision_id) => {
const [decision] = await blockchainService.lazyFetch(
api,
process.env.SOVIET_CONTRACT,
coopname,
'decisions',
decision_id,
decision_id,
1
);
return decision;
};
export { loadAgenda, loadStaff, loadMembers, getDecision };
@@ -6,3 +6,4 @@ export * as blockchainService from './blockchain.service';
export * as orderService from './order.service';
export * as dataService from './data.service';
export * as coopService from './coop.service';
export * as wsService from './ws.service';
@@ -0,0 +1,22 @@
import { SovietContract } from 'cooptypes';
import { userService } from '.';
import { User } from '../models';
export const updateBoard = async (action: SovietContract.Actions.Boards.UpdateBoard.IUpdateBoard): Promise<void> => {
//сброс всех прав
const users = await User.find({ role: { $in: ['member', 'chairman'] } }).exec();
for (const user of users) {
user.role = 'user';
await user.save();
}
for (const member of action.members) {
const user = await userService.getUserByUsername(member.username);
user.role = 'member';
await user.save();
}
const chairman = await userService.getUserByUsername(action.chairman);
chairman.role = 'chairman';
await chairman.save();
};
@@ -9,12 +9,6 @@ export interface loadAgenda {
};
}
export interface loadMembers {
query?: {
coopname: string;
};
}
export interface loadStaff {
query?: {
coopname: string;
@@ -4,16 +4,10 @@ export const loadAgenda = Joi.object({
query: Joi.object().keys({
coopname: Joi.string().required(),
}),
})
});
export const loadStaff = Joi.object({
query: Joi.object().keys({
coopname: Joi.string().required(),
}),
})
export const loadMembers = Joi.object({
query: Joi.object().keys({
coopname: Joi.string().required(),
}),
})
});
+1 -1
View File
@@ -67,7 +67,7 @@ export const installInitialCooperativeData = async () => {
registration: '2.0000 RUB',
initial: '1.0000 RUB',
minimum: '1.0000 RUB',
} as RegistratorContract.Tables.Organizations.IOrganization);
} as RegistratorContract.Tables.Cooperatives.ICooperative);
await insertDelta(delta1);
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.0.71](https://github.com/copenomics/coopdoc-generator-ts/compare/coopdoc-generator-ts@1.0.71-alpha.0...coopdoc-generator-ts@1.0.71) (2024-07-15)
**Note:** Version bump only for package coopdoc-generator-ts
## [1.0.70](https://github.com/copenomics/coopdoc-generator-ts/compare/coopdoc-generator-ts@1.0.70-alpha.0...coopdoc-generator-ts@1.0.70) (2024-07-14)
**Note:** Version bump only for package coopdoc-generator-ts
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "coopdoc-generator-ts",
"type": "module",
"version": "1.0.70",
"version": "1.0.71",
"private": true,
"packageManager": "pnpm@9.0.6",
"description": "",
@@ -56,11 +56,11 @@ export class Cooperative {
filter: JSON.stringify({
code: RegistratorContract.contractName.production,
scope: RegistratorContract.contractName.production,
table: RegistratorContract.Tables.Organizations.tableName,
table: RegistratorContract.Tables.Cooperatives.tableName,
}),
}))
const cooperativeBlockchainData = cooperative_response.results[0]?.value as RegistratorContract.Tables.Organizations.IOrganization
const cooperativeBlockchainData = cooperative_response.results[0]?.value as RegistratorContract.Tables.Cooperatives.ICooperative
if (!cooperativeBlockchainData)
throw new Error('Информация о кооперативе не обнаружена в базе данных.')
@@ -141,7 +141,7 @@ describe('тест генератора документов', async () => {
registration: '2.0000 RUB',
initial: '1.0000 RUB',
minimum: '1.0000 RUB',
} as RegistratorContract.Tables.Organizations.IOrganization,
} as RegistratorContract.Tables.Cooperatives.ICooperative,
})
await deltas.insertOne({
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.0.16](https://github.com/coopenomics/cooptypes/compare/cooptypes@1.0.16-alpha.0...cooptypes@1.0.16) (2024-07-15)
**Note:** Version bump only for package cooptypes
## [1.0.15](https://github.com/coopenomics/cooptypes/compare/cooptypes@1.0.15-alpha.0...cooptypes@1.0.15) (2024-07-14)
**Note:** Version bump only for package cooptypes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "cooptypes",
"type": "module",
"version": "1.0.15",
"version": "1.0.16",
"description": "_description_",
"author": "Alex Ant <dacom.dark.sun@gmail.com>",
"license": "MIT",
@@ -18,4 +18,4 @@ export const scope = ContractNames._gateway
* @interface
* Таблица содержит переводы черновиков документов.
*/
export type IDeposits = Gateway.IDeposits
export type IDeposits = Gateway.IOnedeposit
@@ -15,4 +15,4 @@ export const scope = ContractNames._gateway
* @interface
* Таблица содержит переводы черновиков документов.
*/
export type IWithdraws = Gateway.IWithdraws
export type IWithdraws = Gateway.IOnewithdraw
@@ -13,6 +13,6 @@ export const scope = ContractNames._registrator
/**
* @interface
* Таблица содержит реестр организаций-пайщиков кооператива.
* Таблица содержит реестр кооперативов.
*/
export type IOrganization = Registrator.IOrganization
export type ICooperative = Registrator.ICooperative
@@ -5,6 +5,6 @@
export * as Accounts from './accounts'
/**
* Таблица содержит реестр организаций системы.
* Таблица содержит реестр кооперативов системы.
*/
export * as Organizations from './organizations'
export * as Cooperatives from './cooperatives'
@@ -1,8 +1,8 @@
import type { SovietContract } from '../../contracts'
import type { IOrganization } from '../../contracts/registrator/tables/organizations'
import type { ICooperative } from '../../contracts/registrator/tables/cooperatives'
import type { Details, IIndividualData, IOrganizationData } from '../users'
export interface ICooperativeData extends IOrganizationData, IOrganization {
export interface ICooperativeData extends IOrganizationData, ICooperative {
members: MembersData[]
chairman: IIndividualData
totalMembers: number
+26 -26
View File
@@ -33,19 +33,6 @@ export interface IDeposit {
quantity: IAsset
}
export interface IDeposits {
id: IUint64
username: IName
coopname: IName
type: IName
token_contract: IName
quantity: IAsset
status: IName
link: string
memo: string
expired_at: ITimePointSec
}
export interface IDocument {
hash: IChecksum256
public_key: IPublicKey
@@ -77,6 +64,32 @@ export interface INewwithdrid {
id: IUint64
}
export interface IOnedeposit {
id: IUint64
username: IName
coopname: IName
type: IName
token_contract: IName
quantity: IAsset
status: IName
link: string
memo: string
expired_at: ITimePointSec
}
export interface IOnewithdraw {
id: IUint64
username: IName
coopname: IName
bank_data_id: string
token_contract: IName
quantity: IAsset
status: IName
document: IDocument
memo: string
created_at: ITimePointSec
}
export interface IWithdraw {
coopname: IName
username: IName
@@ -91,19 +104,6 @@ export interface IWithdrawauth {
withdraw_id: IUint64
}
export interface IWithdraws {
id: IUint64
username: IName
coopname: IName
bank_data_id: string
token_contract: IName
quantity: IAsset
status: IName
document: IDocument
memo: string
created_at: ITimePointSec
}
export interface IWthdcomplete {
coopname: IName
admin: IName
@@ -18,7 +18,6 @@ export interface IAccount {
storages: IName[]
verifications: IVerification[]
registered_at: ITimePointSec
signature_expires_at: ITimePointSec
}
export interface IBalances extends IBalancesBase {
@@ -35,9 +34,32 @@ export interface IChangekey {
public_key: IPublicKey
}
export interface ICheck {
hash: IChecksum256
public_key: IPublicKey
signature: ISignature
}
export interface IConfirmreg {
coopname: IName
member: IName
username: IName
}
export interface ICooperative {
username: IName
parent_username: IName
announce: string
description: string
is_cooperative: boolean
is_branched: boolean
is_enrolled: boolean
coop_type: IName
registration: IAsset
initial: IAsset
minimum: IAsset
org_registration: IAsset
org_initial: IAsset
org_minimum: IAsset
}
export interface IDocument {
@@ -47,6 +69,9 @@ export interface IDocument {
meta: string
}
export interface IFix {
}
export interface IInit {
}
@@ -63,7 +88,6 @@ export interface INewaccount {
referer: IName
username: IName
public_key: IPublicKey
signature_hash: string
meta: string
}
@@ -78,23 +102,6 @@ export interface IOrgData {
org_minimum: IAsset
}
export interface IOrganization {
username: IName
parent_username: IName
announce: string
description: string
is_cooperative: boolean
is_branched: boolean
is_enrolled: boolean
coop_type: IName
registration: IAsset
initial: IAsset
minimum: IAsset
org_initial: IAsset
org_minimum: IAsset
org_registration: IAsset
}
export interface IPlotData {
announce: string
description: string
@@ -118,6 +125,7 @@ export interface IReguser {
registrator: IName
coopname: IName
username: IName
type: IName
}
export interface IUpdate {
@@ -125,6 +133,15 @@ export interface IUpdate {
meta: string
}
export interface IUpdatecoop {
coopname: IName
username: IName
initial: IAsset
minimum: IAsset
org_initial: IAsset
org_minimum: IAsset
}
export interface IVerificate {
username: IName
procedure: IName
@@ -234,6 +234,9 @@ export interface IExec {
decision_id: IUint64
}
export interface IFix {
}
export interface IFundwithdraw {
coopname: IName
username: IName
@@ -255,7 +258,6 @@ export interface IJoincoops {
id: IUint64
username: IName
is_paid: boolean
statement: IDocument
notice: string
}
@@ -319,6 +321,7 @@ export interface IParticipants {
is_initial: boolean
is_minimum: boolean
has_vote: boolean
type: IName
}
export interface IProgcomarket {
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.0.20](https://github.com/copenomics/coop-notificator/compare/coop-notificator@0.0.20-alpha.1...coop-notificator@0.0.20) (2024-07-15)
**Note:** Version bump only for package coop-notificator
## [0.0.19](https://github.com/copenomics/coop-notificator/compare/coop-notificator@0.0.19-alpha.0...coop-notificator@0.0.19) (2024-07-14)
**Note:** Version bump only for package coop-notificator
+3 -2
View File
@@ -1,7 +1,7 @@
{
"name": "coop-notificator",
"type": "module",
"version": "0.0.19",
"version": "0.0.20",
"private": true,
"packageManager": "pnpm@9.1.1",
"description": "_description_",
@@ -51,7 +51,8 @@
"dotenv": "^16.4.5",
"handlebars": "^4.7.8",
"import-sync": "^2.2.2",
"ioredis": "^5.4.1"
"ioredis": "^5.4.1",
"socket.io": "^4.7.5"
},
"devDependencies": {
"@antfu/eslint-config": "^2.18.1",
@@ -13,7 +13,8 @@ export class DataCollectorFactory {
return new DataCollectorClass()
}
catch (error) {
// eslint-disable-next-line unused-imports/no-unused-vars
catch (error: any) {
return new DefaultDataCollector()
}
}
@@ -7,14 +7,17 @@ export class EmailNotificationHandler extends BaseHandler {
async handle(event: any) {
const { account, name } = event
const dataCollector = await DataCollectorFactory.createDataCollector(account, name)
const eventData = await dataCollector.collect(event)
const emailTemplateStrategy = TemplateFactory.createTemplateStrategy('email', account, name)
const message = emailTemplateStrategy.fillMessage(eventData)
const subject = emailTemplateStrategy.fillSubject(eventData)
await this.sendEmail(event.receipt.receiver, subject, message)
if (emailTemplateStrategy.process) {
const dataCollector = await DataCollectorFactory.createDataCollector(account, name)
const eventData = await dataCollector.collect(event)
const message = emailTemplateStrategy.fillMessage(eventData)
const subject = emailTemplateStrategy.fillSubject(eventData)
await this.sendEmail(event.receipt.receiver, subject, message)
}
}
async sendEmail(to: string, subject: string, message: string) {
@@ -6,14 +6,17 @@ export class PushNotificationHandler extends BaseHandler {
async handle(_event: any) {
const { account, name } = _event
const dataCollector = await DataCollectorFactory.createDataCollector(account, name)
const eventData = await dataCollector.collect(_event)
const pushTemplateStrategy = TemplateFactory.createTemplateStrategy('push', account, name)
const message = pushTemplateStrategy.fillMessage(eventData)
const subject = pushTemplateStrategy.fillSubject(eventData)
this.sendPushNotification(_event.receipt.receiver, subject, message)
if (!pushTemplateStrategy.process) {
const dataCollector = await DataCollectorFactory.createDataCollector(account, name)
const eventData = await dataCollector.collect(_event)
const message = pushTemplateStrategy.fillMessage(eventData)
const subject = pushTemplateStrategy.fillSubject(eventData)
this.sendPushNotification(_event.receipt.receiver, subject, message)
}
}
sendPushNotification(to: string, subject: string, message: string) {
@@ -1,8 +1,8 @@
import { io } from '../utils/sockets'
import { BaseHandler } from './baseHandler'
export class WebsocketNotificationHandler extends BaseHandler {
async handle(_event: any) {
console.log(`Обрабатываем веб-сокет оповещения:`)
// Логика обработки websocket_notification
async handle(event: any) {
io.emit('event', event)
}
}
+9 -4
View File
@@ -1,9 +1,13 @@
import Redis from 'ioredis'
import dotenv from 'dotenv'
import Redis from 'ioredis'
import { NotificationHandlerFactory } from './factories/notificationHandlerFactory'
import { startSocketServer } from './utils/sockets'
dotenv.config()
startSocketServer()
const consumer = `consumer-${Math.random()}`
// eslint-disable-next-line node/prefer-global/process
@@ -32,9 +36,10 @@ async function createConsumerGroup(stream: string, group: string) {
}
async function handleMessage(group: string, messageId: string, message: string) {
const event: any = JSON.parse(message)
const handler = NotificationHandlerFactory.createHandler(group, event.type)
try {
const event: any = JSON.parse(message)
const handler = NotificationHandlerFactory.createHandler(group, event.type)
if (handler)
await handler.handle(event.event)
else
@@ -63,7 +68,7 @@ async function consumeMessages(group: string) {
// Главная функция выполнения
(async () => {
const groups = ['emailGroup'] // , 'pushGroup', ''websocketGroup''
const groups = ['emailGroup', 'websocketGroup'] // , 'pushGroup'
for (const group of groups)
await createConsumerGroup('notifications', group)
@@ -13,15 +13,23 @@ Handlebars.registerHelper('eq', (a, b) => {
})
export class EmailTemplateStrategy implements ITemplateStrategy {
private message: HandlebarsTemplateDelegate
public subject: HandlebarsTemplateDelegate
public message!: HandlebarsTemplateDelegate
public subject!: HandlebarsTemplateDelegate
public process: boolean
constructor(templateFile: string) {
const templatePath = path.resolve(__dirname, `../../emailTemplates/${templateFile}`)
const { notificationTemplate } = importSync(templatePath)
try {
const templatePath = path.resolve(__dirname, `../../emailTemplates/${templateFile}`)
const { notificationTemplate } = importSync(templatePath)
this.subject = Handlebars.compile(notificationTemplate.subject)
this.message = Handlebars.compile(notificationTemplate.message)
this.subject = Handlebars.compile(notificationTemplate.subject)
this.message = Handlebars.compile(notificationTemplate.message)
this.process = true
}
// eslint-disable-next-line unused-imports/no-unused-vars
catch (e: any) {
this.process = false
}
}
fillMessage(data: any): string {
@@ -1,4 +1,3 @@
import * as fs from 'node:fs'
import * as path from 'node:path'
import { fileURLToPath } from 'node:url'
import Handlebars from 'handlebars'
@@ -13,15 +12,23 @@ Handlebars.registerHelper('eq', (a, b) => {
})
export class PushTemplateStrategy implements ITemplateStrategy {
private message: HandlebarsTemplateDelegate
public subject: HandlebarsTemplateDelegate
public message!: HandlebarsTemplateDelegate
public subject!: HandlebarsTemplateDelegate
public process: boolean
constructor(templateFile: string) {
const templatePath = path.resolve(__dirname, `../../pushTemplates/${templateFile}`)
const { notificationTemplate } = importSync(templatePath)
try {
const templatePath = path.resolve(__dirname, `../../pushTemplates/${templateFile}`)
const { notificationTemplate } = importSync(templatePath)
this.subject = Handlebars.compile(notificationTemplate.subject)
this.message = Handlebars.compile(notificationTemplate.message)
this.subject = Handlebars.compile(notificationTemplate.subject)
this.message = Handlebars.compile(notificationTemplate.message)
this.process = true
}
// eslint-disable-next-line unused-imports/no-unused-vars
catch (e: any) {
this.process = false
}
}
fillMessage(data: any): string {
@@ -1,4 +1,5 @@
export interface ITemplateStrategy {
fillMessage: (data: any) => string
fillSubject: (data: any) => string
process: boolean
}
+2 -2
View File
@@ -34,8 +34,8 @@ export async function postRequest(url: string, data: any): Promise<any> {
})
return response.data
}
catch (error) {
console.error('Ошибка при выполнении POST запроса:', error)
catch (error: any) {
console.error('Ошибка при выполнении POST запроса:', error.message)
throw error
}
}
@@ -0,0 +1,25 @@
import type { Socket } from 'socket.io'
import { Server } from 'socket.io'
// eslint-disable-next-line node/prefer-global/process
const PORT = Number(process.env.SOCKET_PORT)
export const io: Server = new Server()
io.on('connection', (socket: Socket) => {
console.log('WS-клиент подключен', socket.id)
socket.on('disconnect', () => {
console.log('WS-клиент отключен', socket.id)
})
})
export function startSocketServer() {
io.listen(PORT)
console.log(`WS-cервер запущен на http://localhost:${PORT}`)
}
export function stopSocketServer() {
io.close()
console.log('WS-cервер остановлен.')
}
+24
View File
@@ -3,6 +3,30 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.1.29](https://github.com/coopenomics/monocoop/compare/terminal@0.1.29-alpha.1...terminal@0.1.29) (2024-07-15)
**Note:** Version bump only for package terminal
## [0.1.28](https://github.com/coopenomics/monocoop/compare/terminal@0.1.28-alpha.0...terminal@0.1.28) (2024-07-14)
**Note:** Version bump only for package terminal
## [0.1.27](https://github.com/coopenomics/monocoop/compare/terminal@0.1.27-alpha.0...terminal@0.1.27) (2024-07-14)
**Note:** Version bump only for package terminal
## [0.1.26](https://github.com/coopenomics/monocoop/compare/terminal@0.1.26-alpha.0...terminal@0.1.26) (2024-07-14)
**Note:** Version bump only for package terminal
+1 -1
View File
@@ -1,6 +1,6 @@
# Terminal App (terminal)
A Terminal Project.
A Terminal Project
## Install the dependencies
```bash
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "terminal",
"version": "0.1.26",
"version": "0.1.29",
"description": "A Terminal Project",
"productName": "Terminal App",
"author": "Alex Ant <dacom.dark.sun@gmail.com>",
+4
View File
@@ -113,12 +113,16 @@ module.exports = configure(function (/* ctx */) {
// https: true
open: false, // opens browser window automatically
port: 3005,
hmr:{
overlay: false
}
},
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#framework
framework: {
config: {},
lang: 'ru',
iconSet: 'material-icons', // Quasar icon set
// For special cases outside of where the auto-import strategy can have an impact
+3
View File
@@ -15,9 +15,12 @@ const isLoaded = ref(false)
onMounted(async () => {
try {
removeLoader()
isLoaded.value = true
} catch (e: unknown) {
console.error(e)
handleException(e)
router.push({ name: 'somethingBad' })
@@ -50,7 +50,13 @@ export default route(function (/* { store, ssrContext } */) {
if (!session.isAuth && !currentUser.userAccount){
await session.init()
await currentUser.loadProfile(session.username, COOPNAME)
if (session.isAuth)
try{
await currentUser.loadProfile(session.username, COOPNAME)
} catch(e: any){
console.error(e)
}
}
const menuStore = useMenuStore()
@@ -4,7 +4,7 @@ import blank from 'src/pages/blank/blank.vue';
import permissionDenied from 'src/pages/_layouts/permissionDenied.vue';
// import sovietPage from 'src/components/soviet/index.vue'
// import { CoopSettingsPage } from 'src/pages/CoopSettings';
import { CoopSettingsPage } from 'src/pages/CoopSettings';
import { WalletPage } from 'src/pages/wallet';
import { ModerationPage } from 'src/pages/marketplace/Moderation';
import { CreateParentOfferPage } from 'src/pages/marketplace/CreateParentOffer';
@@ -48,17 +48,17 @@ const baseRoutes = [
//страница управления кооперативом
// {
// path: ':coopname/settings',
// name: 'soviet',
// component: CoopSettingsPage,
// meta: {
// is_desktop_menu: true,
// title: 'Настройки',
// icon: 'fa-solid fa-cog',
// roles: ['admin'],
// },
// },
{
path: ':coopname/settings',
name: 'soviet',
component: CoopSettingsPage,
meta: {
is_desktop_menu: true,
title: 'Настройки',
icon: 'fa-solid fa-cog',
roles: ['chairman', 'member'],
},
},
{
path: ':coopname/agenda',
name: 'agenda',
@@ -67,7 +67,7 @@ const baseRoutes = [
is_desktop_menu: true,
title: 'Повестка',
icon: 'fa-solid fa-check-to-slot',
roles: ['admin'],
roles: ['chairman', 'member'],
},
},
{
@@ -78,7 +78,7 @@ const baseRoutes = [
is_desktop_menu: true,
title: 'Пайщики',
icon: 'fa-solid fa-users',
roles: ['admin'],
roles: ['chairman', 'member'],
},
},
{
@@ -89,7 +89,7 @@ const baseRoutes = [
is_desktop_menu: true,
title: 'Документы',
icon: 'fa-solid fa-file-invoice',
roles: ['admin'],
roles: ['chairman', 'member'],
},
},
{
@@ -25,23 +25,28 @@ async function loadAdmins(coopname: string): Promise<IAdministratorData[]> {
})) as IAdministratorData[];
}
async function loadCooperativeData(): Promise<Cooperative.Model.IContacts> {
return (await sendGET('/v1/coop/info', {}, true)) as Cooperative.Model.IContacts;
async function loadPrivateCooperativeData(): Promise<Cooperative.Model.ICooperativeData> {
return (await sendGET('/v1/coop/info', {}, false)) as Cooperative.Model.ICooperativeData;
}
async function loadContacts(): Promise<Cooperative.Model.IContacts> {
return (await sendGET('/v1/coop/contacts', {}, true)) as Cooperative.Model.IContacts;
}
async function loadPublicCooperativeData(
coopname: string
): Promise<RegistratorContract.Tables.Organizations.IOrganization> {
): Promise<RegistratorContract.Tables.Cooperatives.ICooperative> {
return (
await fetchTable(
RegistratorContract.contractName.production,
RegistratorContract.contractName.production,
RegistratorContract.Tables.Organizations.tableName,
RegistratorContract.Tables.Cooperatives.tableName,
coopname,
coopname,
1
)
)[0] as RegistratorContract.Tables.Organizations.IOrganization;
)[0] as RegistratorContract.Tables.Cooperatives.ICooperative;
}
async function loadCooperativeAddresses(
@@ -59,5 +64,6 @@ export const api = {
loadCooperativeAddresses,
loadPublicCooperativeData,
loadAdmins,
loadCooperativeData
loadPrivateCooperativeData,
loadContacts,
};
@@ -16,6 +16,7 @@ interface ICooperativeStore {
// методы
loadAddresses: (params: ILoadCooperativeAddresses) => Promise<void>;
loadMarketPrograms: (params: ILoadCoopMarketPrograms) => Promise<void>;
loadPrivateCooperativeData: () => Promise<void>;
loadContacts: () => Promise<void>;
loadPublicCooperativeData: (coopname: string) => Promise<void>;
loadAdmins: (coopname: string) => Promise<void>;
@@ -23,8 +24,9 @@ interface ICooperativeStore {
admins: Ref<IAdministratorData[]>;
marketPrograms: Ref<ICoopMarketProgramData[]>;
addresses: Ref<IAddressesData[]>;
contacts: Ref<Cooperative.Model.IContacts>
publicCooperativeData: Ref<RegistratorContract.Tables.Organizations.IOrganization>;
contacts: Ref<Cooperative.Model.IContacts | undefined>
publicCooperativeData: Ref<RegistratorContract.Tables.Cooperatives.ICooperative | undefined>;
privateCooperativeData: Ref<Cooperative.Model.ICooperativeData | undefined>;
}
export const useCooperativeStore = defineStore(
@@ -33,14 +35,18 @@ export const useCooperativeStore = defineStore(
const marketPrograms = ref([] as ICoopMarketProgramData[]);
const addresses = ref([] as IAddressesData[]);
const admins = ref([] as IAdministratorData[]);
const publicCooperativeData = ref(
{} as RegistratorContract.Tables.Organizations.IOrganization
);
const publicCooperativeData = ref<RegistratorContract.Tables.Cooperatives.ICooperative>();
const contacts = ref({} as Cooperative.Model.IContacts)
const privateCooperativeData = ref<Cooperative.Model.ICooperativeData>()
const contacts = ref<Cooperative.Model.IContacts>()
const loadContacts = async(): Promise<void> => {
contacts.value = await api.loadCooperativeData()
contacts.value = await api.loadContacts()
}
const loadPrivateCooperativeData = async(): Promise<void> => {
privateCooperativeData.value = await api.loadPrivateCooperativeData()
}
const loadPublicCooperativeData = async (
@@ -72,9 +78,11 @@ export const useCooperativeStore = defineStore(
loadAddresses,
loadContacts,
loadPublicCooperativeData,
loadPrivateCooperativeData,
marketPrograms,
addresses,
contacts,
privateCooperativeData,
publicCooperativeData,
loadAdmins,
admins,
@@ -21,12 +21,12 @@ async function loadCopenomicsAccount(
await fetchTable(
RegistratorContract.contractName.production,
RegistratorContract.contractName.production,
RegistratorContract.Tables.Organizations.tableName,
RegistratorContract.Tables.Cooperatives.tableName,
username,
username,
LimitsList.One
)
)[0] as RegistratorContract.Tables.Organizations.IOrganization;
)[0] as RegistratorContract.Tables.Cooperatives.ICooperative;
const account = (
await fetchTable(
@@ -41,6 +41,6 @@ export interface IUserAccountData {
export interface ICopenomicsAccount
extends Partial<RegistratorContract.Tables.Accounts.IAccount>,
Partial<RegistratorContract.Tables.Organizations.IOrganization> {}
Partial<RegistratorContract.Tables.Cooperatives.ICooperative> {}
export type IBlockchainAccountResult = AccountResult;
@@ -8,7 +8,7 @@ export function useUpdateBoard() {
data: SovietContract.Actions.Boards.UpdateBoard.IUpdateBoard
): Promise<TransactResult | undefined> {
const session = useSessionStore();
console.log('action: ', data)
const result = useGlobalStore().transact({
account: SovietContract.contractName.production,
name: SovietContract.Actions.Boards.UpdateBoard.actionName,
@@ -1,22 +1,20 @@
<template lang="pug">
div
p here {{tab}}
q-tabs( v-model="tab" dense switch-indicator inline-label outside-arrows mobile-arrows align="justify" active-bg-color="teal" active-color="white" indicator-color="secondary")
q-tab(name="Дашборд" label="Дашборд")
q-tabs( v-model="tab" dense switch-indicator inline-label outside-arrows mobile-arrows align="justify" active-bg-color="teal" active-color="white" indicator-color="secondary" style="border-bottom: 1px solid teal;")
q-tab(name="Реквизиты" label="Реквизиты")
q-tab(name="Члены совета" label="Совет")
q-tab(name="Совет" label="Совет")
q-tab(name="Администраторы" label="Администраторы")
//- q-tab(name="Участки" label="Участки")
q-tab(name="Кооператив" label="Кооператив")
//- q-tab(name="Администраторы" label="Администраторы")
q-tab(name="Участки" label="Участки")
//- q-tab(name="Фонды" label="Фонды")
q-tab(name="Фонды" label="Фонды")
//- q-tab(name="Контакты" label="Контакты")
//- // q-tab(name="Программы" label="Программы")
//- // q-tab(name="Собрания" icon="people" label="Собрания")
//- p info {{ info }}
q-tab-panels(
v-model="tab"
@@ -24,56 +22,57 @@ div
transition-prev="fade"
transition-next="fade"
)
// q-tab-panel(name="Дашборд")
// p Дашборд
//- q-tab-panel(name="Кооператив")
//- cooperative
// boards.col-md-12.col-xs-12.q-pa-md
q-tab-panel(name="Реквизиты")
CooperativeDetails
//- q-tab-panel(name="Члены совета")
//- members
q-tab-panel(name="Совет")
CooperativeMembers
q-tab-panel(name="Участки")
p Действующие участки
p Входящие заявления на создание участка
p Связь с участками
q-tab-panel(name="Администраторы")
//- staff
//- q-tab-panel(name="Участки")
//- p Действующие участки
//- p Входящие заявления на создание участка
//- p Связь с участками
q-tab-panel(name="Повестка")
//- decisions
//- q-tab-panel(name="Администраторы")
//- //- staff
q-tab-panel(name="Пайщики")
//- participants
//- q-tab-panel(name="Повестка")
//- //- decisions
q-tab-panel(name="Документы")
//- documents(:receiver="coopname")
//- q-tab-panel(name="Пайщики")
//- //- participants
q-tab-panel(name="Программы")
div.text-h6 Программы
p Lorem ipsum dolor sit amet consectetur adipisicing elit.
//- q-tab-panel(name="Документы")
//- //- documents(:receiver="coopname")
q-tab-panel(name="Собрания")
div.text-h6 Собрания
p Lorem ipsum dolor sit amet consectetur adipisicing elit.
//- q-tab-panel(name="Программы")
//- div.text-h6 Программы
//- p Lorem ipsum dolor sit amet consectetur adipisicing elit.
q-tab-panel(name="Фонды")
div.text-h6 Фонды
p Lorem ipsum dolor sit amet consectetur adipisicing elit.
//- q-tab-panel(name="Фонды")
//- div.text-h6 Фонды
//- p Lorem ipsum dolor sit amet consectetur adipisicing elit.
</template>
<script setup lang="ts">//
import { computed, ref } from 'vue'
import { COOPNAME } from 'src/shared/config'
const coopname = computed(() => COOPNAME)
const tab = ref('Дашборд')
console.log(coopname)
import { computed, ref } from 'vue'
import { CooperativeDetails } from 'src/widgets/Cooperative/Details';
import { CooperativeMembers } from 'src/widgets/Cooperative/Members';
// import { COOPNAME } from 'src/shared/config'
import { useCooperativeStore } from 'src/entities/Cooperative';
// const coopname = computed(() => COOPNAME)
const tab = ref('Реквизиты')
</script>
const coop = useCooperativeStore()
coop.loadPrivateCooperativeData()
// const info = computed(() => coop.privateCooperativeData)
</script>
<style>
.q-tab-panel {
padding: 0px !important;
@@ -0,0 +1 @@
export const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
@@ -45,7 +45,8 @@ watch(step, (newValue) => {
createInitialPayment()
})
const initialPayment = computed(() => user.userAccount?.type === 'organization' ? parseFloat(coop.publicCooperativeData.org_registration) : parseFloat(coop.publicCooperativeData.registration))
const initialPayment = computed(() => user.userAccount?.type === 'organization' ? parseFloat(String(coop.publicCooperativeData?.org_registration)) : parseFloat(String(coop.publicCooperativeData?.registration)))
const baseFee = ref(parseFloat(BASE_PAYMENT_FEE))
const toPay = computed(() => {
@@ -1,12 +1,13 @@
<template lang="pug">
q-card(v-if="contacts && contacts.details" flat bordered).q-pa-sm
q-input(type="textarea" autogrow readonly label="Наименование организации" v-model="contacts.full_name")
q-input(type="textarea" autogrow readonly label="ИНН" v-model="contacts.details.inn")
q-input(type="textarea" autogrow readonly label="ОГРН" v-model="contacts.details.ogrn")
q-input(type="textarea" autogrow readonly label="Юридический адрес" v-model="contacts.full_address")
q-input(type="textarea" autogrow readonly label="Телефон" v-model="contacts.phone")
q-input(type="textarea" autogrow readonly label="Электронная почта" v-model="contacts.email")
q-input(type="textarea" autogrow readonly label="Председатель" v-model="chairman")
div
q-card(v-if="contacts && contacts.details" flat bordered).q-pa-sm
q-input(type="textarea" autogrow readonly label="Наименование организации" v-model="contacts.full_name")
q-input(type="textarea" autogrow readonly label="ИНН" v-model="contacts.details.inn")
q-input(type="textarea" autogrow readonly label="ОГРН" v-model="contacts.details.ogrn")
q-input(type="textarea" autogrow readonly label="Юридический адрес" v-model="contacts.full_address")
q-input(type="textarea" autogrow readonly label="Телефон" v-model="contacts.phone")
q-input(type="textarea" autogrow readonly label="Электронная почта" v-model="contacts.email")
q-input(type="textarea" autogrow readonly label="Председатель" v-model="chairman")
</template>
@@ -0,0 +1 @@
export * from './ui'
@@ -0,0 +1,30 @@
<template lang="pug">
div
q-card(v-if="details" flat bordered).q-pa-sm
q-input(type="textarea" autogrow readonly label="Полное наименование" v-model="details.full_name")
q-input(type="textarea" autogrow readonly label="Сокращенное наименование" v-model="details.short_name")
q-input(type="textarea" autogrow readonly label="ИНН" v-model="details.details.inn")
q-input(type="textarea" autogrow readonly label="ОГРН" v-model="details.details.ogrn")
q-input(type="textarea" autogrow readonly label="Юридический адрес" v-model="details.full_address")
q-input(type="textarea" autogrow readonly label="Телефон" v-model="details.phone")
q-input(type="textarea" autogrow readonly label="Электронная почта" v-model="details.email")
q-input(type="textarea" autogrow readonly label="Председатель" v-model="chairman")
q-input(type="textarea" autogrow readonly label="Наименование банка" v-model="details.bank_account.bank_name")
q-input(type="textarea" autogrow readonly label="БИК" v-model="details.bank_account.details.bik")
q-input(type="textarea" autogrow readonly label="Корреспондентский счёт" v-model="details.bank_account.details.corr")
q-input(type="textarea" autogrow readonly label="Номер счета" v-model="details.bank_account.account_number")
</template>
<script lang="ts" setup>
import { useCooperativeStore } from 'src/entities/Cooperative';
import { computed } from 'vue';
const cooperative = useCooperativeStore()
cooperative.loadContacts()
const details = computed(() => cooperative.privateCooperativeData)
const chairman = computed(() => `${details.value?.chairman?.last_name} ${details.value?.chairman?.first_name} ${details.value?.chairman?.middle_name}`)
</script>
@@ -0,0 +1 @@
export {default as CooperativeDetails} from './Details.vue'
@@ -0,0 +1 @@
export * from './ui'
@@ -0,0 +1,227 @@
<template lang="pug">
div
div(v-if="members")
q-card(v-if="members.length > 0" flat)
q-table(
ref="tableRef" flat
bordered
:rows="members"
:columns="columns"
:table-colspan="9"
row-key="username"
:pagination="pagination"
virtual-scroll
:virtual-scroll-item-size="48"
:rows-per-page-options="[10]"
).full-height
template(#top)
q-btn(icon="add" @click="showAdd = true") добавить участника
template(#header="props")
q-tr(:props="props")
q-th(
v-for="col in props.cols"
:key="col.name"
:props="props"
) {{ col.label }}
q-th(auto-width)
template(#body="props")
q-tr(:key="`m_${props.row.username}`" :props="props")
q-td {{ props.row.position_title }}
q-td {{ props.row.username }}
q-td {{ props.row.last_name }}
q-td {{ props.row.first_name }}
q-td {{ props.row.middle_name }}
q-td {{ props.row.phone }}
q-td {{ props.row.email }}
q-td(auto-width)
q-btn(size="sm" color="red" dense @click="removeMember(props.row.username)" :loading="showLoading") удалить
q-dialog(v-model="showAdd" persistent :maximized="false" )
q-card
div()
q-bar.bg-primary.text-white
span Добавить члена совета
q-space
q-btn(v-close-popup dense flat icon="close")
q-tooltip Close
div.q-pa-sm
div.q-pa-md
p Внимание! Вы собираетесь добавить участника в совет кооператива. Введите идентификатор аккаунта для добавления:
div.q-pa-md
q-input(v-model="persona.username" label="Идентификатор имени аккаунта" filled)
//- q-input(v-model="persona.position_title" label="Позиция")
div
q-btn(flat @click="showAdd = false") Отменить
q-btn(color="primary" @click="addMember" :loading="showLoading") Добавить
</template>
<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { Notify } from 'quasar';
import moment from 'moment-with-locales-es6'
import { readBlockchain } from 'src/shared/api'
import { useSessionStore } from 'src/entities/Session';
import { useUpdateBoard } from 'src/features/Cooperative/UpdateBoard';
import { COOPNAME } from 'src/shared/config';
import { useCooperativeStore } from 'src/entities/Cooperative';
import { sleep } from 'src/shared/api/sleep';
const coop = useCooperativeStore()
const showAdd = ref(false)
const members = computed(() => coop.privateCooperativeData?.members || [])
let members_reserve: any = []
const persona = ref({
username: '',
position_title: 'Член совета',
})
watch(members, () => {
members_reserve = JSON.parse(JSON.stringify(members.value))
})
const loadMembers = async () => {
coop.loadPrivateCooperativeData()
}
const showLoading = ref(false)
loadMembers()
const addMember = async () => {
const verified = await verify(persona.value.username)
if (!verified) {
Notify.create({
message: 'Имя аккаунта на найдено',
type: 'negative',
})
return
}
let members_for_send = members.value.map((el: { username: any; position_title: any; position: any; is_voting: any; }) => {
return {
username: el.username,
position_title: el.position_title,
position: el.position,
is_voting: el.is_voting
}
})
members_for_send.push({ username: persona.value.username, position_title: persona.value.position_title, position: 'member', is_voting: true });
showLoading.value = true
try {
await updateBoard(members_for_send)
} catch(e:any){
}
showLoading.value = false
showAdd.value = false
};
const removeMember = async (username: string) => {
let members_for_send = members.value.map((el: { username: any; position_title: any; position: any; is_voting: any; }) => {
return {
username: el.username,
position_title: el.position_title,
position: el.position,
is_voting: el.is_voting
}
})
members_for_send = members_for_send.filter((el: { username: string; }) => el.username != username)
showLoading.value = true
try {
await updateBoard(members_for_send)
} catch(e:any){
}
showLoading.value = false
};
const verify = async (username: string) => {
try {
await readBlockchain.v1.chain.get_account(username);
return true;
} catch (e) {
return false;
}
};
const updateBoard = async (new_members: any) => {
try {
const coop = useUpdateBoard()
await coop.updateBoard({
coopname: COOPNAME,
chairman: useSessionStore().username,
board_id: 0,
members: new_members,
name: 'Совет',
description: 'Совет кооператива'
})
await sleep(3000)
Notify.create({
message: 'Совет обновлен',
type: 'positive',
})
loadMembers()
} catch (e: any) {
loadMembers()
Notify.create({
message: e.message,
type: 'negative',
})
}
}
const columns = [
{ name: 'position_title', align: 'left', label: 'Позиция', field: 'position_title', sortable: true },
{ name: 'username', align: 'left', label: 'Аккаунт', field: 'username', sortable: true },
{ name: 'last_name', align: 'left', label: 'Фамилия', field: 'last_name', sortable: true },
{ name: 'first_name', align: 'left', label: 'Имя', field: 'first_name', sortable: true },
{ name: 'middle_name', align: 'left', label: 'Отчество', field: 'middle_name', sortable: true },
{ name: 'phone', align: 'left', label: 'Телефон', field: 'phone', sortable: false },
{ name: 'email', align: 'left', label: 'Е-почта', field: 'email', sortable: false },
] as any
const tableRef = ref(null)
const pagination = ref({ rowsPerPage: 10 })
</script>
@@ -0,0 +1 @@
export { default as CooperativeMembers} from './Members.vue'
+1 -1
View File
@@ -16,7 +16,7 @@
"scripts": {
"dev": "lerna run dev --parallel",
"gpt-commit": "git add . && commitgpt",
"testnet": "git checkout testnet && git merge dev && lerna publish prerelease && git push && git checkout dev",
"testnet": "git checkout testnet && git merge dev && lerna publish prerelease && git push && git checkout dev && git merge testnet",
"production": "git checkout main && git merge -X theirs testnet && lerna publish --conventional-commits --conventional-graduate && git push && git checkout dev && git merge main"
}
}
+11878 -9337
View File
File diff suppressed because it is too large Load Diff