package service import ( "context" "testing" "time" "apskel-pos-be/internal/models" "github.com/google/uuid" "github.com/stretchr/testify/require" ) type analyticsProcessorStub struct{} func (analyticsProcessorStub) GetPaymentMethodAnalytics(context.Context, *models.PaymentMethodAnalyticsRequest) (*models.PaymentMethodAnalyticsResponse, error) { return nil, nil } func (analyticsProcessorStub) GetSalesAnalytics(context.Context, *models.SalesAnalyticsRequest) (*models.SalesAnalyticsResponse, error) { return nil, nil } func (analyticsProcessorStub) GetPurchasingAnalytics(context.Context, *models.PurchasingAnalyticsRequest) (*models.PurchasingAnalyticsResponse, error) { return &models.PurchasingAnalyticsResponse{}, nil } func (analyticsProcessorStub) GetProductAnalytics(context.Context, *models.ProductAnalyticsRequest) (*models.ProductAnalyticsResponse, error) { return nil, nil } func (analyticsProcessorStub) GetProductAnalyticsPerCategory(context.Context, *models.ProductAnalyticsPerCategoryRequest) (*models.ProductAnalyticsPerCategoryResponse, error) { return nil, nil } func (analyticsProcessorStub) GetDashboardAnalytics(context.Context, *models.DashboardAnalyticsRequest) (*models.DashboardAnalyticsResponse, error) { return nil, nil } func (analyticsProcessorStub) GetProfitLossAnalytics(context.Context, *models.ProfitLossAnalyticsRequest) (*models.ProfitLossAnalyticsResponse, error) { return nil, nil } func TestAnalyticsServiceGetPurchasingAnalyticsValidation(t *testing.T) { service := NewAnalyticsServiceImpl(analyticsProcessorStub{}) now := time.Date(2026, 5, 1, 0, 0, 0, 0, time.UTC) tests := []struct { name string req *models.PurchasingAnalyticsRequest wantErr string }{ { name: "missing organization", req: &models.PurchasingAnalyticsRequest{ DateFrom: now, DateTo: now, }, wantErr: "organization ID is required", }, { name: "missing date_from", req: &models.PurchasingAnalyticsRequest{ OrganizationID: uuid.New(), DateTo: now, }, wantErr: "date_from is required", }, { name: "missing date_to", req: &models.PurchasingAnalyticsRequest{ OrganizationID: uuid.New(), DateFrom: now, }, wantErr: "date_to is required", }, { name: "reversed dates", req: &models.PurchasingAnalyticsRequest{ OrganizationID: uuid.New(), DateFrom: now.AddDate(0, 0, 1), DateTo: now, }, wantErr: "date_from cannot be after date_to", }, { name: "invalid group_by", req: &models.PurchasingAnalyticsRequest{ OrganizationID: uuid.New(), DateFrom: now, DateTo: now, GroupBy: "quarter", }, wantErr: "invalid group_by value: quarter", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { resp, err := service.GetPurchasingAnalytics(context.Background(), tt.req) require.Nil(t, resp) require.Error(t, err) require.Contains(t, err.Error(), tt.wantErr) }) } } func TestAnalyticsServiceGetPurchasingAnalyticsAllowsEmptyGroupBy(t *testing.T) { service := NewAnalyticsServiceImpl(analyticsProcessorStub{}) now := time.Date(2026, 5, 1, 0, 0, 0, 0, time.UTC) resp, err := service.GetPurchasingAnalytics(context.Background(), &models.PurchasingAnalyticsRequest{ OrganizationID: uuid.New(), DateFrom: now, DateTo: now, }) require.NoError(t, err) require.NotNil(t, resp) } func TestAnalyticsServiceGetProfitLossAnalyticsValidation(t *testing.T) { service := NewAnalyticsServiceImpl(analyticsProcessorStub{}) now := time.Date(2026, 5, 1, 0, 0, 0, 0, time.UTC) tests := []struct { name string req *models.ProfitLossAnalyticsRequest wantErr string }{ { name: "missing date_from", req: &models.ProfitLossAnalyticsRequest{ OrganizationID: uuid.New(), DateTo: now, }, wantErr: "date_from is required", }, { name: "missing date_to", req: &models.ProfitLossAnalyticsRequest{ OrganizationID: uuid.New(), DateFrom: now, }, wantErr: "date_to is required", }, { name: "reversed dates", req: &models.ProfitLossAnalyticsRequest{ OrganizationID: uuid.New(), DateFrom: now.AddDate(0, 0, 1), DateTo: now, }, wantErr: "date_from cannot be after date_to", }, { name: "invalid group_by", req: &models.ProfitLossAnalyticsRequest{ OrganizationID: uuid.New(), DateFrom: now, DateTo: now, GroupBy: "quarter", }, wantErr: "invalid group_by value: quarter", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { resp, err := service.GetProfitLossAnalytics(context.Background(), tt.req) require.Nil(t, resp) require.Error(t, err) require.Contains(t, err.Error(), tt.wantErr) }) } } func TestAnalyticsServiceGetProfitLossAnalyticsAllowsEmptyGroupBy(t *testing.T) { service := NewAnalyticsServiceImpl(analyticsProcessorStub{}) now := time.Date(2026, 5, 1, 0, 0, 0, 0, time.UTC) resp, err := service.GetProfitLossAnalytics(context.Background(), &models.ProfitLossAnalyticsRequest{ OrganizationID: uuid.New(), DateFrom: now, DateTo: now, }) require.NoError(t, err) require.Nil(t, resp) }