Skip to content

This is an internal working record, not an everyday instruction. It was written while the system was being rebuilt, for whoever maintains it. If you are here to do today's work, use the everyday documents instead: Procedures · Processes · Runbooks · The working day, step by step

CTC Billing, QBO, Files And Email Policy Decision Matrix

  • Status: CURRENT P6-007 POLICY DECISION INPUT
  • Operating profile: ctc-execution
  • Source reconciliation: CTC_BILLING_QBO_FILES_EMAIL_RECONCILIATION.md
  • Composite process: PROC-BMS-BILLING-CLOSE-CTC
  • Atomic owners:
  • PROC-BMS-TRANSACTION-LIFECYCLE-CTC
  • PROC-BMS-AR-BILLING-CONFIRM-CTC
  • PROC-BMS-AR-QBO-DELIVERY-CTC
  • PROC-BMS-TRANSACTION-DOCUMENT-CTC
  • PROC-TMS-BOL-EMAIL-CTC
  • PROC-TMS-PACKING-LIST-EMAIL-CTC
  • Scope: document current facts, recommended target policies, unresolved decisions and owners before Runtime implementation or migration.
  • Does not authorize: code, schema, provider, Wiki DB, role/config, deployment or Production changes.

1. Decision Vocabulary

Value Meaning
FIXED CURRENT FACT Verified current source behavior that must be preserved or intentionally migrated.
USER-APPROVED User decision already fixed and not open to reinterpretation.
RECOMMENDED Proposed policy based on current integrity and migration requirements; requires owner/user approval before implementation.
OPEN Material policy or operational ownership is unresolved.
CURRENT COMPATIBILITY Existing behavior may remain temporarily but is not the target contract.
DEFERRED Intentionally postponed with owner and activation condition.
REJECTED Explicitly prohibited direction.

A recommendation is not current behavior. An open item must not be filled by implementation convenience.


2. Decision Summary

ID Topic Current fact Recommended/fixed direction Status Primary owner Blocks
BILL-POL-010 Generic close allowed fields Current close accepts normalized UI-supplied T_TRANSACTION columns for selected IDs. Replace target behavior with an explicit CloseTransactions command and allowlisted fields/status predicates. RECOMMENDED BMS transaction + P5/P6 Target write packet, correction policy
BILL-POL-020 Mixed-company/value batch Current UI can apply first-row/common values to all selected rows; server does not prove compatibility. Server must group or reject rows whose billing company, account or close values are incompatible. RECOMMENDED BMS transaction Safe bulk close
BILL-POL-030 Prior-state predicate Current generic close lacks a documented prior-state predicate. Every target close/correction transition uses explicit allowed source states and exactly-one/per-row affected result. RECOMMENDED BMS transaction State machine, idempotency
BILL-POL-040 Synced transaction edit/delete Current generic paths do not provide one approved policy for rows already represented in QBO. Block ordinary edit/delete after provider sync; use explicit accounting correction/void/reconciliation procedure. RECOMMENDED Accounting owner + QBO owner Data integrity, audit
BILL-POL-050 Source transaction idempotency Current source-specific create/delete behavior varies by adapter and relation. Define tenant + source UUID + account + semantic transaction type as duplicate identity. RECOMMENDED BMS transaction + source modules Create replay, migration
BILL-POL-060 AR Review requirement Review-first is an operator safety practice; current top-level Complete can use defaults. Require server-confirmed preview fingerprint or equivalent recomputation at confirm; UI Review may remain optional only when same authoritative calculation is used. RECOMMENDED AR Billing Stale preview, hidden defaults
BILL-POL-070 Active container AR uniqueness No proven active booking/container AR uniqueness or serialized confirm exists. One active container AR per tenant + billing scope + booking UUID + container UUID, with explicit invoice version/correction semantics. RECOMMENDED AR Billing + DB owner Duplicate invoices, migration
BILL-POL-080 Unsynced AR rewrite Current unsynced AR header is rewritten and old lines soft-deleted. Preserve current bounded rewrite only until explicit invoice-version/correction history is approved; target command records version lineage. CURRENT COMPATIBILITY AR Billing Audit, PostgreSQL model
BILL-POL-090 Post-confirm correction Current approved correction path after local confirm but before QBO is unclear. Define CorrectLocalContainerInvoice with state predicate READY/ERROR and immutable audit/version evidence; prohibit raw row edits. OPEN Accounting owner Operator recovery, M4
BILL-POL-100 Automatic QBO handoff Browser calls QBO after local confirm; interruption can leave READY with no attempt. Local confirm records a durable QBO effect intent when delivery is applicable; worker or explicit send command owns attempts. RECOMMENDED P6-004/P12 + QBO owner Durable delivery
BILL-POL-110 QBO group identity Current grouping is per transaction or customer-key + invoice number. Persist immutable effect group identity from sorted transaction UUIDs + customer ref + invoice number + payload hash. RECOMMENDED QBO application Idempotency/reconciliation
BILL-POL-120 QBO provider idempotency Current client has no provider idempotency key or search. Add provider-supported request identity where available and always implement provider search/reconcile before resend. RECOMMENDED QBO integration Duplicate provider invoice
BILL-POL-130 SYNCING timeout Current stale SYNCING recovery is not implemented. Do not time-reset blindly. After threshold, reconcile provider using effect identity and evidence, then mark SYNCED, FAILED_RETRYABLE, or MANUAL_REVIEW. OPEN Accounting/QBO support owner Worker, Runbook
BILL-POL-140 QBO_ERROR dual use Current field stores claim token during SYNCING, then error text. Separate effect intent/attempt identity from safe error detail in target model; retain field only as compatibility projection. RECOMMENDED P5/P12/QBO owner Target data model
BILL-POL-150 QBO correction/void Current client creates invoices only. Provider correction, void/delete and local reconciliation require separate approved commands and accounting authority; ordinary resend is not correction. OPEN Accounting owner Synced correction SOP
BILL-POL-160 Token refresh ownership Token refresh occurs in invoice request path and writes tenant config. Platform integration credential service owns refresh; business command consumes a valid provider session without owning secrets. RECOMMENDED Platform/P4/P12 Security, worker
BILL-POL-170 File object/link model Current T_FILE use combines object metadata and business link. Target model separates FileObject and FileLink; first MySQL adapter may map both to current rows only with explicit reference rules. RECOMMENDED Shared Files/P5/P12 Safe migration/delete
BILL-POL-180 Shared-object delete A physical path can have multiple active links; storage delete behavior differs. Unlink business relation first; delete object only when no active links/retention hold remain and cleanup is explicitly owned. RECOMMENDED Shared Files Data loss prevention
BILL-POL-190 Upload/link atomicity Object upload and MySQL registration are separate. Record upload intent/result and make link creation idempotent; orphan cleanup is a separately reconciled worker action. RECOMMENDED Shared Files/P6-004 Partial recovery
BILL-POL-200 File link uniqueness Current retry can create duplicate links and sequence allocation can race. Define active uniqueness by tenant + file-object identity + business target + link type; order is presentation metadata, not identity. RECOMMENDED Shared Files/DB owner Duplicate links
BILL-POL-210 File retention Current process lacks one approved retention/legal-hold policy. Retention and legal hold are explicit metadata/policy; user unlink does not bypass retention or audit. OPEN Operations/legal/platform Object cleanup
BILL-POL-220 Durable email effect ledger BOL and Packing List return provider results but persist no durable send ledger. Add email intent, attempt and reconciliation records before migrating sends to worker. RECOMMENDED P6-004/P12 + Gmail owner No-blind-retry, audit
BILL-POL-230 BOL email identity Current identity is transload/reference/recipient/subject/time. Use immutable intent UUID + source UUID + recipient-set hash + attachment-set hash + content version. RECOMMENDED TMS/Gmail owner Duplicate reconciliation
BILL-POL-240 Packing target-part identity Current Results identify target/part only in response memory. Persist batch UUID + target + part index/total + content/attachment hash; permit resume of only missing/failed parts. RECOMMENDED Booking/Gmail owner Partial send recovery
BILL-POL-250 Gmail unknown result Current timeout requires manual Sent search. Worker/support must search by provider/message identity or deterministic headers before resend; unknown remains a first-class state. RECOMMENDED Gmail integration Duplicate sends
BILL-POL-260 Recipient source ownership Company email rows supply BOL/Packing recipients. Recipient categories remain tenant-configured master data with named business owner and last-review evidence. OPEN Operations/customer master owner Wrong recipient risk
BILL-POL-270 Username-based admin override admin redirects email to a fixed developer address. Remove from target policy; replace with explicit environment-safe test-recipient configuration unavailable in ordinary Production operation. RECOMMENDED Platform/Operations Tenant safety
BILL-POL-280 BOL send completion No durable local send status. Completion requires provider reconciliation; future local projection must reference a durable email effect record, not transload flags. RECOMMENDED TMS/Gmail owner Runbook/Wiki
BILL-POL-290 Packing batch atomicity Target/part sends are sequential and irreversible. Treat every target-part as an independent effect under one batch; preserve successes and resume only unresolved parts. RECOMMENDED Booking/Gmail owner Partial result
BILL-POL-300 Composite daily close No stored composite status. Keep as human/composite reconciliation. Do not create one universal BILLING_CLOSED field. FIXED CURRENT FACT Operations Billing Process integrity
BILL-POL-310 Daily close owner/cadence Named accountable owner, cutoff and escalation are not approved. Assign accountable role, normal cadence, unresolved-item cutoff and escalation evidence. OPEN Operations owner Field acceptance, Wiki
BILL-POL-320 Role/API matrix Current menu/module access is data-driven; row-level negative matrix incomplete. P2/P4 must define semantic capabilities and test page/API/record allow/deny for Billing, Files and provider actions. OPEN P2-007/P4 M3/M4
BILL-POL-330 Provider effects in web request Current QBO/Gmail effects run in request path. Durable retryable provider effects move to Node worker after intent commit; synchronous preview/read remains Web/API. RECOMMENDED P12/P6-004 Reliability
BILL-POL-340 PostgreSQL timing DB transition is planned later. Preserve accepted TypeScript/MySQL semantics first; do not combine first provider/transaction cutover with PostgreSQL. USER-APPROVED P11/P12 Migration order

3. Generic Transaction Decisions

BILL-POL-010 — Close command shape

Current fact

The current close route accepts selected transaction IDs plus a normalized set of actual T_TRANSACTION columns. A blank invoice number is removed, and the remaining fields are bulk-applied.

Risk

  • browser/schema shape becomes the command contract;
  • unintended new columns can become writable through future UI/helper changes;
  • no state-specific validation;
  • mixed selections can receive one common value;
  • response does not identify each row's final state.

Recommendation

Define:

CloseTransactions

with a bounded DTO such as:

transactionIds[]
completeDate
invoiceNumber?
checkNumber?
remark?
expectedVersion/updatedAt per row or batch snapshot

Server resolves billing company/account/source and rejects incompatible rows. Return per-row exact readback.

Status

RECOMMENDED; no Runtime change authorized here.


BILL-POL-030 — Prior-state and repeat behavior

Target transitions must declare:

allowed current states
terminal/locked provider states
expected row version
exact affected row count
repeat behavior
correction path

A repeat after unknown response rereads all selected IDs. It does not reapply close blindly.


BILL-POL-040 — Provider-synced local mutation

Ordinary generic edit/delete must not mutate a provider-synced financial record as if no external representation exists.

Target separation:

EditDraftTransaction
CloseTransaction
CorrectLocalTransaction
RequestProviderCorrection
ReconcileProviderCorrection

Deletion of a source relation, local transaction and provider invoice are separate effects with separate authority.


4. AR Billing Decisions

BILL-POL-060 — Preview consistency

The target does not need to force an extra modal click when it can guarantee the same result through server recomputation. It must guarantee:

  • source/rate/preset version is current at confirm;
  • client-supplied calculated amount is not authoritative;
  • lines returned by preview can be compared with committed lines;
  • material drift is shown before an irreversible next effect.

Possible target approaches:

A. previewToken + source fingerprint required at confirm
B. confirm recomputes and returns a conflict when preview fingerprint changed
C. single command recomputes and requires explicit acknowledgement of returned final lines

Owner decision remains required.


BILL-POL-070 — Active invoice uniqueness

Recommended identity:

tenant
+ BILLING_SCOPE='CONTAINER'
+ booking UUID
+ container/equipment UUID
+ active/non-void invoice generation

A later corrected version should relate to the prior invoice rather than silently replacing its historical meaning.

Current unsynced rewrite can remain only as bounded compatibility until the version/correction model is accepted.


5. QBO Decisions

BILL-POL-100 — Durable delivery intent

Recommended sequence:

local AR confirm transaction
-> persist QBO delivery intent when applicable
-> commit local invoice and intent
-> worker claims intent
-> provider create/search
-> persist attempt/result
-> reconcile local invoice projection

The business request may expose PENDING_QBO after local commit. It must not wait for provider completion to report local confirm success.


BILL-POL-130 — Stale SYNCING

A time threshold alone does not prove failure. Required reconciliation inputs:

  • effect intent/attempt ID;
  • sorted local transaction UUIDs;
  • customer reference;
  • document number;
  • total amount/currency;
  • payload hash;
  • provider request/response metadata;
  • local claim time/actor;
  • provider search result.

Allowed target dispositions:

SYNCED
FAILED_RETRYABLE
FAILED_FINAL
UNKNOWN_PROVIDER_RESULT
MANUAL_REVIEW

Releasing back to READY requires provider absence or an accepted duplicate-risk decision.


BILL-POL-150 — Provider correction

This family currently documents invoice creation. Provider correction/void/delete is a separate accounting capability and must specify:

  • normal actor and approval;
  • provider operation allowed;
  • local status and correction relation;
  • customer/document-number behavior;
  • file/email downstream impact;
  • audit and evidence;
  • reversal versus replacement;
  • tax/accounting retention.

Do not implement correction by clearing QBO_INVOICE_ID and resending.


6. File Decisions

BILL-POL-170 — Conceptual model

Target concepts:

FileObject
- storage provider/key
- size/hash/content type
- original filename
- created/retention/cleanup state

FileLink
- target entity type/UUID
- file object UUID
- link type/sequence/label
- active lifecycle

FileReadability
- current object availability/check result

FileCleanupDisposition
- eligible/held/referenced/deleted/failed/manual review

The first MySQL adapter may retain T_FILE, but application contracts must not expose path-sharing as business identity.


BILL-POL-180 — Delete semantics

Required target command split:

UnlinkFileFromTransaction
EvaluateFileObjectCleanup
DeleteUnreferencedFileObject
ReconcileFileObject

DELETE /files/{id} compatibility must not become the target domain command without reference and retention checks.


7. Email Decisions

BILL-POL-220 — Effect ledger

Recommended target entities:

EmailIntent
EmailTarget
EmailPart
EmailAttempt
EmailReconciliation

At minimum preserve:

  • source capability/entity UUID;
  • intended recipient set;
  • subject/body/content version;
  • attachment object UUIDs/hashes;
  • target (BOL, CUSTOMER, INSPECTOR);
  • part index/total;
  • attempt number;
  • provider message/thread IDs;
  • result/error/unknown state;
  • actor/request/correlation ID.

BILL-POL-240 — Packing part resume

Target retry rules:

  • do not rebuild already accepted parts unless content changed and a new version is intentionally sent;
  • retry only unresolved target/part identities;
  • if generated attachment partitioning changes, create a new batch version rather than mixing old/new parts;
  • show the operator every target/part state;
  • preserve provider message IDs for each success.

BILL-POL-270 — Test recipient override

Target test-safety contract:

explicit non-Production or approved test mode
+ tenant/environment configuration
+ visible banner/result recipient
+ audit/correlation
+ impossible to activate silently in ordinary Production

Username comparison is rejected as the target selector.


8. Composite Close Decisions

BILL-POL-300 — No universal status

The daily composite remains a reconciliation view. It may have a derived worklist/disposition record later, but it must not mutate or replace child states.

Possible derived dispositions:

VERIFIED
CARRIED
NOT_APPLICABLE
BLOCKED
UNKNOWN

If persisted, each disposition references exact child identity/evidence and owner. It is not a business completion authority.


BILL-POL-310 — Operating ownership

Required user/operations decision:

Question Decision needed
Accountable role Who owns daily Billing/document close?
Cadence Continuous, end-of-shift, end-of-day, or accounting cutoff?
Cutoff timezone Tenant operating timezone and business day definition.
Carry threshold When does unresolved QBO/email/file work escalate?
Escalation owner Accounting, operations manager, system support, provider support.
Required evidence IDs, screenshots, provider message/invoice IDs, amounts and timestamps.
Retention Where is the reconciliation record retained?

Until approved, Wiki content must describe child procedures and recovery without inventing an SLA.


9. Role And Capability Recommendations

Proposed semantic capabilities for later P2/P4/P12 mapping:

bms.transaction.view
bms.transaction.create
bms.transaction.edit
bms.transaction.close
bms.transaction.correct
bms.transaction.delete

bms.ar-billing.view
bms.ar-billing.preview
bms.ar-billing.confirm
bms.ar-billing.correct

bms.qbo.view
bms.qbo.request-delivery
bms.qbo.reconcile
bms.qbo.correct

files.transaction.view
files.transaction.upload
files.transaction.link
files.transaction.unlink
files.object.cleanup

tms.bol-email.view
tms.bol-email.send
tms.bol-email.reconcile

tms.packing-email.view
tms.packing-email.send
tms.packing-email.reconcile

operations.billing-close.review

These names are target semantics, not proof of current role IDs or menu rows.


10. Decision Activation Order

Before any new current-Runtime Billing write

Resolve or explicitly bound:

BILL-POL-010
BILL-POL-020
BILL-POL-030
BILL-POL-040
BILL-POL-320

Before AR/QBO migration or worker implementation

Resolve:

BILL-POL-060 through BILL-POL-160
BILL-POL-320
BILL-POL-330

Before File migration

Resolve:

BILL-POL-170 through BILL-POL-210
BILL-POL-320

Before Gmail worker migration

Resolve:

BILL-POL-220 through BILL-POL-290
BILL-POL-320
BILL-POL-330

Before Wiki field acceptance

Resolve:

BILL-POL-260
BILL-POL-310
BILL-POL-320

11. Explicitly Rejected Shortcuts

  • One BILLING_COMPLETE or DOCUMENT_SENT column for all children.
  • Treating QBO_SYNC_STATUS='ERROR' as provider absence.
  • Resetting stale SYNCING solely by age and resending.
  • Clearing provider IDs to force a resend.
  • Reusing QBO_ERROR as permanent intent identity in the target model.
  • Treating object path as the only file identity.
  • Deleting a physical object when one selected link is deleted without checking other links/retention.
  • Retrying the entire Packing List target/batch after one part failure without reconciliation.
  • Using username, numeric tenant ID or customer name as target policy.
  • Putting provider calls, object cleanup or multipart replay directly in React components or page-owned Server Actions.
  • Migrating Billing/QBO/Gmail and PostgreSQL in one cutover.

12. Review Ledger

Decision ID Reviewer Decision Date Evidence/notes

No OPEN or RECOMMENDED row becomes approved merely because implementation code was written.

---

Source: docs/processes/CTC_BILLING_QBO_FILES_EMAIL_POLICY_DECISION_MATRIX.md — ctc repository · This page is an English translation of the source document. Identifiers, file paths and code symbols are unchanged.