111 lines
3.5 KiB
Go
111 lines
3.5 KiB
Go
package service
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"github.com/google/uuid"
|
||
|
|
"github.com/stretchr/testify/assert"
|
||
|
|
"github.com/stretchr/testify/require"
|
||
|
|
|
||
|
|
"apskel-pos-be/internal/entities"
|
||
|
|
"apskel-pos-be/internal/logger"
|
||
|
|
"apskel-pos-be/internal/models"
|
||
|
|
"apskel-pos-be/internal/repository"
|
||
|
|
)
|
||
|
|
|
||
|
|
type discrepancyFinderFake struct {
|
||
|
|
found []repository.WalletDiscrepancy
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *discrepancyFinderFake) FindDiscrepancies(context.Context, int) ([]repository.WalletDiscrepancy, error) {
|
||
|
|
return f.found, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
type orgUsersFake map[uuid.UUID][]*entities.User
|
||
|
|
|
||
|
|
func (f orgUsersFake) GetByOrganizationID(_ context.Context, org uuid.UUID) ([]*entities.User, error) {
|
||
|
|
return f[org], nil
|
||
|
|
}
|
||
|
|
|
||
|
|
type notifierFake struct {
|
||
|
|
sent []*models.SendNotificationRequest
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *notifierFake) Send(_ context.Context, req *models.SendNotificationRequest) (*models.NotificationResponse, error) {
|
||
|
|
f.sent = append(f.sent, req)
|
||
|
|
return &models.NotificationResponse{}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestWalletReconciliationJob(t *testing.T) {
|
||
|
|
logger.Setup("fatal", "json")
|
||
|
|
org := uuid.New()
|
||
|
|
admin, owner, manager, cashier := uuid.New(), uuid.New(), uuid.New(), uuid.New()
|
||
|
|
users := orgUsersFake{org: {
|
||
|
|
{ID: admin, Role: entities.RoleAdmin},
|
||
|
|
{ID: owner, Role: entities.RoleOwner},
|
||
|
|
{ID: manager, Role: entities.RoleManager},
|
||
|
|
{ID: cashier, Role: entities.RoleCashier},
|
||
|
|
}}
|
||
|
|
finder := &discrepancyFinderFake{}
|
||
|
|
notifier := ¬ifierFake{}
|
||
|
|
job := NewWalletReconciliationJob(finder, users, notifier)
|
||
|
|
ctx := context.Background()
|
||
|
|
|
||
|
|
// Consistent data: nothing reported.
|
||
|
|
found, err := job.RunOnce(ctx)
|
||
|
|
require.NoError(t, err)
|
||
|
|
assert.Empty(t, found)
|
||
|
|
assert.Empty(t, notifier.sent)
|
||
|
|
|
||
|
|
// A discrepancy notifies the organization's admins, owners and managers.
|
||
|
|
customer := uuid.New()
|
||
|
|
lot := uuid.New()
|
||
|
|
finder.found = []repository.WalletDiscrepancy{
|
||
|
|
{Check: repository.WalletCheckBalanceVsLots, OrganizationID: org, CustomerID: customer, Currency: "POINT", Expected: 100, Actual: 105},
|
||
|
|
{Check: repository.WalletCheckLotVsAllocations, OrganizationID: org, CustomerID: customer, Currency: "POINT", ObjectID: &lot, Expected: 50, Actual: 55},
|
||
|
|
}
|
||
|
|
found, err = job.RunOnce(ctx)
|
||
|
|
require.NoError(t, err)
|
||
|
|
assert.Len(t, found, 2)
|
||
|
|
require.Len(t, notifier.sent, 1)
|
||
|
|
sent := notifier.sent[0]
|
||
|
|
assert.ElementsMatch(t, []uuid.UUID{admin, owner, manager}, sent.ReceiverIDs, "cashiers are not told")
|
||
|
|
assert.Equal(t, &org, sent.NotifiableID)
|
||
|
|
assert.Equal(t, 2, sent.Data["discrepancies"])
|
||
|
|
assert.Equal(t, []string{customer.String()}, sent.Data["customer_ids"])
|
||
|
|
assert.Equal(t, entities.NotificationPriorityHigh, sent.Priority)
|
||
|
|
|
||
|
|
// The same problem, still unfixed and in a different order, does not notify again.
|
||
|
|
finder.found = []repository.WalletDiscrepancy{finder.found[1], finder.found[0]}
|
||
|
|
_, err = job.RunOnce(ctx)
|
||
|
|
require.NoError(t, err)
|
||
|
|
assert.Len(t, notifier.sent, 1)
|
||
|
|
|
||
|
|
// A changed problem does.
|
||
|
|
finder.found = finder.found[:1]
|
||
|
|
_, err = job.RunOnce(ctx)
|
||
|
|
require.NoError(t, err)
|
||
|
|
assert.Len(t, notifier.sent, 2)
|
||
|
|
|
||
|
|
// Once clean the organization is forgotten, so the same problem coming back
|
||
|
|
// notifies again.
|
||
|
|
previous := finder.found
|
||
|
|
finder.found = nil
|
||
|
|
_, err = job.RunOnce(ctx)
|
||
|
|
require.NoError(t, err)
|
||
|
|
assert.Len(t, notifier.sent, 2)
|
||
|
|
finder.found = previous
|
||
|
|
_, err = job.RunOnce(ctx)
|
||
|
|
require.NoError(t, err)
|
||
|
|
assert.Len(t, notifier.sent, 3)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestWalletReconciliationJobStartStop(t *testing.T) {
|
||
|
|
logger.Setup("fatal", "json")
|
||
|
|
job := NewWalletReconciliationJob(&discrepancyFinderFake{}, orgUsersFake{}, ¬ifierFake{})
|
||
|
|
job.Start(0)
|
||
|
|
job.Stop()
|
||
|
|
job.Stop() // stopping twice is harmless
|
||
|
|
}
|