const { getErrorReason } = require("../constants/errorReasons"); const { buildBusinessValidationError } = require("../utils/businessValidationError"); function resolvePaymentBatchCreationReadiness({ entityType, entityIds, paymentChannel = "bank", snapshots, departmentReadiness, accountReadiness, reservedEntityIds, reviewerIds }) { const blockers = []; const addPaymentReadinessBlocker = (reasonCode, snapshot) => { getErrorReason(reasonCode); blockers.push({ reasonCode, ...(snapshot ? { entityId: snapshot.entityId, entityCode: snapshot.entityCode } : {}) }); }; if (entityType !== "reimbursement") addPaymentReadinessBlocker("payment_batch.travel_payment_frozen"); const selected = snapshots.filter((snapshot) => entityIds.includes(snapshot.entityId)); if (!entityIds.length || selected.length !== entityIds.length) addPaymentReadinessBlocker("payment_batch.source_not_found"); const companies = new Set(); for (const snapshot of selected) { if (snapshot.status !== "approved" || snapshot.snapshotJson?.paidAt) addPaymentReadinessBlocker("payment_batch.source_status_invalid", snapshot); if (!departmentReadiness.get(snapshot.departmentId ?? null)?.enabled) addPaymentReadinessBlocker("payment_batch.department_unavailable", snapshot); if (reservedEntityIds.has(snapshot.entityId)) addPaymentReadinessBlocker("payment_batch.active_batch_exists", snapshot); const payee = snapshot.snapshotJson?.payee; if (payee?.bankAccountUnavailable) addPaymentReadinessBlocker("payment_batch.payee_account_unavailable", snapshot); if (paymentChannel !== "bank") continue; if (!snapshot.legalEntityId) addPaymentReadinessBlocker("payment_batch.legal_entity_required", snapshot); else companies.add(snapshot.legalEntityId); if (!payee?.bankInstitutionCode) addPaymentReadinessBlocker("payment_batch.payee_bank_required", snapshot); else if (payee.bankInstitutionCode !== "CCB") addPaymentReadinessBlocker("payment_batch.payee_bank_unsupported", snapshot); if (!payee?.bankAccountEncrypted) addPaymentReadinessBlocker("payment_batch.payee_account_required", snapshot); } if (paymentChannel === "bank") { if (companies.size > 1) addPaymentReadinessBlocker("payment_batch.multiple_legal_entities"); for (const companyId of companies) { const account = accountReadiness.get(companyId); if (!account?.paymentAccount) addPaymentReadinessBlocker("payment_batch.payment_account_required"); else if (!account.paymentAccountSnapshot) addPaymentReadinessBlocker("payment_batch.payment_account_unavailable"); } } if (!reviewerIds.length) addPaymentReadinessBlocker("payment_batch.reviewer_required"); return { ready: blockers.length === 0, blockers }; } function paymentReadinessError(readiness, departmentReadiness) { const blocker = readiness.blockers[0]; const detailsByReason = { "payment_batch.travel_payment_frozen": { entityType: "travel_payment_frozen" }, "payment_batch.source_not_found": { entityIds: "contains_not_found" }, "payment_batch.source_status_invalid": { entity: `${blocker.entityCode}:invalid_pay_status` }, "payment_batch.department_unavailable": { featureFlag: "payment_batch_v1_disabled", reason: [...departmentReadiness.values()].find((value) => !value.enabled)?.gate?.reason ?? "department_not_allowed" }, "payment_batch.active_batch_exists": { entityIds: "contains_active_payment_batch" }, "payment_batch.payee_account_unavailable": { payeeBankAccount: "decrypt_failed" }, "payment_batch.legal_entity_required": { legalEntity: "single_legal_entity_required" }, "payment_batch.multiple_legal_entities": { legalEntity: "single_legal_entity_required" }, "payment_batch.payee_bank_required": { payeeBankAccount: `${blocker.entityCode}:ccb_account_required` }, "payment_batch.payee_account_required": { payeeBankAccount: `${blocker.entityCode}:ccb_account_required` }, "payment_batch.payee_bank_unsupported": { payeeBankAccount: `${blocker.entityCode}:ccb_account_required` }, "payment_batch.payment_account_required": { paymentAccount: "active_ccb_account_required" }, "payment_batch.payment_account_unavailable": { paymentAccount: "decrypt_failed" }, "payment_batch.reviewer_required": { review: "no_eligible_reviewer" }, }; return buildBusinessValidationError(getErrorReason(blocker.reasonCode).code, detailsByReason[blocker.reasonCode], blocker.reasonCode === "payment_batch.source_not_found" ? 404 : 409); } module.exports = { resolvePaymentBatchCreationReadiness, paymentReadinessError };