feat(loyalty): give new balances their expiry
Every lot now gets its expiry when it is created (docs/prd-point-coin.md F12, PC-502), where it used to never expire until note N4 was settled: - EARN and an ADJUSTMENT that adds: ComputeExpiry of the organization's settings for that currency, from the moment received. - EXCHANGE_IN: the sooner of the EnakCoin lot's expiry and when EnakPoint received now expire (F4). - PAYMENT_REFUND: the expiry of the lot the EnakPoint came from, but at least seven days from the refund (N4, decided). A lot that never expired stays so. - TRANSFER_IN: unchanged, exactly the sender's expiry. Turning expiry on for a currency for the first time dates every lot of the organization that still holds something and has no expiry, MIGRATION lots included, in the same transaction as the setting: a full period from now when ROLLING, the second fixed date on or after today when FIXED_DATE, so no customer loses a balance soon after the rule is announced (N4, decided). Turning it off leaves dated lots as they are. PUT /marketing/loyalty-settings reports these as expiry_activations (currency, lots, amount, expires_at); a dry run counts them without dating anything. The earning processor now also reads the organization settings, and the wallet admin processor takes the settings reader. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
9ce55e6002
commit
4d63673a25
@@ -22,7 +22,7 @@ import (
|
||||
// failingSettings fails for the outlet settings until healed, to stand in for the
|
||||
// database being unreachable right after a payment.
|
||||
type failingSettings struct {
|
||||
real outletSettingsReader
|
||||
real earningSettingsReader
|
||||
mu sync.Mutex
|
||||
fail bool
|
||||
}
|
||||
@@ -227,3 +227,7 @@ func TestEarningProcessor_AgainstPostgres(t *testing.T) {
|
||||
assert.Equal(t, int64(875+250+600+400), balance.PointBalance)
|
||||
assert.Equal(t, int64(3+1+2+1), balance.CoinBalance)
|
||||
}
|
||||
|
||||
func (f *failingSettings) Organization(ctx context.Context, organizationID uuid.UUID) (*models.OrganizationLoyaltySettings, error) {
|
||||
return f.real.Organization(ctx, organizationID)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user