diff --git a/src/api/crisp/crisp-api.interfaces.ts b/src/api/crisp/crisp-api.interfaces.ts index 572fd27d..6bda1d0b 100644 --- a/src/api/crisp/crisp-api.interfaces.ts +++ b/src/api/crisp/crisp-api.interfaces.ts @@ -16,8 +16,8 @@ export interface CrispProfileCustomFields { course_dbr_sessions?: string; course_iaro?: string; course_iaro_sessions?: string; - course_rtr?: string; - course_rtr_sessions?: string; + course_rtar?: string; + course_rtar_sessions?: string; course_rryts?: string; course_rryts_sessions?: string; course_ma?: string; diff --git a/src/api/mailchimp/mailchimp-api.interfaces.ts b/src/api/mailchimp/mailchimp-api.interfaces.ts index 1af6d29d..6f5f19fc 100644 --- a/src/api/mailchimp/mailchimp-api.interfaces.ts +++ b/src/api/mailchimp/mailchimp-api.interfaces.ts @@ -31,8 +31,8 @@ export interface ListMemberCustomFields { C_DBR_S?: string; C_IARO?: string; C_IARO_S?: string; - C_RTR?: string; - C_RTR_S?: string; + C_RTAR?: string; + C_RTAR_S?: string; C_RRYTS?: string; C_RRYTS_S?: string; C_MA?: string; diff --git a/src/api/mailchimp/mailchimp-api.ts b/src/api/mailchimp/mailchimp-api.ts index 8b48bbe3..2bd8eaac 100644 --- a/src/api/mailchimp/mailchimp-api.ts +++ b/src/api/mailchimp/mailchimp-api.ts @@ -13,7 +13,7 @@ mailchimp.setConfig({ server: mailchimpServerPrefix, }); -export async function getEmailMD5Hash(email: string) { +export function getEmailMD5Hash(email: string) { return createHash('md5').update(email).digest('hex'); } @@ -22,13 +22,15 @@ export async function ping() { console.log(response); } -export async function createMailchimpProfile(profileData: Partial) { +export const createMailchimpProfile = async ( + profileData: Partial, +): Promise => { try { return await mailchimp.lists.addListMember(mailchimpAudienceId, profileData); } catch (error) { throw new Error(`Create mailchimp profile API call failed: ${error}`); } -} +}; // Note getMailchimpProfile is not currently used export const getMailchimpProfile = async (email: string): Promise => { @@ -44,9 +46,11 @@ export const updateMailchimpProfile = async ( email: string, ): Promise => { try { - return await mailchimp.lists.updateListMember(mailchimpAudienceId, getEmailMD5Hash(email), { + return await mailchimp.lists.updateListMember( + mailchimpAudienceId, + getEmailMD5Hash(email), newProfileData, - }); + ); } catch (error) { throw new Error(`Update mailchimp profile API call failed: ${error}`); } @@ -54,11 +58,13 @@ export const updateMailchimpProfile = async ( export const createMailchimpMergeField = async ( name: string, + tag: string, type: MAILCHIMP_MERGE_FIELD_TYPES, ): Promise => { try { return await mailchimp.lists.addListMergeField(mailchimpAudienceId, { name, + tag, type, required: false, }); @@ -79,7 +85,7 @@ export const deleteCypressMailchimpProfiles = async () => { try { const cypressProfiles = (await mailchimp.lists.getSegmentMembersList( mailchimpAudienceId, - '874073', + '5101590', )) as { members: ListMember[] }; cypressProfiles.members.forEach(async (profile: ListMember) => { diff --git a/src/partner-access/partner-access.service.ts b/src/partner-access/partner-access.service.ts index ed51de1d..fc725cda 100644 --- a/src/partner-access/partner-access.service.ts +++ b/src/partner-access/partner-access.service.ts @@ -98,7 +98,7 @@ export class PartnerAccessService { async validatePartnerAutomaticAccessCode(partnerId: string) { const partner = await this.partnerRepository.findOne({ where: { id: partnerId }, - relations: { partnerFeature: true }, + relations: { partnerFeature: { feature: true } }, }); if (!partner) { @@ -109,7 +109,7 @@ export class PartnerAccessService { (pf) => pf.feature.name === FEATURES.AUTOMATIC_ACCESS_CODE, ); - if (!automaticAccessCodePartnerFeature) { + if (!automaticAccessCodePartnerFeature || !partner.partnerFeature) { throw new HttpException( 'Partner does not have automatic access code Feature', HttpStatus.BAD_REQUEST, diff --git a/src/session-user/session-user.service.ts b/src/session-user/session-user.service.ts index d2dcd3fa..397d7237 100644 --- a/src/session-user/session-user.service.ts +++ b/src/session-user/session-user.service.ts @@ -38,11 +38,11 @@ export class SessionUserService { courseUser: CourseUserEntity, course: CourseEntity, ): Promise { - const userSessionIds = courseUser.sessionUser.map((sessionUser) => { + const userSessionIds = courseUser.sessionUser?.map((sessionUser) => { if (sessionUser.completed) return sessionUser.sessionId; }); - const courseSessionIds = course.session.map((session) => { + const courseSessionIds = course.session?.map((session) => { if (session.status === STORYBLOK_STORY_STATUS_ENUM.PUBLISHED) return session.id; }); @@ -178,7 +178,7 @@ export class SessionUserService { sessionUser.completedAt = completed ? new Date() : null; await this.sessionUserRepository.save(sessionUser); - courseUser.sessionUser.map((su) => { + courseUser.sessionUser?.map((su) => { if (su.sessionId === id) { su.completed = completed; } @@ -195,7 +195,10 @@ export class SessionUserService { } // Attach data to object to be serialized for response - const course = await this.courseRepository.findOneBy({ id: courseId }); + const course = await this.courseRepository.findOne({ + where: { id: courseId }, + relations: { session: true }, + }); courseUser = await this.checkCourseIsComplete(courseUser, course); courseUser.course = course; const formattedResponse = formatCourseUserObjects([courseUser])[0]; diff --git a/src/user/user.service.spec.ts b/src/user/user.service.spec.ts index d886e8b1..c189cba0 100644 --- a/src/user/user.service.spec.ts +++ b/src/user/user.service.spec.ts @@ -4,7 +4,6 @@ import { HttpException, HttpStatus } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; import { createCrispProfile, updateCrispProfile } from 'src/api/crisp/crisp-api'; -import { createMailchimpProfile } from 'src/api/mailchimp/mailchimp-api'; import { PartnerAccessEntity } from 'src/entities/partner-access.entity'; import { PartnerEntity } from 'src/entities/partner.entity'; import { SubscriptionUserService } from 'src/subscription-user/subscription-user.service'; @@ -134,19 +133,7 @@ describe('UserService', () => { person: { nickname: user.user.name, locales: [user.user.signUpLanguage] }, segments: ['public'], }); - expect(createMailchimpProfile).toHaveBeenCalledWith({ - email_address: user.user.email, - language: user.user.signUpLanguage, - status: 'subscribed', - marketing_permissions: [ - { - marketing_permission_id: '874073', - text: 'Marketing Permissions', - enabled: false, - }, - ], - merge_fields: { NAME: user.user.name }, - }); + expect(updateCrispProfile).toHaveBeenCalled(); }); it('when supplied with user dto and partner access code, it should return a new partner user', async () => { @@ -191,26 +178,6 @@ describe('UserService', () => { }, 'user@email.com', ); - expect(createMailchimpProfile).toHaveBeenCalledWith({ - email_address: user.user.email, - language: 'en', - status: 'subscribed', - marketing_permissions: [ - { - marketing_permission_id: '874073', - text: 'Marketing Permissions', - enabled: true, - }, - ], - merge_fields: { - NAME: 'name', - PARTNERS: 'bumble', - THERREMAIN: 5, - THERREDEEM: 1, - FEATTHER: 'true', - FEATCHAT: 'true', - }, - }); }); it('when supplied with user dto and partner access that has already been used, it should return an error', async () => { diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 308ebe9d..a0e71c48 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -48,15 +48,17 @@ export class UserService { ? SIGNUP_TYPE.PARTNER_USER_WITHOUT_CODE : SIGNUP_TYPE.PUBLIC_USER; - let partnerAccess: PartnerAccessEntity | null = null; - const partner = partnerId ? await this.partnerRepository.findOneBy({ id: partnerId }) : null; - try { + let partnerAccess: PartnerAccessEntity; + let partner: PartnerEntity; + if (signUpType === SIGNUP_TYPE.PARTNER_USER_WITHOUT_CODE) { await this.partnerAccessService.validatePartnerAutomaticAccessCode(partnerId); + partner = await this.partnerRepository.findOneBy({ id: partnerId }); } if (signUpType === SIGNUP_TYPE.PARTNER_USER_WITH_CODE) { partnerAccess = await this.partnerAccessService.getPartnerAccessByCode(partnerAccessCode); + partner = partnerAccess.partner; } const firebaseUser = await this.authService.createFirebaseUser(email, password); @@ -73,6 +75,7 @@ export class UserService { null, user.id, ); + this.logger.log(`Create user: (no access code) created partner user in db. User: ${email}`); } else if (signUpType === SIGNUP_TYPE.PARTNER_USER_WITH_CODE) { // Assign the existing partner access to new user @@ -85,13 +88,11 @@ export class UserService { this.logger.log(`Create user: created public user in db. User: ${email}`); } - // Create profiles for external services createServiceUserProfiles(user, partner, partnerAccess); - this.logger.log(`Create user: updated crisp profile ${email}`); const userDto = formatUserObject({ ...user, - ...(partnerAccess && { partnerAccess: [partnerAccess] }), + ...(partnerAccess && { partnerAccess: [{ ...partnerAccess, partner }] }), }); return userDto; } catch (error) { diff --git a/src/utils/constants.ts b/src/utils/constants.ts index fd4e5e98..d08ef46a 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -131,6 +131,10 @@ export const respondIoDeleteContactWebhook = getEnv( ); export const mailchimpApiKey = getEnv(process.env.MAILCHIMP_API_KEY, 'MAILCHIMP_API_KEY'); +export const mailchimpMarketingPermissionId = getEnv( + process.env.MAILCHIMP_MARKETING_PERMISSION_ID, + 'MAILCHIMP_MARKETING_PERMISSION_ID', +); export const mailchimpAudienceId = getEnv( process.env.MAILCHIMP_AUDIENCE_ID, 'MAILCHIMP_AUDIENCE_ID', diff --git a/src/utils/serialize.ts b/src/utils/serialize.ts index 2e686c77..fed5488c 100644 --- a/src/utils/serialize.ts +++ b/src/utils/serialize.ts @@ -56,7 +56,7 @@ export const formatPartnerAccessObjects = (partnerAccessObjects: PartnerAccessEn therapySessionsRedeemed: partnerAccess.therapySessionsRedeemed, partner: partnerAccess.partner ? formatPartnerObject(partnerAccess.partner) : null, therapySessions: - partnerAccess.therapySession.length === 0 + partnerAccess.therapySession?.length === 0 ? [] : partnerAccess.therapySession?.map((ts) => { return { diff --git a/src/utils/serviceUserProfiles.spec.ts b/src/utils/serviceUserProfiles.spec.ts index fc5bb8fd..d5108b32 100644 --- a/src/utils/serviceUserProfiles.spec.ts +++ b/src/utils/serviceUserProfiles.spec.ts @@ -16,7 +16,7 @@ import { mockPartnerEntity, mockUserEntity, } from 'test/utils/mockData'; -import { SIMPLYBOOK_ACTION_ENUM } from './constants'; +import { SIMPLYBOOK_ACTION_ENUM, mailchimpMarketingPermissionId } from './constants'; import { createMailchimpCourseMergeField, createServiceUserProfiles, @@ -50,6 +50,11 @@ describe('Service user profiles', () => { marketing_permission: mockUserEntity.contactPermission, service_emails_permission: mockUserEntity.serviceEmailsPermission, signed_up_at: mockUserEntity.createdAt.toISOString(), + feature_live_chat: true, + feature_therapy: false, + partners: '', + therapy_sessions_redeemed: 0, + therapy_sessions_remaining: 0, }, mockUserEntity.email, ); @@ -60,14 +65,19 @@ describe('Service user profiles', () => { status: 'subscribed', marketing_permissions: [ { - marketing_permission_id: '874073', - text: 'Marketing Permissions', + marketing_permission_id: mailchimpMarketingPermissionId, + text: 'Email', enabled: mockUserEntity.contactPermission, }, ], merge_fields: { SIGNUPD: mockUserEntity.createdAt.toISOString(), NAME: mockUserEntity.name, + FEATCHAT: 'true', + FEATTHER: 'false', + PARTNERS: '', + THERREMAIN: 0, + THERREDEEM: 0, }, }); }); @@ -103,8 +113,8 @@ describe('Service user profiles', () => { status: 'subscribed', marketing_permissions: [ { - marketing_permission_id: '874073', - text: 'Marketing Permissions', + marketing_permission_id: mailchimpMarketingPermissionId, + text: 'Email', enabled: mockUserEntity.contactPermission, }, ], @@ -138,8 +148,8 @@ describe('Service user profiles', () => { status: 'subscribed', marketing_permissions: [ { - marketing_permission_id: '874073', - text: 'Marketing Permissions', + marketing_permission_id: mailchimpMarketingPermissionId, + text: 'Email', enabled: mockUserEntity.contactPermission, }, ], @@ -172,8 +182,8 @@ describe('Service user profiles', () => { status: 'unsubscribed', marketing_permissions: [ { - marketing_permission_id: '874073', - text: 'Marketing Permissions', + marketing_permission_id: mailchimpMarketingPermissionId, + text: 'Email', enabled: false, }, ], @@ -478,10 +488,21 @@ describe('Service user profiles', () => { }); describe('createMailchimpCourseMergeField', () => { - it('should update crisp and mailchimp profile course data', async () => { + it('should create mailchimp course merge field', async () => { await createMailchimpCourseMergeField('Full course name'); - expect(createMailchimpMergeField).toHaveBeenNthCalledWith(1, 'C_FCN', 'text'); + expect(createMailchimpMergeField).toHaveBeenNthCalledWith( + 1, + 'Course FCN Status', + 'C_FCN', + 'text', + ); + expect(createMailchimpMergeField).toHaveBeenNthCalledWith( + 2, + 'Course FCN Sessions', + 'C_FCN_S', + 'text', + ); }); }); }); diff --git a/src/utils/serviceUserProfiles.ts b/src/utils/serviceUserProfiles.ts index a556c4f7..7046bdf9 100644 --- a/src/utils/serviceUserProfiles.ts +++ b/src/utils/serviceUserProfiles.ts @@ -17,7 +17,11 @@ import { CourseUserEntity } from 'src/entities/course-user.entity'; import { PartnerAccessEntity } from 'src/entities/partner-access.entity'; import { PartnerEntity } from 'src/entities/partner.entity'; import { UserEntity } from 'src/entities/user.entity'; -import { PROGRESS_STATUS, SIMPLYBOOK_ACTION_ENUM } from './constants'; +import { + PROGRESS_STATUS, + SIMPLYBOOK_ACTION_ENUM, + mailchimpMarketingPermissionId, +} from './constants'; import { getAcronym } from './utils'; // Functionality for syncing user profiles for Crisp and Mailchimp communications services. @@ -26,50 +30,54 @@ import { getAcronym } from './utils'; // Note errors are not thrown to prevent the more important calling functions from failing // Instead log errors which are also captured by rollbar error reporting -const logger = new Logger('UserService'); +const logger = new Logger('ServiceUserProfiles'); export const createServiceUserProfiles = async ( user: UserEntity, partner?: PartnerEntity | null, partnerAccess?: PartnerAccessEntity | null, ) => { + const { email } = user; try { const userData = serializeUserData(user); - const partnerData = partnerAccess - ? serializePartnerAccessData([{ ...partnerAccess, partner }]) - : null; + + const partnerData = serializePartnerAccessData( + partnerAccess ? [{ ...partnerAccess, partner }] : [], + ); await createCrispProfile({ - email: user.email, + email: email, person: { nickname: user.name, locales: [user.signUpLanguage || 'en'] }, segments: serializeCrispPartnerSegments(partner ? [partner] : []), }); const userSignedUpAt = user.createdAt?.toISOString(); - updateCrispProfile( + await updateCrispProfile( { signed_up_at: userSignedUpAt, ...userData.crispSchema, - ...(partnerData && partnerData.crispSchema), + ...partnerData.crispSchema, }, - user.email, + email, ); const mailchimpMergeFields = { SIGNUPD: userSignedUpAt, ...userData.mailchimpSchema.merge_fields, - ...(partnerData && partnerData.mailchimpSchema.merge_fields), + ...partnerData.mailchimpSchema.merge_fields, }; - createMailchimpProfile({ - email_address: user.email, + await createMailchimpProfile({ + email_address: email, ...userData.mailchimpSchema, - ...(partnerData && partnerData.mailchimpSchema), + ...partnerData.mailchimpSchema, merge_fields: mailchimpMergeFields, }); + + logger.log(`Create user: updated service user profiles. User: ${email}`); } catch (error) { - logger.error(`Create service user profiles error - ${error}`); + logger.error(`Create service user profiles error - ${error}. User: ${email}`); throw error; } }; @@ -82,14 +90,14 @@ export const updateServiceUserProfilesUser = async ( try { if (isCrispBaseUpdateRequired) { // Extra call required to update crisp "base" profile when name or sign up language is changed - updateCrispProfileBase( + await updateCrispProfileBase( { person: { nickname: user.name, locales: [user.signUpLanguage || 'en'] } }, email, ); } const userData = serializeUserData(user); - updateCrispProfile(userData.crispSchema, email); - updateMailchimpProfile(userData.mailchimpSchema, email); + await updateCrispProfile(userData.crispSchema, email); + await updateMailchimpProfile(userData.mailchimpSchema, email); } catch (error) { logger.error(`Update service user profiles user error - ${error}`); } @@ -101,7 +109,7 @@ export const updateServiceUserProfilesPartnerAccess = async ( ) => { try { const partners = partnerAccesses.map((pa) => pa.partner); - updateCrispProfileBase( + await updateCrispProfileBase( { segments: serializeCrispPartnerSegments(partners), }, @@ -109,8 +117,8 @@ export const updateServiceUserProfilesPartnerAccess = async ( ); const partnerAccessData = serializePartnerAccessData(partnerAccesses); - updateCrispProfile(partnerAccessData.crispSchema, email); - updateMailchimpProfile(partnerAccessData.mailchimpSchema, email); + await updateCrispProfile(partnerAccessData.crispSchema, email); + await updateMailchimpProfile(partnerAccessData.mailchimpSchema, email); } catch (error) { logger.error(`Update service user profiles partner access error - ${error}`); } @@ -128,8 +136,8 @@ export const updateServiceUserProfilesTherapy = async ( therapySessionAction, therapySessionDate, ); - updateCrispProfile(therapyData.crispSchema, email); - updateMailchimpProfile(therapyData.mailchimpSchema, email); + await updateCrispProfile(therapyData.crispSchema, email); + await updateMailchimpProfile(therapyData.mailchimpSchema, email); } catch (error) { logger.error(`Update service user profiles therapy error - ${error}`); } @@ -141,8 +149,8 @@ export const updateServiceUserProfilesCourse = async ( ) => { try { const courseData = serializeCourseData(courseUser); - updateCrispProfile(courseData.crispSchema, email); - updateMailchimpProfile(courseData.mailchimpSchema, email); + await updateCrispProfile(courseData.crispSchema, email); + await updateMailchimpProfile(courseData.mailchimpSchema, email); } catch (error) { logger.error(`Update service user profiles course error - ${error}`); } @@ -153,18 +161,28 @@ export const updateServiceUserProfilesCourse = async ( export const createMailchimpCourseMergeField = async (courseName: string) => { try { const courseAcronym = getAcronym(courseName); - const courseMergeFieldKey = `C_${courseAcronym}`; - const courseSessionsMergeFieldKey = `C_${courseAcronym}_S`; - - createMailchimpMergeField(courseMergeFieldKey, MAILCHIMP_MERGE_FIELD_TYPES.TEXT); - createMailchimpMergeField(courseSessionsMergeFieldKey, MAILCHIMP_MERGE_FIELD_TYPES.TEXT); + const courseMergeFieldName = `Course ${courseAcronym} Status`; + const courseMergeFieldTag = `C_${courseAcronym}`; + const courseSessionsMergeFieldName = `Course ${courseAcronym} Sessions`; + const courseSessionsMergeFieldTag = `C_${courseAcronym}_S`; + + await createMailchimpMergeField( + courseMergeFieldName, + courseMergeFieldTag, + MAILCHIMP_MERGE_FIELD_TYPES.TEXT, + ); + await createMailchimpMergeField( + courseSessionsMergeFieldName, + courseSessionsMergeFieldTag, + MAILCHIMP_MERGE_FIELD_TYPES.TEXT, + ); } catch (error) { logger.error(`Create mailchimp course merge fields error - ${error}`); } }; export const serializePartnersString = (partnerAccesses: PartnerAccessEntity[]) => { - return partnerAccesses.map((pa) => pa.partner.name.toLowerCase()).join('; ') || ''; + return partnerAccesses?.map((pa) => pa.partner.name.toLowerCase()).join('; ') || ''; }; const serializeUserData = (user: UserEntity) => { @@ -180,8 +198,8 @@ const serializeUserData = (user: UserEntity) => { status: serviceEmailsPermission ? 'subscribed' : 'unsubscribed', marketing_permissions: [ { - marketing_permission_id: '874073', - text: 'Marketing Permissions', + marketing_permission_id: mailchimpMarketingPermissionId, + text: 'Email', enabled: contactPermission, }, ], @@ -193,17 +211,27 @@ const serializeUserData = (user: UserEntity) => { }; const serializePartnerAccessData = (partnerAccesses: PartnerAccessEntity[]) => { - const data = { - partners: serializePartnersString(partnerAccesses), - featureLiveChat: !!partnerAccesses.find((pa) => pa.featureLiveChat), - featureTherapy: !!partnerAccesses.find((pa) => pa.featureTherapy), - therapySessionsRemaining: partnerAccesses - .map((pa) => pa.therapySessionsRemaining) - .reduce((a, b) => a + b, 0), - therapySessionsRedeemed: partnerAccesses - .map((pa) => pa.therapySessionsRedeemed) - .reduce((a, b) => a + b, 0), - }; + const publicUser = !partnerAccesses || !partnerAccesses[0]?.id; + + const data = publicUser + ? { + partners: '', + featureLiveChat: true, + featureTherapy: false, + therapySessionsRemaining: 0, + therapySessionsRedeemed: 0, + } + : { + partners: serializePartnersString(partnerAccesses), + featureLiveChat: !!partnerAccesses.find((pa) => pa.featureLiveChat) || true, + featureTherapy: !!partnerAccesses.find((pa) => pa.featureTherapy), + therapySessionsRemaining: partnerAccesses + .map((pa) => pa.therapySessionsRemaining) + .reduce((a, b) => a + b, 0), + therapySessionsRedeemed: partnerAccesses + .map((pa) => pa.therapySessionsRedeemed) + .reduce((a, b) => a + b, 0), + }; const crispSchema = { partners: data.partners, @@ -249,10 +277,7 @@ const serializeTherapyData = ( const lastTherapySessionAt = pastTherapySessions?.at(-1)?.startDateTime.toISOString() || ''; - const nextTherapySessionAt = - therapySessionAction === SIMPLYBOOK_ACTION_ENUM.CANCELLED_BOOKING - ? futureTherapySessions?.at(-1)?.startDateTime.toISOString() || '' - : therapySessionDate.toISOString(); + const nextTherapySessionAt = futureTherapySessions?.at(0)?.startDateTime.toISOString() || ''; const data = { therapySessionsRemaining: partnerAccesses.reduce( diff --git a/src/webhooks/webhooks.service.spec.ts b/src/webhooks/webhooks.service.spec.ts index 0abb839b..5555ef35 100644 --- a/src/webhooks/webhooks.service.spec.ts +++ b/src/webhooks/webhooks.service.spec.ts @@ -519,6 +519,7 @@ describe('WebhooksService', () => { userId: 'userId1', active: true, featureTherapy: true, + therapySessionsRemaining: expect.objectContaining({ _value: 0 }), }, relations: { therapySession: true, @@ -576,6 +577,7 @@ describe('WebhooksService', () => { userId: 'userId1', active: true, featureTherapy: true, + therapySessionsRemaining: expect.objectContaining({ _value: 0 }), }, relations: { therapySession: true, diff --git a/src/webhooks/webhooks.service.ts b/src/webhooks/webhooks.service.ts index e7d2a784..36c8c0b0 100644 --- a/src/webhooks/webhooks.service.ts +++ b/src/webhooks/webhooks.service.ts @@ -18,7 +18,7 @@ import { } from 'src/utils/serviceUserProfiles'; import { WebhookCreateEventLogDto } from 'src/webhooks/dto/webhook-create-event-log.dto'; import StoryblokClient from 'storyblok-js-client'; -import { ILike, Repository } from 'typeorm'; +import { ILike, MoreThan, Repository } from 'typeorm'; import { CoursePartnerService } from '../course-partner/course-partner.service'; import { SIMPLYBOOK_ACTION_ENUM, @@ -205,6 +205,7 @@ export class WebhooksService { userId: user.id, active: true, featureTherapy: true, + therapySessionsRemaining: MoreThan(0), }, relations: { therapySession: true,