瀏覽代碼

Отображение pe

Vadim 3 月之前
父節點
當前提交
85103b8078

+ 67 - 18
src/api/v_0.1.0/client/client-pe-api.ts

@@ -1,5 +1,4 @@
 import {
-  CustomField,
   CustomFieldWithUserCopyValue,
   CustomFieldWithValue,
 } from "../types/pe-types.js";
@@ -36,40 +35,90 @@ class ClientPartEntitiesApi {
     }),
   };
 
-  GET_PartEntities = {
+  GET_MyPes = {
     res: z.object({
       code: z.enum(["success"]),
-      partEntities: z.array(
-        z.object({ peId: z.string().uuid(), name: z.string() }),
+      owner: z.array(
+        z.object({
+          peId: z.string().uuid(),
+          peTypeId: z.string().uuid(),
+          peTypeCode: z.string(),
+          peTypeName: z.string(),
+          name: z.string(),
+          eventInstId: z.string().uuid(),
+          ownerId: z.string().uuid(),
+        }),
+      ),
+      memeber: z.array(
+        z.object({
+          peMemberId: z.string().uuid(),
+          peId: z.string().uuid(),
+          peTypeId: z.string().uuid(),
+          peTypeCode: z.string(),
+          peTypeName: z.string(),
+          eventInstId: z.string().uuid(),
+          ownerId: z.string().uuid(),
+          name: z.string(),
+        }),
       ),
     }),
   };
 
-  GET_OwnerPartEntity = {
+  GET_PartEntity = {
     req: z.object({
       peId: z.string().uuid(),
     }),
     res: z.object({
       code: z.enum(["success"]),
-      pe: z.object({
-        peId: z.string().uuid(),
-        name: z.string(),
-        fileds: z.array(CustomFieldWithValue),
-        members: z.array(
-          z.object({
-            memberId: z.string(),
-            userId: z.string().uuid(),
-            email: z.string().email(),
-            fileds: z.array(CustomFieldWithValue),
-          }),
-        ),
-      }),
+      pe: z.discriminatedUnion("userRole", [
+        z.object({
+          userRole: z.literal("owner"),
+          peId: z.string().uuid(),
+          peTypeId: z.string().uuid(),
+          peTypeCode: z.string(),
+          peTypeName: z.string(),
+          eventInstId: z.string().uuid(),
+          name: z.string(),
+          ownerId: z.string().uuid(),
+          fields: z.array(CustomFieldWithValue),
+          members: z.array(
+            z.object({
+              memberId: z.string(),
+              userId: z.string().uuid(),
+              email: z.string().email(),
+              fields: z.array(CustomFieldWithValue),
+            }),
+          ),
+          invites: z.array(
+            z.object({
+              peInviteId: z.string().uuid(),
+              peInviteUuid: z.string().uuid(),
+              name: z.string(),
+              limitVal: z.number().int(),
+              countVal: z.number().int(),
+            }),
+          ),
+        }),
+
+        z.object({
+          userRole: z.literal("member"),
+          peMemberId: z.string().uuid(),
+          peId: z.string().uuid(),
+          peTypeId: z.string().uuid(),
+          peTypeCode: z.string(),
+          peTypeName: z.string(),
+          eventInstId: z.string().uuid(),
+          ownerId: z.string().uuid(),
+          name: z.string(),
+        }),
+      ]),
     }),
   };
 
   POST_PartEntity = {
     req: z.object({
       peTypeId: z.string().uuid(),
+      name: z.string(),
       form: z.array(
         z.object({
           peFfId: z.string().uuid(),

+ 8 - 3
src/api/v_0.1.0/types/pe-types.ts

@@ -24,12 +24,17 @@ export const CustomField = z.object({
   options: z.array(z.string()).nullable(),
 });
 
-export const CustomFieldWithValidators = z.object({
+export const CustomFieldWithValidators = CustomField.extend({
   validators: z.array(Validator),
 });
 
-export const CustomFieldWithValue = z.object({
-  value: z.string(),
+export const CustomFieldWithValidatorsAndValue =
+  CustomFieldWithValidators.extend({
+    value: z.string().nullable(),
+  });
+
+export const CustomFieldWithValue = CustomField.extend({
+  value: z.string().nullable(),
 });
 
 export const CustomFieldWithUserCopyValue = CustomFieldWithValidators.extend({

+ 225 - 79
src/modules/client/activities/participant-entities/c-pe-controller.ts

@@ -13,7 +13,10 @@ import { RouterUtils } from "#utils/router-utils.js";
 
 import { Request, Response } from "express";
 import sessionService from "#modules/users/auth/services/session-service.js";
-import { CustomFieldWithUserCopyValue } from "#api/v_0.1.0/types/pe-types.js";
+import {
+  CustomFieldWithUserCopyValue,
+  CustomFieldWithValue,
+} from "#api/v_0.1.0/types/pe-types.js";
 import { ApiError } from "#exceptions/api-error.js";
 import { v7 } from "uuid";
 
@@ -61,10 +64,10 @@ class ClientPeController {
     const userId = user.userId;
     const peType = await selPool.maybeOne(sql.type(
       z.object({
-        peTypeId: z.string(),
-        code: z.string(),
-        name: z.string(),
-        eventInstId: z.string(),
+        peTypeId: DbSchema.act.peTypes.peTypeId,
+        code: DbSchema.act.peTypes.code,
+        name: DbSchema.act.peTypes.name,
+        eventInstId: DbSchema.act.peTypes.eventInstId,
         fields: z.array(
           CustomFieldWithUserCopyValue.extend({ isCopyUserValue: z.boolean() }),
         ),
@@ -75,7 +78,7 @@ class ClientPeController {
         pt.code,
         pt.name,
         pt.event_inst_id as "eventInstId",
-        coalesce(json_agg(jsonb_build_object(
+        coalesce(jsonb_agg(jsonb_build_object(
         'fieldDefinitionId',
         cfwv.field_definition_id,
         'peFfId',
@@ -98,7 +101,7 @@ class ClientPeController {
         cfwv.validators)) filter (
       where
         cfwv.field_definition_id is not null),
-        '[]'::json) as fields
+        '[]'::jsonb) as fields
       from
         act.pe_types pt
         --	необходимые поля
@@ -135,10 +138,10 @@ class ClientPeController {
     });
   }
 
-  async createPeType(req: Request, res: Response) {
+  async createPe(req: Request, res: Response) {
     const event = await sessionService.getCurrentEventFromReq(req);
     const user = sessionService.getUserFromReq(req);
-    const { form, peTypeId } = api.client.pe.POST_PartEntity.req.parse(
+    const { form, peTypeId, name } = api.client.pe.POST_PartEntity.req.parse(
       req.body,
     );
 
@@ -146,9 +149,9 @@ class ClientPeController {
       const peId = v7();
       await t.query(sql.unsafe`
         insert into act.part_entities 
-          (pe_id, pe_type_id, event_inst_id, owner_id) 
+          (pe_id, pe_type_id, event_inst_id, owner_id, name) 
         values 
-          (${peId}, ${peTypeId}, ${event.eventInstId}, ${user.userId})
+          (${peId}, ${peTypeId}, ${event.eventInstId}, ${user.userId}, ${name})
       `);
 
       for (const field of form) {
@@ -167,87 +170,230 @@ class ClientPeController {
     });
   }
 
-  async getOwnerPe(req: Request, res: Response) {
+  async getMyPes(req: Request, res: Response) {
     const user = sessionService.getUserFromReq(req);
-    const { peId } = api.client.pe.GET_OwnerPartEntity.req.parse(req.body);
+    const event = await sessionService.getCurrentEventFromReq(req);
 
-    // TODO: заменить типы бд
-    const pe = await selPool.maybeOne(sql.type(
+    const ownerPes = await selPool.any(sql.type(
       z.object({
-        peTypeId: z.string().uuid(),
-        code: z.string(),
-        name: z.string(),
-        eventInstId: z.string().uuid(),
-        ownerId: z.string().uuid(),
-        fields: z.array(
-          CustomFieldWithUserCopyValue.extend({ isCopyUserValue: z.boolean() }),
-        ),
+        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,
+        ownerId: DbSchema.act.partEntities.ownerId,
+        name: DbSchema.act.partEntities.name,
+      }),
+    )`
+        select
+          pe.pe_id "peId",
+          pe.event_inst_id "eventInstId",
+          pe.owner_id "ownerId",
+          pe.pe_type_id "peTypeId",
+          pt.code "peTypeCode",
+          pt."name" "peTypeName",
+          pe."name"
+        from
+          act.part_entities pe
+        join act.pe_types pt on
+          pt.pe_type_id = pe.pe_type_id
+        where
+          pe.event_inst_id = ${event.eventInstId}
+          and pe.owner_id = ${user.userId}
+    `);
+
+    const memberPes = await selPool.any(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,
+        eventInstId: DbSchema.act.partEntities.eventInstId,
+        ownerId: DbSchema.act.partEntities.ownerId,
+        name: DbSchema.act.partEntities.name,
       }),
     )`
       select
-        pt.pe_type_id as "peTypeId",
-        pt.code,
-        pt.name,
-        pt.event_inst_id as "eventInstId",
-        pe.owner_id as "ownerId",
-        coalesce(json_agg(jsonb_build_object(
-        'fieldDefinitionId',
-        cfwv.field_definition_id,
-        'peFfId',
-        pff.pe_ff_id,
-        'isCopyUserValue',
-        pff.is_copy_user_value,
-        'code',
-        cfwv.code,
-        'value',
-        pfv.value,
-        'fieldTypeCode',
-        cfwv.field_type_code,
-        'title',
-        COALESCE(pff.field_title_override, cfwv.title),
-        'mask',
-        cfwv.mask,
-        'options',
-        cfwv.options,
-        'validators',
-        cfwv.validators)) filter (
-      where
-        cfwv.field_definition_id is not null),
-        '[]'::json) as fields
+        pm.pe_member_id "peMemberId",
+        pe.pe_id "peId",
+        pe.event_inst_id "peInstId",
+        pe.owner_id "ownerId",
+        pe.pe_type_id "peTypeId",
+        pt.code "peTypeCode",
+        pt."name" "peTypeName",
+        pe."name"
       from
-      	act.part_entities pe 
+        act.pe_members pm
+      join act.part_entities pe on
+        pe.pe_id = pm.pe_id
       join act.pe_types pt on
-      	pt.pe_type_id = pe.pe_type_id
-        --	необходимые поля
-      left join act.pe_form_fields pff on
-        pff.pe_type_id = pt.pe_type_id
-        -- значения
-      left join act.pe_field_values pfv on
-      	pff.pe_ff_id = pfv.pe_ff_id 
-      	and 
-      	pff.pe_type_id = pt.pe_type_id 
-      left join cf.custom_fields_with_validators cfwv on
-        pff.field_definition_id = cfwv.field_definition_id
-      where pe.pe_id = ${peId}
-      group by
-        pt.pe_type_id,
-        pt.code,
-        pt.name,
-        pt.event_inst_id,
-        pe.owner_id
+        pt.pe_type_id = pe.pe_type_id
+      where
+        pe.event_inst_id = ${event.eventInstId}
+        and pm.user_id = ${user.userId}
     `);
 
-    if (!pe)
-      throw ApiError.BadRequest("peNotFound", "Сущность участия не найдена");
+    RouterUtils.validAndSendResponse(api.client.pe.GET_MyPes.res, res, {
+      code: "success",
+      owner: [...ownerPes],
+      memeber: [...memberPes],
+    });
+  }
 
-    RouterUtils.validAndSendResponse(
-      api.client.pe.GET_OwnerPartEntity.res,
-      res,
-      {
+  async getPe(req: Request, res: Response) {
+    const user = sessionService.getUserFromReq(req);
+    const { peId } = api.client.pe.GET_PartEntity.req.parse(req.params);
+
+    const isOwner = await selPool.exists(
+      sql.unsafe`
+        select
+          pe_id
+        from
+          act.part_entities pe
+        where
+          pe.owner_id = ${user.userId}
+          and pe.pe_id = ${peId}
+      `,
+    );
+
+    // валделец
+    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
+    `);
+
+      if (!pe)
+        throw ApiError.BadRequest("peNotFound", "Сущность участия не найдена");
+      if (pe.ownerId !== user.userId) throw ApiError.ForbiddenError();
+
+      RouterUtils.validAndSendResponse(api.client.pe.GET_PartEntity.res, res, {
         code: "success",
-        pe: pe,
-      },
+        pe: { ...pe, userRole: "owner" },
+      });
+      return;
+    }
+
+    // участник
+    const isMember = await selPool.exists(
+      sql.unsafe`
+        select
+          pm.pe_id
+        from
+          act.pe_members pm
+        where 
+          pm.user_id = ${user.userId}
+          and pm.pe_id = ${peId}
+      `,
     );
+
+    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}
+  `);
+    if (!pe)
+      throw ApiError.BadRequest("peNotFound", "Сущность участия не найдена");
+
+    RouterUtils.validAndSendResponse(api.client.pe.GET_PartEntity.res, res, {
+      code: "success",
+      pe: { ...pe, userRole: "member" },
+    });
   }
 }
 

+ 5 - 4
src/modules/client/activities/participant-entities/c-pe-router.ts

@@ -15,7 +15,8 @@ router.get(
   RouterUtils.asyncHandler(clientPeController.getPeTypeForCreate),
 );
 
-router.post(
-  "/peType/create/",
-  RouterUtils.asyncHandler(clientPeController.createPeType),
-);
+router.post("/create/", RouterUtils.asyncHandler(clientPeController.createPe));
+
+router.get("/myPes/", RouterUtils.asyncHandler(clientPeController.getMyPes));
+
+router.get("/:peId", RouterUtils.asyncHandler(clientPeController.getPe));