162 lines
5.4 KiB
Go
162 lines
5.4 KiB
Go
package services
|
|
|
|
import (
|
|
"FamilyHub/src/domain"
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type transactionServiceCreateMock struct {
|
|
createFn func(ctx context.Context, req domain.CreateTransactionRequest) (*domain.Transaction, error)
|
|
getByIDFn func(ctx context.Context, id int64) (*domain.Transaction, error)
|
|
}
|
|
|
|
func (m *transactionServiceCreateMock) Create(ctx context.Context, req domain.CreateTransactionRequest) (*domain.Transaction, error) {
|
|
if m.createFn != nil {
|
|
return m.createFn(ctx, req)
|
|
}
|
|
return nil, errors.New("mock is not configured")
|
|
}
|
|
|
|
func (m *transactionServiceCreateMock) GetByID(ctx context.Context, id int64) (*domain.Transaction, error) {
|
|
if m.getByIDFn != nil {
|
|
return m.getByIDFn(ctx, id)
|
|
}
|
|
return nil, errors.New("mock is not configured")
|
|
}
|
|
|
|
func (m *transactionServiceCreateMock) List(ctx context.Context, filter domain.TransactionListFilter) ([]*domain.Transaction, error) {
|
|
return nil, errors.New("not implemented")
|
|
}
|
|
|
|
func (m *transactionServiceCreateMock) Analytics(ctx context.Context, filter domain.TransactionAnalyticsFilter) (domain.TransactionAnalytics, error) {
|
|
return domain.TransactionAnalytics{}, errors.New("not implemented")
|
|
}
|
|
|
|
func (m *transactionServiceCreateMock) Update(ctx context.Context, id int64, req domain.UpdateTransactionRequest) (*domain.Transaction, error) {
|
|
return nil, errors.New("not implemented")
|
|
}
|
|
|
|
func (m *transactionServiceCreateMock) Delete(ctx context.Context, id int64) error {
|
|
return errors.New("not implemented")
|
|
}
|
|
|
|
type receiptServiceCreateMock struct {
|
|
addReceiptFn func(ctx context.Context, req domain.AddReceiptRequest) (*domain.Receipt, error)
|
|
}
|
|
|
|
func (m *receiptServiceCreateMock) AddReceipt(ctx context.Context, req domain.AddReceiptRequest) (*domain.Receipt, error) {
|
|
if m.addReceiptFn != nil {
|
|
return m.addReceiptFn(ctx, req)
|
|
}
|
|
return nil, errors.New("mock is not configured")
|
|
}
|
|
|
|
type ocrCreateMock struct {
|
|
recognizeFn func(ctx context.Context, image []byte) (string, error)
|
|
}
|
|
|
|
func (m *ocrCreateMock) Recognize(ctx context.Context, image []byte) (string, error) {
|
|
if m.recognizeFn != nil {
|
|
return m.recognizeFn(ctx, image)
|
|
}
|
|
return "", errors.New("mock is not configured")
|
|
}
|
|
|
|
func (m *ocrCreateMock) Close() error {
|
|
return nil
|
|
}
|
|
|
|
func TestTransactionCreationService_Create_Manual(t *testing.T) {
|
|
now := time.Date(2026, time.January, 21, 10, 11, 12, 0, time.UTC)
|
|
svc := NewTransactionCreationService(
|
|
&transactionServiceCreateMock{createFn: func(ctx context.Context, req domain.CreateTransactionRequest) (*domain.Transaction, error) {
|
|
assert.Equal(t, int64(1), req.FamilyID)
|
|
return &domain.Transaction{ID: 1, FamilyID: req.FamilyID, DateTime: now}, nil
|
|
}},
|
|
nil,
|
|
nil,
|
|
)
|
|
|
|
transaction, err := svc.Create(context.Background(), CreateTransactionInput{
|
|
Manual: &domain.CreateTransactionRequest{FamilyID: 1},
|
|
})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(1), transaction.ID)
|
|
}
|
|
|
|
func TestTransactionCreationService_Create_Receipt(t *testing.T) {
|
|
now := time.Date(2026, time.January, 21, 10, 11, 12, 0, time.UTC)
|
|
svc := NewTransactionCreationService(
|
|
&transactionServiceCreateMock{getByIDFn: func(ctx context.Context, id int64) (*domain.Transaction, error) {
|
|
assert.Equal(t, int64(15), id)
|
|
return &domain.Transaction{ID: id, DateTime: now}, nil
|
|
}},
|
|
&receiptServiceCreateMock{addReceiptFn: func(ctx context.Context, req domain.AddReceiptRequest) (*domain.Receipt, error) {
|
|
assert.Equal(t, "123", req.Number)
|
|
return &domain.Receipt{TransactionID: ptrInt64Service(15)}, nil
|
|
}},
|
|
nil,
|
|
)
|
|
|
|
transaction, err := svc.Create(context.Background(), CreateTransactionInput{
|
|
Receipt: &domain.AddReceiptRequest{Number: "123"},
|
|
})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(15), transaction.ID)
|
|
}
|
|
|
|
func TestTransactionCreationService_Create_Photo(t *testing.T) {
|
|
now := time.Date(2026, time.January, 21, 10, 11, 12, 0, time.UTC)
|
|
svc := NewTransactionCreationService(
|
|
&transactionServiceCreateMock{getByIDFn: func(ctx context.Context, id int64) (*domain.Transaction, error) {
|
|
assert.Equal(t, int64(17), id)
|
|
return &domain.Transaction{ID: id, DateTime: now}, nil
|
|
}},
|
|
&receiptServiceCreateMock{addReceiptFn: func(ctx context.Context, req domain.AddReceiptRequest) (*domain.Receipt, error) {
|
|
assert.Equal(t, strings.Repeat("1", 24), req.Number)
|
|
assert.Equal(t, "21.01.2026", req.Date)
|
|
return &domain.Receipt{TransactionID: ptrInt64Service(17)}, nil
|
|
}},
|
|
&ocrCreateMock{recognizeFn: func(ctx context.Context, image []byte) (string, error) {
|
|
assert.Equal(t, []byte("image"), image)
|
|
return "21.01.2026 " + strings.Repeat("1", 24), nil
|
|
}},
|
|
)
|
|
|
|
familyID := int64(1)
|
|
createdBy := int64(2)
|
|
transaction, err := svc.Create(context.Background(), CreateTransactionInput{
|
|
Photo: &CreateTransactionPhotoInput{
|
|
Image: []byte("image"),
|
|
FamilyID: &familyID,
|
|
CreatedBy: &createdBy,
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(17), transaction.ID)
|
|
}
|
|
|
|
func TestTransactionCreationService_Create_PhotoRequiresActors(t *testing.T) {
|
|
svc := NewTransactionCreationService(
|
|
&transactionServiceCreateMock{},
|
|
&receiptServiceCreateMock{},
|
|
&ocrCreateMock{},
|
|
)
|
|
|
|
_, err := svc.Create(context.Background(), CreateTransactionInput{
|
|
Photo: &CreateTransactionPhotoInput{Image: []byte("image")},
|
|
})
|
|
require.ErrorIs(t, err, ErrReceiptTransactionActorsMissing)
|
|
}
|
|
|
|
func ptrInt64Service(v int64) *int64 {
|
|
return &v
|
|
}
|