Enhance Salesforce Account and Contact Creation in Signup Workflow
- Updated SalesforceAccountService to map gender values to Salesforce picklist values and added date of birth handling for contact creation. - Modified SignupWorkflowService to require gender and date of birth during account creation, ensuring complete data submission. - Adjusted SignupAccountResolverService to include gender and date of birth in account creation logic, improving data integrity. - Introduced SalesforceContactRecord interface in domain to standardize contact data structure, enhancing type safety and validation.
This commit is contained in:
parent
1a3032bbd3
commit
a8580b0d61
@ -177,7 +177,7 @@ export class SalesforceAccountService {
|
|||||||
|
|
||||||
const accountPayload: Record<string, unknown> = {
|
const accountPayload: Record<string, unknown> = {
|
||||||
Name: `${data.firstName} ${data.lastName}`,
|
Name: `${data.firstName} ${data.lastName}`,
|
||||||
Phone: data.phone,
|
// Phone is stored on Contact, not Account
|
||||||
// Portal tracking fields
|
// Portal tracking fields
|
||||||
[this.portalStatusField]: "Active",
|
[this.portalStatusField]: "Active",
|
||||||
[this.portalSourceField]: "Portal Checkout",
|
[this.portalSourceField]: "Portal Checkout",
|
||||||
@ -236,12 +236,24 @@ export class SalesforceAccountService {
|
|||||||
email: data.email,
|
email: data.email,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Map gender values to Salesforce picklist values
|
||||||
|
const mapGenderToSalesforce = (gender: "male" | "female" | "other"): string => {
|
||||||
|
const mapping: Record<"male" | "female" | "other", string> = {
|
||||||
|
male: "男性",
|
||||||
|
female: "女性",
|
||||||
|
other: "Other",
|
||||||
|
};
|
||||||
|
return mapping[gender];
|
||||||
|
};
|
||||||
|
|
||||||
const contactPayload: Record<string, unknown> = {
|
const contactPayload: Record<string, unknown> = {
|
||||||
AccountId: data.accountId,
|
AccountId: data.accountId,
|
||||||
FirstName: data.firstName,
|
FirstName: data.firstName,
|
||||||
LastName: data.lastName,
|
LastName: data.lastName,
|
||||||
Email: data.email,
|
Email: data.email,
|
||||||
Phone: data.phone,
|
MobilePhone: data.phone,
|
||||||
|
Sex__c: mapGenderToSalesforce(data.gender),
|
||||||
|
Birthdate: data.dateOfBirth, // Salesforce expects YYYY-MM-DD format
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -350,4 +362,6 @@ export interface CreateSalesforceContactRequest {
|
|||||||
lastName: string;
|
lastName: string;
|
||||||
email: string;
|
email: string;
|
||||||
phone: string;
|
phone: string;
|
||||||
|
gender: "male" | "female" | "other";
|
||||||
|
dateOfBirth: string; // YYYY-MM-DD format
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,7 +35,7 @@ import {
|
|||||||
*
|
*
|
||||||
* Orchestrates the signup process by coordinating:
|
* Orchestrates the signup process by coordinating:
|
||||||
* - SignupValidationService: Validates customer numbers and preflight checks
|
* - SignupValidationService: Validates customer numbers and preflight checks
|
||||||
* - SignupAccountResolverService: Resolves Salesforce accounts
|
* - SalesforceAccountService: Creates new Salesforce accounts and contacts
|
||||||
* - SignupWhmcsService: Creates WHMCS clients
|
* - SignupWhmcsService: Creates WHMCS clients
|
||||||
* - SignupUserCreationService: Creates portal users with ID mappings
|
* - SignupUserCreationService: Creates portal users with ID mappings
|
||||||
*/
|
*/
|
||||||
@ -210,38 +210,16 @@ export class SignupWorkflowService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve Salesforce account for signup
|
* Create a new Salesforce account for signup
|
||||||
* Either finds existing account by customer number or creates new one
|
* Always creates a new account - no lookup by customer number
|
||||||
*/
|
*/
|
||||||
private async resolveSalesforceAccount(signupData: SignupRequest): Promise<{
|
private async resolveSalesforceAccount(signupData: SignupRequest): Promise<{
|
||||||
accountSnapshot: SignupAccountSnapshot;
|
accountSnapshot: SignupAccountSnapshot;
|
||||||
customerNumberForWhmcs: string | null;
|
customerNumberForWhmcs: string | null;
|
||||||
}> {
|
}> {
|
||||||
const { email, firstName, lastName, phone, address, sfNumber } = signupData;
|
const { email, firstName, lastName, phone, address, gender, dateOfBirth } = signupData;
|
||||||
const normalizedCustomerNumber = this.accountResolver.normalizeCustomerNumber(sfNumber);
|
|
||||||
|
|
||||||
if (normalizedCustomerNumber) {
|
// Check if account already exists by email
|
||||||
// Existing customer - find account by customer number
|
|
||||||
const resolved = await this.accountResolver.getAccountSnapshot(normalizedCustomerNumber);
|
|
||||||
if (!resolved) {
|
|
||||||
throw new BadRequestException(
|
|
||||||
`Salesforce account not found for Customer Number: ${normalizedCustomerNumber}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resolved.WH_Account__c && resolved.WH_Account__c.trim() !== "") {
|
|
||||||
throw new ConflictException(
|
|
||||||
"You already have an account. Please use the login page to access your existing account."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
accountSnapshot: resolved,
|
|
||||||
customerNumberForWhmcs: normalizedCustomerNumber,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// New customer - create Salesforce account
|
|
||||||
const normalizedEmail = email.toLowerCase().trim();
|
const normalizedEmail = email.toLowerCase().trim();
|
||||||
const existingAccount = await this.salesforceAccountService.findByEmail(normalizedEmail);
|
const existingAccount = await this.salesforceAccountService.findByEmail(normalizedEmail);
|
||||||
if (existingAccount) {
|
if (existingAccount) {
|
||||||
@ -266,6 +244,15 @@ export class SignupWorkflowService {
|
|||||||
throw new BadRequestException("Phone number is required for account creation");
|
throw new BadRequestException("Phone number is required for account creation");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!gender) {
|
||||||
|
throw new BadRequestException("Gender is required for account creation");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dateOfBirth) {
|
||||||
|
throw new BadRequestException("Date of birth is required for account creation");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new Salesforce account
|
||||||
const created = await this.salesforceAccountService.createAccount({
|
const created = await this.salesforceAccountService.createAccount({
|
||||||
firstName,
|
firstName,
|
||||||
lastName,
|
lastName,
|
||||||
@ -280,6 +267,8 @@ export class SignupWorkflowService {
|
|||||||
lastName,
|
lastName,
|
||||||
email: normalizedEmail,
|
email: normalizedEmail,
|
||||||
phone,
|
phone,
|
||||||
|
gender,
|
||||||
|
dateOfBirth,
|
||||||
// Address not added to Salesforce during signup
|
// Address not added to Salesforce during signup
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,8 @@ export class SignupAccountResolverService {
|
|||||||
async resolveOrCreate(
|
async resolveOrCreate(
|
||||||
signupData: SignupRequest
|
signupData: SignupRequest
|
||||||
): Promise<{ snapshot: SignupAccountSnapshot; customerNumber: string | null }> {
|
): Promise<{ snapshot: SignupAccountSnapshot; customerNumber: string | null }> {
|
||||||
const { sfNumber, email, firstName, lastName, phone, address } = signupData;
|
const { sfNumber, email, firstName, lastName, phone, address, gender, dateOfBirth } =
|
||||||
|
signupData;
|
||||||
const normalizedCustomerNumber = this.normalizeCustomerNumber(sfNumber);
|
const normalizedCustomerNumber = this.normalizeCustomerNumber(sfNumber);
|
||||||
|
|
||||||
if (normalizedCustomerNumber) {
|
if (normalizedCustomerNumber) {
|
||||||
@ -73,6 +74,14 @@ export class SignupAccountResolverService {
|
|||||||
throw new BadRequestException("Phone number is required for account creation");
|
throw new BadRequestException("Phone number is required for account creation");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!gender) {
|
||||||
|
throw new BadRequestException("Gender is required for account creation");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dateOfBirth) {
|
||||||
|
throw new BadRequestException("Date of birth is required for account creation");
|
||||||
|
}
|
||||||
|
|
||||||
const created = await this.salesforceAccountService.createAccount({
|
const created = await this.salesforceAccountService.createAccount({
|
||||||
firstName,
|
firstName,
|
||||||
lastName,
|
lastName,
|
||||||
@ -86,6 +95,8 @@ export class SignupAccountResolverService {
|
|||||||
lastName,
|
lastName,
|
||||||
email: normalizedEmail,
|
email: normalizedEmail,
|
||||||
phone,
|
phone,
|
||||||
|
gender,
|
||||||
|
dateOfBirth,
|
||||||
});
|
});
|
||||||
|
|
||||||
const snapshot: SignupAccountSnapshot = {
|
const snapshot: SignupAccountSnapshot = {
|
||||||
|
|||||||
@ -42,6 +42,23 @@ export interface SalesforceAccountRecord {
|
|||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Salesforce contact record structure
|
||||||
|
* Raw structure from Salesforce API
|
||||||
|
*/
|
||||||
|
export interface SalesforceContactRecord {
|
||||||
|
Id: string;
|
||||||
|
AccountId?: string | null;
|
||||||
|
FirstName?: string | null;
|
||||||
|
LastName?: string | null;
|
||||||
|
Email?: string | null;
|
||||||
|
MobilePhone?: string | null;
|
||||||
|
Phone?: string | null;
|
||||||
|
Sex__c?: string | null;
|
||||||
|
Birthdate?: string | null; // YYYY-MM-DD format
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Re-export Types from Schema (Schema-First Approach)
|
// Re-export Types from Schema (Schema-First Approach)
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
@ -10,7 +10,11 @@ export * from "./portal/index.js";
|
|||||||
export * from "./whmcs/index.js";
|
export * from "./whmcs/index.js";
|
||||||
|
|
||||||
// Provider-specific integration types (BFF-only convenience re-exports)
|
// Provider-specific integration types (BFF-only convenience re-exports)
|
||||||
export type { SalesforceAccountFieldMap, SalesforceAccountRecord } from "../contract.js";
|
export type {
|
||||||
|
SalesforceAccountFieldMap,
|
||||||
|
SalesforceAccountRecord,
|
||||||
|
SalesforceContactRecord,
|
||||||
|
} from "../contract.js";
|
||||||
export type {
|
export type {
|
||||||
WhmcsAddClientParams,
|
WhmcsAddClientParams,
|
||||||
WhmcsValidateLoginParams,
|
WhmcsValidateLoginParams,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user