diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/login/route.ts b/apps/scandic-web/app/[lang]/(live)/(public)/login/route.ts index 608777608..4dd995926 100644 --- a/apps/scandic-web/app/[lang]/(live)/(public)/login/route.ts +++ b/apps/scandic-web/app/[lang]/(live)/(public)/login/route.ts @@ -123,6 +123,7 @@ export async function GET( "booking", "profile_link", "profile_matchtier", + "profile_point_transfer", "availability", ], /** diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/verifymagiclink/route.ts b/apps/scandic-web/app/[lang]/(live)/(public)/verifymagiclink/route.ts index f9da57651..87b29a889 100644 --- a/apps/scandic-web/app/[lang]/(live)/(public)/verifymagiclink/route.ts +++ b/apps/scandic-web/app/[lang]/(live)/(public)/verifymagiclink/route.ts @@ -82,6 +82,7 @@ export async function GET( "availability", "profile_link", "profile_matchtier", + "profile_point_transfer", ].join(" "), loginKey: loginKey, for_origin: publicURL, diff --git a/apps/scandic-web/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/otp/page.tsx b/apps/scandic-web/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/otp/page.tsx index cf883bcb6..ae2f925f1 100644 --- a/apps/scandic-web/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/otp/page.tsx +++ b/apps/scandic-web/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/otp/page.tsx @@ -262,15 +262,22 @@ async function handleTransferPoints({ }) ) - if (!res || error) { + if (!res || error || res.transferState === "error") { console.error("[SAS] transfer points error", error) return { - // TODO better errors? url: `/${lang}/sas-x-scandic/error`, type: "replace", } } + if (res.transferState === "notLinked") { + console.warn("[SAS] transfer points not linked") + return { + url: `/${lang}/sas-x-scandic/link`, + type: "replace", + } + } + console.log("[SAS] transfer points response", res) return { diff --git a/apps/scandic-web/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/transfer/success/page.tsx b/apps/scandic-web/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/transfer/success/page.tsx index 1ad62886a..5226eaab6 100644 --- a/apps/scandic-web/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/transfer/success/page.tsx +++ b/apps/scandic-web/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/transfer/success/page.tsx @@ -20,9 +20,11 @@ import styles from "./transferSuccess.module.css" import type { LangParams, PageArgs, SearchParams } from "@/types/params" import type { Lang } from "@/constants/languages" -export default async function SASxScandicTransferSuccessPage(props: PageArgs & SearchParams<{ p?: string }>) { - const searchParams = await props.searchParams; - const params = await props.params; +export default async function SASxScandicTransferSuccessPage( + props: PageArgs & SearchParams<{ p?: string }> +) { + const searchParams = await props.searchParams + const params = await props.params const intl = await getIntl() const { lang } = params const addedPoints = Number(searchParams.p) || 0 @@ -75,7 +77,6 @@ async function TransactionCard({ const profile = await getProfileSafely() const transferredPoints = intl.formatNumber(addedPoints) - // TODO is this updated immediately? const totalPoints = profile?.membership?.currentPoints ?? 0 const showBonusNight = totalPoints > 10_000 diff --git a/apps/scandic-web/lib/api/endpoints.ts b/apps/scandic-web/lib/api/endpoints.ts index 07a3f5a38..92224fcb1 100644 --- a/apps/scandic-web/lib/api/endpoints.ts +++ b/apps/scandic-web/lib/api/endpoints.ts @@ -177,6 +177,7 @@ export namespace endpoints { export const link = `${base.path.profile}/${version}/${base.enitity.Profile}/link` export const unlink = `${base.path.profile}/${version}/${base.enitity.Profile}/Unlink` export const matchTier = `${base.path.profile}/${version}/${base.enitity.Profile}/MatchTier` + export const pointTransfer = `${base.path.profile}/${version}/${base.enitity.Profile}/PointTransfer/Partner` export function deleteProfile(profileId: string) { return `${profile}/${profileId}` diff --git a/apps/scandic-web/server/routers/partners/sas/transferPoints.ts b/apps/scandic-web/server/routers/partners/sas/transferPoints.ts index ac30bfb9e..e8b9a5be3 100644 --- a/apps/scandic-web/server/routers/partners/sas/transferPoints.ts +++ b/apps/scandic-web/server/routers/partners/sas/transferPoints.ts @@ -1,12 +1,14 @@ +import * as Sentry from "@sentry/nextjs" import { z } from "zod" -// import * as api from "@/lib/api" +import * as api from "@/lib/api" import { protectedProcedure } from "@/server/trpc" +import { getOTPState } from "./otp/getOTPState" import { getSasToken } from "./getSasToken" const outputSchema = z.object({ - transferState: z.enum(["success"]), + transferState: z.enum(["success", "notLinked", "error"]), }) const transferPointsInputSchema = z.object({ @@ -18,24 +20,53 @@ export const transferPoints = protectedProcedure .input(transferPointsInputSchema) .mutation(async function ({ ctx, input }) { const sasAuthToken = await getSasToken() + const { referenceId } = await getOTPState() - console.log("[SAS] transfer points") - console.log({ sasAuthToken }) - console.log({ points: input.points }) + const apiResponse = await api.post(api.endpoints.v1.Profile.pointTransfer, { + headers: { + Authorization: `Bearer ${ctx.session.token.access_token}`, + }, + body: { + partner: "sas_eb", + partnerPoints: input.points, + partnerSpecific: { + eurobonusAccessToken: sasAuthToken, + eurobonusOtpReferenceId: referenceId, + }, + }, + }) - // const apiResponse = await api.post(api.endpoints.v1.Profile.link, { - // headers: { - // Authorization: `Bearer ${ctx.session.token.access_token}`, - // }, - // body: { - // partner: "sas_eb", - // tocDate: getCurrentDateWithoutTime(), - // partnerSpecific: { - // eurobonusAccessToken: sasAuthToken, - // }, - // }, - // }) + if (apiResponse.status === 204) { + return { transferState: "success" } + } + if (apiResponse.status === 400) { + const result = await apiResponse.json() + const data = badRequestSchema.safeParse(result) + if (!data.success) { + const transferPointsBadRequestSchemaError = `[SAS] failed to parse transfer points bad request schema ${JSON.stringify(data.error)}` + console.error(transferPointsBadRequestSchemaError) + Sentry.captureMessage(transferPointsBadRequestSchemaError) + return { transferState: "error" } + } + } + if (apiResponse.status === 404) { + const transferPointsNotFoundError = `[SAS] transfer points failed, no active partner link` + console.error(transferPointsNotFoundError) + Sentry.captureMessage(transferPointsNotFoundError) + return { transferState: "notLinked" } + } - console.log(`[SAS] transfer points success`) - return { transferState: "success" } + const errorMessage = `[SAS] transfer points error with status code ${apiResponse.status} and response ${await apiResponse.text()}` + console.warn(errorMessage) + Sentry.captureMessage(errorMessage) + return { transferState: "error" } }) + +const badRequestSchema = z.object({ + errors: z.array( + z.object({ + code: z.string(), + details: z.string().optional(), + }) + ), +})