feat(purchasae): added team with category parent and central

This commit is contained in:
efrilm
2026-08-11 21:00:39 +07:00
parent a230199ce0
commit 9ae5be2c33
18 changed files with 566 additions and 32 deletions
@@ -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