146 lines
5.3 KiB
Go
146 lines
5.3 KiB
Go
package processor
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/google/uuid"
|
||
|
|
"github.com/stretchr/testify/assert"
|
||
|
|
"github.com/stretchr/testify/require"
|
||
|
|
|
||
|
|
"apskel-pos-be/internal/models"
|
||
|
|
"apskel-pos-be/internal/repository"
|
||
|
|
)
|
||
|
|
|
||
|
|
type customerOrderRepoFake struct {
|
||
|
|
owner map[uuid.UUID]uuid.UUID // order -> customer
|
||
|
|
orders []repository.CustomerOrderRow
|
||
|
|
items map[uuid.UUID][]repository.CustomerOrderItemRow
|
||
|
|
payments map[uuid.UUID][]repository.CustomerOrderPaymentRow
|
||
|
|
offset int
|
||
|
|
limit int
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *customerOrderRepoFake) ListOrders(_ context.Context, customerID uuid.UUID, offset, limit int) ([]repository.CustomerOrderRow, int64, error) {
|
||
|
|
f.offset, f.limit = offset, limit
|
||
|
|
var mine []repository.CustomerOrderRow
|
||
|
|
for _, o := range f.orders {
|
||
|
|
if f.owner[o.ID] == customerID {
|
||
|
|
mine = append(mine, o)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return mine, int64(len(mine)), nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *customerOrderRepoFake) GetOrder(_ context.Context, customerID, orderID uuid.UUID) (*repository.CustomerOrderRow, error) {
|
||
|
|
for _, o := range f.orders {
|
||
|
|
if o.ID == orderID && f.owner[o.ID] == customerID {
|
||
|
|
c := o
|
||
|
|
return &c, nil
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nil, repository.ErrCustomerOrderNotFound
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *customerOrderRepoFake) ListItems(_ context.Context, orderID uuid.UUID) ([]repository.CustomerOrderItemRow, error) {
|
||
|
|
return f.items[orderID], nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *customerOrderRepoFake) ListPayments(_ context.Context, orderID uuid.UUID) ([]repository.CustomerOrderPaymentRow, error) {
|
||
|
|
return f.payments[orderID], nil
|
||
|
|
}
|
||
|
|
|
||
|
|
type earnedFake map[uuid.UUID]OrderEarned
|
||
|
|
|
||
|
|
func (f earnedFake) EarnedByOrders(_ context.Context, ids []uuid.UUID) (map[uuid.UUID]OrderEarned, error) {
|
||
|
|
out := map[uuid.UUID]OrderEarned{}
|
||
|
|
for _, id := range ids {
|
||
|
|
if e, ok := f[id]; ok {
|
||
|
|
out[id] = e
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return out, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func newCustomerOrderTest() (*customerOrderRepoFake, uuid.UUID, uuid.UUID, uuid.UUID) {
|
||
|
|
customer, other := uuid.New(), uuid.New()
|
||
|
|
mine, theirs := uuid.New(), uuid.New()
|
||
|
|
repo := &customerOrderRepoFake{
|
||
|
|
owner: map[uuid.UUID]uuid.UUID{mine: customer, theirs: other},
|
||
|
|
orders: []repository.CustomerOrderRow{
|
||
|
|
{ID: mine, OrderNumber: "ORD-1", OutletName: "Gokuna 1", Status: "completed", PaymentStatus: "completed", Subtotal: 90000, TotalAmount: 99000, ItemCount: 2, CreatedAt: time.Now()},
|
||
|
|
{ID: theirs, OrderNumber: "ORD-2"},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
return repo, customer, mine, theirs
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestCustomerOrders_ListShowsOnlyTheCustomersOrdersWithEarning(t *testing.T) {
|
||
|
|
repo, customer, mine, _ := newCustomerOrderTest()
|
||
|
|
p := NewCustomerOrderProcessor(repo, earnedFake{mine: {Points: 900, Coins: 3}})
|
||
|
|
|
||
|
|
got, err := p.List(context.Background(), customer, models.ListCustomerOrdersQuery{Page: 2, Limit: 10})
|
||
|
|
require.NoError(t, err)
|
||
|
|
require.Len(t, got.Data, 1)
|
||
|
|
assert.Equal(t, "ORD-1", got.Data[0].OrderNumber)
|
||
|
|
assert.Equal(t, int64(900), got.Data[0].PointsEarned)
|
||
|
|
assert.Equal(t, int64(3), got.Data[0].CoinsEarned)
|
||
|
|
assert.Equal(t, 10, repo.offset, "page 2 of 10 skips the first 10")
|
||
|
|
assert.Equal(t, 10, repo.limit)
|
||
|
|
assert.Equal(t, 2, got.Pagination.Page)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestCustomerOrders_ListDefaultsAndLimits(t *testing.T) {
|
||
|
|
repo, customer, _, _ := newCustomerOrderTest()
|
||
|
|
p := NewCustomerOrderProcessor(repo, earnedFake{})
|
||
|
|
|
||
|
|
got, err := p.List(context.Background(), customer, models.ListCustomerOrdersQuery{})
|
||
|
|
require.NoError(t, err)
|
||
|
|
assert.Equal(t, 1, got.Pagination.Page)
|
||
|
|
assert.Equal(t, 20, got.Pagination.Limit)
|
||
|
|
|
||
|
|
for _, q := range []models.ListCustomerOrdersQuery{{Page: -1}, {Limit: 101}, {Limit: -5}} {
|
||
|
|
_, err := p.List(context.Background(), customer, q)
|
||
|
|
assert.ErrorIs(t, err, ErrInvalidWalletQuery, "%+v", q)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestCustomerOrders_DetailHasItemsPaymentsAndEarning(t *testing.T) {
|
||
|
|
repo, customer, mine, _ := newCustomerOrderTest()
|
||
|
|
variant, unit := "Large", "ons"
|
||
|
|
weight := 4.2
|
||
|
|
points, value := int64(12500), 1.0
|
||
|
|
repo.items = map[uuid.UUID][]repository.CustomerOrderItemRow{
|
||
|
|
mine: {
|
||
|
|
{ProductName: "Kopi Susu", VariantName: &variant, Quantity: 2, UnitPrice: 25000, TotalPrice: 50000, Status: "completed"},
|
||
|
|
{ProductName: "Ikan Tude", Quantity: 1, Weight: &weight, UnitName: &unit, UnitPrice: 4500, TotalPrice: 18900, Status: "completed"},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
repo.payments = map[uuid.UUID][]repository.CustomerOrderPaymentRow{
|
||
|
|
mine: {
|
||
|
|
{MethodName: "EnakPoint", MethodType: "point", Amount: 12500, Status: "completed", PointsUsed: &points, PointValue: &value},
|
||
|
|
{MethodName: "Cash", MethodType: "cash", Amount: 86500, Status: "completed"},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
p := NewCustomerOrderProcessor(repo, earnedFake{mine: {Points: 865}})
|
||
|
|
|
||
|
|
got, err := p.Detail(context.Background(), customer, mine)
|
||
|
|
require.NoError(t, err)
|
||
|
|
assert.Equal(t, "Gokuna 1", got.OutletName)
|
||
|
|
assert.Equal(t, float64(90000), got.Subtotal)
|
||
|
|
assert.Equal(t, int64(865), got.PointsEarned)
|
||
|
|
require.Len(t, got.Items, 2)
|
||
|
|
assert.Equal(t, "Large", *got.Items[0].VariantName)
|
||
|
|
assert.Equal(t, []map[string]interface{}{}, got.Items[0].Modifiers, "no modifiers is an empty list, not null")
|
||
|
|
assert.Equal(t, 4.2, *got.Items[1].Weight)
|
||
|
|
require.Len(t, got.Payments, 2)
|
||
|
|
assert.Equal(t, int64(12500), *got.Payments[0].PointsUsed)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestCustomerOrders_AnotherCustomersOrderIsNotFound(t *testing.T) {
|
||
|
|
repo, customer, _, theirs := newCustomerOrderTest()
|
||
|
|
_, err := NewCustomerOrderProcessor(repo, earnedFake{}).Detail(context.Background(), customer, theirs)
|
||
|
|
assert.ErrorIs(t, err, repository.ErrCustomerOrderNotFound)
|
||
|
|
}
|