chore(LOY-175): remove references to old reward endpoints

This commit is contained in:
Christian Andolf
2025-03-10 13:35:07 +01:00
parent 4ff44311a9
commit 0ae4c5db17
8 changed files with 13 additions and 193 deletions

View File

@@ -60,6 +60,5 @@ ENABLE_BOOKING_WIDGET_HOTELRESERVATION_PATH="false"
SHOW_SITE_WIDE_ALERT="false" SHOW_SITE_WIDE_ALERT="false"
SHOW_SIGNUP_FLOW="true" SHOW_SIGNUP_FLOW="true"
USE_NEW_REWARDS_ENDPOINT="true"
USE_NEW_REWARD_MODEL="true" USE_NEW_REWARD_MODEL="true"

View File

@@ -43,7 +43,6 @@ GOOGLE_STATIC_MAP_ID="test"
GOOGLE_DYNAMIC_MAP_ID="test" GOOGLE_DYNAMIC_MAP_ID="test"
NEXT_PUBLIC_HIDE_FOR_NEXT_RELEASE="true" NEXT_PUBLIC_HIDE_FOR_NEXT_RELEASE="true"
SALESFORCE_PREFERENCE_BASE_URL="test" SALESFORCE_PREFERENCE_BASE_URL="test"
USE_NEW_REWARDS_ENDPOINT="true"
USE_NEW_REWARD_MODEL="true" USE_NEW_REWARD_MODEL="true"
TZ=UTC TZ=UTC

View File

@@ -31,7 +31,7 @@ export default async function CurrentRewardsBlock({
<SectionHeader title={title} link={link} preamble={subtitle} /> <SectionHeader title={title} link={link} preamble={subtitle} />
<ClientCurrentRewards <ClientCurrentRewards
rewards={rewardsResponse.rewards} rewards={rewardsResponse.rewards}
showRedeem={env.USE_NEW_REWARDS_ENDPOINT && env.USE_NEW_REWARD_MODEL} showRedeem={env.USE_NEW_REWARD_MODEL}
membershipNumber={membershipLevel?.membershipNumber} membershipNumber={membershipLevel?.membershipNumber}
/> />
<SectionLink link={link} variant="mobile" /> <SectionLink link={link} variant="mobile" />

View File

@@ -141,13 +141,6 @@ export const env = createEnv({
// transform to boolean // transform to boolean
.transform((s) => s === "true") .transform((s) => s === "true")
.default("false"), .default("false"),
USE_NEW_REWARDS_ENDPOINT: z
.string()
// only allow "true" or "false"
.refine((s) => s === "true" || s === "false")
// transform to boolean
.transform((s) => s === "true")
.default("false"),
USE_NEW_REWARD_MODEL: z USE_NEW_REWARD_MODEL: z
.string() .string()
// only allow "true" or "false" // only allow "true" or "false"
@@ -268,7 +261,6 @@ export const env = createEnv({
GOOGLE_STATIC_MAP_ID: process.env.GOOGLE_STATIC_MAP_ID, GOOGLE_STATIC_MAP_ID: process.env.GOOGLE_STATIC_MAP_ID,
GOOGLE_DYNAMIC_MAP_ID: process.env.GOOGLE_DYNAMIC_MAP_ID, GOOGLE_DYNAMIC_MAP_ID: process.env.GOOGLE_DYNAMIC_MAP_ID,
HIDE_FOR_NEXT_RELEASE: process.env.NEXT_PUBLIC_HIDE_FOR_NEXT_RELEASE, HIDE_FOR_NEXT_RELEASE: process.env.NEXT_PUBLIC_HIDE_FOR_NEXT_RELEASE,
USE_NEW_REWARDS_ENDPOINT: process.env.USE_NEW_REWARDS_ENDPOINT,
USE_NEW_REWARD_MODEL: process.env.USE_NEW_REWARD_MODEL, USE_NEW_REWARD_MODEL: process.env.USE_NEW_REWARD_MODEL,
ENABLE_BOOKING_FLOW: process.env.ENABLE_BOOKING_FLOW, ENABLE_BOOKING_FLOW: process.env.ENABLE_BOOKING_FLOW,
ENABLE_BOOKING_WIDGET: process.env.ENABLE_BOOKING_WIDGET, ENABLE_BOOKING_WIDGET: process.env.ENABLE_BOOKING_WIDGET,

View File

@@ -171,10 +171,6 @@ export namespace endpoints {
export const unlink = `${base.path.profile}/${version}/${base.enitity.Profile}/Unlink` export const unlink = `${base.path.profile}/${version}/${base.enitity.Profile}/Unlink`
export const matchTier = `${base.path.profile}/${version}/${base.enitity.Profile}/MatchTier` export const matchTier = `${base.path.profile}/${version}/${base.enitity.Profile}/MatchTier`
// TODO: Remove once new endpoints are out in production.
export const reward = `${base.path.profile}/${version}/${base.enitity.Profile}/reward`
export const tierRewards = `${base.path.profile}/${version}/${base.enitity.Profile}/tierRewards`
export function deleteProfile(profileId: string) { export function deleteProfile(profileId: string) {
return `${profile}/${profileId}` return `${profile}/${profileId}`
} }

View File

@@ -12,66 +12,6 @@ import { systemSchema } from "../schemas/system"
import type { RewardCategory } from "@/types/components/myPages/rewards" import type { RewardCategory } from "@/types/components/myPages/rewards"
const Coupon = z.object({
code: z.string().optional(),
status: z.string().optional(),
createdAt: z.string().datetime({ offset: true }).optional(),
customer: z.object({
id: z.string().optional(),
}),
name: z.string().optional(),
claimedAt: z.string().datetime({ offset: true }).optional(),
redeemedAt: z
.date({ coerce: true })
.optional()
.transform((value) => {
if (value?.getFullYear() === 1) {
return null
}
return value
}),
type: z.string().optional(),
value: z.number().optional(),
pool: z.string().optional(),
cfUnwrapped: z.boolean().default(false),
})
const SurpriseReward = z.object({
title: z.string().optional(),
id: z.string().optional(),
type: z.literal("coupon"),
status: z.string().optional(),
rewardId: z.string().optional(),
redeemLocation: z.string().optional(),
autoApplyReward: z.boolean().default(false),
rewardType: z.string().optional(),
endsAt: z.string().datetime({ offset: true }).optional(),
coupons: z.array(Coupon).optional(),
operaRewardId: z.string().default(""),
})
export const validateApiRewardSchema = z
.object({
data: z.array(
z.discriminatedUnion("type", [
z.object({
title: z.string().optional(),
id: z.string().optional(),
type: z.literal("custom"),
status: z.string().optional(),
rewardId: z.string().optional(),
redeemLocation: z.string().optional(),
autoApplyReward: z.boolean().default(false),
rewardType: z.string().optional(),
rewardTierLevel: z.string().optional(),
operaRewardId: z.string().default(""),
}),
SurpriseReward,
])
),
})
.transform((data) => data.data)
enum TierKey { enum TierKey {
tier1 = MembershipLevelEnum.L1, tier1 = MembershipLevelEnum.L1,
tier2 = MembershipLevelEnum.L2, tier2 = MembershipLevelEnum.L2,
@@ -84,26 +24,6 @@ enum TierKey {
type Key = keyof typeof TierKey type Key = keyof typeof TierKey
export const validateApiTierRewardsSchema = z.record(
z.nativeEnum(TierKey).transform((data) => {
return TierKey[data as unknown as Key]
}),
z.array(
z.object({
title: z.string().optional(),
id: z.string().optional(),
type: z.string().optional(),
status: z.string().optional(),
rewardId: z.string().optional(),
redeemLocation: z.string().optional(),
autoApplyReward: z.boolean().default(false),
rewardType: z.string().optional(),
rewardTierLevel: z.string().optional(),
operaRewardId: z.string().default(""),
})
)
)
export const validateCmsRewardsSchema = z export const validateCmsRewardsSchema = z
.object({ .object({
data: z.object({ data: z.object({
@@ -168,10 +88,6 @@ export const validateCmsRewardsWithRedeemSchema = z
}) })
.transform((data) => data.data.all_reward.items) .transform((data) => data.data.all_reward.items)
export type ApiReward = z.output<typeof validateApiRewardSchema>[number]
export type SurpriseReward = z.output<typeof SurpriseReward>
export type CmsRewardsResponse = z.input<typeof validateCmsRewardsSchema> export type CmsRewardsResponse = z.input<typeof validateCmsRewardsSchema>
export type CmsRewardsWithRedeemResponse = z.input< export type CmsRewardsWithRedeemResponse = z.input<

View File

@@ -1,4 +1,3 @@
import { env } from "@/env/server"
import * as api from "@/lib/api" import * as api from "@/lib/api"
import { dt } from "@/lib/dt" import { dt } from "@/lib/dt"
import { notFound } from "@/server/errors/trpc" import { notFound } from "@/server/errors/trpc"
@@ -20,11 +19,9 @@ import {
import { import {
type Reward, type Reward,
type Surprise, type Surprise,
validateApiRewardSchema,
validateCategorizedRewardsSchema, validateCategorizedRewardsSchema,
} from "./output" } from "./output"
import { import {
getAllCachedApiRewards,
getAllRewardCounter, getAllRewardCounter,
getAllRewardFailCounter, getAllRewardFailCounter,
getAllRewardSuccessCounter, getAllRewardSuccessCounter,
@@ -52,9 +49,7 @@ export const rewardQueryRouter = router({
.query(async function ({ input, ctx }) { .query(async function ({ input, ctx }) {
getAllRewardCounter.add(1) getAllRewardCounter.add(1)
const allApiRewards = env.USE_NEW_REWARDS_ENDPOINT const allApiRewards = await getCachedAllTierRewards(ctx.serviceToken)
? await getCachedAllTierRewards(ctx.serviceToken)
: await getAllCachedApiRewards(ctx.serviceToken)
if (!allApiRewards) { if (!allApiRewards) {
return [] return []
@@ -114,9 +109,9 @@ export const rewardQueryRouter = router({
getByLevelRewardCounter.add(1) getByLevelRewardCounter.add(1)
const { level_id } = input const { level_id } = input
const allUpcomingApiRewards = env.USE_NEW_REWARDS_ENDPOINT const allUpcomingApiRewards = await getCachedAllTierRewards(
? await getCachedAllTierRewards(ctx.serviceToken) ctx.serviceToken
: await getAllCachedApiRewards(ctx.serviceToken) )
if (!allUpcomingApiRewards || !allUpcomingApiRewards[level_id]) { if (!allUpcomingApiRewards || !allUpcomingApiRewards[level_id]) {
getByLevelRewardFailCounter.add(1) getByLevelRewardFailCounter.add(1)
@@ -167,10 +162,7 @@ export const rewardQueryRouter = router({
.query(async function ({ ctx }) { .query(async function ({ ctx }) {
getCurrentRewardCounter.add(1) getCurrentRewardCounter.add(1)
const isNewEndpoint = env.USE_NEW_REWARDS_ENDPOINT const endpoint = api.endpoints.v1.Profile.Reward.reward
const endpoint = isNewEndpoint
? api.endpoints.v1.Profile.Reward.reward
: api.endpoints.v1.Profile.reward
const apiResponse = await api.get(endpoint, { const apiResponse = await api.get(endpoint, {
headers: { headers: {
@@ -203,9 +195,8 @@ export const rewardQueryRouter = router({
const data = await apiResponse.json() const data = await apiResponse.json()
const validatedApiRewards = isNewEndpoint const validatedApiRewards =
? validateCategorizedRewardsSchema.safeParse(data) validateCategorizedRewardsSchema.safeParse(data)
: validateApiRewardSchema.safeParse(data)
if (!validatedApiRewards.success) { if (!validatedApiRewards.success) {
getCurrentRewardFailCounter.add(1, { getCurrentRewardFailCounter.add(1, {
@@ -301,10 +292,7 @@ export const rewardQueryRouter = router({
.query(async ({ ctx }) => { .query(async ({ ctx }) => {
getCurrentRewardCounter.add(1) getCurrentRewardCounter.add(1)
const isNewEndpoint = env.USE_NEW_REWARDS_ENDPOINT const endpoint = api.endpoints.v1.Profile.Reward.reward
const endpoint = isNewEndpoint
? api.endpoints.v1.Profile.Reward.reward
: api.endpoints.v1.Profile.reward
const apiResponse = await api.get(endpoint, { const apiResponse = await api.get(endpoint, {
cache: undefined, cache: undefined,
@@ -337,9 +325,8 @@ export const rewardQueryRouter = router({
} }
const data = await apiResponse.json() const data = await apiResponse.json()
const validatedApiRewards = isNewEndpoint const validatedApiRewards =
? validateCategorizedRewardsSchema.safeParse(data) validateCategorizedRewardsSchema.safeParse(data)
: validateApiRewardSchema.safeParse(data)
if (!validatedApiRewards.success) { if (!validatedApiRewards.success) {
getCurrentRewardFailCounter.add(1, { getCurrentRewardFailCounter.add(1, {

View File

@@ -17,14 +17,12 @@ import {
} from "@/utils/generateTag" } from "@/utils/generateTag"
import { import {
type ApiReward,
type CategorizedApiReward, type CategorizedApiReward,
type CmsRewardsResponse, type CmsRewardsResponse,
type CmsRewardsWithRedeemResponse, type CmsRewardsWithRedeemResponse,
type GetRewardWithRedeemRefsSchema, type GetRewardWithRedeemRefsSchema,
rewardWithRedeemRefsSchema, rewardWithRedeemRefsSchema,
validateApiAllTiersSchema, validateApiAllTiersSchema,
validateApiTierRewardsSchema,
validateCmsRewardsSchema, validateCmsRewardsSchema,
validateCmsRewardsWithRedeemSchema, validateCmsRewardsWithRedeemSchema,
} from "./output" } from "./output"
@@ -93,71 +91,6 @@ export function getUniqueRewardIds(rewardIds: string[]) {
return Array.from(uniqueRewardIds) return Array.from(uniqueRewardIds)
} }
/**
* Uses the legacy profile/v1/Profile/tierRewards endpoint.
* TODO: Delete when the new endpoint is out in production.
*/
export async function getAllCachedApiRewards(token: string) {
const cacheClient = await getCacheClient()
return await cacheClient.cacheOrGet(
"getAllApiRewards",
async () => {
const apiResponse = await api.get(api.endpoints.v1.Profile.tierRewards, {
headers: {
Authorization: `Bearer ${token}`,
},
})
if (!apiResponse.ok) {
const text = await apiResponse.text()
getAllRewardFailCounter.add(1, {
error_type: "http_error",
error: JSON.stringify({
status: apiResponse.status,
statusText: apiResponse.statusText,
text,
}),
})
console.error(
"api.rewards.tierRewards error ",
JSON.stringify({
error: {
status: apiResponse.status,
statusText: apiResponse.statusText,
text,
},
})
)
throw apiResponse
}
const data = await apiResponse.json()
const validatedApiTierRewards =
validateApiTierRewardsSchema.safeParse(data)
if (!validatedApiTierRewards.success) {
getAllRewardFailCounter.add(1, {
error_type: "validation_error",
error: JSON.stringify(validatedApiTierRewards.error),
})
console.error(validatedApiTierRewards.error)
console.error(
"api.rewards validation error",
JSON.stringify({
error: validatedApiTierRewards.error,
})
)
throw validatedApiTierRewards.error
}
return validatedApiTierRewards.data
},
"1h"
)
}
/** /**
* Cached for 1 hour. * Cached for 1 hour.
*/ */
@@ -364,9 +297,7 @@ export async function getCmsRewards(lang: Lang, rewardIds: string[]) {
return validatedCmsRewards.data return validatedCmsRewards.data
} }
export function getNonRedeemedRewardIds( export function getNonRedeemedRewardIds(rewards: Array<CategorizedApiReward>) {
rewards: Array<ApiReward | CategorizedApiReward>
) {
return rewards return rewards
.filter((reward) => { .filter((reward) => {
if ("coupon" in reward && reward.coupon.length > 0) { if ("coupon" in reward && reward.coupon.length > 0) {