# Customer Value & Credit Bundle v42

v42 adds three separate customer-value ledgers:

1. Loyalty points
2. Monetary wallet/cashback
3. Customer credit / accounts receivable

They are deliberately separate domains. Points are not money, wallet balance is stored value,
and credit is a receivable rather than a fake payment method.

## Loyalty

Immutable signed points entries support:
- earn
- redeem
- expiry
- reversal
- adjustment

The account row is a rebuildable projection with current balance and lifetime totals.

## Wallet

Immutable signed monetary entries support:
- credit
- debit
- cashback
- refund
- expiry
- reversal
- adjustment

Wallet cannot become negative.

A dedicated sale-wallet endpoint debits the wallet atomically and creates a real captured
`payments.payment` with `method_type=wallet`. Normal payment status calculation therefore
continues to work.

## Customer Credit / AR

Credit is not inserted into `payments.payments`.

The credit account keeps:
- credit limit
- outstanding receivable
- available credit
- account status

Signed credit entries support:
- charge
- payment
- return credit
- reversal
- adjustment

A sale charged fully to credit becomes operationally completed with
`payment_status=on_account`. Partial credit coverage uses `partially_on_account`.

## Customer financial summary

CRM exposes one combined summary:
- loyalty balance
- wallet balances per currency
- credit limit / outstanding / available credit per currency

## API

- GET  `/api/v1/crm/customers/{customerPublicId}/value`
- POST `/api/v1/crm/customers/{customerPublicId}/loyalty/entries`
- POST `/api/v1/crm/customers/{customerPublicId}/wallet/entries`
- PUT  `/api/v1/crm/customers/{customerPublicId}/credit-limit`
- POST `/api/v1/crm/customers/{customerPublicId}/credit/entries`
- POST `/api/v1/sales/{salePublicId}/wallet-payment`
- POST `/api/v1/sales/{salePublicId}/credit-charge`

## Integration boundary

v42 establishes correct ledgers and sale settlement contracts.

Automatic points earning/cashback rules, expiry batch processing, and automatic reversal
allocation from complex mixed-tender returns remain follow-up policy orchestration, rather
than being hidden inside Eloquent hooks.
