# Automatic Cash Payment → Open Shift Orchestration v37

## Existing payment behavior

The Payments module already defines:
- cash collection outcome as immediately succeeded
- succeeded outcome → captured payment
- card/external unknown resolution path
- Sale.register_id copied from Cart during checkout

No transactional outbox exists yet.

## v37 decision

Use synchronous application orchestration inside the existing payment transaction.

This guarantees:

Captured registered cash payment
→ open register shift
→ cash movement
→ shift entry
→ cashbox balance
→ expected shift cash

as one transaction.

If a registered cash sale has no open shift, collection fails and the payment capture is
rolled back.

## Legacy/admin boundary

A sale with `register_id = null` remains collectible without automatic shift posting.

The explicit v32 API remains the recovery/manual assignment boundary.

## Idempotency

`cash.sale_payment_postings` already has one posting per payment.

Retries of payment collection can therefore safely repair a missing historical posting
without applying cash twice.

## Resolution path

The same orchestration is also called after a payment becomes captured in
`ResolvePaymentAction`.

Current normal cash collection never becomes UNKNOWN, but this keeps the integration
correct for imported/legacy/future payment flows.

## Why no Eloquent hooks

Cash posting is business orchestration, not persistence behavior.

It stays explicit in application services and is executed inside the same DB transaction.

## Future outbox

When transactional outbox infrastructure is introduced, asynchronous integrations may be
published from the same transaction. Cash accounting itself should remain strongly
consistent and must not depend on eventual delivery.
