From 1af8f0832b86f1234519d3cfc74627a5104ed99d Mon Sep 17 00:00:00 2001 From: Jake Levine Date: Wed, 2 Apr 2025 22:50:29 +0000 Subject: [PATCH] exchange route --- src/api/routes/tickets.ts | 76 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/src/api/routes/tickets.ts b/src/api/routes/tickets.ts index 74783b90..02306010 100644 --- a/src/api/routes/tickets.ts +++ b/src/api/routes/tickets.ts @@ -4,6 +4,8 @@ import { QueryCommand, ScanCommand, UpdateItemCommand, + TransactWriteItemsCommand, + TransactWriteItemsInput, } from "@aws-sdk/client-dynamodb"; import { genericConfig } from "../../common/config.js"; import { @@ -92,6 +94,21 @@ const postSchema = z.union([postMerchSchema, postTicketSchema]); type VerifyPostRequest = z.infer; +const itemExchangeSchema = z.object({ + itemId: z.string().min(1), + ticketId: z.string().min(1), + originalSize: z.string(), + newSize: z.string(), + quantityExchanged: z.number(), +}); + +type ItemExchangeRequest = z.infer; + +const itemExchangeResponseSchema = z.object({ + ticketId: z.string().min(1), + successful: z.boolean(), +}); + type TicketsGetRequest = { Params: { id: string }; Querystring: { type: string }; @@ -439,6 +456,65 @@ const ticketsPlugin: FastifyPluginAsync = async (fastify, _options) => { ); }, ); + fastify.post<{ Body: ItemExchangeRequest }>( + "/exchange", + { + schema: { + response: { 200: itemExchangeResponseSchema }, + }, + preValidation: async (request, reply) => { + await fastify.zodValidateBody(request, reply, itemExchangeSchema); + }, + onRequest: async (request, reply) => { + await fastify.authorize(request, reply, [AppRoles.TICKETS_SCANNER]); + }, + }, + async (request, reply) => { + const transaction: TransactWriteItemsInput = { + TransactItems: [ + { + Update: { + Key: { itemId: { S: request.body.itemId } }, + UpdateExpression: + "SET total_avail.#sizeold = total_avail.#sizeold + :quantity, total_avail.#sizenew = total_avail.#sizenew + :quantity", + ConditionExpression: "total_avail.#sizenew >= :quantity", + ExpressionAttributeNames: { + "#sizeold": request.body.originalSize, + "#sizenew": request.body.newSize, + }, + ExpressionAttributeValues: { + ":quantity": { N: request.body.quantityExchanged.toString() }, + }, + TableName: genericConfig.MerchStoreMetadataTableName, + }, + }, + { + Update: { + Key: { stripePi: { S: request.body.ticketId } }, + UpdateExpression: "SET size = :sizenew", + ConditionExpression: "quantity >= :quantity", + ExpressionAttributeValues: { + ":quantity": { N: request.body.quantityExchanged.toString() }, + ":sizenew": { S: request.body.newSize }, + }, + TableName: genericConfig.MerchStorePurchasesTableName, + }, + }, + ], + }; + const command = new TransactWriteItemsCommand(transaction); + try { + const resp = await fastify.dynamoClient.send(command); + if (resp.$metadata.httpStatusCode == 200) { + reply.send({ ticketId: request.body.ticketId, successful: true }); + } else { + reply.send({ ticketId: request.body.ticketId, successful: false }); + } + } catch { + reply.send({ ticketId: request.body.ticketId, successful: false }); + } + }, + ); }; export default ticketsPlugin;