Files
apskel-pos-backend/internal/models/wallet_trace.go
efrilmandClaude Opus 5.5 8bf1d5c1a8 feat(loyalty): trace a wallet row lot by lot in the dashboard
Adds GET /marketing/wallet-transactions/:id/trace (docs/prd-point-coin.md
F7, §8.1, PC-404).

From any ledger row of the organization, the trace lists the lots a debit
took from, with how much it took from each, or the lots a credit created.
Each lot is followed back through origin_lot_id, across transfers,
exchanges and refunds, to the lot an EARN, ADJUSTMENT or MIGRATION first
created. Every step shows the lot and the row that created it, with the
real name of the customer it belongs to, so the example of §8 (A sends 120
to B, B pays 30) leads from B's payment to A's order #ORD-1.

Lots are loaded a generation at a time, and a chain stops at 100 steps or
at a lot it has already seen, which only bad data could cause. A row of
another organization answers 404.

The dashboard's wallet view now builds its lots with the same helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:25:17 +07:00

47 lines
1.8 KiB
Go

package models
import (
"time"
"github.com/google/uuid"
)
// AdminWalletTrace is GET /marketing/wallet-transactions/:id/trace
// (docs/prd-point-coin.md F7, §8.1): the lots a ledger row took from or created, and
// where each of them came from, lot by lot, back to the lot that first brought the
// balance into a wallet. It follows balance across transfers, exchanges and refunds.
type AdminWalletTrace struct {
Transaction AdminWalletTraceRow `json:"transaction"`
// One per lot the row took from (a debit) or created (a credit).
Lots []AdminWalletTraceLot `json:"lots"`
}
// AdminWalletTraceLot is how much of a row went through one lot, and that lot's chain.
type AdminWalletTraceLot struct {
Amount int64 `json:"amount"`
// The lot itself first, then the lot it was carried over from, and so on. The
// last step is the lot an EARN, ADJUSTMENT or MIGRATION created.
Chain []AdminWalletTraceStep `json:"chain"`
}
// AdminWalletTraceStep is one lot on a chain and the row that created it.
type AdminWalletTraceStep struct {
Lot AdminWalletLot `json:"lot"`
Source AdminWalletTraceRow `json:"source"`
}
// AdminWalletTraceRow is a ledger row as a trace shows it, with the real name of the
// customer it belongs to.
type AdminWalletTraceRow struct {
ID uuid.UUID `json:"id"`
Customer AdminWalletNamedRef `json:"customer"`
Currency string `json:"currency"`
Type string `json:"type"`
Amount int64 `json:"amount"`
Description string `json:"description"`
ReferenceType string `json:"reference_type"`
ReferenceID uuid.UUID `json:"reference_id"`
OutletID *uuid.UUID `json:"outlet_id,omitempty"`
CreatedAt time.Time `json:"created_at"`
}