feat(purchasae): added team with category parent and central
This commit is contained in:
@@ -76,6 +76,10 @@ func (v *PurchaseOrderValidatorImpl) ValidateCreatePurchaseOrderRequest(req *con
|
||||
}
|
||||
}
|
||||
|
||||
if err, code := validatePurchaseTeamSelection(req.TeamScope, req.TeamCategoryID, false); err != nil {
|
||||
return err, code
|
||||
}
|
||||
|
||||
if len(req.Items) == 0 {
|
||||
return errors.New("at least one item is required"), constants.MissingFieldErrorCode
|
||||
}
|
||||
@@ -139,6 +143,10 @@ func (v *PurchaseOrderValidatorImpl) ValidateUpdatePurchaseOrderRequest(req *con
|
||||
}
|
||||
}
|
||||
|
||||
if err, code := validatePurchaseTeamSelection(req.TeamScope, req.TeamCategoryID, true); err != nil {
|
||||
return err, code
|
||||
}
|
||||
|
||||
// Validate items if provided
|
||||
if req.Items != nil {
|
||||
for i, item := range req.Items {
|
||||
@@ -151,6 +159,40 @@ func (v *PurchaseOrderValidatorImpl) ValidateUpdatePurchaseOrderRequest(req *con
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
// validatePurchaseTeamSelection keeps team_scope and team_category_id in step with
|
||||
// the database check constraint: a category team needs a category, Pusat must not
|
||||
// carry one. allowClear lets an update send an empty scope to drop the team.
|
||||
func validatePurchaseTeamSelection(scope *string, categoryID *uuid.UUID, allowClear bool) (error, string) {
|
||||
if scope == nil {
|
||||
if categoryID != nil {
|
||||
return errors.New("team_scope is required when team_category_id is provided"), constants.MissingFieldErrorCode
|
||||
}
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
switch strings.TrimSpace(*scope) {
|
||||
case "":
|
||||
if !allowClear {
|
||||
return errors.New("team_scope must be one of: category, central"), constants.MalformedFieldErrorCode
|
||||
}
|
||||
if categoryID != nil {
|
||||
return errors.New("team_category_id must be empty when clearing the team"), constants.MalformedFieldErrorCode
|
||||
}
|
||||
case constants.PurchaseTeamScopeCategory:
|
||||
if categoryID == nil || *categoryID == uuid.Nil {
|
||||
return errors.New("team_category_id is required when team_scope is category"), constants.MissingFieldErrorCode
|
||||
}
|
||||
case constants.PurchaseTeamScopeCentral:
|
||||
if categoryID != nil {
|
||||
return errors.New("team_category_id must be empty when team_scope is central"), constants.MalformedFieldErrorCode
|
||||
}
|
||||
default:
|
||||
return errors.New("team_scope must be one of: category, central"), constants.MalformedFieldErrorCode
|
||||
}
|
||||
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (v *PurchaseOrderValidatorImpl) ValidateListPurchaseOrdersRequest(req *contract.ListPurchaseOrdersRequest) (error, string) {
|
||||
if req == nil {
|
||||
return errors.New("request body is required"), constants.MissingFieldErrorCode
|
||||
@@ -171,6 +213,21 @@ func (v *PurchaseOrderValidatorImpl) ValidateListPurchaseOrdersRequest(req *cont
|
||||
}
|
||||
}
|
||||
|
||||
if req.TeamScope != "" {
|
||||
validScopes := []string{constants.PurchaseTeamScopeCategory, constants.PurchaseTeamScopeCentral}
|
||||
if !contains(validScopes, req.TeamScope) {
|
||||
return errors.New("team_scope must be one of: category, central"), constants.MalformedFieldErrorCode
|
||||
}
|
||||
|
||||
if req.TeamScope == constants.PurchaseTeamScopeCentral && req.TeamCategoryID != nil {
|
||||
return errors.New("team_category_id must be empty when team_scope is central"), constants.MalformedFieldErrorCode
|
||||
}
|
||||
}
|
||||
|
||||
if req.TeamCategoryID != nil && *req.TeamCategoryID == uuid.Nil {
|
||||
return errors.New("team_category_id cannot be empty"), constants.MalformedFieldErrorCode
|
||||
}
|
||||
|
||||
if req.StartDate != nil && req.EndDate != nil {
|
||||
if req.EndDate.Before(*req.StartDate) {
|
||||
return errors.New("end_date must be after start_date"), constants.MalformedFieldErrorCode
|
||||
|
||||
@@ -90,3 +90,122 @@ func TestPurchaseOrderValidatorCreateRejectsDueDateBeforeTransactionDate(t *test
|
||||
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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user