c-act-controller.ts 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. // db
  2. import { selPool, updPool } from "#db";
  3. import { DbSchema } from "#db-schema";
  4. import { sql } from "slonik";
  5. // api
  6. import { api } from "#api";
  7. // other
  8. import { z } from "zod";
  9. import { RouterUtils } from "#utils/router-utils.js";
  10. import { Request, Response } from "express";
  11. import sessionService from "#modules/client/users/auth/services/session-service.js";
  12. import { apiTypes } from "#api/current-api.js";
  13. import { validateActValidators } from "./validators/act-validators.js";
  14. import { ApiError } from "#exceptions/api-error.js";
  15. import { cCustomFieldsValidateService } from "../custom-fields/c-cf-validate-service.js";
  16. import { v7 } from "uuid";
  17. import { cPeService } from "./participant-entities/c-pe-service.js";
  18. import { cActService } from "./c-act-service.js";
  19. import { validatePeForAct } from "./validators/act-pe-validators.js";
  20. import { generateRandomNumber } from "#utils/other-utils.js";
  21. import { PeMemberWithIdentityShema } from "#api/v_0.1.0/types/pe-types.js";
  22. class ClientActivitiesController {
  23. async getEventActivities(
  24. req: Request,
  25. res: Response,
  26. // next: NextFunction
  27. ) {
  28. const event = await sessionService.getCurrentEventFromReq(req);
  29. const categories = await selPool.any(sql.type(
  30. apiTypes.activities.ActCategory,
  31. )`
  32. select
  33. c.category_id "categoryId" ,
  34. c.code,
  35. c."name",
  36. c.parent_id "parentId",
  37. p.code "parentCode"
  38. from
  39. act.activity_categories c
  40. left join act.activity_categories p
  41. on c.parent_id = p.category_id
  42. where
  43. c.event_inst_id = ${event.eventInstId}
  44. and c.parent_id is null
  45. `);
  46. const activities = await selPool.any(sql.type(
  47. z.object({
  48. activityId: DbSchema.act.activities.activityId,
  49. code: DbSchema.act.activities.code,
  50. publicName: DbSchema.act.activities.publicName,
  51. eventInstId: DbSchema.act.activities.eventInstId,
  52. categoryId: DbSchema.act.activities.categoryId,
  53. categoryCode: DbSchema.act.activityCategories.code,
  54. validators: z.array(apiTypes.activities.ActValidator),
  55. peTypes: z.array(
  56. z.object({
  57. peTypeId: DbSchema.act.peTypes.peTypeId,
  58. code: DbSchema.act.peTypes.code,
  59. name: DbSchema.act.peTypes.name,
  60. }),
  61. ),
  62. isUserReg: DbSchema.act.activities.isUserReg,
  63. }),
  64. )`
  65. select
  66. a.activity_id "activityId",
  67. a.code,
  68. a.public_name "publicName",
  69. a.event_inst_id "eventInstId",
  70. a.category_id "categoryId",
  71. a.category_code "categoryCode",
  72. a.validators,
  73. a.pe_types "peTypes",
  74. a.is_user_reg "isUserReg"
  75. from
  76. act.act_with_validators a
  77. where
  78. a.event_inst_id = ${event.eventInstId}
  79. and a.category_id is null
  80. `);
  81. const validatedActivities = await Promise.all(
  82. activities.map(async (activity) => {
  83. const validatorsWithData = await cActService.addDataToActValidators({
  84. validators: activity.validators,
  85. activityId: activity.activityId,
  86. });
  87. const validatedActivity = validateActValidators(validatorsWithData);
  88. return {
  89. activityId: activity.activityId,
  90. code: activity.code,
  91. publicName: activity.publicName,
  92. categoryId: activity.categoryId,
  93. categoryCode: activity.categoryCode,
  94. peTypes: activity.peTypes,
  95. isUserReg: activity.isUserReg,
  96. isOpen: validatedActivity.isOpen,
  97. messages: validatedActivity.messages,
  98. };
  99. }),
  100. );
  101. RouterUtils.validAndSendResponse(
  102. api.client.activities.GET_EventActivities.res,
  103. res,
  104. {
  105. code: "success",
  106. categories: [...categories],
  107. activities: [...validatedActivities],
  108. },
  109. );
  110. }
  111. async getCategory(req: Request, res: Response) {
  112. const { categoryCode } =
  113. api.client.activities.GET_Category.req.params.parse(req.params);
  114. const categories = await selPool.any(sql.type(
  115. apiTypes.activities.ActCategory,
  116. )`
  117. select
  118. c.category_id "categoryId" ,
  119. c.code,
  120. c."name",
  121. c.parent_id "parentId",
  122. p.code "parentCode"
  123. from
  124. act.activity_categories c
  125. left join act.activity_categories p
  126. on c.parent_id = p.category_id
  127. where
  128. p.code = ${categoryCode}
  129. `);
  130. const activities = await selPool.any(sql.type(
  131. z.object({
  132. activityId: DbSchema.act.activities.activityId,
  133. code: DbSchema.act.activities.code,
  134. publicName: DbSchema.act.activities.publicName,
  135. eventInstId: DbSchema.act.activities.eventInstId,
  136. categoryId: DbSchema.act.activities.categoryId,
  137. categoryCode: DbSchema.act.activityCategories.code,
  138. validators: z.array(apiTypes.activities.ActValidator),
  139. peTypes: z.array(
  140. z.object({
  141. peTypeId: DbSchema.act.peTypes.peTypeId,
  142. code: DbSchema.act.peTypes.code,
  143. name: DbSchema.act.peTypes.name,
  144. }),
  145. ),
  146. isUserReg: DbSchema.act.activities.isUserReg,
  147. }),
  148. )`
  149. select
  150. a.activity_id "activityId",
  151. a.code,
  152. a.public_name "publicName",
  153. a.event_inst_id "eventInstId",
  154. a.category_id "categoryId",
  155. a.category_code "categoryCode",
  156. a.validators,
  157. a.pe_types "peTypes",
  158. a.is_user_reg "isUserReg"
  159. from
  160. act.act_with_validators a
  161. where
  162. a.category_code = ${categoryCode}
  163. `);
  164. const validatedActivities = await Promise.all(
  165. activities.map(async (activity) => {
  166. const validatorsWithData = await cActService.addDataToActValidators({
  167. validators: activity.validators,
  168. activityId: activity.activityId,
  169. });
  170. const validatedActivity = validateActValidators(validatorsWithData);
  171. return {
  172. activityId: activity.activityId,
  173. code: activity.code,
  174. publicName: activity.publicName,
  175. categoryId: activity.categoryId,
  176. categoryCode: activity.categoryCode,
  177. peTypes: activity.peTypes,
  178. isUserReg: activity.isUserReg,
  179. isOpen: validatedActivity.isOpen,
  180. messages: validatedActivity.messages,
  181. };
  182. }),
  183. );
  184. RouterUtils.validAndSendResponse(
  185. api.client.activities.GET_Category.res,
  186. res,
  187. {
  188. code: "success",
  189. categories: [...categories],
  190. activities: [...validatedActivities],
  191. },
  192. );
  193. }
  194. async getActRegData(req: Request, res: Response) {
  195. const event = await sessionService.getCurrentEventFromReq(req);
  196. const user = sessionService.getUserFromReq(req);
  197. const { activityCode } =
  198. api.client.activities.GET_ActRegData.req.params.parse(req.params);
  199. const actRegData =
  200. await cActService.getActRegDataWithUserCopyValuesAndActValidators(
  201. user.userId,
  202. event.eventId,
  203. activityCode,
  204. );
  205. // TODO: заменить все BadRequest
  206. if (!actRegData)
  207. throw ApiError.BadRequest(
  208. "actRegDataNotFound",
  209. "Данные для регистрации на мероприятии не найдены",
  210. );
  211. // validate act
  212. const validatorsWithData = await cActService.addDataToActValidators({
  213. validators: actRegData.validators,
  214. activityId: actRegData.activityId,
  215. });
  216. const validatedActivity = validateActValidators(validatorsWithData);
  217. if (!validatedActivity.isOpen)
  218. throw ApiError.BadRequest(
  219. "actValidatorFailed",
  220. validatedActivity.messages.join(", "),
  221. );
  222. //
  223. // validate pes
  224. const pes = await cPeService.getUserOwnerPesWithFieldsAndMembers({
  225. userId: user.userId,
  226. eventInstId: event.eventInstId,
  227. });
  228. const validatedPes = await Promise.all(
  229. pes.map(async (pe) => {
  230. const validationResult = await validatePeForAct(actRegData, pe);
  231. return {
  232. peId: pe.peId,
  233. peTypeId: pe.peTypeId,
  234. peTypeCode: pe.peTypeCode,
  235. peTypeName: pe.peTypeName,
  236. name: pe.name,
  237. isValid: validationResult.isValid,
  238. messages: validationResult.messages,
  239. };
  240. }),
  241. );
  242. RouterUtils.validAndSendResponse(
  243. api.client.activities.GET_ActRegData.res,
  244. res,
  245. {
  246. code: "success",
  247. actRegData: {
  248. isOpen: validatedActivity.isOpen,
  249. messages: validatedActivity.messages,
  250. activityId: actRegData.activityId,
  251. code: actRegData.code,
  252. publicName: actRegData.publicName,
  253. eventInstId: actRegData.eventInstId,
  254. categoryId: actRegData.categoryId,
  255. categoryCode: actRegData.categoryCode,
  256. isUserReg: actRegData.isUserReg,
  257. peTypes: actRegData.peTypes,
  258. fields: actRegData.fields,
  259. validatedPes: validatedPes,
  260. },
  261. },
  262. );
  263. }
  264. async registerToAct(req: Request, res: Response) {
  265. const { fields, peId } =
  266. api.client.activities.POST_RegisterToAct.req.body.parse(
  267. JSON.parse(req.body.body),
  268. );
  269. const { activityCode } =
  270. api.client.activities.POST_RegisterToAct.req.params.parse(req.params);
  271. const files = req.files;
  272. const user = sessionService.getUserFromReq(req);
  273. const actRegData =
  274. await cActService.getActRegDataWithFieldsAndValidatorsAndActValidators(
  275. activityCode,
  276. );
  277. if (!actRegData)
  278. throw ApiError.BadRequest(
  279. "actRegDataNotFound",
  280. "Данные для регистрации на мероприятии не найдены",
  281. );
  282. //
  283. // проверка доступа
  284. if (!actRegData.isUserReg) {
  285. if (!peId)
  286. throw ApiError.BadRequest(
  287. "peIdNotFound",
  288. "ID сущности участия не передан",
  289. );
  290. const isOwner = await cPeService.checkPeOwner(user.userId, peId);
  291. if (!isOwner) throw ApiError.ForbiddenError();
  292. }
  293. //
  294. // -- ВАЛИДАЦИЯ --
  295. // валидация активности
  296. const validatorsWithData = await cActService.addDataToActValidators({
  297. validators: actRegData.validators,
  298. activityId: actRegData.activityId,
  299. });
  300. const validatedActivity = validateActValidators(validatorsWithData);
  301. if (!validatedActivity.isOpen)
  302. throw ApiError.BadRequest(
  303. "actValidatorFailed",
  304. validatedActivity.messages.join(", "),
  305. );
  306. //
  307. // валидация pe
  308. if (!actRegData.isUserReg) {
  309. if (!peId)
  310. throw ApiError.BadRequest(
  311. "peIdNotFound",
  312. "ID сущности участия не передан",
  313. );
  314. const pe = await cPeService.getPeWithValues(peId);
  315. const members = await cPeService.getPeMembersWithFields(peId);
  316. if (!pe)
  317. throw ApiError.BadRequest("peNotFound", "Сущность участия не найдена");
  318. const fullPe = {
  319. ...pe,
  320. members: [...members],
  321. };
  322. const validationResult = await validatePeForAct(actRegData, fullPe);
  323. if (!validationResult.isValid)
  324. throw ApiError.BadRequest(
  325. "peValidatorFailed",
  326. validationResult.messages.join(", "),
  327. );
  328. }
  329. //
  330. // валидация формы
  331. const refFields = actRegData.fields.map((f) => ({
  332. ...f,
  333. idKey: "arffId",
  334. }));
  335. const validationResult =
  336. await cCustomFieldsValidateService.processAndValidateFields({
  337. inputFields: fields,
  338. referenceFields: refFields,
  339. files,
  340. idKey: "arffId",
  341. addOldValue: false,
  342. });
  343. if (!validationResult.isValid)
  344. throw ApiError.BadRequest(
  345. "fieldsValidationFailed",
  346. JSON.stringify(validationResult.messages),
  347. );
  348. const validatedFields = validationResult.checkedfields;
  349. //
  350. //
  351. // вставляем в базу и сохраняем файлы
  352. const activityRegId = v7();
  353. let activityRegNumber = generateRandomNumber();
  354. while (await cActService.checkActivityRegNumber(activityRegNumber)) {
  355. activityRegNumber = generateRandomNumber();
  356. }
  357. await updPool.transaction(async (tr) => {
  358. if (actRegData.isUserReg) {
  359. // для user
  360. // сама регистрация
  361. await tr.query(sql.unsafe`
  362. insert into act.activity_regs
  363. (activity_reg_id, activity_id, user_id, number)
  364. values
  365. (${activityRegId}, ${actRegData.activityId}, ${user.userId}, ${activityRegNumber})
  366. `);
  367. } else {
  368. // для pe
  369. if (!peId)
  370. throw ApiError.BadRequest(
  371. "peIdNotFound",
  372. "ID сущности участия не передан",
  373. );
  374. // сама регистрация
  375. await tr.query(sql.unsafe`
  376. insert into act.activity_regs
  377. (activity_reg_id, activity_id, pe_id, number)
  378. values
  379. (${activityRegId}, ${actRegData.activityId}, ${peId}, ${activityRegNumber})
  380. `);
  381. }
  382. const initialRegStatusId = await cActService.getInitialRegStatusId(
  383. actRegData.activityId,
  384. );
  385. // устанавливаем начальный статус
  386. // FIXME: проверить во всех транзациях что я дождаюсь ответа
  387. await tr.query(sql.unsafe`
  388. insert into act.act_reg_status_history
  389. (status_history_id, activity_reg_id, act_reg_status_id, note)
  390. values
  391. (${v7()}, ${activityRegId}, ${initialRegStatusId}, 'Отправлена заявка на регистрацию')
  392. `);
  393. await cCustomFieldsValidateService.saveCustomFieldValuesInTransaction({
  394. tr,
  395. parentId: activityRegId,
  396. action: "activityPeReg",
  397. inputFields: validatedFields,
  398. files,
  399. isDeleteBefore: false,
  400. });
  401. // TODO: отправка уведомления
  402. });
  403. RouterUtils.validAndSendResponse(
  404. api.client.activities.POST_RegisterToAct.res,
  405. res,
  406. {
  407. code: "success",
  408. activityRegId,
  409. },
  410. );
  411. }
  412. async getActRegs(req: Request, res: Response) {
  413. const user = sessionService.getUserFromReq(req);
  414. const actRegs = await cActService.getActRegs(user.userId);
  415. RouterUtils.validAndSendResponse(
  416. api.client.activities.GET_ActRegs.res,
  417. res,
  418. {
  419. code: "success",
  420. actRegs: [...actRegs],
  421. },
  422. );
  423. }
  424. async getActReg(req: Request, res: Response) {
  425. const { activityRegId } = api.client.activities.GET_ActReg.req.params.parse(
  426. req.params,
  427. );
  428. const user = sessionService.getUserFromReq(req);
  429. const role = await cActService.checkActRegOwner(user.userId, activityRegId);
  430. if (!role) throw ApiError.ForbiddenError();
  431. let actReg: z.infer<
  432. typeof api.client.activities.GET_ActReg.res.shape.actReg
  433. > | null;
  434. if (role === "owner") {
  435. const r = await cActService.getActRegWithValues(activityRegId);
  436. if (!r)
  437. throw ApiError.BadRequest(
  438. "actRegNotFound",
  439. "Регистрация на мероприятии не найдена",
  440. );
  441. let peMembers:
  442. | (z.infer<typeof PeMemberWithIdentityShema> & { isPaid: boolean })[]
  443. | undefined = undefined;
  444. if (r.peId) {
  445. const m = [...(await cPeService.getPeMembersWithIdentity(r.peId))];
  446. peMembers = await Promise.all(
  447. m.map(async (m) => ({
  448. ...m,
  449. // TODO: слишком много операций, проще одним запросом вместо getPeMembersWithIdentity
  450. isPaid: await cActService.checkPeMemberActivityRegPayment({
  451. peMemberId: m.peMemberId,
  452. activityRegId: activityRegId,
  453. }),
  454. })),
  455. );
  456. }
  457. actReg = {
  458. ...r,
  459. peMembers,
  460. role,
  461. };
  462. } else {
  463. const r = await cActService.getActRegForPeMember(activityRegId);
  464. if (!r)
  465. throw ApiError.BadRequest(
  466. "actRegNotFound",
  467. "Регистрация на мероприятии не найдена",
  468. );
  469. actReg = {
  470. ...r,
  471. role,
  472. };
  473. }
  474. RouterUtils.validAndSendResponse(
  475. api.client.activities.GET_ActReg.res,
  476. res,
  477. {
  478. code: "success",
  479. actReg,
  480. },
  481. );
  482. }
  483. async getActivity(req: Request, res: Response) {
  484. const { activityCode } =
  485. api.client.activities.GET_Activity.req.params.parse(req.params);
  486. const act = await cActService.getActivity(activityCode);
  487. if (!act)
  488. throw ApiError.BadRequest("actNotFound", "Мероприятие не найдено");
  489. RouterUtils.validAndSendResponse(
  490. api.client.activities.GET_Activity.res,
  491. res,
  492. {
  493. code: "success",
  494. act,
  495. },
  496. );
  497. }
  498. async getActRegForPatch(req: Request, res: Response) {
  499. const { activityRegId } =
  500. api.client.activities.GET_ActRegForPatch.req.params.parse(req.params);
  501. const actReg =
  502. await cActService.getActRegWithFieldsAndValuesWithValidators(
  503. activityRegId,
  504. );
  505. if (!actReg)
  506. throw ApiError.BadRequest(
  507. "actRegNotFound",
  508. "Регистрация на мероприятии не найдена",
  509. );
  510. const user = sessionService.getUserFromReq(req);
  511. if (actReg.userId !== user.userId && actReg.peOwnerId !== user.userId)
  512. throw ApiError.ForbiddenError();
  513. RouterUtils.validAndSendResponse(
  514. api.client.activities.GET_ActRegForPatch.res,
  515. res,
  516. {
  517. code: "success",
  518. actReg,
  519. },
  520. );
  521. }
  522. async patchActReg(req: Request, res: Response) {
  523. const { activityRegId } =
  524. api.client.activities.PATCH_ActReg.req.params.parse(req.params);
  525. const { peId, fields } =
  526. api.client.activities.PATCH_ActReg.req.formData.body.parse(
  527. JSON.parse(req.body.body),
  528. );
  529. const files = req.files;
  530. const user = sessionService.getUserFromReq(req);
  531. const actReg = await cActService.getActRegForPeMember(activityRegId);
  532. if (!actReg)
  533. throw ApiError.BadRequest(
  534. "actRegNotFound",
  535. "Регистрация на мероприятии не найдена",
  536. );
  537. if (actReg.userId !== user.userId && actReg.peOwnerId !== user.userId)
  538. throw ApiError.ForbiddenError();
  539. const actRegData =
  540. await cActService.getActRegDataWithFieldsAndValidatorsAndActValidators(
  541. actReg.activityCode,
  542. );
  543. const oldActRegWithValues = await cActService.getActRegWithValues(
  544. actReg.activityRegId,
  545. );
  546. if (!actRegData || !oldActRegWithValues)
  547. throw ApiError.BadRequest(
  548. "actRegDataNotFound",
  549. "Данные для регистрации на мероприятии не найдены",
  550. );
  551. //
  552. //
  553. // -- ВАЛИДАЦИЯ --
  554. const validatorsWithData = await cActService.addDataToActValidators({
  555. validators: actRegData.validators,
  556. activityId: actRegData.activityId,
  557. });
  558. // валидация активности
  559. const validatedActivity = validateActValidators(validatorsWithData);
  560. if (!validatedActivity.isOpen)
  561. throw ApiError.BadRequest(
  562. "actValidatorFailed",
  563. validatedActivity.messages.join(", "),
  564. );
  565. //
  566. // валидация pe
  567. if (
  568. !actRegData.isUserReg &&
  569. peId // может не быть потому что patch
  570. ) {
  571. const pe = await cPeService.getPeWithValues(peId);
  572. const members = await cPeService.getPeMembersWithFields(peId);
  573. if (!pe)
  574. throw ApiError.BadRequest("peNotFound", "Сущность участия не найдена");
  575. const fullPe = {
  576. ...pe,
  577. members: [...members],
  578. };
  579. const validationResult = await validatePeForAct(actRegData, fullPe);
  580. if (!validationResult.isValid)
  581. throw ApiError.BadRequest(
  582. "peValidatorFailed",
  583. validationResult.messages.join(", "),
  584. );
  585. }
  586. //
  587. // валидация формы
  588. const refFields = actRegData.fields
  589. .map((f) => ({
  590. ...f,
  591. idKey: "arffId",
  592. value:
  593. oldActRegWithValues.fields.find((v) => v.arffId === f.arffId)
  594. ?.value || null,
  595. isChangeResetStatus:
  596. oldActRegWithValues.fields.find((v) => v.arffId === f.arffId)
  597. ?.isChangeResetStatus || false,
  598. }))
  599. // только изменяемые
  600. .filter((f) => fields.some((ff) => ff.arffId === f.arffId));
  601. const validationResult =
  602. await cCustomFieldsValidateService.processAndValidateFields({
  603. inputFields: fields,
  604. referenceFields: refFields,
  605. files,
  606. idKey: "arffId",
  607. addOldValue: true,
  608. });
  609. if (!validationResult.isValid)
  610. throw ApiError.BadRequest(
  611. "fieldsValidationFailed",
  612. JSON.stringify(validationResult.messages),
  613. );
  614. const validatedFields = validationResult.checkedfields;
  615. //
  616. const isNeedReset = refFields.some((f) => f.isChangeResetStatus);
  617. //
  618. // вставляем в базу и сохраняем файлы
  619. await updPool.transaction(async (tr) => {
  620. if (!actRegData.isUserReg && peId) {
  621. await tr.query(sql.unsafe`
  622. update act.activity_regs
  623. set
  624. pe_id = ${peId}
  625. where
  626. activity_reg_id = ${activityRegId}
  627. `);
  628. }
  629. const initialRegStatusId = await cActService.getInitialRegStatusId(
  630. actRegData.activityId,
  631. );
  632. // устанавливаем начальный статус если были измены поля сбрасывающие регистрацию
  633. if (isNeedReset) {
  634. await tr.query(sql.unsafe`
  635. insert into act.act_reg_status_history
  636. (status_history_id, activity_reg_id, act_reg_status_id, note)
  637. values
  638. (${v7()}, ${activityRegId}, ${initialRegStatusId}, 'Изменена заявка на регистрацию')
  639. `);
  640. }
  641. await cCustomFieldsValidateService.saveCustomFieldValuesInTransaction({
  642. tr,
  643. parentId: activityRegId,
  644. action: "activityPeReg",
  645. inputFields: validatedFields,
  646. files,
  647. isDeleteBefore: true,
  648. });
  649. });
  650. RouterUtils.validAndSendResponse(
  651. api.client.activities.PATCH_ActReg.res,
  652. res,
  653. {
  654. code: "success",
  655. },
  656. );
  657. }
  658. async cancelActivityReg(req: Request, res: Response) {
  659. const { activityRegId } =
  660. api.client.activities.DELETE_ActivityReg.req.params.parse(req.params);
  661. const user = sessionService.getUserFromReq(req);
  662. const role = await cActService.checkActRegOwner(user.userId, activityRegId);
  663. if (role !== "owner") throw ApiError.ForbiddenError();
  664. await updPool.transaction(async (tr) => {
  665. await tr.query(sql.unsafe`
  666. update act.activity_regs
  667. set
  668. is_canceled = true
  669. where
  670. activity_reg_id = ${activityRegId}
  671. `);
  672. await tr.query(sql.unsafe`
  673. insert into act.act_reg_status_history
  674. (status_history_id, activity_reg_id, act_reg_status_id, note)
  675. values
  676. (${v7()}, ${activityRegId}, 'e324fddb-81fe-45f4-90fe-074c0beaae45', 'Заявка отменена')
  677. `);
  678. });
  679. // возвраты
  680. await cActService.refundByActivityRegId(activityRegId);
  681. RouterUtils.validAndSendResponse(
  682. api.client.activities.DELETE_ActivityReg.res,
  683. res,
  684. {
  685. code: "success",
  686. },
  687. );
  688. }
  689. }
  690. export const clientActController = new ClientActivitiesController();