@cfxlabsinc/b2b-services
    Preparing search index...
    WireEmailPostOutcome:
        | { accountKey: string; bankTransactionId: string; status: "POSTED" }
        | {
            bankTransactionId: string;
            status: "MATCHED_EXISTING";
            type: BankTransaction["type"];
        }
        | {
            reason: "no-account-match"
            | "ambiguous-account-match";
            status: "UNRESOLVED";
        }
        | {
            reason: "bank-not-enabled"
            | "not-a-credit"
            | "no-account-ending";
            status: "SKIPPED";
        }

    What came of posting one wire email.

    UNRESOLVED and SKIPPED both mean "no row was written", and they are separate statuses because the caller owes them different things: we TRIED to place an UNRESOLVED wire and failed, so it needs a human and an alert, while a SKIPPED one was never a candidate. Folding them into one status with a reason code pushed that judgement onto every caller, and buried the handful that need attention among the hundreds working as designed.

    Type Declaration

    • { accountKey: string; bankTransactionId: string; status: "POSTED" }
    • {
          bankTransactionId: string;
          status: "MATCHED_EXISTING";
          type: BankTransaction["type"];
      }
      • bankTransactionId: string
      • status: "MATCHED_EXISTING"
      • type: BankTransaction["type"]

        The matched row's own direction — update is discriminated on it.

    • { reason: "no-account-match" | "ambiguous-account-match"; status: "UNRESOLVED" }
    • {
          reason: "bank-not-enabled" | "not-a-credit" | "no-account-ending";
          status: "SKIPPED";
      }