Skip to content

Commit a179462

Browse files
committed
add the ability to get the metadata for events
1 parent 36f1e00 commit a179462

File tree

6 files changed

+400
-1
lines changed

6 files changed

+400
-1
lines changed

cloudformation/iam.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ Resources:
6969
- !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-merchstore-purchase-history
7070
- !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-events-tickets
7171
- !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-events-tickets/*
72+
- !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-events-ticketing-metadata/*
73+
- !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-events-ticketing-metadata
74+
- !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-merchstore-metadata/*
75+
- !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-merchstore-metadata
76+
7277
PolicyName: lambda-dynamo
7378
Outputs:
7479
MainFunctionRoleArn:

src/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ type GenericConfigType = {
2727
EntraTenantId: string;
2828
MerchStorePurchasesTableName: string;
2929
TicketPurchasesTableName: string;
30+
TicketMetadataTableName: string;
31+
MerchStoreMetadataTableName: string;
3032
};
3133

3234
type EnvironmentConfigType = {
@@ -41,7 +43,9 @@ const genericConfig: GenericConfigType = {
4143
AwsRegion: process.env.AWS_REGION || "us-east-1",
4244
EntraTenantId: "c8d9148f-9a59-4db3-827d-42ea0c2b6e2e",
4345
MerchStorePurchasesTableName: "infra-merchstore-purchase-history",
46+
MerchStoreMetadataTableName: "infra-merchstore-metadata",
4447
TicketPurchasesTableName: "infra-events-tickets",
48+
TicketMetadataTableName: "infra-events-ticketing-metadata",
4549
} as const;
4650

4751
const environmentConfig: EnvironmentConfigType = {

src/routes/tickets.ts

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { z } from "zod";
33
import {
44
DynamoDBClient,
55
QueryCommand,
6+
ScanCommand,
67
UpdateItemCommand,
78
} from "@aws-sdk/client-dynamodb";
89
import { genericConfig } from "../config.js";
@@ -64,6 +65,31 @@ const getTicketsResponseJsonSchema = zodToJsonSchema(
6465
}),
6566
);
6667

68+
const baseItemMetadata = z.object({
69+
itemId: z.string().min(1),
70+
itemName: z.string().min(1),
71+
itemSalesActive: z.union([z.date(), z.literal(false)]),
72+
priceDollars: z.object({
73+
member: z.number().min(0),
74+
nonMember: z.number().min(0),
75+
}),
76+
});
77+
78+
const ticketingItemMetadata = baseItemMetadata.extend({
79+
eventCapacity: z.number(),
80+
ticketsSold: z.number(),
81+
});
82+
83+
type ItemMetadata = z.infer<typeof baseItemMetadata>;
84+
type TicketItemMetadata = z.infer<typeof ticketingItemMetadata>;
85+
86+
const listMerchItemsResponseJsonSchema = zodToJsonSchema(
87+
z.object({
88+
merch: z.array(baseItemMetadata),
89+
tickets: z.array(ticketingItemMetadata),
90+
}),
91+
);
92+
6793
const postSchema = z.union([postMerchSchema, postTicketSchema]);
6894

6995
type VerifyPostRequest = z.infer<typeof postSchema>;
@@ -78,7 +104,80 @@ type TicketsGetRequest = {
78104
Body: undefined;
79105
};
80106

107+
type TicketsListRequest = {
108+
Params: undefined;
109+
Querystring: undefined;
110+
Body: undefined;
111+
};
112+
81113
const ticketsPlugin: FastifyPluginAsync = async (fastify, _options) => {
114+
fastify.get<TicketsListRequest>(
115+
"/",
116+
{
117+
schema: {
118+
response: {
119+
200: listMerchItemsResponseJsonSchema,
120+
},
121+
},
122+
onRequest: async (request, reply) => {
123+
await fastify.authorize(request, reply, [AppRoles.TICKETS_MANAGER]);
124+
},
125+
},
126+
async (request, reply) => {
127+
const merchCommand = new ScanCommand({
128+
TableName: genericConfig.MerchStoreMetadataTableName,
129+
ProjectionExpression: "item_id, item_name, item_sales_active_utc",
130+
});
131+
const merchItems: ItemMetadata[] = [];
132+
const response = await dynamoClient.send(merchCommand);
133+
if (response.Items) {
134+
for (const item of response.Items.map((x) => unmarshall(x))) {
135+
const memberPrice = parseInt(item.item_price?.paid, 10) || 0;
136+
const nonMemberPrice = parseInt(item.item_price?.others, 10) || 0;
137+
merchItems.push({
138+
itemId: item.item_id,
139+
itemName: item.item_name,
140+
itemSalesActive:
141+
item.item_sales_active_utc === -1
142+
? false
143+
: new Date(parseInt(item.item_sales_active_utc, 10)),
144+
priceDollars: {
145+
member: memberPrice,
146+
nonMember: nonMemberPrice,
147+
},
148+
});
149+
}
150+
}
151+
const ticketCommand = new ScanCommand({
152+
TableName: genericConfig.TicketMetadataTableName,
153+
ProjectionExpression:
154+
"event_id, event_name, event_sales_active_utc, event_capacity, tickets_sold",
155+
});
156+
const ticketItems: TicketItemMetadata[] = [];
157+
const ticketResponse = await dynamoClient.send(ticketCommand);
158+
if (ticketResponse.Items) {
159+
for (const item of ticketResponse.Items.map((x) => unmarshall(x))) {
160+
const memberPrice = parseInt(item.eventCost?.paid, 10) || 0;
161+
const nonMemberPrice = parseInt(item.eventCost?.others, 10) || 0;
162+
ticketItems.push({
163+
itemId: item.event_id,
164+
itemName: item.event_name,
165+
itemSalesActive:
166+
item.event_sales_active_utc === -1
167+
? false
168+
: new Date(parseInt(item.event_sales_active_utc, 10)),
169+
eventCapacity: item.event_capacity,
170+
ticketsSold: item.tickets_sold,
171+
priceDollars: {
172+
member: memberPrice,
173+
nonMember: nonMemberPrice,
174+
},
175+
});
176+
}
177+
}
178+
reply.send({ merch: merchItems, tickets: ticketItems });
179+
},
180+
);
82181
fastify.get<TicketsGetRequest>(
83182
"/:eventId",
84183
{
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
const merchMetadata = [
2+
{
3+
item_id: {
4+
S: "2024_spr_tshirt",
5+
},
6+
item_email_desc: {
7+
S: "Please pick up your item in the ACM room on Wednesdays between 6pm and 6:30pm.",
8+
},
9+
item_image: {
10+
S: "img/tshirt.png",
11+
},
12+
item_name: {
13+
S: "ACM T-Shirt: Spring 2024 Series",
14+
},
15+
item_price: {
16+
M: {
17+
others: {
18+
N: "26",
19+
},
20+
paid: {
21+
N: "22",
22+
},
23+
},
24+
},
25+
item_sales_active_utc: {
26+
N: "0",
27+
},
28+
member_price: {
29+
S: "price_1OchTUDiGOXU9RuSQXnpbSHS",
30+
},
31+
nonmember_price: {
32+
S: "price_1OchTrDiGOXU9RuStYC6XgXp",
33+
},
34+
sizes: {
35+
L: [
36+
{
37+
S: "S",
38+
},
39+
{
40+
S: "M",
41+
},
42+
{
43+
S: "L",
44+
},
45+
{
46+
S: "XL",
47+
},
48+
],
49+
},
50+
total_avail: {
51+
M: {
52+
L: {
53+
N: "10",
54+
},
55+
M: {
56+
N: "22",
57+
},
58+
S: {
59+
N: "23",
60+
},
61+
XL: {
62+
N: "9",
63+
},
64+
},
65+
},
66+
},
67+
{
68+
item_id: {
69+
S: "2024_fa_barcrawl",
70+
},
71+
item_email_desc: {
72+
S: "Shirts will be availiable for pickup one week before the event. Check your email near then for more details. Make sure to join the ACM Discord for updates!",
73+
},
74+
item_image: {
75+
S: "img/barcrawl_fa24_design.png",
76+
},
77+
item_name: {
78+
S: "ACM Bar Crawl: Fall 2024 (Nov 14)",
79+
},
80+
item_price: {
81+
M: {
82+
others: {
83+
N: "18",
84+
},
85+
paid: {
86+
N: "15",
87+
},
88+
},
89+
},
90+
item_sales_active_utc: {
91+
N: "0",
92+
},
93+
member_price: {
94+
S: "price_1QFSCiDiGOXU9RuSNJ90SblG",
95+
},
96+
nonmember_price: {
97+
S: "price_1QFSDVDiGOXU9RuSEUH0DQtx",
98+
},
99+
ready_for_pickup: {
100+
BOOL: false,
101+
},
102+
sizes: {
103+
L: [
104+
{
105+
S: "S",
106+
},
107+
{
108+
S: "M",
109+
},
110+
{
111+
S: "L",
112+
},
113+
{
114+
S: "XL",
115+
},
116+
{
117+
S: "2XL",
118+
},
119+
],
120+
},
121+
total_avail: {
122+
M: {
123+
"2XL": {
124+
N: "2",
125+
},
126+
L: {
127+
N: "22",
128+
},
129+
M: {
130+
N: "0",
131+
},
132+
S: {
133+
N: "7",
134+
},
135+
XL: {
136+
N: "1",
137+
},
138+
},
139+
},
140+
},
141+
];
142+
143+
const ticketsMetadata = [
144+
{
145+
event_id: {
146+
S: "fa23_barcrawl",
147+
},
148+
eventCost: {
149+
M: {
150+
others: {
151+
N: "18",
152+
},
153+
paid: {
154+
N: "15",
155+
},
156+
},
157+
},
158+
eventDetails: {
159+
S: "Join ACM and meet your fellow members as we visit KAMS, Joe's, and Legends on our semesterly bar crawl! Get a free t-shirt with sign-up! Alcohol will be provided by ACM to members over 21 wearing bar crawl t-shirts. We will also be hosting an official pregame (details released closer to the event)! This ticket does not pay for cover at the bars.",
160+
},
161+
eventImage: {
162+
S: "img/bar_crawl_fa23.png",
163+
},
164+
event_capacity: {
165+
N: "130",
166+
},
167+
event_name: {
168+
S: "ACM Fall 2023 Bar Crawl",
169+
},
170+
event_sales_active_utc: {
171+
N: "-1",
172+
},
173+
event_time: {
174+
N: "1699578000",
175+
},
176+
member_price: {
177+
S: "price_1O6mXBDiGOXU9RuS2ZfBXaEc",
178+
},
179+
nonmember_price: {
180+
S: "price_1O6mXBDiGOXU9RuSq7PUcC1C",
181+
},
182+
tickets_sold: {
183+
N: "55",
184+
},
185+
},
186+
{
187+
event_id: {
188+
S: "fa22_barcrawl",
189+
},
190+
eventCost: {
191+
M: {
192+
others: {
193+
N: "18",
194+
},
195+
paid: {
196+
N: "15",
197+
},
198+
},
199+
},
200+
eventDetails: {
201+
S: "Join ACM and meet your fellow members as we visit KAMS, Joe's, and Legends on our semesterly bar crawl! Get a free t-shirt with sign-up! Alcohol will be provided by ACM to members over 21 wearing bar crawl t-shirts. We will also be hosting an official pregame (details released closer to the event)! This ticket does not pay for cover at the bars.",
202+
},
203+
eventImage: {
204+
S: "img/bar_crawl_fa23.png",
205+
},
206+
event_capacity: {
207+
N: "130",
208+
},
209+
event_name: {
210+
S: "ACM Fall 2023 Bar Crawl",
211+
},
212+
event_sales_active_utc: {
213+
N: "-1",
214+
},
215+
event_time: {
216+
N: "1699578000",
217+
},
218+
member_price: {
219+
S: "price_1O6mXBDiGOXU9RuS2ZfBXaEc",
220+
},
221+
nonmember_price: {
222+
S: "price_1O6mXBDiGOXU9RuSq7PUcC1C",
223+
},
224+
tickets_sold: {
225+
N: "55",
226+
},
227+
},
228+
];
229+
230+
export { merchMetadata, ticketsMetadata };

tests/unit/entraInviteUser.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ vi.mock("../../src/functions/entraId.js", () => {
1717
return "ey.test.token";
1818
}),
1919
addToTenant: vi.fn().mockImplementation(async (email) => {
20-
console.log("FUCK", email);
2120
return { success: true, email: "[email protected]" };
2221
}),
2322
};

0 commit comments

Comments
 (0)