|
@@ -13,12 +13,10 @@ import { RouterUtils } from "#utils/router-utils.js";
|
|
|
|
|
|
import { Request, Response } from "express";
|
|
import { Request, Response } from "express";
|
|
import sessionService from "#modules/users/auth/services/session-service.js";
|
|
import sessionService from "#modules/users/auth/services/session-service.js";
|
|
-import {
|
|
|
|
- CustomFieldWithUserCopyValue,
|
|
|
|
- CustomFieldWithValue,
|
|
|
|
-} from "#api/v_0.1.0/types/pe-types.js";
|
|
|
|
|
|
+import { CustomFieldWithUserCopyValue } from "#api/v_0.1.0/types/pe-types.js";
|
|
import { ApiError } from "#exceptions/api-error.js";
|
|
import { ApiError } from "#exceptions/api-error.js";
|
|
-import { v7 } from "uuid";
|
|
|
|
|
|
+import { v4, v7 } from "uuid";
|
|
|
|
+import { cPeService } from "./c-pe-service.js";
|
|
|
|
|
|
class ClientPeController {
|
|
class ClientPeController {
|
|
async getEventPeTypes(
|
|
async getEventPeTypes(
|
|
@@ -209,7 +207,6 @@ class ClientPeController {
|
|
peTypeId: DbSchema.act.partEntities.peTypeId,
|
|
peTypeId: DbSchema.act.partEntities.peTypeId,
|
|
peTypeCode: DbSchema.act.peTypes.code,
|
|
peTypeCode: DbSchema.act.peTypes.code,
|
|
peTypeName: DbSchema.act.peTypes.name,
|
|
peTypeName: DbSchema.act.peTypes.name,
|
|
- eventInstId: DbSchema.act.partEntities.eventInstId,
|
|
|
|
ownerId: DbSchema.act.partEntities.ownerId,
|
|
ownerId: DbSchema.act.partEntities.ownerId,
|
|
name: DbSchema.act.partEntities.name,
|
|
name: DbSchema.act.partEntities.name,
|
|
}),
|
|
}),
|
|
@@ -259,77 +256,9 @@ class ClientPeController {
|
|
|
|
|
|
// валделец
|
|
// валделец
|
|
if (isOwner) {
|
|
if (isOwner) {
|
|
- const pe = await selPool.maybeOne(sql.type(
|
|
|
|
- z.object({
|
|
|
|
- peId: DbSchema.act.partEntities.peId,
|
|
|
|
- peTypeId: DbSchema.act.partEntities.peTypeId,
|
|
|
|
- peTypeCode: DbSchema.act.peTypes.code,
|
|
|
|
- peTypeName: DbSchema.act.peTypes.name,
|
|
|
|
- eventInstId: DbSchema.act.partEntities.eventInstId,
|
|
|
|
- name: DbSchema.act.partEntities.name,
|
|
|
|
- ownerId: DbSchema.act.partEntities.ownerId,
|
|
|
|
- fields: z.array(CustomFieldWithValue),
|
|
|
|
- members: z.array(
|
|
|
|
- z.object({
|
|
|
|
- memberId: DbSchema.act.peMembers.peMemberId,
|
|
|
|
- userId: DbSchema.act.peMembers.userId,
|
|
|
|
- email: DbSchema.usr.users.email,
|
|
|
|
- fields: z.array(CustomFieldWithValue),
|
|
|
|
- }),
|
|
|
|
- ),
|
|
|
|
- invites: z.array(
|
|
|
|
- z.object({
|
|
|
|
- peInviteId: DbSchema.act.peInvites.peInviteId,
|
|
|
|
- peInviteUuid: DbSchema.act.peInvites.peInviteUuid,
|
|
|
|
- name: DbSchema.act.peInvites.name,
|
|
|
|
- limitVal: DbSchema.act.peInvites.limitVal,
|
|
|
|
- countVal: DbSchema.act.peInvites.countVal,
|
|
|
|
- }),
|
|
|
|
- ),
|
|
|
|
- }),
|
|
|
|
- )`
|
|
|
|
- select
|
|
|
|
- pe.pe_id "peId",
|
|
|
|
- pe.pe_type_id "peTypeId",
|
|
|
|
- pe.pe_type_code "peTypeCode",
|
|
|
|
- pe.pe_type_name "peTypeName",
|
|
|
|
- pe.event_inst_id "eventInstId",
|
|
|
|
- pe.name,
|
|
|
|
- pe.owner_id "ownerId",
|
|
|
|
- pe.fields::jsonb,
|
|
|
|
- pe.members::jsonb,
|
|
|
|
- coalesce(jsonb_agg(jsonb_build_object(
|
|
|
|
- 'peInviteId',
|
|
|
|
- i.pe_invite_id,
|
|
|
|
- 'peInviteUuid',
|
|
|
|
- i.pe_invite_uuid,
|
|
|
|
- 'name',
|
|
|
|
- i."name",
|
|
|
|
- 'limitVal',
|
|
|
|
- i.limit_val,
|
|
|
|
- 'countVal',
|
|
|
|
- i.count_val
|
|
|
|
- )) filter (
|
|
|
|
- where
|
|
|
|
- i.pe_id is not null),
|
|
|
|
- '[]'::jsonb) as invites
|
|
|
|
- from
|
|
|
|
- act.pe_with_fields_and_members pe
|
|
|
|
- left join act.pe_invites i on
|
|
|
|
- i.pe_id = pe.pe_id
|
|
|
|
- where
|
|
|
|
- pe.pe_id = ${peId}
|
|
|
|
- group by
|
|
|
|
- pe.pe_id,
|
|
|
|
- pe.pe_type_id,
|
|
|
|
- pe.pe_type_code,
|
|
|
|
- pe.pe_type_name,
|
|
|
|
- pe.event_inst_id,
|
|
|
|
- pe.name,
|
|
|
|
- pe.owner_id,
|
|
|
|
- pe.fields,
|
|
|
|
- pe.members
|
|
|
|
- `);
|
|
|
|
|
|
+ const pe = await cPeService.getPeWithFieldsAndValues(peId);
|
|
|
|
+ const members = await cPeService.getMembers(peId);
|
|
|
|
+ const invites = await cPeService.getInvites(peId);
|
|
|
|
|
|
if (!pe)
|
|
if (!pe)
|
|
throw ApiError.BadRequest("peNotFound", "Сущность участия не найдена");
|
|
throw ApiError.BadRequest("peNotFound", "Сущность участия не найдена");
|
|
@@ -337,7 +266,12 @@ class ClientPeController {
|
|
|
|
|
|
RouterUtils.validAndSendResponse(api.client.pe.GET_PartEntity.res, res, {
|
|
RouterUtils.validAndSendResponse(api.client.pe.GET_PartEntity.res, res, {
|
|
code: "success",
|
|
code: "success",
|
|
- pe: { ...pe, userRole: "owner" },
|
|
|
|
|
|
+ pe: {
|
|
|
|
+ ...pe,
|
|
|
|
+ members: [...members],
|
|
|
|
+ invites: [...invites],
|
|
|
|
+ userRole: "owner",
|
|
|
|
+ },
|
|
});
|
|
});
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -357,36 +291,7 @@ class ClientPeController {
|
|
|
|
|
|
if (!isMember) throw ApiError.ForbiddenError();
|
|
if (!isMember) throw ApiError.ForbiddenError();
|
|
|
|
|
|
- const pe = await selPool.maybeOne(sql.type(
|
|
|
|
- z.object({
|
|
|
|
- peMemberId: DbSchema.act.peMembers.peMemberId,
|
|
|
|
- peId: DbSchema.act.partEntities.peId,
|
|
|
|
- peTypeId: DbSchema.act.partEntities.peTypeId,
|
|
|
|
- peTypeCode: DbSchema.act.peTypes.code,
|
|
|
|
- peTypeName: DbSchema.act.peTypes.name,
|
|
|
|
- name: DbSchema.act.partEntities.name,
|
|
|
|
- eventInstId: DbSchema.act.partEntities.eventInstId,
|
|
|
|
- ownerId: DbSchema.act.partEntities.ownerId,
|
|
|
|
- }),
|
|
|
|
- )`
|
|
|
|
- select
|
|
|
|
- pm.pe_member_id "peMemberId",
|
|
|
|
- pe.pe_id "peId",
|
|
|
|
- pt.pe_type_id "peTypeId",
|
|
|
|
- pt.code "peTypeCode",
|
|
|
|
- pt.name "peTypeName",
|
|
|
|
- pe.event_inst_id "eventInstId",
|
|
|
|
- pe.owner_id "ownerId",
|
|
|
|
- pe.name
|
|
|
|
- from
|
|
|
|
- act.pe_members pm
|
|
|
|
- left join act.part_entities pe on
|
|
|
|
- pe.pe_id = pm.pe_member_id
|
|
|
|
- left join act.pe_types pt on
|
|
|
|
- pt.pe_type_id = pe.pe_type_id
|
|
|
|
- where
|
|
|
|
- pe.pe_id = ${peId}
|
|
|
|
- `);
|
|
|
|
|
|
+ const pe = await cPeService.getSimplePe(peId);
|
|
if (!pe)
|
|
if (!pe)
|
|
throw ApiError.BadRequest("peNotFound", "Сущность участия не найдена");
|
|
throw ApiError.BadRequest("peNotFound", "Сущность участия не найдена");
|
|
|
|
|
|
@@ -395,6 +300,136 @@ class ClientPeController {
|
|
pe: { ...pe, userRole: "member" },
|
|
pe: { ...pe, userRole: "member" },
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ async createInvite(req: Request, res: Response) {
|
|
|
|
+ const user = sessionService.getUserFromReq(req);
|
|
|
|
+ const { name, limitVal, expirationDate } =
|
|
|
|
+ api.client.pe.POST_Invite.req.body.parse(req.body);
|
|
|
|
+ const { peId } = api.client.pe.POST_Invite.req.params.parse(req.params);
|
|
|
|
+
|
|
|
|
+ const isOwner = await cPeService.checkPeOwner(user.userId, peId);
|
|
|
|
+
|
|
|
|
+ if (!isOwner) throw ApiError.ForbiddenError();
|
|
|
|
+
|
|
|
|
+ const peInviteId = v7();
|
|
|
|
+ const peInviteUuid = v4();
|
|
|
|
+
|
|
|
|
+ await updPool.transaction(async (t) => {
|
|
|
|
+ await t.query(sql.unsafe`
|
|
|
|
+ insert into act.pe_invites
|
|
|
|
+ (pe_invite_id, pe_invite_uuid, pe_id, limit_val, name, expiration_date)
|
|
|
|
+ values
|
|
|
|
+ (${peInviteId}, ${peInviteUuid}, ${peId}, ${limitVal}, ${name}, ${expirationDate})
|
|
|
|
+ `);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ RouterUtils.validAndSendResponse(api.client.pe.POST_Invite.res, res, {
|
|
|
|
+ code: "success",
|
|
|
|
+ peInviteId,
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ async getInvites(req: Request, res: Response) {
|
|
|
|
+ const user = sessionService.getUserFromReq(req);
|
|
|
|
+ const { peId } = api.client.pe.GET_Invites.req.parse(req.params);
|
|
|
|
+
|
|
|
|
+ const isOwner = await cPeService.checkPeOwner(user.userId, peId);
|
|
|
|
+
|
|
|
|
+ if (!isOwner) throw ApiError.ForbiddenError();
|
|
|
|
+
|
|
|
|
+ const invites = await cPeService.getInvites(peId);
|
|
|
|
+
|
|
|
|
+ RouterUtils.validAndSendResponse(api.client.pe.GET_Invites.res, res, {
|
|
|
|
+ code: "success",
|
|
|
|
+ invites: [...invites],
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ async getInviteInfo(req: Request, res: Response) {
|
|
|
|
+ const { peInviteUuid } = api.client.pe.GET_InviteInfo.req.params.parse(
|
|
|
|
+ req.params,
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ const invite = await cPeService.getInviteInfo(peInviteUuid);
|
|
|
|
+
|
|
|
|
+ if (!invite)
|
|
|
|
+ throw ApiError.BadRequest("inviteNotFound", "Приглашение не найдено");
|
|
|
|
+
|
|
|
|
+ RouterUtils.validAndSendResponse(api.client.pe.GET_InviteInfo.res, res, {
|
|
|
|
+ code: "success",
|
|
|
|
+ invite,
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ async acceptInvite(req: Request, res: Response) {
|
|
|
|
+ const user = sessionService.getUserFromReq(req);
|
|
|
|
+ const { peInviteUuid } = api.client.pe.POST_AcceptInvite.req.params.parse(
|
|
|
|
+ req.params,
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ const invite = await cPeService.getInviteInfo(peInviteUuid);
|
|
|
|
+
|
|
|
|
+ if (!invite) {
|
|
|
|
+ RouterUtils.validAndSendResponse(
|
|
|
|
+ api.client.pe.POST_AcceptInvite.res,
|
|
|
|
+ res,
|
|
|
|
+ {
|
|
|
|
+ code: "inviteNotFound",
|
|
|
|
+ },
|
|
|
|
+ 400,
|
|
|
|
+ );
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (invite.limitVal && invite.countVal >= invite.limitVal) {
|
|
|
|
+ RouterUtils.validAndSendResponse(
|
|
|
|
+ api.client.pe.POST_AcceptInvite.res,
|
|
|
|
+ res,
|
|
|
|
+ {
|
|
|
|
+ code: "inviteLimitExceeded",
|
|
|
|
+ },
|
|
|
|
+ 400,
|
|
|
|
+ );
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // TODO: много лишних данных
|
|
|
|
+ const peMembers = await cPeService.getMembers(invite.peId);
|
|
|
|
+ const isFound = peMembers.find((m) => m.userId === user.userId);
|
|
|
|
+ if (isFound) {
|
|
|
|
+ RouterUtils.validAndSendResponse(
|
|
|
|
+ api.client.pe.POST_AcceptInvite.res,
|
|
|
|
+ res,
|
|
|
|
+ {
|
|
|
|
+ code: "peMemberAlreadyExists",
|
|
|
|
+ },
|
|
|
|
+ 400,
|
|
|
|
+ );
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ updPool.transaction(async (t) => {
|
|
|
|
+ t.query(sql.unsafe`
|
|
|
|
+ insert into act.pe_members
|
|
|
|
+ (pe_member_id, pe_id, user_id)
|
|
|
|
+ values
|
|
|
|
+ (${v7()}, ${invite.peId}, ${user.userId})
|
|
|
|
+ `);
|
|
|
|
+
|
|
|
|
+ t.query(sql.unsafe`
|
|
|
|
+ update act.pe_invites
|
|
|
|
+ set
|
|
|
|
+ count_val = count_val + 1
|
|
|
|
+ where
|
|
|
|
+ pe_id = ${invite.peId}
|
|
|
|
+ `);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ RouterUtils.validAndSendResponse(api.client.pe.POST_AcceptInvite.res, res, {
|
|
|
|
+ code: "success",
|
|
|
|
+ peId: invite.peId,
|
|
|
|
+ });
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
export const clientPeController = new ClientPeController();
|
|
export const clientPeController = new ClientPeController();
|