Fixes/Update-logic-reward-program

This commit is contained in:
John Yeo
2025-09-22 13:17:56 +01:00
parent 5f9eb4f02d
commit 59aaf3c430
2 changed files with 134 additions and 137 deletions

View File

@@ -7,164 +7,163 @@ import { notNullish } from "@/utils/genUtils.js";
import { createStripeCli } from "../utils.js";
export async function handleCusDiscountDeleted({
db,
org,
discount,
env,
logger,
res,
db,
org,
discount,
env,
logger,
res,
}: {
db: DrizzleCli;
org: any;
discount: any;
env: any;
logger: any;
res: any;
db: DrizzleCli;
org: any;
discount: any;
env: any;
logger: any;
res: any;
}) {
const customer = await CusService.getByStripeId({
db,
stripeId: discount.customer,
});
const customer = await CusService.getByStripeId({
db,
stripeId: discount.customer,
});
if (!customer) {
logger.warn(`discount.deleted: customer ${discount.customer} not found`);
return;
}
if (!customer) {
logger.warn(`discount.deleted: customer ${discount.customer} not found`);
return;
}
if (customer.env !== env || customer.org_id !== org.id) {
logger.info(
`discount.deleted: env or org mismatch, skipping, ${customer.env} !== ${env} || ${customer.org_id} !== ${org.id}`,
);
return;
}
if (customer.env !== env || customer.org_id !== org.id) {
logger.info(
`discount.deleted: env or org mismatch, skipping, ${customer.env} !== ${env} || ${customer.org_id} !== ${org.id}`
);
return;
}
// Check if any redemptions available, and apply to customer if so
const redemptions = await RewardRedemptionService.getUnappliedRedemptions({
db,
internalCustomerId: customer.internal_id,
});
// Check if any redemptions available, and apply to customer if so
const redemptions = await RewardRedemptionService.getUnappliedRedemptions({
db,
internalCustomerId: customer.internal_id,
});
logger.info(
`discount.deleted:, discount ID: ${discount.id}, found ${redemptions.length} redemptions`,
);
logger.info(
`discount.deleted:, discount ID: ${discount.id}, found ${redemptions.length} redemptions`
);
if (redemptions.length == 0) return;
if (redemptions.length == 0) return;
const paidProductRedemption = redemptions.find(
(r) =>
r.reward_program.reward.id ===
(typeof discount.coupon == "string"
? discount.coupon
: discount.coupon.id),
);
const paidProductRedemption = redemptions.find(
(r) =>
r.reward_program.reward.id ===
(typeof discount.coupon == "string"
? discount.coupon
: discount.coupon.id)
);
if (discount.subscription) {
logger.info(
`Discount is a subscription, paidProductRedemption: ${paidProductRedemption?.id}`,
);
if (discount.subscription) {
logger.info(
`Discount is a subscription, paidProductRedemption: ${paidProductRedemption?.id}`
);
if (!paidProductRedemption) return;
if (!paidProductRedemption) return;
// Re-apply coupon and mark applied / redeemer applied to true
const stripeCli = createStripeCli({
org,
env,
});
// Re-apply coupon and mark applied / redeemer applied to true
const stripeCli = createStripeCli({
org,
env,
});
// Mark reward redemption as applied / redeemer applied to true
// Mark reward redemption as applied / redeemer applied to true
const sub = await stripeCli.subscriptions.retrieve(discount.subscription);
const sub = await stripeCli.subscriptions.retrieve(discount.subscription);
// can't really test because it modifies subscription affected by test clock...
try {
await stripeCli.subscriptions.update(discount.subscription, {
discounts: [
...(sub.discounts as string[]).map((d: string) => ({
discount: d,
})),
{
coupon: paidProductRedemption.reward_program.reward.id as string,
},
],
});
} catch (error: any) {
logger.error(
`Failed to update subscription ${discount.subscription} with paid product coupon, error: ${error.message}`
);
throw error;
}
// can't really test because it modifies subscription affected by test clock...
try {
await stripeCli.subscriptions.update(discount.subscription, {
discounts: [
...(sub.discounts as string[]).map((d: string) => ({
discount: d,
})),
{
coupon: paidProductRedemption.reward_program.reward.id as string,
},
],
});
} catch (error: any) {
logger.error(
`Failed to update subscription ${discount.subscription} with paid product coupon, error: ${error.message}`,
);
throw error;
}
// Mark reward redemption as applied / redeemer applied to true
const isReferrer =
paidProductRedemption.referral_code.internal_customer_id ===
customer.internal_id;
// Mark reward redemption as applied / redeemer applied to true
const isReferrer =
paidProductRedemption.referral_code.internal_customer_id ===
customer.internal_id;
await RewardRedemptionService.update({
db,
id: paidProductRedemption.id,
updates: {
applied: isReferrer ? true : undefined,
redeemer_applied: isReferrer ? undefined : true,
},
});
await RewardRedemptionService.update({
db,
id: paidProductRedemption.id,
updates: {
applied: isReferrer ? true : undefined,
redeemer_applied: isReferrer ? undefined : true,
},
});
return;
}
return;
}
const redemption = redemptions[0];
const redemption = redemptions[0];
// Apply redemption to customer
const stripeCli = createStripeCli({
org,
env,
});
// Apply redemption to customer
const stripeCli = createStripeCli({
org,
env,
});
const stripeCus = (await stripeCli.customers.retrieve(
discount.customer
)) as Stripe.Customer;
const stripeCus = (await stripeCli.customers.retrieve(
discount.customer,
)) as Stripe.Customer;
if (stripeCus && notNullish(stripeCus.discount)) {
logger.info(
`discount.deleted: stripe customer ${discount.customer} already has a discount`
);
return;
}
if (stripeCus && notNullish(stripeCus.discount)) {
logger.info(
`discount.deleted: stripe customer ${discount.customer} already has a discount`,
);
return;
}
const reward = await RewardService.get({
db,
orgId: org.id,
env,
idOrInternalId: redemption.reward_program.internal_reward_id!,
});
const reward = await RewardService.get({
db,
orgId: org.id,
env,
idOrInternalId: redemption.reward_program.internal_reward_id!,
});
if (!reward) {
logger.warn(
`discount.deleted: reward ${redemption.reward_program.internal_id} not found`
);
return;
}
if (!reward) {
logger.warn(
`discount.deleted: reward ${redemption.reward_program.internal_id} not found`,
);
return;
}
const legacyStripe = createStripeCli({
org,
env,
legacyVersion: true,
});
const legacyStripe = createStripeCli({
org,
env,
legacyVersion: true,
});
await legacyStripe.customers.update(discount.customer, {
// @ts-expect-error
coupon: reward.id,
});
await legacyStripe.customers.update(discount.customer, {
// @ts-expect-error
coupon: reward.id,
});
await RewardRedemptionService.update({
db,
id: redemption.id,
updates: {
applied: true,
},
});
await RewardRedemptionService.update({
db,
id: redemption.id,
updates: {
applied: true,
},
});
logger.info(
`discount.deleted: applied reward ${reward.name} on customer ${customer.name} (${customer.id})`,
);
logger.info(`Redemption ID: ${redemption.id}`);
logger.info(
`discount.deleted: applied reward ${reward.name} on customer ${customer.name} (${customer.id})`
);
logger.info(`Redemption ID: ${redemption.id}`);
}

View File

@@ -46,8 +46,6 @@ rewardProgramRouter.put("/:id", (req, res) =>
env,
});
// console.log("Existing program:", existingProgram);
if (!existingProgram) {
throw new RecaseError({
message: `Program with ID ${id} does not exist`,
@@ -65,7 +63,7 @@ rewardProgramRouter.put("/:id", (req, res) =>
env,
});
// console.log("Updating program to:", rewardProgram);
// Update on existing redemptions? (should be none unless affecting stacked rewards...)
if (
rewardProgram.when == RewardTriggerEvent.Checkout &&