Skip to content

Commit

Permalink
fix: Actualizar estado de orden de compra para addons gratuitos (#302)
Browse files Browse the repository at this point in the history
Este PR corrige el comportamiento de las órdenes de compra cuando se
reclaman addons gratuitos.
Anteriormente, las órdenes de compra para addons gratuitos quedaban en
un estado incorrecto.

### Cambios principales
- Se actualiza el estado de la orden de compra a "complete" cuando solo
se reclaman addons gratuitos
- Se establece el estado de pago como "not_required" para addons
gratuitos
- Se establece el precio total en "0" para addons gratuitos
- Se añaden pruebas para verificar el comportamiento tanto para addons
gratuitos como pagados
  • Loading branch information
TextC0de authored Nov 3, 2024
1 parent 17a3601 commit 2d9639a
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 2 deletions.
22 changes: 21 additions & 1 deletion src/schema/userTicketsAddons/mutations.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { eq } from "drizzle-orm";
import { GraphQLError } from "graphql";

import { builder } from "~/builder";
import {
userTicketAddonsSchema,
selectPurchaseOrdersSchema,
purchaseOrdersSchema,
} from "~/datasources/db/schema";
import { applicationError, ServiceErrors } from "~/errors";
import { handlePaymentLinkGeneration } from "~/schema/purchaseOrder/actions";
Expand Down Expand Up @@ -208,9 +210,27 @@ builder.mutationField("claimUserTicketAddons", (t) =>
});
}

const [updatedPurchaseOrder] = await trx
.update(purchaseOrdersSchema)
.set({
purchaseOrderPaymentStatus: "not_required",
status: "complete",
totalPrice: "0",
})
.where(eq(purchaseOrdersSchema.id, createdPurchaseOrder.id))
.returning();

if (!updatedPurchaseOrder) {
throw applicationError(
"Failed to update purchase order",
ServiceErrors.FAILED_PRECONDITION,
logger,
);
}

return {
purchaseOrder:
selectPurchaseOrdersSchema.parse(createdPurchaseOrder),
selectPurchaseOrdersSchema.parse(updatedPurchaseOrder),
ticketsIds: uniqueUserTicketIds,
};
} catch (e: unknown) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export type ClaimUserTicketAddonsMutationVariables = Types.Exact<{
}>;


export type ClaimUserTicketAddonsMutation = { __typename?: 'Mutation', claimUserTicketAddons: { __typename: 'PurchaseOrder', id: string, status: Types.PurchaseOrderStatusEnum | null, paymentLink: string | null, userTicketAddons: Array<{ __typename?: 'UserTicketAddon', id: string, userTicketId: string, addonId: string, quantity: number }> } | { __typename: 'RedeemUserTicketAddonsError', error: boolean, errorMessage: string } };
export type ClaimUserTicketAddonsMutation = { __typename?: 'Mutation', claimUserTicketAddons: { __typename: 'PurchaseOrder', id: string, status: Types.PurchaseOrderStatusEnum | null, purchasePaymentStatus: Types.PurchaseOrderPaymentStatusEnum | null, paymentLink: string | null, userTicketAddons: Array<{ __typename?: 'UserTicketAddon', id: string, userTicketId: string, addonId: string, quantity: number }> } | { __typename: 'RedeemUserTicketAddonsError', error: boolean, errorMessage: string } };


export const ClaimUserTicketAddons = gql`
Expand All @@ -22,6 +22,7 @@ export const ClaimUserTicketAddons = gql`
... on PurchaseOrder {
id
status
purchasePaymentStatus
paymentLink
userTicketAddons {
id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mutation ClaimUserTicketAddons(
... on PurchaseOrder {
id
status
purchasePaymentStatus
paymentLink
userTicketAddons {
id
Expand Down
187 changes: 187 additions & 0 deletions src/schema/userTicketsAddons/tests/claimUserTicketAddons.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1306,4 +1306,191 @@ describe("claimUserTicketAddons mutation", () => {
"PurchaseOrder",
);
});

it("should set purchase order status to completed when claiming only free addons", async () => {
const community = await insertCommunity();
const event = await insertEvent();
const user = await insertUser();

await insertEventToCommunity({
eventId: event.id,
communityId: community.id,
});

const ticket = await insertTicketTemplate({
eventId: event.id,
quantity: 100,
});

const userTicket = await insertTicket({
userId: user.id,
ticketTemplateId: ticket.id,
approvalStatus: "approved",
});

const freeAddon = await insertAddon({
name: "Free Addon",
eventId: event.id,
isFree: true,
maxPerTicket: 2,
});

await insertTicketAddon({
ticketId: ticket.id,
addonId: freeAddon.id,
orderDisplay: 1,
});

const response = await executeGraphqlOperationAsUser<
ClaimUserTicketAddonsMutation,
ClaimUserTicketAddonsMutationVariables
>(
{
document: ClaimUserTicketAddons,
variables: {
addonsClaims: [
{
userTicketId: userTicket.id,
addonId: freeAddon.id,
quantity: 1,
},
],
currencyId: null,
},
},
user,
);

assert.equal(response.errors, undefined);

assert.equal(
response.data?.claimUserTicketAddons.__typename,
"PurchaseOrder",
);

if (response.data?.claimUserTicketAddons.__typename === "PurchaseOrder") {
assert.equal(response.data.claimUserTicketAddons.status, "complete");

assert.equal(
response.data.claimUserTicketAddons.purchasePaymentStatus,
"not_required",
);

assert.equal(response.data.claimUserTicketAddons.paymentLink, null);
}
});

it("should set purchase order status to open when claiming paid addons", async () => {
const community = await insertCommunity();
const event = await insertEvent();
const user = await insertUser();
const usdCurrency = await insertAllowedCurrency({
currency: "USD",
validPaymentMethods: "stripe",
});

await insertEventToCommunity({
eventId: event.id,
communityId: community.id,
});

const ticket = await insertTicketTemplate({
eventId: event.id,
quantity: 100,
});

const userTicket = await insertTicket({
userId: user.id,
ticketTemplateId: ticket.id,
approvalStatus: "approved",
});

const paidAddon = await insertAddon({
name: "Paid Addon",
eventId: event.id,
isFree: false,
maxPerTicket: 2,
});

await insertTicketAddon({
ticketId: ticket.id,
addonId: paidAddon.id,
orderDisplay: 1,
});

await insertAddonPrice({
addonId: paidAddon.id,
priceId: (
await insertPrice({
price_in_cents: 1000,
currencyId: usdCurrency.id,
})
).id,
});

vi.mocked(handlePaymentLinkGeneration).mockResolvedValue({
purchaseOrder: {
id: SAMPLE_TEST_UUID,
publicId: "some-public-id",
userId: user.id,
idempotencyUUIDKey: "some-idempotency-key",
totalPrice: "1000",
description: null,
status: "open",
createdAt: new Date(),
updatedAt: null,
deletedAt: null,
currencyId: usdCurrency.id,
paymentPlatform: "stripe",
paymentPlatformPaymentLink: "https://test-payment-link.com",
purchaseOrderPaymentStatus: "unpaid",
paymentPlatformExpirationDate: null,
paymentPlatformReferenceID: null,
paymentPlatformStatus: null,
paymentPlatformMetadata: null,
},
ticketsIds: [],
});

const response = await executeGraphqlOperationAsUser<
ClaimUserTicketAddonsMutation,
ClaimUserTicketAddonsMutationVariables
>(
{
document: ClaimUserTicketAddons,
variables: {
addonsClaims: [
{
userTicketId: userTicket.id,
addonId: paidAddon.id,
quantity: 1,
},
],
currencyId: usdCurrency.id,
},
},
user,
);

assert.equal(response.errors, undefined);

assert.equal(
response.data?.claimUserTicketAddons.__typename,
"PurchaseOrder",
);

if (response.data?.claimUserTicketAddons.__typename === "PurchaseOrder") {
assert.equal(response.data.claimUserTicketAddons.status, "open");

assert.equal(
response.data.claimUserTicketAddons.purchasePaymentStatus,
"unpaid",
);

assert.equal(
response.data.claimUserTicketAddons.paymentLink,
"https://test-payment-link.com",
);
}
});
});

0 comments on commit 2d9639a

Please sign in to comment.