// 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 { CustomFieldWithUserCopyValue } from "#api/v_0.1.0/types/pe-types.js"; import { ApiError } from "#exceptions/api-error.js"; import { v7 } from "uuid"; 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, }); } async createPeType(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( req.body, ); await updPool.transaction(async (t) => { const peId = v7(); await t.query(sql.unsafe` insert into act.part_entities (pe_id, pe_type_id, event_inst_id, owner_id) values (${peId}, ${peTypeId}, ${event.eventInstId}, ${user.userId}) `); for (const field of form) { await t.query(sql.unsafe` insert into act.pe_field_values (pe_ff_id, pe_id, value) values (${field.peFfId}, ${peId}, ${field.value}) `); } RouterUtils.validAndSendResponse(api.client.pe.POST_PartEntity.res, res, { code: "success", peId, }); }); } async getOwnerPe(req: Request, res: Response) { const user = sessionService.getUserFromReq(req); const { peId } = api.client.pe.GET_OwnerPartEntity.req.parse(req.body); // TODO: заменить типы бд const pe = await selPool.maybeOne(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() }), ), }), )` 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 from act.part_entities pe 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 `); if (!pe) throw ApiError.BadRequest("peNotFound", "Сущность участия не найдена"); RouterUtils.validAndSendResponse( api.client.pe.GET_OwnerPartEntity.res, res, { code: "success", pe: pe, }, ); } } export const clientPeController = new ClientPeController();