Sfoglia il codice sorgente

Добавлены формы userProfile и createPe

Vadim 3 mesi fa
parent
commit
09bb69172c

+ 25 - 6
src/api/v_0.1.0/client/client-pe-api.ts

@@ -1,27 +1,46 @@
-import { CustomField } from "#api/v_0.1.0/types/pe-types.js";
+import { CustomFieldWithUserCopyValue } from "../types/pe-types.js";
 import { z } from "zod";
 
 class ClientPartEntitiesApi {
-  GET_PartEntities = {
+  GET_EventPeTypes = {
     res: z.object({
       code: z.enum(["success"]),
-      partEntities: z.array(
-        z.object({ peId: z.string().uuid(), name: z.string() }),
+      peTypes: z.array(
+        z.object({
+          peTypeId: z.string().uuid(),
+          code: z.string(),
+          name: z.string(),
+        }),
       ),
     }),
   };
 
-  GET_PeCreateTypeData = {
+  GET_PeType = {
+    req: z.object({
+      peTypeCode: z.string(),
+    }),
     res: z.object({
       code: z.enum(["success"]),
       peType: z.object({
         peTypeId: z.string().uuid(),
         code: z.string(),
-        fields: z.array(CustomField),
+        name: z.string(),
+        fields: z.array(
+          CustomFieldWithUserCopyValue.extend({ isCopyUserValue: z.boolean() }),
+        ),
       }),
     }),
   };
 
+  GET_PartEntities = {
+    res: z.object({
+      code: z.enum(["success"]),
+      partEntities: z.array(
+        z.object({ peId: z.string().uuid(), name: z.string() }),
+      ),
+    }),
+  };
+
   GET_PartEntity = {
     req: z.object({
       peId: z.string().uuid(),

+ 11 - 5
src/api/v_0.1.0/client/client-users-api.ts

@@ -1,4 +1,4 @@
-import { CustomField } from "#api/v_0.1.0/types/pe-types.js";
+import { CustomField } from "../types/pe-types.js";
 import { z } from "zod";
 
 class ClientUsersApi {
@@ -6,17 +6,23 @@ class ClientUsersApi {
     res: z.object({
       code: z.enum(["success"]),
       userData: z.array(
-        CustomField.extend({ userValue: z.string().nullable() }),
+        CustomField.extend({
+          userEfId: z.string().uuid(),
+          value: z.string().nullable(),
+        }),
       ),
     }),
   };
 
   PATCH_UserEventData = {
-    req: {
+    req: z.object({
       userData: z.array(
-        z.object({ fieldDefinitionId: z.string().uuid(), value: z.string() }),
+        z.object({
+          userEfId: z.string().uuid(),
+          value: z.string().nullable(),
+        }),
       ),
-    },
+    }),
     res: z.object({
       code: z.enum(["success"]),
     }),

+ 15 - 2
src/api/v_0.1.0/types/pe-types.ts

@@ -8,10 +8,11 @@ export const FieldTypeCode = z.enum([
   "date",
 ]);
 export const Validator = z.object({
-  fieldType: z.string(),
+  validatorId: z.string().uuid(),
   code: z.string(),
+  fieldTypeCode: FieldTypeCode,
   name: z.string(),
-  value: z.string(),
+  value: z.string().nullable(),
 });
 
 export const CustomField = z.object({
@@ -23,3 +24,15 @@ export const CustomField = z.object({
   options: z.array(z.string()).nullable(),
   validators: z.array(Validator),
 });
+export const CustomFieldWithUserCopyValue = CustomField.extend({
+  peFfId: z.string(),
+  userCopyValue: z.string().nullable(),
+});
+
+export const PeTypeWithFields = z.object({
+  peTypeId: z.string(),
+  code: z.string(),
+  name: z.string(),
+  eventInstId: z.string(),
+  fields: z.array(CustomField),
+});

+ 10 - 0
src/main.ts

@@ -42,8 +42,17 @@ logger.info("Импорт роутеров...");
 // users-management
 import authRouter from "./modules/users/auth/routers/auth-router.js";
 app.use("/api/auth/", authRouter);
+
 import authMiddleware from "#middlewares/auth-middleware.js";
 app.use("/api/", authMiddleware());
+// client
+// user
+import cUsersRouter from "./modules/client/users/c-users-router.js";
+app.use("/api/client/users/", cUsersRouter);
+
+// pe
+import cPeRouter from "./modules/client/activities/participant-entities/c-pe-router.js";
+app.use("/api/client/pe/", cPeRouter);
 
 // events-management
 // import EventsRouter from "./modules/management/events-router.js";
@@ -54,6 +63,7 @@ app.use("/api/", authMiddleware());
 
 // обработчик ошибок
 import errorMiddleware from "./middlewares/error-middleware.js";
+
 app.use(errorMiddleware);
 //
 

+ 120 - 0
src/modules/client/activities/c-activities-controller.ts

@@ -0,0 +1,120 @@
+// // db
+// import { selPool, updPool } from "#db";
+// import { DbSchema } from "#db-schema";
+// import { sql } from "slonik";
+
+// // api
+// import { api } from "#api";
+
+// // other
+// import { z } from "zod";
+
+// import { RouterUtils } from "#utils/router-utils.js";
+
+// import { Request, Response } from "express";
+// import sessionService from "#modules/users/auth/services/session-service.js";
+// import { Validator } from "#api/v_0.1.0/types/pe-types.js";
+
+// class ClientActivitiesController {
+//   async getEventActivities(
+//     req: Request,
+//     res: Response,
+//     // next: NextFunction
+//   ) {
+//     const event = await sessionService.getCurrentEventFromReq(req);
+
+//     const activities = await selPool.any(sql.type(
+//       z.object({
+//         // fieldDefinitionId: DbSchema.cf.customFieldDefinitions.fieldDefinitionId,
+//         // code: DbSchema.cf.customFieldDefinitions.code,
+//         // fieldTypeCode: DbSchema.cf.fieldTypes.code,
+//         // title: DbSchema.cf.customFieldDefinitions.title,
+//         // mask: DbSchema.cf.customFieldDefinitions.mask,
+//         // options: DbSchema.cf.customFieldDefinitions.options,
+//         // validators: z.array(Validator),
+//         // userValue: DbSchema.ev.userEventFieldValues.value,
+//       }),
+//     )`
+//       select
+//         uef.field_definition_id as "fieldDefinitionId",
+//         cfwv.code,
+//         cfwv.field_type_code as "fieldTypeCode",
+//         cfwv.title,
+//         cfwv.mask,
+//         cfwv."options",
+//         cfwv.validators,
+//         uefv.value as "userValue"
+//       from
+//         ev.user_event_fields uef
+//       join cf.custom_fields_with_validators cfwv on
+//         uef.field_definition_id = cfwv.field_definition_id
+//       left join ev.user_event_field_values uefv on
+//         uef.field_definition_id = uefv.field_definition_id
+//         and uefv.user_id = ${user.userId}
+//       where
+//         uef.event_id = ${event.eventId}
+//     `);
+
+//     RouterUtils.validAndSendResponse(
+//       api.client.users.GET_UserEventData.res,
+//       res,
+//       {
+//         code: "success",
+//         userData: [...userData],
+//       },
+//     );
+//   }
+
+//   // async getUserEventData(
+//   //   req: Request,
+//   //   res: Response,
+//   //   // next: NextFunction
+//   // ) {
+//   //   const event = await sessionService.getCurrentEventFromReq(req);
+//   //   const user = sessionService.getUserFromReq(req);
+
+//   //   const userData = await selPool.any(sql.type(
+//   //     z.object({
+//   //       fieldDefinitionId: DbSchema.cf.customFieldDefinitions.fieldDefinitionId,
+//   //       code: DbSchema.cf.customFieldDefinitions.code,
+//   //       fieldTypeCode: DbSchema.cf.fieldTypes.code,
+//   //       title: DbSchema.cf.customFieldDefinitions.title,
+//   //       mask: DbSchema.cf.customFieldDefinitions.mask,
+//   //       options: DbSchema.cf.customFieldDefinitions.options,
+//   //       validators: z.array(Validator),
+//   //       userValue: DbSchema.ev.userEventFieldValues.value,
+//   //     }),
+//   //   )`
+//   //     select
+//   //       uef.field_definition_id as "fieldDefinitionId",
+//   //       cfwv.code,
+//   //       cfwv.field_type_code as "fieldTypeCode",
+//   //       cfwv.title,
+//   //       cfwv.mask,
+//   //       cfwv."options",
+//   //       cfwv.validators,
+//   //       uefv.value as "userValue"
+//   //     from
+//   //       ev.user_event_fields uef
+//   //     join cf.custom_fields_with_validators cfwv on
+//   //       uef.field_definition_id = cfwv.field_definition_id
+//   //     left join ev.user_event_field_values uefv on
+//   //       uef.field_definition_id = uefv.field_definition_id
+//   //       and uefv.user_id = ${user.userId}
+//   //     where
+//   //       uef.event_id = ${event.eventId}
+//   //   `);
+
+//   //   RouterUtils.validAndSendResponse(
+//   //     api.client.users.GET_UserEventData.res,
+//   //     res,
+//   //     {
+//   //       code: "success",
+//   //       userData: [...userData],
+//   //     },
+//   //   );
+//   // }
+
+// }
+
+// export const clientUsersController = new ClientUsersController();

+ 138 - 0
src/modules/client/activities/participant-entities/c-pe-controller.ts

@@ -0,0 +1,138 @@
+// db
+import { selPool } from "#db";
+import { DbSchema } from "#db-schema";
+import { sql } from "slonik";
+
+// api
+import { api } from "#api";
+
+// other
+import { z } from "zod";
+
+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 { ApiError } from "#exceptions/api-error.js";
+
+class ClientPeController {
+  async getEventPeTypes(
+    req: Request,
+    res: Response,
+    // next: NextFunction
+  ) {
+    const event = await sessionService.getCurrentEventFromReq(req);
+
+    const peTypes = await selPool.any(sql.type(
+      z.object({
+        peTypeId: DbSchema.act.peTypes.peTypeId,
+        code: DbSchema.act.peTypes.code,
+        name: DbSchema.act.peTypes.name,
+      }),
+    )`
+      select
+        pe_type_id as "peTypeId",
+        code,
+        "name"
+      from
+        act.pe_types pt
+      where
+        pt.event_inst_id = ${event.eventInstId}
+    `);
+
+    RouterUtils.validAndSendResponse(api.client.pe.GET_EventPeTypes.res, res, {
+      code: "success",
+      peTypes: [...peTypes],
+    });
+  }
+
+  async getPeTypeForCreate(
+    req: Request,
+    res: Response,
+    // next: NextFunction
+  ) {
+    const event = await sessionService.getCurrentEventFromReq(req);
+    const user = sessionService.getUserFromReq(req);
+    const { peTypeCode } = api.client.pe.GET_PeType.req.parse(req.params);
+
+    const eventId = event.eventId;
+    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(),
+        fields: z.array(
+          CustomFieldWithUserCopyValue.extend({ isCopyUserValue: z.boolean() }),
+        ),
+      }),
+    )`
+      select
+        pt.pe_type_id as "peTypeId",
+        pt.code,
+        pt.name,
+        pt.event_inst_id as "eventInstId",
+        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,
+        'userCopyValue',
+        ufwv.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
+      from
+        act.pe_types pt
+        --	необходимые поля
+      left join act.pe_form_fields pff on
+        pff.pe_type_id = pt.pe_type_id
+        -- значение из профиля юзера
+      left join ev.user_fields_with_values ufwv on
+        pff.field_definition_id = ufwv.field_definition_id
+        and ufwv.user_id = ${userId}
+        and ufwv.event_id = ${eventId}
+        and ufwv.value is not null
+        -- только если нужно копировать
+        and pff.is_copy_user_value = true
+      left join cf.custom_fields_with_validators cfwv on
+        pff.field_definition_id = cfwv.field_definition_id
+      where 
+        pt.code = ${peTypeCode}
+      group by
+        pt.pe_type_id,
+        pt.code,
+        pt.name,
+        pt.event_inst_id
+    `);
+
+    if (!peType)
+      throw ApiError.BadRequest(
+        "peTypeNotFound",
+        "Тип сущности участия не найден",
+      );
+
+    RouterUtils.validAndSendResponse(api.client.pe.GET_PeType.res, res, {
+      code: "success",
+      peType: peType,
+    });
+  }
+}
+
+export const clientPeController = new ClientPeController();

+ 16 - 0
src/modules/client/activities/participant-entities/c-pe-router.ts

@@ -0,0 +1,16 @@
+import { RouterUtils } from "#utils/router-utils.js";
+
+import express from "express";
+import { clientPeController } from "./c-pe-controller.js";
+const router = express.Router();
+export default router;
+
+router.get(
+  "/eventPeTypes",
+  RouterUtils.asyncHandler(clientPeController.getEventPeTypes),
+);
+
+router.get(
+  "/peType/create/:peTypeCode",
+  RouterUtils.asyncHandler(clientPeController.getPeTypeForCreate),
+);

+ 14 - 9
src/modules/client/users/c-users-controller.ts

@@ -27,33 +27,36 @@ class ClientUsersController {
     const userData = await selPool.any(sql.type(
       z.object({
         fieldDefinitionId: DbSchema.cf.customFieldDefinitions.fieldDefinitionId,
+        userEfId: DbSchema.ev.userEventFields.userEfId,
         code: DbSchema.cf.customFieldDefinitions.code,
         fieldTypeCode: DbSchema.cf.fieldTypes.code,
         title: DbSchema.cf.customFieldDefinitions.title,
         mask: DbSchema.cf.customFieldDefinitions.mask,
         options: DbSchema.cf.customFieldDefinitions.options,
         validators: z.array(Validator),
-        userValue: DbSchema.ev.userEventFieldValues.value,
+        value: DbSchema.ev.userEventFieldValues.value,
       }),
     )`
       select
         uef.field_definition_id as "fieldDefinitionId",
+        uef.user_ef_id as "userEfId",
         cfwv.code,
         cfwv.field_type_code as "fieldTypeCode",
-        cfwv.title,
+        COALESCE(uef.field_title_override, cfwv.title) as "title",
         cfwv.mask,
         cfwv."options",
         cfwv.validators,
-        uefv.value as "userValue"
+        uefv.value as "value"
       from
         ev.user_event_fields uef
       join cf.custom_fields_with_validators cfwv on
         uef.field_definition_id = cfwv.field_definition_id
       left join ev.user_event_field_values uefv on
-        uef.field_definition_id = uefv.field_definition_id
+        uef.user_ef_id = uefv.user_ef_id 
         and uefv.user_id = ${user.userId}
       where
         uef.event_id = ${event.eventId}
+
     `);
 
     RouterUtils.validAndSendResponse(
@@ -72,7 +75,7 @@ class ClientUsersController {
     // next: NextFunction
   ) {
     const user = sessionService.getUserFromReq(req);
-    const userData = api.client.users.PATCH_UserEventData.req.userData.parse(
+    const { userData } = api.client.users.PATCH_UserEventData.req.parse(
       req.body,
     );
 
@@ -80,26 +83,28 @@ class ClientUsersController {
     // TODO: добавить валидацию
     updPool.transaction(async (t) => {
       for (const field of userData) {
-        const fieldDefinitionId = field.fieldDefinitionId;
+        const userEfId = field.userEfId;
         const value = field.value;
 
         t.query(sql.unsafe`
             delete from
               ev.user_event_field_values v
             where
-              v.field_definition_id = ${fieldDefinitionId}
+              v.user_ef_id = ${userEfId}
               and 
               v.user_id = ${userId};
+          `);
 
+        t.query(sql.unsafe`
             insert
               into
               ev.user_event_field_values (
               user_id,
-              field_definition_id,
+              user_ef_id,
               value)
             values (
               ${userId},
-              ${fieldDefinitionId},
+              ${userEfId},
               ${value}
             );
           `);