GET /customer/wallet now reads the EnakPoint & EnakCoin wallet (docs/prd-point-coin.md F6, PC-106): spendable point and coin balances, the rupiah value of one EnakPoint and of the balance, the nearest day each currency loses balance (grouped by Asia/Jakarta day), and recent ledger rows. The fields of the pre-wallet response stay, filled from the wallet, so app versions that read them keep working. Adds GET /customer/wallet/transactions with pagination and filters for currency, one or more types, and an inclusive date range. Each row shows where the value came from (additions) or went to (deductions) as in §8.1, and additions list their lots and earliest expiry. The counterparty id, the admin and the metadata are left out; the description already carries the masked name. A malformed query answers 400, a missing customer 404. /customer/points and /customer/tokens keep their shape and now read the wallet too, so customer_points_repository is no longer used for balances. Balances are what the customer can spend: lots that have expired but that the expiry job has not processed are not counted. The point value is read from organization_settings (loyalty.point.value, default 1) through a small repository that the typed settings reader in PC-109 will build on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
72 lines
2.5 KiB
Go
72 lines
2.5 KiB
Go
package models
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// CustomerWalletTransaction is one ledger row as the customer app shows it
|
|
// (docs/prd-point-coin.md F6).
|
|
type CustomerWalletTransaction struct {
|
|
ID uuid.UUID `json:"id"`
|
|
Currency string `json:"currency"`
|
|
Type string `json:"type"`
|
|
// Signed: positive added to the balance, negative taken from it.
|
|
Amount int64 `json:"amount"`
|
|
BalanceAfter int64 `json:"balance_after"`
|
|
Description string `json:"description"`
|
|
// Where the value came from, set on additions.
|
|
Source *CustomerWalletTransactionRef `json:"source,omitempty"`
|
|
// Where the value went, set on deductions.
|
|
Destination *CustomerWalletTransactionRef `json:"destination,omitempty"`
|
|
OutletID *uuid.UUID `json:"outlet_id,omitempty"`
|
|
ReversesTransactionID *uuid.UUID `json:"reverses_transaction_id,omitempty"`
|
|
// Shared by the two rows of an exchange or a transfer.
|
|
GroupID *uuid.UUID `json:"group_id,omitempty"`
|
|
// Additions only: the earliest expiry among the lots it created, nil when none of
|
|
// them expire, and the lots themselves.
|
|
ExpiresAt *time.Time `json:"expires_at,omitempty"`
|
|
Lots []CustomerWalletLot `json:"lots,omitempty"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
}
|
|
|
|
// CustomerWalletTransactionRef points at what a ledger row came from or went to, as
|
|
// listed in §8.1: ORDER, PAYMENT, WALLET_TX, GAME_PLAY, LOT, USER and so on.
|
|
type CustomerWalletTransactionRef struct {
|
|
Type string `json:"type"`
|
|
ID uuid.UUID `json:"id"`
|
|
}
|
|
|
|
type CustomerWalletLot struct {
|
|
Amount int64 `json:"amount"`
|
|
Remaining int64 `json:"remaining"`
|
|
ExpiresAt *time.Time `json:"expires_at"`
|
|
}
|
|
|
|
// CustomerWalletExpiring is how much expires on one day.
|
|
type CustomerWalletExpiring struct {
|
|
Amount int64 `json:"amount"`
|
|
// YYYY-MM-DD, Asia/Jakarta.
|
|
Date string `json:"date"`
|
|
}
|
|
|
|
// CustomerWalletNearestExpiring is the next day each currency loses balance, nil when
|
|
// nothing is due to expire.
|
|
type CustomerWalletNearestExpiring struct {
|
|
Point *CustomerWalletExpiring `json:"point"`
|
|
Coin *CustomerWalletExpiring `json:"coin"`
|
|
}
|
|
|
|
// ListCustomerWalletTransactionsQuery is GET /customer/wallet/transactions.
|
|
type ListCustomerWalletTransactionsQuery struct {
|
|
Page int `form:"page"`
|
|
Limit int `form:"limit"`
|
|
Currency string `form:"currency"`
|
|
// One type, or several separated by commas.
|
|
Type string `form:"type"`
|
|
// Inclusive calendar dates, YYYY-MM-DD, Asia/Jakarta.
|
|
From string `form:"from"`
|
|
To string `form:"to"`
|
|
}
|