package validator import ( "testing" "apskel-pos-be/internal/constants" "apskel-pos-be/internal/contract" "github.com/google/uuid" "github.com/stretchr/testify/require" ) func validCreatePurchaseOrderRequest() *contract.CreatePurchaseOrderRequest { vendorID := uuid.New() ingredientID := uuid.New() quantity := 1.0 unitID := uuid.New() return &contract.CreatePurchaseOrderRequest{ VendorID: &vendorID, PONumber: "PO-001", TransactionDate: "2026-05-29", Items: []contract.CreatePurchaseOrderItemRequest{ { IngredientID: &ingredientID, PurchaseCategoryID: uuid.New(), Quantity: &quantity, UnitID: &unitID, Amount: 1000, }, }, } } func TestPurchaseOrderValidatorCreateAllowsMissingVendor(t *testing.T) { validator := NewPurchaseOrderValidator() req := validCreatePurchaseOrderRequest() req.VendorID = nil err, code := validator.ValidateCreatePurchaseOrderRequest(req) require.NoError(t, err) require.Empty(t, code) } func TestPurchaseOrderValidatorCreateRejectsEmptyVendor(t *testing.T) { validator := NewPurchaseOrderValidator() req := validCreatePurchaseOrderRequest() vendorID := uuid.Nil req.VendorID = &vendorID err, code := validator.ValidateCreatePurchaseOrderRequest(req) require.Error(t, err) require.Equal(t, constants.MalformedFieldErrorCode, code) require.Contains(t, err.Error(), "vendor_id cannot be empty") } func TestPurchaseOrderValidatorCreateAllowsMissingDueDate(t *testing.T) { validator := NewPurchaseOrderValidator() err, code := validator.ValidateCreatePurchaseOrderRequest(validCreatePurchaseOrderRequest()) require.NoError(t, err) require.Empty(t, code) } func TestPurchaseOrderValidatorCreateRejectsInvalidDueDate(t *testing.T) { validator := NewPurchaseOrderValidator() req := validCreatePurchaseOrderRequest() dueDate := "29-05-2026" req.DueDate = &dueDate err, code := validator.ValidateCreatePurchaseOrderRequest(req) require.Error(t, err) require.Equal(t, constants.MalformedFieldErrorCode, code) require.Contains(t, err.Error(), "due_date must be in YYYY-MM-DD format") } func TestPurchaseOrderValidatorCreateRejectsDueDateBeforeTransactionDate(t *testing.T) { validator := NewPurchaseOrderValidator() req := validCreatePurchaseOrderRequest() dueDate := "2026-05-28" req.DueDate = &dueDate err, code := validator.ValidateCreatePurchaseOrderRequest(req) require.Error(t, err) require.Equal(t, constants.MalformedFieldErrorCode, code) require.Contains(t, err.Error(), "due_date must be after transaction_date") } func TestPurchaseOrderValidatorCreateAllowsCentralTeam(t *testing.T) { validator := NewPurchaseOrderValidator() req := validCreatePurchaseOrderRequest() scope := constants.PurchaseTeamScopeCentral req.TeamScope = &scope err, code := validator.ValidateCreatePurchaseOrderRequest(req) require.NoError(t, err) require.Empty(t, code) } func TestPurchaseOrderValidatorCreateRejectsCentralTeamWithCategory(t *testing.T) { validator := NewPurchaseOrderValidator() req := validCreatePurchaseOrderRequest() scope := constants.PurchaseTeamScopeCentral categoryID := uuid.New() req.TeamScope = &scope req.TeamCategoryID = &categoryID err, code := validator.ValidateCreatePurchaseOrderRequest(req) require.Error(t, err) require.Equal(t, constants.MalformedFieldErrorCode, code) require.Contains(t, err.Error(), "team_category_id must be empty") } func TestPurchaseOrderValidatorCreateRejectsCategoryTeamWithoutCategory(t *testing.T) { validator := NewPurchaseOrderValidator() req := validCreatePurchaseOrderRequest() scope := constants.PurchaseTeamScopeCategory req.TeamScope = &scope err, code := validator.ValidateCreatePurchaseOrderRequest(req) require.Error(t, err) require.Equal(t, constants.MissingFieldErrorCode, code) require.Contains(t, err.Error(), "team_category_id is required") } func TestPurchaseOrderValidatorCreateRejectsCategoryWithoutScope(t *testing.T) { validator := NewPurchaseOrderValidator() req := validCreatePurchaseOrderRequest() categoryID := uuid.New() req.TeamCategoryID = &categoryID err, code := validator.ValidateCreatePurchaseOrderRequest(req) require.Error(t, err) require.Equal(t, constants.MissingFieldErrorCode, code) require.Contains(t, err.Error(), "team_scope is required") } func TestPurchaseOrderValidatorCreateRejectsUnknownTeamScope(t *testing.T) { validator := NewPurchaseOrderValidator() req := validCreatePurchaseOrderRequest() scope := "outlet" req.TeamScope = &scope err, code := validator.ValidateCreatePurchaseOrderRequest(req) require.Error(t, err) require.Equal(t, constants.MalformedFieldErrorCode, code) require.Contains(t, err.Error(), "team_scope must be one of") } // An update may clear the team with an empty scope; a create may not, because // leaving the field out already means "no team". func TestPurchaseOrderValidatorUpdateAllowsClearingTeam(t *testing.T) { validator := NewPurchaseOrderValidator() scope := "" err, code := validator.ValidateUpdatePurchaseOrderRequest(&contract.UpdatePurchaseOrderRequest{TeamScope: &scope}) require.NoError(t, err) require.Empty(t, code) } func TestPurchaseOrderValidatorCreateRejectsEmptyTeamScope(t *testing.T) { validator := NewPurchaseOrderValidator() req := validCreatePurchaseOrderRequest() scope := "" req.TeamScope = &scope err, code := validator.ValidateCreatePurchaseOrderRequest(req) require.Error(t, err) require.Equal(t, constants.MalformedFieldErrorCode, code) } func TestPurchaseOrderValidatorUpdateRejectsClearingTeamWithCategory(t *testing.T) { validator := NewPurchaseOrderValidator() scope := "" categoryID := uuid.New() err, code := validator.ValidateUpdatePurchaseOrderRequest(&contract.UpdatePurchaseOrderRequest{ TeamScope: &scope, TeamCategoryID: &categoryID, }) require.Error(t, err) require.Equal(t, constants.MalformedFieldErrorCode, code) } func TestPurchaseOrderValidatorListRejectsCentralScopeWithCategory(t *testing.T) { validator := NewPurchaseOrderValidator() categoryID := uuid.New() err, code := validator.ValidateListPurchaseOrdersRequest(&contract.ListPurchaseOrdersRequest{ Page: 1, Limit: 10, TeamScope: constants.PurchaseTeamScopeCentral, TeamCategoryID: &categoryID, }) require.Error(t, err) require.Equal(t, constants.MalformedFieldErrorCode, code) }