feat: trigger Freebit APIs on "Processed" status instead of "Approved"
Some checks failed
Pull Request Checks / Code Quality & Security (push) Has been cancelled
Security Audit / Security Vulnerability Audit (push) Has been cancelled
Security Audit / Dependency Review (push) Has been cancelled
Security Audit / CodeQL Security Analysis (push) Has been cancelled
Security Audit / Check Outdated Dependencies (push) Has been cancelled
Some checks failed
Pull Request Checks / Code Quality & Security (push) Has been cancelled
Security Audit / Security Vulnerability Audit (push) Has been cancelled
Security Audit / Dependency Review (push) Has been cancelled
Security Audit / CodeQL Security Analysis (push) Has been cancelled
Security Audit / Check Outdated Dependencies (push) Has been cancelled
- CDC subscriber now listens for Status="Processed" to fire SIM APIs - On API error, order Status reverts to "Approved" for retry - Provisioning processor validates "Processed" for Physical SIM flow Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e7d1371c48
commit
afc18988cd
@ -49,7 +49,7 @@ const INTERNAL_ORDER_FIELDS = new Set([
|
||||
const INTERNAL_ORDER_ITEM_FIELDS = new Set(["WHMCS_Service_ID__c"]);
|
||||
|
||||
/** Statuses that trigger provisioning */
|
||||
const PROVISION_TRIGGER_STATUSES = new Set(["Approved", "Reactivate"]);
|
||||
const PROVISION_TRIGGER_STATUSES = new Set(["Processed", "Reactivate"]);
|
||||
|
||||
@Injectable()
|
||||
export class OrderCdcSubscriber implements OnModuleInit {
|
||||
@ -134,9 +134,9 @@ export class OrderCdcSubscriber implements OnModuleInit {
|
||||
await this.handleActivationStatusChange(payload, orderId);
|
||||
}
|
||||
|
||||
// Check for provisioning trigger (Status change to "Approved")
|
||||
// Check for provisioning trigger (Status change to "Processed")
|
||||
if (payload && changedFields.has("Status")) {
|
||||
await this.handleStatusApprovedChange(payload, orderId);
|
||||
await this.handleStatusProcessedChange(payload, orderId);
|
||||
}
|
||||
|
||||
// Cache invalidation - only for customer-facing field changes
|
||||
@ -222,9 +222,9 @@ export class OrderCdcSubscriber implements OnModuleInit {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle order status changes to "Approved"
|
||||
* Handle order status changes to "Processed"
|
||||
*
|
||||
* Enqueues a provisioning job when Status changes to "Approved".
|
||||
* Enqueues a provisioning job when Status changes to "Processed".
|
||||
* The provisioning processor will fetch the full order from Salesforce
|
||||
* and validate the conditions (SIM_Type__c, Assign_Physical_SIM__c, etc.)
|
||||
*
|
||||
@ -232,27 +232,20 @@ export class OrderCdcSubscriber implements OnModuleInit {
|
||||
* because CDC only includes CHANGED fields. If only Status was updated, those fields
|
||||
* will be null in the payload even though they have values on the record.
|
||||
*
|
||||
* The processor handles:
|
||||
* - Physical SIM: Status="Approved" + SIM_Type="Physical SIM" + Assigned_Physical_SIM set
|
||||
* - Standard: Activation_Status__c="Activating"
|
||||
* - Idempotency via WHMCS_Order_ID__c check
|
||||
* On API failure, the orchestrator reverts the order Status back to "Approved".
|
||||
*/
|
||||
private async handleStatusApprovedChange(
|
||||
private async handleStatusProcessedChange(
|
||||
payload: Record<string, unknown>,
|
||||
orderId: string
|
||||
): Promise<void> {
|
||||
const status = extractStringField(payload, ["Status"]);
|
||||
|
||||
// Only trigger when status changes to "Approved"
|
||||
if (status !== "Approved") {
|
||||
// Only trigger when status changes to "Processed"
|
||||
if (status !== "Processed") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: We intentionally do NOT check SIM_Type__c or Assign_Physical_SIM__c here
|
||||
// because CDC payloads only contain changed fields. The provisioning processor
|
||||
// will fetch the full order and validate all conditions.
|
||||
|
||||
this.logger.log("Enqueuing provisioning job for order status change to Approved", {
|
||||
this.logger.log("Enqueuing provisioning job for order status change to Processed", {
|
||||
orderId,
|
||||
status,
|
||||
});
|
||||
@ -260,15 +253,15 @@ export class OrderCdcSubscriber implements OnModuleInit {
|
||||
try {
|
||||
await this.provisioningQueue.enqueue({
|
||||
sfOrderId: orderId,
|
||||
idempotencyKey: `cdc-status-approved-${Date.now()}-${orderId}`,
|
||||
correlationId: `cdc-status-approved-${orderId}`,
|
||||
idempotencyKey: `cdc-status-processed-${Date.now()}-${orderId}`,
|
||||
correlationId: `cdc-status-processed-${orderId}`,
|
||||
});
|
||||
|
||||
this.logger.log("Successfully enqueued provisioning job for Approved status", {
|
||||
this.logger.log("Successfully enqueued provisioning job for Processed status", {
|
||||
orderId,
|
||||
});
|
||||
} catch (error) {
|
||||
this.logger.error("Failed to enqueue provisioning job for Approved status", {
|
||||
this.logger.error("Failed to enqueue provisioning job for Processed status", {
|
||||
orderId,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
|
||||
@ -34,10 +34,10 @@ export class ProvisioningProcessor extends WorkerHost {
|
||||
|
||||
// Guard: Determine if this is a valid provisioning request
|
||||
// Case 1: Standard flow - Activation_Status__c = "Activating"
|
||||
// Case 2: Physical SIM flow - Status = "Approved" with SIM_Type__c = "Physical SIM"
|
||||
// Case 2: Physical SIM flow - Status = "Processed" with SIM_Type__c = "Physical SIM"
|
||||
const isStandardActivation = activationStatus === "Activating";
|
||||
const isPhysicalSimApproval =
|
||||
orderStatus === "Approved" && simType === "Physical SIM" && !!assignedPhysicalSim;
|
||||
orderStatus === "Processed" && simType === "Physical SIM" && !!assignedPhysicalSim;
|
||||
|
||||
if (!isStandardActivation && !isPhysicalSimApproval) {
|
||||
this.logger.log("Skipping provisioning job: Order not in activatable state", {
|
||||
|
||||
@ -312,7 +312,7 @@ export class OrderFulfillmentOrchestrator {
|
||||
failedStep: context.steps.find(s => s.status === "failed")?.step,
|
||||
});
|
||||
|
||||
// Update Salesforce with failure status
|
||||
// Update Salesforce with failure status — revert to "Approved" so it can be retried
|
||||
const errorShortCode = (
|
||||
this.orderFulfillmentErrorService.getShortCode(error) || String(errorCode)
|
||||
)
|
||||
@ -321,7 +321,7 @@ export class OrderFulfillmentOrchestrator {
|
||||
try {
|
||||
await this.salesforceFacade.updateOrder({
|
||||
Id: sfOrderId,
|
||||
Status: "Pending Review",
|
||||
Status: "Approved",
|
||||
Activation_Status__c: "Failed",
|
||||
Activation_Error_Code__c: errorShortCode,
|
||||
Activation_Error_Message__c: userMessage?.slice(0, 255),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user