Files
calendar/packages/features/bookings/lib/payment/processPaymentRefund.ts
T
Benny JooGitHubbenny@cal.com <sldisek783@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
3aab13b4da refactor: circular deps between app store and lib [3] (#23742)
* getEnabledAppsFromCredentials

* wip

* wip

* mv more

* fix: update test mocking for PrismockClient in processPaymentRefund.test.ts

- Replace prismaMock with prismock for proper PrismockClient usage
- Update mock data structure to include required fields (id, userId, teamId, etc.)
- Create app and credential records separately to handle PrismockClient limitations
- Replace 'as any' type casting with vi.mocked() for proper type safety
- Adjust test expectations to match PrismockClient's actual return structure
- Add proper cleanup in beforeEach hook for both credential and app records

Fixes failing unit tests after migration from packages/lib to packages/features/bookings/lib/payment

Co-Authored-By: benny@cal.com <sldisek783@gmail.com>

* publish platform libraries

* fix import

* bump version

* fix apiv2

* publish platform-libraries

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2025-09-14 11:24:16 -03:00

85 lines
2.7 KiB
TypeScript

import { getPaymentAppData } from "@calcom/app-store/_utils/payments/getPaymentAppData";
import dayjs from "@calcom/dayjs";
import { handlePaymentRefund } from "@calcom/features/bookings/lib/payment/handlePaymentRefund";
import { RefundPolicy } from "@calcom/lib/payment/types";
import prisma from "@calcom/prisma";
import type { Payment, Prisma } from "@calcom/prisma/client";
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
export const processPaymentRefund = async ({
booking,
teamId,
}: {
booking: {
startTime: Date;
endTime: Date;
payment: Payment[];
eventType: {
owner?: {
id: number;
} | null;
metadata?: Prisma.JsonValue;
} | null;
};
teamId?: number | null;
}) => {
const { startTime, eventType, payment } = booking;
if (!teamId && !eventType?.owner) return;
const successPayment = payment.find((p) => p.success);
if (!successPayment) return;
const eventTypeMetadata = EventTypeMetaDataSchema.parse(eventType?.metadata);
const appData = getPaymentAppData({
currency: successPayment.currency,
metadata: eventTypeMetadata,
price: successPayment.amount,
});
if (!appData?.refundPolicy || appData.refundPolicy === RefundPolicy.NEVER) return;
const credentialWhereClause: Prisma.CredentialFindManyArgs["where"] = {
appId: successPayment.appId,
};
if (eventType?.owner) {
credentialWhereClause.userId = eventType.owner.id;
} else if (teamId) {
credentialWhereClause.teamId = teamId;
}
const paymentAppCredentials = await prisma.credential.findMany({
where: credentialWhereClause,
select: {
key: true,
appId: true,
app: {
select: {
categories: true,
dirName: true,
},
},
},
});
const paymentAppCredential = paymentAppCredentials.find((credential) => {
return credential.appId === successPayment.appId;
});
if (!paymentAppCredential) return;
const { refundPolicy, refundCountCalendarDays, refundDaysCount } = appData;
//refundDaysCount would always be present in case DAYS is selected, but adding it in AND jut for type safety
if (refundPolicy === RefundPolicy.DAYS && refundDaysCount) {
const refundDeadline =
refundCountCalendarDays === true
? dayjs(startTime).subtract(refundDaysCount, "days")
: // businessDaysSubtract exists on extended dayjs instance, but ts is messing up
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
dayjs(startTime).businessDaysSubtract(refundDaysCount);
if (dayjs().isAfter(refundDeadline)) return;
}
await handlePaymentRefund(successPayment.id, paymentAppCredential);
};