refactor: enhance error handling in WHMCS and signup workflows
- Introduced structured error codes in BadRequestException for better clarity in WHMCS and signup workflows. - Updated error messages to include specific context, improving user feedback during account verification and migration processes. - Refined validation logic to ensure consistent error handling across services.
This commit is contained in:
parent
230a61c520
commit
49e9dba3a3
@ -7,6 +7,7 @@ import { CacheService } from "@bff/infra/cache/cache.service.js";
|
||||
import { SalesforceFacade } from "@bff/integrations/salesforce/facades/salesforce.facade.js";
|
||||
import { SalesforceAccountService } from "@bff/integrations/salesforce/services/salesforce-account.service.js";
|
||||
import { extractErrorMessage } from "@bff/core/utils/error.util.js";
|
||||
import { ErrorCode } from "@customer-portal/domain/common";
|
||||
import type { SignupRequest } from "@customer-portal/domain/auth";
|
||||
import type { SignupAccountSnapshot, SignupAccountCacheEntry } from "./signup.types.js";
|
||||
import { PORTAL_SOURCE_NEW_SIGNUP } from "@bff/modules/auth/constants/portal.constants.js";
|
||||
@ -37,9 +38,10 @@ export class SignupAccountResolverService {
|
||||
if (normalizedCustomerNumber) {
|
||||
const resolved = await this.getAccountSnapshot(normalizedCustomerNumber);
|
||||
if (!resolved) {
|
||||
throw new BadRequestException(
|
||||
`Salesforce account not found for Customer Number: ${normalizedCustomerNumber}`
|
||||
);
|
||||
throw new BadRequestException({
|
||||
code: ErrorCode.CUSTOMER_NOT_FOUND,
|
||||
message: `Salesforce account not found for Customer Number: ${normalizedCustomerNumber}`,
|
||||
});
|
||||
}
|
||||
|
||||
if (resolved.WH_Account__c && resolved.WH_Account__c.trim() !== "") {
|
||||
|
||||
@ -13,6 +13,7 @@ import { WhmcsAccountDiscoveryService } from "@bff/integrations/whmcs/services/w
|
||||
import { WhmcsClientService } from "@bff/integrations/whmcs/services/whmcs-client.service.js";
|
||||
import { SalesforceFacade } from "@bff/integrations/salesforce/facades/salesforce.facade.js";
|
||||
import { extractErrorMessage } from "@bff/core/utils/error.util.js";
|
||||
import { ErrorCode } from "@customer-portal/domain/common";
|
||||
import { mapPrismaUserToDomain } from "@bff/infra/mappers/index.js";
|
||||
import { getCustomFieldValue } from "@customer-portal/domain/customer/providers";
|
||||
import { safeOperation, OperationCriticality } from "@bff/core/utils/safe-operation.util.js";
|
||||
@ -79,9 +80,10 @@ export class WhmcsLinkWorkflowService {
|
||||
getCustomFieldValue(clientDetails.customfields, "Customer Number")?.trim();
|
||||
|
||||
if (!customerNumber) {
|
||||
throw new BadRequestException(
|
||||
`Customer Number not found in WHMCS custom field 198. Please contact support.`
|
||||
);
|
||||
throw new BadRequestException({
|
||||
code: ErrorCode.ACCOUNT_MAPPING_MISSING,
|
||||
message: `Customer Number not found in WHMCS custom field 198 for client ${clientNumericId}`,
|
||||
});
|
||||
}
|
||||
|
||||
this.logger.log("Found Customer Number for WHMCS client", {
|
||||
@ -91,7 +93,10 @@ export class WhmcsLinkWorkflowService {
|
||||
|
||||
const sfAccount = await this.salesforceService.findAccountByCustomerNumber(customerNumber);
|
||||
if (!sfAccount) {
|
||||
throw new BadRequestException("Salesforce account not found. Please contact support.");
|
||||
throw new BadRequestException({
|
||||
code: ErrorCode.CUSTOMER_NOT_FOUND,
|
||||
message: `Salesforce account not found for Customer Number: ${customerNumber}`,
|
||||
});
|
||||
}
|
||||
|
||||
const createdUser = await this.usersService.create(
|
||||
|
||||
@ -4,6 +4,7 @@ import { Logger } from "nestjs-pino";
|
||||
import * as argon2 from "argon2";
|
||||
|
||||
import { type MigrateWhmcsAccountRequest } from "@customer-portal/domain/get-started";
|
||||
import { ErrorCode } from "@customer-portal/domain/common";
|
||||
import {
|
||||
getCustomFieldValue,
|
||||
serializeWhmcsKeyValueMap,
|
||||
@ -112,7 +113,10 @@ export class WhmcsMigrationWorkflowService {
|
||||
// Verify WHMCS client still exists and matches session
|
||||
const whmcsClient = await this.whmcsDiscovery.findAccountByEmail(email);
|
||||
if (!whmcsClient || whmcsClient.id !== whmcsClientId) {
|
||||
throw new BadRequestException("WHMCS account verification failed. Please start over.");
|
||||
throw new BadRequestException({
|
||||
code: ErrorCode.VALIDATION_FAILED,
|
||||
message: `WHMCS client mismatch for email ${email}: expected ${whmcsClientId}, got ${whmcsClient?.id ?? "none"}`,
|
||||
});
|
||||
}
|
||||
|
||||
// Check for existing portal user
|
||||
@ -124,9 +128,10 @@ export class WhmcsMigrationWorkflowService {
|
||||
// Find Salesforce account for mapping
|
||||
const sfAccount = await this.findSalesforceAccountForMigration(email, whmcsClientId);
|
||||
if (!sfAccount) {
|
||||
throw new BadRequestException(
|
||||
"Unable to find your Salesforce account. Please contact support."
|
||||
);
|
||||
throw new BadRequestException({
|
||||
code: ErrorCode.CUSTOMER_NOT_FOUND,
|
||||
message: `No Salesforce account found for migration: email=${email}, whmcsClientId=${whmcsClientId}`,
|
||||
});
|
||||
}
|
||||
|
||||
// Hash password for portal storage
|
||||
|
||||
@ -293,11 +293,7 @@ export const whmcsCurrenciesResponseSchema = z
|
||||
result: z.enum(["success", "error"]).optional(),
|
||||
message: z.string().optional(),
|
||||
errorcode: z.string().optional(),
|
||||
totalresults: z
|
||||
.string()
|
||||
.transform(val => Number.parseInt(val, 10))
|
||||
.or(z.number())
|
||||
.optional(),
|
||||
totalresults: whmcsOptionalNumber,
|
||||
currencies: z
|
||||
.object({
|
||||
currency: z.array(whmcsCurrencySchema).or(whmcsCurrencySchema),
|
||||
|
||||
@ -208,21 +208,19 @@ const nullableProfileOverrides = nullableProfileFields.reduce<Record<string, z.Z
|
||||
{}
|
||||
);
|
||||
|
||||
export const whmcsClientSchema = whmcsRawClientSchema
|
||||
.extend({
|
||||
...nullableProfileOverrides,
|
||||
defaultpaymethodid: whmcsOptionalNumber.nullable(),
|
||||
currency: whmcsOptionalNumber.nullable(),
|
||||
allowSingleSignOn: whmcsOptionalBoolean.nullable(),
|
||||
email_verified: whmcsOptionalBoolean.nullable(),
|
||||
marketing_emails_opt_in: whmcsOptionalBoolean.nullable(),
|
||||
address: addressSchema.nullable().optional(),
|
||||
email_preferences: emailPreferencesSchema.nullable().optional(),
|
||||
customfields: whmcsCustomFieldsSchema,
|
||||
users: whmcsUsersSchema,
|
||||
stats: statsSchema.optional(),
|
||||
})
|
||||
.transform(raw => ({ ...raw }));
|
||||
export const whmcsClientSchema = whmcsRawClientSchema.extend({
|
||||
...nullableProfileOverrides,
|
||||
defaultpaymethodid: whmcsOptionalNumber.nullable(),
|
||||
currency: whmcsOptionalNumber.nullable(),
|
||||
allowSingleSignOn: whmcsOptionalBoolean.nullable(),
|
||||
email_verified: whmcsOptionalBoolean.nullable(),
|
||||
marketing_emails_opt_in: whmcsOptionalBoolean.nullable(),
|
||||
address: addressSchema.nullable().optional(),
|
||||
email_preferences: emailPreferencesSchema.nullable().optional(),
|
||||
customfields: whmcsCustomFieldsSchema,
|
||||
users: whmcsUsersSchema,
|
||||
stats: statsSchema.optional(),
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// User Schema (API Response - Normalized camelCase)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user