Refactor Linting Configuration and Update GitHub Workflows
- Updated linting configuration to use 'eslint --fix' for automatic code formatting on staged files. - Removed explicit version specification for pnpm in GitHub workflows to allow for flexibility in version management. - Enhanced opportunity resolution service with locking mechanism to prevent race conditions during opportunity creation. - Simplified Salesforce account service by querying the auto-generated account number instead of generating it manually. - Improved cancellation date handling in internet cancellation service to avoid timezone issues.
This commit is contained in:
parent
a688121a16
commit
75dc6ec15d
2
.github/workflows/deploy.yml
vendored
2
.github/workflows/deploy.yml
vendored
@ -23,8 +23,6 @@ jobs:
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10.25.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
2
.github/workflows/pr-checks.yml
vendored
2
.github/workflows/pr-checks.yml
vendored
@ -22,8 +22,6 @@ jobs:
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: "10.25.0"
|
||||
|
||||
- name: Get pnpm store directory
|
||||
id: pnpm-cache
|
||||
|
||||
4
.github/workflows/security.yml
vendored
4
.github/workflows/security.yml
vendored
@ -30,8 +30,6 @@ jobs:
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: "10.25.0"
|
||||
|
||||
- name: Get pnpm store directory
|
||||
id: pnpm-cache
|
||||
@ -139,8 +137,6 @@ jobs:
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: "10.25.0"
|
||||
|
||||
- name: Check for outdated dependencies
|
||||
run: |
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{
|
||||
"*.{ts,tsx,js,jsx}": ["eslint --no-warn-ignored", "prettier -w"],
|
||||
"*.{ts,tsx,js,jsx}": ["eslint --fix --no-warn-ignored", "prettier -w"],
|
||||
"*.{json,md,yml,yaml,css,scss}": ["prettier -w"]
|
||||
}
|
||||
|
||||
@ -43,26 +43,33 @@ export class OpportunityResolutionService {
|
||||
wasCreated: boolean;
|
||||
}> {
|
||||
const safeAccountId = assertSalesforceId(accountId, "accountId");
|
||||
const lockKey = `opportunity:eligibility:${safeAccountId}:Internet`;
|
||||
|
||||
const existing = await this.opportunities.findOpenOpportunityForAccount(
|
||||
safeAccountId,
|
||||
OPPORTUNITY_PRODUCT_TYPE.INTERNET,
|
||||
{ stages: OPPORTUNITY_MATCH_STAGES_INTERNET_ELIGIBILITY }
|
||||
return this.lockService.withLock(
|
||||
lockKey,
|
||||
async () => {
|
||||
const existing = await this.opportunities.findOpenOpportunityForAccount(
|
||||
safeAccountId,
|
||||
OPPORTUNITY_PRODUCT_TYPE.INTERNET,
|
||||
{ stages: OPPORTUNITY_MATCH_STAGES_INTERNET_ELIGIBILITY }
|
||||
);
|
||||
|
||||
if (existing) {
|
||||
return { opportunityId: existing, wasCreated: false };
|
||||
}
|
||||
|
||||
const created = await this.opportunities.createOpportunity({
|
||||
accountId: safeAccountId,
|
||||
productType: OPPORTUNITY_PRODUCT_TYPE.INTERNET,
|
||||
stage: OPPORTUNITY_STAGE.INTRODUCTION,
|
||||
source: OPPORTUNITY_SOURCE.INTERNET_ELIGIBILITY,
|
||||
applicationStage: APPLICATION_STAGE.INTRO_1,
|
||||
});
|
||||
|
||||
return { opportunityId: created, wasCreated: true };
|
||||
},
|
||||
{ ttlMs: 10_000 }
|
||||
);
|
||||
|
||||
if (existing) {
|
||||
return { opportunityId: existing, wasCreated: false };
|
||||
}
|
||||
|
||||
const created = await this.opportunities.createOpportunity({
|
||||
accountId: safeAccountId,
|
||||
productType: OPPORTUNITY_PRODUCT_TYPE.INTERNET,
|
||||
stage: OPPORTUNITY_STAGE.INTRODUCTION,
|
||||
source: OPPORTUNITY_SOURCE.INTERNET_ELIGIBILITY,
|
||||
applicationStage: APPLICATION_STAGE.INTRO_1,
|
||||
});
|
||||
|
||||
return { opportunityId: created, wasCreated: true };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -175,12 +175,8 @@ export class SalesforceAccountService {
|
||||
): Promise<{ accountId: string; accountNumber: string }> {
|
||||
this.logger.log("Creating new Salesforce Account", { email: data.email });
|
||||
|
||||
// Generate unique account number (SF_Account_No__c)
|
||||
const accountNumber = await this.generateAccountNumber();
|
||||
|
||||
const accountPayload = {
|
||||
Name: `${data.firstName} ${data.lastName}`,
|
||||
SF_Account_No__c: accountNumber,
|
||||
BillingStreet:
|
||||
data.address.address1 + (data.address.address2 ? `\n${data.address.address2}` : ""),
|
||||
BillingCity: data.address.city,
|
||||
@ -207,6 +203,18 @@ export class SalesforceAccountService {
|
||||
|
||||
const accountId = result.id as string;
|
||||
|
||||
// Query back the auto-generated account number
|
||||
const accountRecord = (await this.connection.query(
|
||||
`SELECT SF_Account_No__c FROM Account WHERE Id = '${this.safeSoql(accountId)}'`,
|
||||
{ label: "checkout:getCreatedAccountNumber" }
|
||||
)) as SalesforceResponse<{ SF_Account_No__c: string }>;
|
||||
|
||||
const accountNumber = accountRecord.records[0]?.SF_Account_No__c || "";
|
||||
|
||||
if (!accountNumber) {
|
||||
this.logger.warn("Account number not found for newly created account", { accountId });
|
||||
}
|
||||
|
||||
this.logger.log("Salesforce Account created", {
|
||||
accountId,
|
||||
accountNumber,
|
||||
@ -273,38 +281,6 @@ export class SalesforceAccountService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique customer number for new accounts
|
||||
* Format: PNNNNNNN (P = Portal, 7 digits)
|
||||
*/
|
||||
private async generateAccountNumber(): Promise<string> {
|
||||
try {
|
||||
// Query for max existing portal account number
|
||||
const result = (await this.connection.query(
|
||||
`SELECT SF_Account_No__c FROM Account WHERE SF_Account_No__c LIKE 'P%' ORDER BY SF_Account_No__c DESC LIMIT 1`,
|
||||
{ label: "checkout:getMaxAccountNumber" }
|
||||
)) as SalesforceResponse<{ SF_Account_No__c: string }>;
|
||||
|
||||
let nextNumber = 1000001; // Start from P1000001
|
||||
|
||||
if (result.totalSize > 0 && result.records[0]?.SF_Account_No__c) {
|
||||
const lastNumber = result.records[0].SF_Account_No__c;
|
||||
const numPart = parseInt(lastNumber.substring(1), 10);
|
||||
if (!isNaN(numPart)) {
|
||||
nextNumber = numPart + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return `P${nextNumber}`;
|
||||
} catch (error) {
|
||||
this.logger.error("Failed to generate account number, using timestamp fallback", {
|
||||
error: getErrorMessage(error),
|
||||
});
|
||||
// Fallback: use timestamp to ensure uniqueness
|
||||
return `P${Date.now().toString().slice(-7)}`;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Portal Field Update Methods
|
||||
// ============================================================================
|
||||
|
||||
@ -194,7 +194,12 @@ export class InternetCancellationService {
|
||||
|
||||
// Cancellation date is end of selected month
|
||||
const lastDayOfMonth = new Date(year, month, 0);
|
||||
const cancellationDate = lastDayOfMonth.toISOString().split("T")[0];
|
||||
// Use local date components to avoid timezone shifts when converting to string
|
||||
const cancellationDate = [
|
||||
lastDayOfMonth.getFullYear(),
|
||||
String(lastDayOfMonth.getMonth() + 1).padStart(2, "0"),
|
||||
String(lastDayOfMonth.getDate()).padStart(2, "0"),
|
||||
].join("-");
|
||||
|
||||
this.logger.log("Processing Internet cancellation request", {
|
||||
userId,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user