barsa 1b944f57aa Update Configuration Files and Refactor Code Structure
- Adjusted .prettierrc to ensure consistent formatting with a newline at the end of the file.
- Reformatted eslint.config.mjs for improved readability by aligning array elements.
- Updated pnpm-lock.yaml to use single quotes for consistency across dependencies.
- Simplified worktree setup in .cursor/worktrees.json for cleaner configuration.
- Enhanced documentation in .cursor/plans to clarify architecture refactoring.
- Refactored various service files for improved readability and maintainability, including rate-limiting and auth services.
- Updated imports and exports across multiple files for consistency and clarity.
- Improved error handling and logging in service methods to enhance debugging capabilities.
- Streamlined utility functions for better performance and maintainability across the domain packages.
2025-12-25 17:30:02 +09:00

168 lines
4.7 KiB
TypeScript

/**
* Support Domain - Salesforce Provider Mapper
*
* Transform functions to convert raw Salesforce Case records to domain types.
*/
import { supportCaseSchema, type SupportCase } from "../../schema.js";
import type { SalesforceCaseRecord } from "./raw.types.js";
import {
getStatusDisplayLabel,
getPriorityDisplayLabel,
SALESFORCE_CASE_STATUS,
SALESFORCE_CASE_PRIORITY,
} from "./raw.types.js";
// ============================================================================
// Helper Functions
// ============================================================================
/**
* Safely coerce a value to string or return undefined
*/
function ensureString(value: unknown): string | undefined {
if (typeof value === "string" && value.length > 0) {
return value;
}
return undefined;
}
/**
* Get current ISO timestamp
*/
function nowIsoString(): string {
return new Date().toISOString();
}
// ============================================================================
// Transform Functions
// ============================================================================
/**
* Transform a raw Salesforce Case record to a portal SupportCase.
*
* Converts Salesforce API values (often in Japanese) to portal display labels (English).
*
* @param record - Raw Salesforce Case record from SOQL query
* @returns Validated SupportCase domain object
*/
export function transformSalesforceCaseToSupportCase(record: SalesforceCaseRecord): SupportCase {
// Get raw values
const rawStatus = ensureString(record.Status) ?? SALESFORCE_CASE_STATUS.NEW;
const rawPriority = ensureString(record.Priority) ?? SALESFORCE_CASE_PRIORITY.MEDIUM;
return supportCaseSchema.parse({
id: record.Id,
caseNumber: record.CaseNumber,
subject: ensureString(record.Subject) ?? "",
// Convert Japanese SF values to English display labels
status: getStatusDisplayLabel(rawStatus),
priority: getPriorityDisplayLabel(rawPriority),
category: ensureString(record.Type) ?? null,
description: ensureString(record.Description) ?? "",
createdAt: ensureString(record.CreatedDate) ?? nowIsoString(),
updatedAt: ensureString(record.LastModifiedDate) ?? nowIsoString(),
closedAt: ensureString(record.ClosedDate) ?? null,
});
}
/**
* Transform multiple Salesforce Case records to SupportCase array.
*
* @param records - Array of raw Salesforce Case records
* @returns Array of validated SupportCase domain objects
*/
export function transformSalesforceCasesToSupportCases(
records: SalesforceCaseRecord[]
): SupportCase[] {
return records.map(transformSalesforceCaseToSupportCase);
}
/**
* Build the SOQL SELECT fields for Case queries.
*
* Standard Salesforce Case fields based on org configuration.
* Note: Type field is not accessible via API in this org.
*
* @param additionalFields - Optional additional fields to include
* @returns Array of field names for SOQL SELECT clause
*/
export function buildCaseSelectFields(additionalFields: string[] = []): string[] {
const baseFields = [
// Core identifiers
"Id",
"CaseNumber",
// Case content
"Subject",
"Description",
// Picklist fields
"Status",
"Priority",
"Origin",
// Relationships
"AccountId",
"ContactId",
"OwnerId",
// Timestamps
"CreatedDate",
"LastModifiedDate",
"ClosedDate",
// Flags
"IsEscalated",
];
return [...new Set([...baseFields, ...additionalFields])];
}
/**
* Build a SOQL query for fetching cases for an account.
*
* @param accountId - Salesforce Account ID
* @param origin - Case origin to filter by (e.g., "Portal Website")
* @param additionalFields - Optional additional fields to include
* @returns SOQL query string
*/
export function buildCasesForAccountQuery(
accountId: string,
origin: string,
additionalFields: string[] = []
): string {
const fields = buildCaseSelectFields(additionalFields).join(", ");
return `
SELECT ${fields}
FROM Case
WHERE AccountId = '${accountId}' AND Origin = '${origin}'
ORDER BY CreatedDate DESC
LIMIT 100
`.trim();
}
/**
* Build a SOQL query for fetching a single case by ID.
*
* @param caseId - Salesforce Case ID
* @param accountId - Salesforce Account ID (for ownership validation)
* @param origin - Case origin to filter by
* @param additionalFields - Optional additional fields to include
* @returns SOQL query string
*/
export function buildCaseByIdQuery(
caseId: string,
accountId: string,
origin: string,
additionalFields: string[] = []
): string {
const fields = buildCaseSelectFields(additionalFields).join(", ");
return `
SELECT ${fields}
FROM Case
WHERE Id = '${caseId}' AND AccountId = '${accountId}' AND Origin = '${origin}'
LIMIT 1
`.trim();
}