Merged in feat/basic-user (pull request #3135)

feat(SW-3610): Get basic user from api

* feat(SW-3610): Get basic user from api

* .

* Optional profileid


Approved-by: Anton Gunnarsson
This commit is contained in:
Linus Flood
2025-11-12 14:00:56 +00:00
parent 88644597df
commit 19495eed28
11 changed files with 123 additions and 23 deletions

View File

@@ -224,6 +224,7 @@ export namespace endpoints {
*/
export namespace Profile {
export const profile = `${base.path.profile}/${version}/${base.enitity.Profile}`
export const basicProfile = `${profile}/BasicInfo`
export const promoCampaign = `${profile}/Promotion`
export function teamMemberCard(employeeId: string) {

View File

@@ -2,6 +2,7 @@ import type { Lang } from "@scandic-hotels/common/constants/language"
import type { User } from "next-auth"
import type { JWT } from "next-auth/jwt"
import type { getBasicUser } from "./routers/user/utils/getBasicUser"
import type { getVerifiedUser } from "./routers/user/utils/getVerifiedUser"
type Session = {
@@ -12,6 +13,7 @@ type Session = {
}
type ScandicUser = Awaited<ReturnType<typeof getVerifiedUser>>
type ScandicBasicUser = Awaited<ReturnType<typeof getBasicUser>>
type CreateContextOptions = {
auth: () => Promise<Session | null>
lang: Lang
@@ -26,6 +28,7 @@ type CreateContextOptions = {
getScandicUser: (input?: {
withExtendedPartnerData: boolean
}) => Promise<ScandicUser | null>
getScandicBasicUser: () => Promise<ScandicBasicUser | null>
}
export function createContext(opts: CreateContextOptions) {
@@ -41,6 +44,7 @@ export function createContext(opts: CreateContextOptions) {
getScandicUserToken: opts.getScandicUserToken,
getUserPointsBalance: opts.getUserPointsBalance,
getScandicUser: opts.getScandicUser,
getScandicBasicUser: opts.getScandicBasicUser,
}
}

View File

@@ -9,7 +9,7 @@ import { safeTry } from "@scandic-hotels/common/utils/safeTry"
import * as api from "../../../api"
import { protectedProcedure } from "../../../procedures"
import { getUserSchema } from "../../user/output"
import { getVerifiedUser } from "../../user/utils/getVerifiedUser"
import { getBasicUser } from "../../user/utils/getBasicUser"
import type { FriendsTier } from "../../../types/user"
@@ -33,12 +33,12 @@ export const performLevelUpgrade = protectedProcedure
}
const [profile, error] = await safeTry(
getVerifiedUser({ token: ctx.session.token })
getBasicUser({ token: ctx.session.token })
)
if (!profile?.membership || error) {
if (!profile || error) {
return { tierMatchState: "error" }
}
const currentLevel = profile.membership.membershipLevel
const currentLevel = profile.tier
sasLogger.debug("tier match started")

View File

@@ -128,6 +128,30 @@ export const getUserSchema = z
}
})
export const getBasicUserSchema = z.object({
dateOfBirth: z.string().optional().default("1900-01-01"),
firstName: z.string(),
language: z
.string()
.transform((s) => s.charAt(0).toUpperCase() + s.slice(1))
.optional(),
lastName: z.string(),
phoneNumber: z.string().optional(),
profileId: z.string().optional(),
membershipNumber: z.string(),
tier: scandicFriendsTier,
address: z
.object({
city: z.string().optional(),
country: z.string().optional(),
countryCode: z.nativeEnum(countriesMap).optional(),
streetAddress: z.string().optional(),
zipCode: z.string().optional(),
})
.optional()
.nullable(),
})
export const creditCardSchema = z
.object({
attribute: z.object({

View File

@@ -83,7 +83,7 @@ export const userQueryRouter = router({
if (!isValidSession(ctx.session)) {
return null
}
const user = await ctx.getScandicUser()
const user = await ctx.getScandicBasicUser()
if (!user) {
return null

View File

@@ -3,8 +3,7 @@ import { createCounter } from "@scandic-hotels/common/telemetry"
import { safeProtectedProcedure } from "../../../procedures"
import { isValidSession } from "../../../utils/session"
import { getEuroBonusProfileData } from "../../partners/sas/getEuroBonusProfile"
import { getFriendsMembership } from "../helpers"
import { getVerifiedUser } from "../utils/getVerifiedUser"
import { getBasicUser } from "../utils/getBasicUser"
import type { LoginType } from "@scandic-hotels/common/constants/loginType"
import type { Session } from "next-auth"
@@ -48,9 +47,9 @@ async function getScandicFriendsUserTrackingData(session: Session | null) {
}
try {
const verifiedUserData = await getVerifiedUser({ token: session.token })
const verifiedUserData = await getBasicUser({ token: session.token })
if (!verifiedUserData || !verifiedUserData.loyalty) {
if (!verifiedUserData) {
metricsUserTrackingInfo.success({
reason: "invalid user data",
data: notLoggedInUserTrackingData,
@@ -58,14 +57,12 @@ async function getScandicFriendsUserTrackingData(session: Session | null) {
return notLoggedInUserTrackingData
}
const membership = getFriendsMembership(verifiedUserData.loyalty)
const loggedInUserTrackingData: TrackingUserData = {
loginStatus: "logged in",
loginType: session.token.loginType as LoginType,
memberId: verifiedUserData.profileId,
membershipNumber: membership?.membershipNumber,
memberLevel: membership?.membershipLevel,
membershipNumber: verifiedUserData.membershipNumber,
memberLevel: verifiedUserData?.tier,
loginAction: "login success",
memberType,
}
@@ -126,19 +123,17 @@ async function getSasEurobonusUserTrackingData(
async function getScandicFriendsDataHelper(scandicUserToken: string | null) {
if (!scandicUserToken) return null
const verifiedUserData = await getVerifiedUser({
const verifiedUserData = await getBasicUser({
token: { access_token: scandicUserToken },
})
if (!verifiedUserData || !verifiedUserData.loyalty) {
if (!verifiedUserData) {
return null
}
const membership = getFriendsMembership(verifiedUserData.loyalty)
return {
memberId: verifiedUserData.profileId,
membershipNumber: membership?.membershipNumber,
memberLevel: membership?.membershipLevel,
membershipNumber: verifiedUserData.membershipNumber,
memberLevel: verifiedUserData.tier,
}
}

View File

@@ -9,7 +9,7 @@ import { cache } from "../../DUPLICATED/cache"
import { creditCardsSchema } from "../../routers/user/output"
import { toApiLang } from "../../utils"
import { encrypt } from "../../utils/encryption"
import { getVerifiedUser } from "./utils/getVerifiedUser"
import { getBasicUser } from "./utils/getBasicUser"
import { type FriendTransaction, getStaysSchema, type Stay } from "./output"
import type { Lang } from "@scandic-hotels/common/constants/language"
@@ -190,7 +190,7 @@ export async function updateStaysBookingUrl(
lang: Lang
) {
const [user, error] = await safeTry(
getVerifiedUser({
getBasicUser({
token: session.token,
})
)

View File

@@ -0,0 +1,48 @@
import { createCounter } from "@scandic-hotels/common/telemetry"
import * as api from "../../../api"
import { cache } from "../../../DUPLICATED/cache"
import { serverErrorByStatus, sessionExpiredError } from "../../../errors"
import { getBasicUserSchema } from "../output"
export const getBasicUser = cache(
async ({
token,
}: {
token: { expires_at?: number; access_token: string }
}) => {
const getBasicUserCounter = createCounter("user", "getBasicUser")
const metricsGetBasicUser = getBasicUserCounter.init()
metricsGetBasicUser.start()
const now = Date.now()
if (token.expires_at && token.expires_at < now) {
metricsGetBasicUser.dataError(`Token expired`)
throw sessionExpiredError()
}
const apiResponse = await api.get(api.endpoints.v2.Profile.basicProfile, {
headers: {
Authorization: `Bearer ${token.access_token}`,
},
})
if (!apiResponse.ok) {
await metricsGetBasicUser.httpError(apiResponse)
throw serverErrorByStatus(apiResponse.status, apiResponse)
}
const apiJson = await apiResponse.json()
const verifiedData = getBasicUserSchema.safeParse(apiJson)
if (!verifiedData.success) {
metricsGetBasicUser.validationError(verifiedData.error)
throw verifiedData.error
}
metricsGetBasicUser.success()
return verifiedData.data
}
)

View File

@@ -5,7 +5,7 @@ import { safeTry } from "@scandic-hotels/common/utils/safeTry"
import { env } from "../../../../env/server"
import { encrypt } from "../../../utils/encryption"
import { getVerifiedUser } from "./getVerifiedUser"
import { getBasicUser } from "./getBasicUser"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { Session } from "next-auth"
@@ -30,7 +30,7 @@ export async function updateStaysBookingUrl(
lang: Lang
) {
const [user, error] = await safeTry(
getVerifiedUser({
getBasicUser({
token: {
access_token: session.token.access_token,
expires_at: session.token.expires_at ?? 0,