207 lines
6.0 KiB
Go
207 lines
6.0 KiB
Go
package processor
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"apskel-pos-be/internal/entities"
|
|
"apskel-pos-be/internal/models"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type expenseRepositoryCaptureStub struct {
|
|
createdExpense *entities.Expense
|
|
createdItems []*entities.ExpenseItem
|
|
analytics *entities.ExpenseAnalytics
|
|
}
|
|
|
|
func (s *expenseRepositoryCaptureStub) Create(_ context.Context, expense *entities.Expense) error {
|
|
if expense.ID == uuid.Nil {
|
|
expense.ID = uuid.New()
|
|
}
|
|
s.createdExpense = expense
|
|
return nil
|
|
}
|
|
|
|
func (s *expenseRepositoryCaptureStub) GetByID(context.Context, uuid.UUID) (*entities.Expense, error) {
|
|
if s.createdExpense == nil {
|
|
return nil, nil
|
|
}
|
|
items := make([]entities.ExpenseItem, len(s.createdItems))
|
|
for i, item := range s.createdItems {
|
|
items[i] = *item
|
|
}
|
|
s.createdExpense.Items = items
|
|
return s.createdExpense, nil
|
|
}
|
|
|
|
func (*expenseRepositoryCaptureStub) GetByIDAndOrganizationID(context.Context, uuid.UUID, uuid.UUID) (*entities.Expense, error) {
|
|
return nil, nil
|
|
}
|
|
func (*expenseRepositoryCaptureStub) Update(context.Context, *entities.Expense) error { return nil }
|
|
func (*expenseRepositoryCaptureStub) Delete(context.Context, uuid.UUID) error { return nil }
|
|
func (*expenseRepositoryCaptureStub) List(context.Context, uuid.UUID, map[string]interface{}, int, int) ([]*entities.Expense, int64, error) {
|
|
return nil, 0, nil
|
|
}
|
|
func (s *expenseRepositoryCaptureStub) GetAnalytics(context.Context, uuid.UUID, *uuid.UUID, time.Time, time.Time, string) (*entities.ExpenseAnalytics, error) {
|
|
return s.analytics, nil
|
|
}
|
|
func (s *expenseRepositoryCaptureStub) CreateItem(_ context.Context, item *entities.ExpenseItem) error {
|
|
if item.ID == uuid.Nil {
|
|
item.ID = uuid.New()
|
|
}
|
|
s.createdItems = append(s.createdItems, item)
|
|
return nil
|
|
}
|
|
func (*expenseRepositoryCaptureStub) DeleteItemsByExpenseID(context.Context, uuid.UUID) error {
|
|
return nil
|
|
}
|
|
|
|
func TestExpenseProcessorCreatePersistsItemName(t *testing.T) {
|
|
repo := &expenseRepositoryCaptureStub{}
|
|
p := NewExpenseProcessorImpl(repo)
|
|
chartOfAccountID := uuid.New()
|
|
|
|
resp, err := p.CreateExpense(context.Background(), uuid.New(), &models.CreateExpenseRequest{
|
|
Receiver: "Cashier",
|
|
TransactionDate: "2026-05-29",
|
|
CodeNumber: "EXP-001",
|
|
OutletID: uuid.NewString(),
|
|
Total: 10000,
|
|
Items: []models.CreateExpenseItemRequest{
|
|
{
|
|
ChartOfAccountID: chartOfAccountID.String(),
|
|
Item: "Cleaning supplies",
|
|
Amount: 10000,
|
|
},
|
|
},
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
require.Len(t, repo.createdItems, 1)
|
|
require.Equal(t, "Cleaning supplies", repo.createdItems[0].Item)
|
|
require.Len(t, resp.Items, 1)
|
|
require.Equal(t, "Cleaning supplies", resp.Items[0].Item)
|
|
}
|
|
|
|
func TestExpenseProcessorCreateDefaultsStatusToDraft(t *testing.T) {
|
|
repo := &expenseRepositoryCaptureStub{}
|
|
p := NewExpenseProcessorImpl(repo)
|
|
|
|
resp, err := p.CreateExpense(context.Background(), uuid.New(), &models.CreateExpenseRequest{
|
|
Receiver: "Cashier",
|
|
TransactionDate: "2026-05-29",
|
|
CodeNumber: "EXP-001",
|
|
OutletID: uuid.NewString(),
|
|
Total: 10000,
|
|
Items: []models.CreateExpenseItemRequest{
|
|
{
|
|
ChartOfAccountID: uuid.NewString(),
|
|
Item: "Cleaning supplies",
|
|
Amount: 10000,
|
|
},
|
|
},
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
require.Equal(t, "draft", repo.createdExpense.Status)
|
|
require.Equal(t, "draft", resp.Status)
|
|
}
|
|
|
|
func TestExpenseProcessorCreatePersistsProvidedStatus(t *testing.T) {
|
|
repo := &expenseRepositoryCaptureStub{}
|
|
p := NewExpenseProcessorImpl(repo)
|
|
status := "approved"
|
|
|
|
resp, err := p.CreateExpense(context.Background(), uuid.New(), &models.CreateExpenseRequest{
|
|
Receiver: "Cashier",
|
|
TransactionDate: "2026-05-29",
|
|
CodeNumber: "EXP-001",
|
|
OutletID: uuid.NewString(),
|
|
Status: &status,
|
|
Total: 10000,
|
|
Items: []models.CreateExpenseItemRequest{
|
|
{
|
|
ChartOfAccountID: uuid.NewString(),
|
|
Item: "Cleaning supplies",
|
|
Amount: 10000,
|
|
},
|
|
},
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
require.Equal(t, "approved", repo.createdExpense.Status)
|
|
require.Equal(t, "approved", resp.Status)
|
|
}
|
|
|
|
func TestExpenseProcessorGetExpenseAnalyticsDefaultsGroupByAndMapsResponse(t *testing.T) {
|
|
coaID := uuid.New()
|
|
outletID := uuid.New()
|
|
now := time.Date(2026, 5, 1, 0, 0, 0, 0, time.UTC)
|
|
repo := &expenseRepositoryCaptureStub{
|
|
analytics: &entities.ExpenseAnalytics{
|
|
Summary: entities.ExpenseAnalyticsSummary{
|
|
TotalExpenses: 100000,
|
|
TotalExpenseCount: 2,
|
|
TotalTax: 10000,
|
|
AverageExpenseValue: 50000,
|
|
TotalCategories: 1,
|
|
TotalItems: 2,
|
|
},
|
|
Data: []entities.ExpenseAnalyticsData{
|
|
{
|
|
Date: now,
|
|
Expenses: 100000,
|
|
ExpenseCount: 2,
|
|
Tax: 10000,
|
|
Items: 2,
|
|
Categories: 1,
|
|
},
|
|
},
|
|
CategoryData: []entities.ExpenseAnalyticsCategoryData{
|
|
{
|
|
ChartOfAccountID: coaID,
|
|
ChartOfAccountName: "Operational",
|
|
TotalAmount: 100000,
|
|
ExpenseCount: 2,
|
|
ItemCount: 2,
|
|
},
|
|
},
|
|
ItemData: []entities.ExpenseAnalyticsItemData{
|
|
{
|
|
Item: "Cleaning supplies",
|
|
TotalAmount: 100000,
|
|
ExpenseCount: 2,
|
|
ItemCount: 2,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
p := NewExpenseProcessorImpl(repo)
|
|
|
|
resp, err := p.GetExpenseAnalytics(context.Background(), &models.ExpenseAnalyticsRequest{
|
|
OrganizationID: uuid.New(),
|
|
OutletID: &outletID,
|
|
DateFrom: now,
|
|
DateTo: now,
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
require.Equal(t, "day", resp.GroupBy)
|
|
require.Equal(t, &outletID, resp.OutletID)
|
|
require.Equal(t, float64(100000), resp.Summary.TotalExpenses)
|
|
require.Len(t, resp.Data, 1)
|
|
require.Equal(t, int64(2), resp.Data[0].ExpenseCount)
|
|
require.Len(t, resp.CategoryData, 1)
|
|
require.Equal(t, coaID, resp.CategoryData[0].ChartOfAccountID)
|
|
require.Len(t, resp.ItemData, 1)
|
|
require.Equal(t, "Cleaning supplies", resp.ItemData[0].Item)
|
|
}
|