Skip to content

Commit 86804ca

Browse files
authored
Mejora en la validación de datos de usuario para la aprobación de tickets (#264)
Este PR introduce mejoras en el proceso de validación de datos de usuario para la aprobación de tickets. Los cambios principales incluyen: 1. Refactorización de la lógica de validación para diferenciar entre tickets de equipo (hackathon) y otros. 2. Eliminación de la lista hardcodeada de IDs de tickets de hackathon en producción, reemplazándola por una verificación basada en tags. 3. Actualización de las pruebas para cubrir escenarios de tickets de equipo y otros.
1 parent 3e0820f commit 86804ca

3 files changed

Lines changed: 191 additions & 21 deletions

File tree

src/schema/userTickets/helpers.ts

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,6 @@ type ValidateUserDataAndApproveUserTicketsOptions = {
117117
logger: Logger;
118118
};
119119

120-
const HACKATHON_TICKETS_IDS_IN_PROD = [
121-
// Dia 1
122-
"8ab45972-2497-48b0-8714-f678d18bc5a9",
123-
// Dia 2
124-
"fae5b2cd-e441-4c43-845c-bfa7c59c7af1",
125-
// Inauguracion
126-
"900b2eab-3166-4e68-ab93-1831df094471",
127-
];
128-
129120
export const validateUserDataAndApproveUserTickets = async ({
130121
DB,
131122
userId,
@@ -180,16 +171,40 @@ export const validateUserDataAndApproveUserTickets = async ({
180171
},
181172
});
182173

183-
const hackathonUserTickets = [];
184-
const nonHackathonUserTickets = [];
174+
const ticketTemplatesOfUserTicketsByTemplateId = await ticketsFetcher
175+
.searchTickets({
176+
DB,
177+
search: {
178+
ticketIds: userTickets.map((ut) => ut.ticketTemplateId),
179+
},
180+
})
181+
.then((tickets) => {
182+
return tickets.reduce(
183+
(acc, ticket) => {
184+
acc[ticket.id] = ticket;
185+
186+
return acc;
187+
},
188+
{} as Record<
189+
string,
190+
Awaited<ReturnType<typeof ticketsFetcher.searchTickets>>[0]
191+
>,
192+
);
193+
});
194+
195+
const ticketTemplatesForTeams = [];
196+
const ticketTemplatesForAnyone = [];
185197

186198
for (let i = 0; i < userTickets.length; i++) {
187199
const ut = userTickets[i];
188200

189-
if (HACKATHON_TICKETS_IDS_IN_PROD.includes(ut.ticketTemplateId)) {
190-
hackathonUserTickets.push(ut);
201+
const ticketTemplate =
202+
ticketTemplatesOfUserTicketsByTemplateId[ut.ticketTemplateId];
203+
204+
if (ticketTemplate.tags.includes("hackathon")) {
205+
ticketTemplatesForTeams.push(ticketTemplate);
191206
} else {
192-
nonHackathonUserTickets.push(ut);
207+
ticketTemplatesForAnyone.push(ticketTemplate);
193208
}
194209
}
195210

@@ -207,7 +222,7 @@ export const validateUserDataAndApproveUserTickets = async ({
207222
errors.push("City is missing");
208223
}
209224

210-
if (hackathonUserTickets.length > 0) {
225+
if (ticketTemplatesForTeams.length > 0) {
211226
// If the user has a team, we check some values of userData.
212227
if (!userData.emergencyPhoneNumber) {
213228
errors.push("Emergency contact is missing");

src/schema/userTickets/tests/triggerUserTicketApprovalReview/triggerUserTicketApprovalReview.test.ts

Lines changed: 159 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { faker } from "@faker-js/faker";
22
import { it, describe, assert } from "vitest";
33

4+
import { TeamStatusEnum } from "~/datasources/db/teams";
5+
import { UserParticipationStatusEnum } from "~/datasources/db/userTeams";
46
import { userTicketsApprovalStatusEnum } from "~/datasources/db/userTickets";
57
import {
68
executeGraphqlOperationAsUser,
@@ -12,6 +14,8 @@ import {
1214
insertTicketTemplate,
1315
insertUser,
1416
insertUserData,
17+
insertTeam,
18+
insertUserTeams,
1519
} from "~/tests/fixtures";
1620

1721
import {
@@ -22,6 +26,7 @@ import {
2226

2327
const prepareTickets = async (
2428
status: (typeof userTicketsApprovalStatusEnum)[number] = "gifted",
29+
isTeamOnly = false,
2530
) => {
2631
const community1 = await insertCommunity();
2732
const event1 = await insertEvent();
@@ -33,6 +38,7 @@ const prepareTickets = async (
3338
const user1 = await insertUser();
3439
const ticketTemplate1 = await insertTicketTemplate({
3540
eventId: event1.id,
41+
tags: isTeamOnly ? ["hackathon"] : [],
3642
});
3743
const purchaseOrder = await insertPurchaseOrder();
3844
const ticket1 = await insertTicket({
@@ -47,13 +53,57 @@ const prepareTickets = async (
4753

4854
describe("triggerUserTicketApprovalReview mutation", () => {
4955
describe("It should approve tickets", () => {
50-
it("If data is complete and ticket is Gifted", async () => {
51-
const { event, user } = await prepareTickets("gifted");
56+
it("If data is complete for non-team tickets", async () => {
57+
const { event, user } = await prepareTickets("gifted", false);
5258

5359
await insertUserData({
5460
userId: user.id,
5561
rut: faker.random.alphaNumeric(10),
62+
countryOfResidence: "Chile",
63+
city: "Santiago",
5664
});
65+
66+
const response = await executeGraphqlOperationAsUser<
67+
TriggerUserTicketApprovalReviewMutation,
68+
TriggerUserTicketApprovalReviewMutationVariables
69+
>(
70+
{
71+
document: TriggerUserTicketApprovalReview,
72+
variables: {
73+
eventId: event.id,
74+
userId: user.id,
75+
},
76+
},
77+
user,
78+
);
79+
80+
assert.equal(response.errors, undefined);
81+
82+
assert.equal(response.data?.triggerUserTicketApprovalReview.length, 1);
83+
});
84+
85+
it("If data is complete for team tickets", async () => {
86+
const { event, user } = await prepareTickets("gifted", true);
87+
const team = await insertTeam({
88+
eventId: event.id,
89+
teamStatus: TeamStatusEnum.accepted,
90+
});
91+
92+
await insertUserTeams({
93+
userId: user.id,
94+
teamId: team.id,
95+
userParticipationStatus: UserParticipationStatusEnum.accepted,
96+
});
97+
98+
await insertUserData({
99+
userId: user.id,
100+
rut: faker.random.alphaNumeric(10),
101+
countryOfResidence: "Chile",
102+
city: "Santiago",
103+
emergencyPhoneNumber: "123456789",
104+
foodAllergies: "None",
105+
});
106+
57107
const response = await executeGraphqlOperationAsUser<
58108
TriggerUserTicketApprovalReviewMutation,
59109
TriggerUserTicketApprovalReviewMutationVariables
@@ -75,13 +125,16 @@ describe("triggerUserTicketApprovalReview mutation", () => {
75125
});
76126

77127
describe("It should not approve tickets", () => {
78-
it("If ticket is not pending", async () => {
128+
it("If ticket is not gifted", async () => {
79129
const { event, user } = await prepareTickets("cancelled");
80130

81131
await insertUserData({
82132
userId: user.id,
83133
rut: faker.random.alphaNumeric(10),
134+
countryOfResidence: "Chile",
135+
city: "Santiago",
84136
});
137+
85138
const response = await executeGraphqlOperationAsUser<
86139
TriggerUserTicketApprovalReviewMutation,
87140
TriggerUserTicketApprovalReviewMutationVariables
@@ -100,5 +153,108 @@ describe("triggerUserTicketApprovalReview mutation", () => {
100153

101154
assert.equal(response.data?.triggerUserTicketApprovalReview.length, 0);
102155
});
156+
157+
it("If data is incomplete for non-team tickets", async () => {
158+
const { event, user } = await prepareTickets("gifted", false);
159+
160+
await insertUserData({
161+
userId: user.id,
162+
rut: faker.random.alphaNumeric(10),
163+
// Missing countryOfResidence and city
164+
});
165+
166+
const response = await executeGraphqlOperationAsUser<
167+
TriggerUserTicketApprovalReviewMutation,
168+
TriggerUserTicketApprovalReviewMutationVariables
169+
>(
170+
{
171+
document: TriggerUserTicketApprovalReview,
172+
variables: {
173+
eventId: event.id,
174+
userId: user.id,
175+
},
176+
},
177+
user,
178+
);
179+
180+
assert.notEqual(response.errors, undefined);
181+
});
182+
183+
it("If data is incomplete for team tickets", async () => {
184+
const { event, user } = await prepareTickets("gifted", true);
185+
const team = await insertTeam({
186+
eventId: event.id,
187+
teamStatus: TeamStatusEnum.accepted,
188+
});
189+
190+
await insertUserTeams({
191+
userId: user.id,
192+
teamId: team.id,
193+
userParticipationStatus: UserParticipationStatusEnum.accepted,
194+
});
195+
196+
await insertUserData({
197+
userId: user.id,
198+
rut: faker.random.alphaNumeric(10),
199+
countryOfResidence: "Chile",
200+
city: "Santiago",
201+
// Missing emergencyPhoneNumber and foodAllergies
202+
});
203+
204+
const response = await executeGraphqlOperationAsUser<
205+
TriggerUserTicketApprovalReviewMutation,
206+
TriggerUserTicketApprovalReviewMutationVariables
207+
>(
208+
{
209+
document: TriggerUserTicketApprovalReview,
210+
variables: {
211+
eventId: event.id,
212+
userId: user.id,
213+
},
214+
},
215+
user,
216+
);
217+
218+
assert.notEqual(response.errors, undefined);
219+
});
220+
221+
it("If team is not accepted for team tickets", async () => {
222+
const { event, user } = await prepareTickets("gifted", true);
223+
const team = await insertTeam({
224+
eventId: event.id,
225+
teamStatus: TeamStatusEnum.not_accepted,
226+
});
227+
228+
await insertUserTeams({
229+
userId: user.id,
230+
teamId: team.id,
231+
userParticipationStatus: UserParticipationStatusEnum.accepted,
232+
});
233+
234+
await insertUserData({
235+
userId: user.id,
236+
rut: faker.random.alphaNumeric(10),
237+
countryOfResidence: "Chile",
238+
city: "Santiago",
239+
emergencyPhoneNumber: "123456789",
240+
foodAllergies: "None",
241+
});
242+
243+
const response = await executeGraphqlOperationAsUser<
244+
TriggerUserTicketApprovalReviewMutation,
245+
TriggerUserTicketApprovalReviewMutationVariables
246+
>(
247+
{
248+
document: TriggerUserTicketApprovalReview,
249+
variables: {
250+
eventId: event.id,
251+
userId: user.id,
252+
},
253+
},
254+
user,
255+
);
256+
257+
assert.notEqual(response.errors, undefined);
258+
});
103259
});
104260
});

src/tests/fixtures/index.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,8 @@ export const insertUserData = async (
287287
) => {
288288
const possibleInput = {
289289
id: partialInput?.id ?? faker.string.uuid(),
290-
city: partialInput?.city ?? faker.address.city(),
291-
countryOfResidence:
292-
partialInput?.countryOfResidence ?? faker.address.country(),
290+
city: partialInput?.city || "",
291+
countryOfResidence: partialInput?.countryOfResidence || "",
293292
worksInOrganization: partialInput?.worksInOrganization ?? false,
294293
emergencyPhoneNumber: partialInput?.emergencyPhoneNumber,
295294
foodAllergies: partialInput?.foodAllergies,

0 commit comments

Comments
 (0)