feat: update client-approval settings
This commit is contained in:
parent
adb0184035
commit
9ba425540e
|
|
@ -1,11 +1,12 @@
|
||||||
package approval_workflows
|
package approval_workflows
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gofiber/fiber/v2"
|
|
||||||
"go.uber.org/fx"
|
|
||||||
"netidhub-saas-be/app/module/approval_workflows/controller"
|
"netidhub-saas-be/app/module/approval_workflows/controller"
|
||||||
"netidhub-saas-be/app/module/approval_workflows/repository"
|
"netidhub-saas-be/app/module/approval_workflows/repository"
|
||||||
"netidhub-saas-be/app/module/approval_workflows/service"
|
"netidhub-saas-be/app/module/approval_workflows/service"
|
||||||
|
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/fx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ApprovalWorkflowsRouter struct of ApprovalWorkflowsRouter
|
// ApprovalWorkflowsRouter struct of ApprovalWorkflowsRouter
|
||||||
|
|
@ -50,6 +51,7 @@ func (_i *ApprovalWorkflowsRouter) RegisterApprovalWorkflowsRoutes() {
|
||||||
router.Get("/:id/with-steps", approvalWorkflowsController.GetWithSteps)
|
router.Get("/:id/with-steps", approvalWorkflowsController.GetWithSteps)
|
||||||
router.Post("/", approvalWorkflowsController.Save)
|
router.Post("/", approvalWorkflowsController.Save)
|
||||||
router.Post("/with-steps", approvalWorkflowsController.SaveWithSteps)
|
router.Post("/with-steps", approvalWorkflowsController.SaveWithSteps)
|
||||||
|
router.Post("/with-client-settings", approvalWorkflowsController.SaveWithClientSettings)
|
||||||
router.Put("/:id", approvalWorkflowsController.Update)
|
router.Put("/:id", approvalWorkflowsController.Update)
|
||||||
router.Put("/:id/with-steps", approvalWorkflowsController.UpdateWithSteps)
|
router.Put("/:id/with-steps", approvalWorkflowsController.UpdateWithSteps)
|
||||||
router.Put("/:id/set-default", approvalWorkflowsController.SetDefault)
|
router.Put("/:id/set-default", approvalWorkflowsController.SetDefault)
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ type ApprovalWorkflowsController interface {
|
||||||
GetWithSteps(c *fiber.Ctx) error
|
GetWithSteps(c *fiber.Ctx) error
|
||||||
SaveWithSteps(c *fiber.Ctx) error
|
SaveWithSteps(c *fiber.Ctx) error
|
||||||
UpdateWithSteps(c *fiber.Ctx) error
|
UpdateWithSteps(c *fiber.Ctx) error
|
||||||
|
SaveWithClientSettings(c *fiber.Ctx) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewApprovalWorkflowsController(approvalWorkflowsService service.ApprovalWorkflowsService, log zerolog.Logger) ApprovalWorkflowsController {
|
func NewApprovalWorkflowsController(approvalWorkflowsService service.ApprovalWorkflowsService, log zerolog.Logger) ApprovalWorkflowsController {
|
||||||
|
|
@ -479,3 +480,44 @@ func (_i *approvalWorkflowsController) UpdateWithSteps(c *fiber.Ctx) error {
|
||||||
Messages: utilRes.Messages{"ApprovalWorkflows with steps successfully updated"},
|
Messages: utilRes.Messages{"ApprovalWorkflows with steps successfully updated"},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SaveWithClientSettings ApprovalWorkflows
|
||||||
|
// @Summary Create comprehensive ApprovalWorkflows with client settings
|
||||||
|
// @Description API for creating ApprovalWorkflows with workflow steps and client approval settings in a single call
|
||||||
|
// @Tags ApprovalWorkflows
|
||||||
|
// @Security Bearer
|
||||||
|
// @Param Authorization header string true "Insert the Authorization"
|
||||||
|
// @Param req body request.CreateApprovalWorkflowWithClientSettingsRequest true "Comprehensive approval workflow data"
|
||||||
|
// @Success 201 {object} response.Response
|
||||||
|
// @Failure 400 {object} response.BadRequestError
|
||||||
|
// @Failure 401 {object} response.UnauthorizedError
|
||||||
|
// @Failure 500 {object} response.InternalServerError
|
||||||
|
// @Router /approval-workflows/with-client-settings [post]
|
||||||
|
func (_i *approvalWorkflowsController) SaveWithClientSettings(c *fiber.Ctx) error {
|
||||||
|
req := new(request.CreateApprovalWorkflowWithClientSettingsRequest)
|
||||||
|
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get authToken from context
|
||||||
|
authToken := c.Get("Authorization")
|
||||||
|
|
||||||
|
// Create comprehensive workflow with client settings
|
||||||
|
workflowData, clientSettingsData, err := _i.approvalWorkflowsService.CreateWorkflowWithClientSettings(authToken, *req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine workflow, steps, and client settings data
|
||||||
|
responseData := map[string]interface{}{
|
||||||
|
"workflow": workflowData,
|
||||||
|
"clientSettings": clientSettingsData,
|
||||||
|
"message": "Comprehensive approval workflow with client settings created successfully",
|
||||||
|
}
|
||||||
|
|
||||||
|
return utilRes.Resp(c, utilRes.Response{
|
||||||
|
Success: true,
|
||||||
|
Messages: utilRes.Messages{"Comprehensive approval workflow with client settings successfully created"},
|
||||||
|
Data: responseData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -186,6 +186,86 @@ type ApprovalWorkflowsQueryRequestContext struct {
|
||||||
IsDefault string `json:"isDefault"`
|
IsDefault string `json:"isDefault"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateApprovalWorkflowWithClientSettingsRequest - Comprehensive request for creating approval workflow with client settings
|
||||||
|
type CreateApprovalWorkflowWithClientSettingsRequest struct {
|
||||||
|
// Workflow details
|
||||||
|
Name string `json:"name" validate:"required"`
|
||||||
|
Description string `json:"description" validate:"required"`
|
||||||
|
IsActive *bool `json:"isActive"`
|
||||||
|
IsDefault *bool `json:"isDefault"`
|
||||||
|
RequiresApproval *bool `json:"requiresApproval"`
|
||||||
|
AutoPublish *bool `json:"autoPublish"`
|
||||||
|
Steps []ApprovalWorkflowStepRequest `json:"steps" validate:"required,min=1"`
|
||||||
|
|
||||||
|
// Client approval settings
|
||||||
|
ClientApprovalSettings ClientApprovalSettingsRequest `json:"clientApprovalSettings" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ClientApprovalSettingsRequest struct {
|
||||||
|
RequiresApproval *bool `json:"requiresApproval"`
|
||||||
|
AutoPublishArticles *bool `json:"autoPublishArticles"`
|
||||||
|
ApprovalExemptUsers []uint `json:"approvalExemptUsers"`
|
||||||
|
ApprovalExemptRoles []uint `json:"approvalExemptRoles"`
|
||||||
|
ApprovalExemptCategories []uint `json:"approvalExemptCategories"`
|
||||||
|
RequireApprovalFor []string `json:"requireApprovalFor"`
|
||||||
|
SkipApprovalFor []string `json:"skipApprovalFor"`
|
||||||
|
IsActive *bool `json:"isActive"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (req CreateApprovalWorkflowWithClientSettingsRequest) ToWorkflowEntity() *entity.ApprovalWorkflows {
|
||||||
|
return &entity.ApprovalWorkflows{
|
||||||
|
Name: req.Name,
|
||||||
|
Description: &req.Description,
|
||||||
|
IsActive: req.IsActive,
|
||||||
|
IsDefault: req.IsDefault,
|
||||||
|
RequiresApproval: req.RequiresApproval,
|
||||||
|
AutoPublish: req.AutoPublish,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (req CreateApprovalWorkflowWithClientSettingsRequest) ToStepsEntity() []*entity.ApprovalWorkflowSteps {
|
||||||
|
steps := make([]*entity.ApprovalWorkflowSteps, len(req.Steps))
|
||||||
|
for i, stepReq := range req.Steps {
|
||||||
|
steps[i] = &entity.ApprovalWorkflowSteps{
|
||||||
|
StepOrder: stepReq.StepOrder,
|
||||||
|
StepName: stepReq.StepName,
|
||||||
|
RequiredUserLevelId: stepReq.RequiredUserLevelId,
|
||||||
|
CanSkip: stepReq.CanSkip,
|
||||||
|
AutoApproveAfterHours: stepReq.AutoApproveAfterHours,
|
||||||
|
IsActive: stepReq.IsActive,
|
||||||
|
|
||||||
|
// Multi-branch support fields
|
||||||
|
ParentStepId: stepReq.ParentStepId,
|
||||||
|
ConditionType: stepReq.ConditionType,
|
||||||
|
ConditionValue: stepReq.ConditionValue,
|
||||||
|
IsParallel: stepReq.IsParallel,
|
||||||
|
BranchName: stepReq.BranchName,
|
||||||
|
BranchOrder: stepReq.BranchOrder,
|
||||||
|
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return steps
|
||||||
|
}
|
||||||
|
|
||||||
|
func (req CreateApprovalWorkflowWithClientSettingsRequest) ToClientApprovalSettingsEntity() *entity.ClientApprovalSettings {
|
||||||
|
return &entity.ClientApprovalSettings{
|
||||||
|
RequiresApproval: req.ClientApprovalSettings.RequiresApproval,
|
||||||
|
AutoPublishArticles: req.ClientApprovalSettings.AutoPublishArticles,
|
||||||
|
ApprovalExemptUsers: req.ClientApprovalSettings.ApprovalExemptUsers,
|
||||||
|
ApprovalExemptRoles: req.ClientApprovalSettings.ApprovalExemptRoles,
|
||||||
|
ApprovalExemptCategories: req.ClientApprovalSettings.ApprovalExemptCategories,
|
||||||
|
RequireApprovalFor: req.ClientApprovalSettings.RequireApprovalFor,
|
||||||
|
SkipApprovalFor: req.ClientApprovalSettings.SkipApprovalFor,
|
||||||
|
IsActive: req.ClientApprovalSettings.IsActive,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (req ApprovalWorkflowsQueryRequestContext) ToParamRequest() ApprovalWorkflowsQueryRequest {
|
func (req ApprovalWorkflowsQueryRequestContext) ToParamRequest() ApprovalWorkflowsQueryRequest {
|
||||||
var name *string
|
var name *string
|
||||||
var description *string
|
var description *string
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
stepRepo "netidhub-saas-be/app/module/approval_workflow_steps/repository"
|
stepRepo "netidhub-saas-be/app/module/approval_workflow_steps/repository"
|
||||||
"netidhub-saas-be/app/module/approval_workflows/repository"
|
"netidhub-saas-be/app/module/approval_workflows/repository"
|
||||||
"netidhub-saas-be/app/module/approval_workflows/request"
|
"netidhub-saas-be/app/module/approval_workflows/request"
|
||||||
|
clientApprovalSettingsRepo "netidhub-saas-be/app/module/client_approval_settings/repository"
|
||||||
usersRepo "netidhub-saas-be/app/module/users/repository"
|
usersRepo "netidhub-saas-be/app/module/users/repository"
|
||||||
"netidhub-saas-be/utils/paginator"
|
"netidhub-saas-be/utils/paginator"
|
||||||
utilSvc "netidhub-saas-be/utils/service"
|
utilSvc "netidhub-saas-be/utils/service"
|
||||||
|
|
@ -19,6 +20,7 @@ import (
|
||||||
type approvalWorkflowsService struct {
|
type approvalWorkflowsService struct {
|
||||||
ApprovalWorkflowsRepository repository.ApprovalWorkflowsRepository
|
ApprovalWorkflowsRepository repository.ApprovalWorkflowsRepository
|
||||||
ApprovalWorkflowStepsRepository stepRepo.ApprovalWorkflowStepsRepository
|
ApprovalWorkflowStepsRepository stepRepo.ApprovalWorkflowStepsRepository
|
||||||
|
ClientApprovalSettingsRepository clientApprovalSettingsRepo.ClientApprovalSettingsRepository
|
||||||
UsersRepository usersRepo.UsersRepository
|
UsersRepository usersRepo.UsersRepository
|
||||||
Log zerolog.Logger
|
Log zerolog.Logger
|
||||||
}
|
}
|
||||||
|
|
@ -46,17 +48,22 @@ type ApprovalWorkflowsService interface {
|
||||||
// Validation
|
// Validation
|
||||||
ValidateWorkflow(authToken string, workflow *entity.ApprovalWorkflows, steps []*entity.ApprovalWorkflowSteps) (isValid bool, errors []string, err error)
|
ValidateWorkflow(authToken string, workflow *entity.ApprovalWorkflows, steps []*entity.ApprovalWorkflowSteps) (isValid bool, errors []string, err error)
|
||||||
CanDeleteWorkflow(authToken string, id uint) (canDelete bool, reason string, err error)
|
CanDeleteWorkflow(authToken string, id uint) (canDelete bool, reason string, err error)
|
||||||
|
|
||||||
|
// Comprehensive workflow creation with client settings
|
||||||
|
CreateWorkflowWithClientSettings(authToken string, req request.CreateApprovalWorkflowWithClientSettingsRequest) (workflow *entity.ApprovalWorkflows, clientSettings *entity.ClientApprovalSettings, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewApprovalWorkflowsService(
|
func NewApprovalWorkflowsService(
|
||||||
approvalWorkflowsRepository repository.ApprovalWorkflowsRepository,
|
approvalWorkflowsRepository repository.ApprovalWorkflowsRepository,
|
||||||
approvalWorkflowStepsRepository stepRepo.ApprovalWorkflowStepsRepository,
|
approvalWorkflowStepsRepository stepRepo.ApprovalWorkflowStepsRepository,
|
||||||
|
clientApprovalSettingsRepository clientApprovalSettingsRepo.ClientApprovalSettingsRepository,
|
||||||
usersRepository usersRepo.UsersRepository,
|
usersRepository usersRepo.UsersRepository,
|
||||||
log zerolog.Logger,
|
log zerolog.Logger,
|
||||||
) ApprovalWorkflowsService {
|
) ApprovalWorkflowsService {
|
||||||
return &approvalWorkflowsService{
|
return &approvalWorkflowsService{
|
||||||
ApprovalWorkflowsRepository: approvalWorkflowsRepository,
|
ApprovalWorkflowsRepository: approvalWorkflowsRepository,
|
||||||
ApprovalWorkflowStepsRepository: approvalWorkflowStepsRepository,
|
ApprovalWorkflowStepsRepository: approvalWorkflowStepsRepository,
|
||||||
|
ClientApprovalSettingsRepository: clientApprovalSettingsRepository,
|
||||||
UsersRepository: usersRepository,
|
UsersRepository: usersRepository,
|
||||||
Log: log,
|
Log: log,
|
||||||
}
|
}
|
||||||
|
|
@ -579,3 +586,130 @@ func (_i *approvalWorkflowsService) CanDeleteWorkflow(authToken string, id uint)
|
||||||
|
|
||||||
return true, "", nil
|
return true, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateWorkflowWithClientSettings creates a comprehensive approval workflow with client settings in a single transaction
|
||||||
|
func (_i *approvalWorkflowsService) CreateWorkflowWithClientSettings(authToken string, req request.CreateApprovalWorkflowWithClientSettingsRequest) (workflow *entity.ApprovalWorkflows, clientSettings *entity.ClientApprovalSettings, err error) {
|
||||||
|
// Extract clientId from authToken
|
||||||
|
var clientId *uuid.UUID
|
||||||
|
if authToken != "" {
|
||||||
|
user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
|
||||||
|
if user != nil && user.ClientId != nil {
|
||||||
|
clientId = user.ClientId
|
||||||
|
_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if clientId == nil {
|
||||||
|
return nil, nil, errors.New("clientId not found in auth token")
|
||||||
|
}
|
||||||
|
|
||||||
|
_i.Log.Info().
|
||||||
|
Str("workflowName", req.Name).
|
||||||
|
Interface("clientId", clientId).
|
||||||
|
Msg("Creating comprehensive approval workflow with client settings")
|
||||||
|
|
||||||
|
// Convert request to entities
|
||||||
|
workflowEntity := req.ToWorkflowEntity()
|
||||||
|
stepsEntity := req.ToStepsEntity()
|
||||||
|
clientSettingsEntity := req.ToClientApprovalSettingsEntity()
|
||||||
|
|
||||||
|
// Set client ID for all entities
|
||||||
|
workflowEntity.ClientId = clientId
|
||||||
|
clientSettingsEntity.ClientId = *clientId
|
||||||
|
|
||||||
|
// Validate workflow and steps
|
||||||
|
isValid, validationErrors, err := _i.ValidateWorkflow(authToken, workflowEntity, stepsEntity)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isValid {
|
||||||
|
return nil, nil, errors.New(fmt.Sprintf("Validation failed: %v", validationErrors))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if client approval settings already exist
|
||||||
|
existingSettings, err := _i.ClientApprovalSettingsRepository.FindByClientId(*clientId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("failed to check existing client approval settings: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if existingSettings != nil {
|
||||||
|
return nil, nil, errors.New("client approval settings already exist for this client")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create workflow
|
||||||
|
workflow, err = _i.ApprovalWorkflowsRepository.Create(clientId, workflowEntity)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("failed to create workflow: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_i.Log.Info().
|
||||||
|
Uint("workflowId", workflow.ID).
|
||||||
|
Str("workflowName", workflow.Name).
|
||||||
|
Msg("Workflow created successfully")
|
||||||
|
|
||||||
|
// Create workflow steps
|
||||||
|
for i, step := range stepsEntity {
|
||||||
|
step.WorkflowId = workflow.ID
|
||||||
|
step.StepOrder = i + 1
|
||||||
|
step.ClientId = clientId
|
||||||
|
_, err = _i.ApprovalWorkflowStepsRepository.Create(clientId, step)
|
||||||
|
if err != nil {
|
||||||
|
// Rollback workflow creation if step creation fails
|
||||||
|
_i.Log.Error().Err(err).Msg("Failed to create workflow step, rolling back workflow")
|
||||||
|
_i.ApprovalWorkflowsRepository.Delete(clientId, workflow.ID)
|
||||||
|
return nil, nil, fmt.Errorf("failed to create workflow step %d: %w", i+1, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_i.Log.Info().
|
||||||
|
Uint("workflowId", workflow.ID).
|
||||||
|
Int("stepsCount", len(stepsEntity)).
|
||||||
|
Msg("All workflow steps created successfully")
|
||||||
|
|
||||||
|
// Set the workflow as default in client settings if specified
|
||||||
|
if req.IsDefault != nil && *req.IsDefault {
|
||||||
|
clientSettingsEntity.DefaultWorkflowId = &workflow.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create client approval settings
|
||||||
|
clientSettings, err = _i.ClientApprovalSettingsRepository.Create(clientId, clientSettingsEntity)
|
||||||
|
if err != nil {
|
||||||
|
// Rollback workflow and steps creation if client settings creation fails
|
||||||
|
_i.Log.Error().Err(err).Msg("Failed to create client approval settings, rolling back workflow and steps")
|
||||||
|
|
||||||
|
// Delete workflow steps
|
||||||
|
for _, step := range stepsEntity {
|
||||||
|
_i.ApprovalWorkflowStepsRepository.Delete(clientId, step.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete workflow
|
||||||
|
_i.ApprovalWorkflowsRepository.Delete(clientId, workflow.ID)
|
||||||
|
|
||||||
|
return nil, nil, fmt.Errorf("failed to create client approval settings: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_i.Log.Info().
|
||||||
|
Uint("workflowId", workflow.ID).
|
||||||
|
Interface("clientId", clientId).
|
||||||
|
Msg("Client approval settings created successfully")
|
||||||
|
|
||||||
|
// If this workflow is set as default, update the default workflow setting
|
||||||
|
if req.IsDefault != nil && *req.IsDefault {
|
||||||
|
err = _i.ApprovalWorkflowsRepository.SetDefault(clientId, workflow.ID)
|
||||||
|
if err != nil {
|
||||||
|
_i.Log.Warn().Err(err).Msg("Failed to set workflow as default, but workflow and settings were created successfully")
|
||||||
|
} else {
|
||||||
|
_i.Log.Info().
|
||||||
|
Uint("workflowId", workflow.ID).
|
||||||
|
Msg("Workflow set as default successfully")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_i.Log.Info().
|
||||||
|
Uint("workflowId", workflow.ID).
|
||||||
|
Interface("clientId", clientId).
|
||||||
|
Msg("Comprehensive approval workflow with client settings created successfully")
|
||||||
|
|
||||||
|
return workflow, clientSettings, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ func UsersResponseMapper(usersReq *users.Users, userLevelsRepo userLevelsReposit
|
||||||
IsActive: usersReq.IsActive,
|
IsActive: usersReq.IsActive,
|
||||||
CreatedAt: usersReq.CreatedAt,
|
CreatedAt: usersReq.CreatedAt,
|
||||||
UpdatedAt: usersReq.UpdatedAt,
|
UpdatedAt: usersReq.UpdatedAt,
|
||||||
|
// ApprovalWorkflowInfo will be set by the service layer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return usersRes
|
return usersRes
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,18 @@ type UsersResponse struct {
|
||||||
IsActive *bool `json:"isActive"`
|
IsActive *bool `json:"isActive"`
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
UpdatedAt time.Time `json:"updatedAt"`
|
UpdatedAt time.Time `json:"updatedAt"`
|
||||||
|
|
||||||
|
// Approval Workflow Info
|
||||||
|
ApprovalWorkflowInfo *ApprovalWorkflowInfo `json:"approvalWorkflowInfo,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ApprovalWorkflowInfo struct {
|
||||||
|
HasWorkflowSetup bool `json:"hasWorkflowSetup"`
|
||||||
|
DefaultWorkflowId *uint `json:"defaultWorkflowId,omitempty"`
|
||||||
|
DefaultWorkflowName *string `json:"defaultWorkflowName,omitempty"`
|
||||||
|
RequiresApproval *bool `json:"requiresApproval,omitempty"`
|
||||||
|
AutoPublishArticles *bool `json:"autoPublishArticles,omitempty"`
|
||||||
|
IsApprovalActive *bool `json:"isApprovalActive,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ParetoLoginResponse struct {
|
type ParetoLoginResponse struct {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"netidhub-saas-be/app/database/entity"
|
"netidhub-saas-be/app/database/entity"
|
||||||
"netidhub-saas-be/app/database/entity/users"
|
"netidhub-saas-be/app/database/entity/users"
|
||||||
|
approvalWorkflowsRepo "netidhub-saas-be/app/module/approval_workflows/repository"
|
||||||
|
clientApprovalSettingsRepo "netidhub-saas-be/app/module/client_approval_settings/repository"
|
||||||
userLevelsRepository "netidhub-saas-be/app/module/user_levels/repository"
|
userLevelsRepository "netidhub-saas-be/app/module/user_levels/repository"
|
||||||
"netidhub-saas-be/app/module/users/mapper"
|
"netidhub-saas-be/app/module/users/mapper"
|
||||||
"netidhub-saas-be/app/module/users/repository"
|
"netidhub-saas-be/app/module/users/repository"
|
||||||
|
|
@ -27,6 +29,8 @@ import (
|
||||||
type usersService struct {
|
type usersService struct {
|
||||||
Repo repository.UsersRepository
|
Repo repository.UsersRepository
|
||||||
UserLevelsRepo userLevelsRepository.UserLevelsRepository
|
UserLevelsRepo userLevelsRepository.UserLevelsRepository
|
||||||
|
ApprovalWorkflowsRepo approvalWorkflowsRepo.ApprovalWorkflowsRepository
|
||||||
|
ClientApprovalSettingsRepo clientApprovalSettingsRepo.ClientApprovalSettingsRepository
|
||||||
Log zerolog.Logger
|
Log zerolog.Logger
|
||||||
Keycloak *config.KeycloakConfig
|
Keycloak *config.KeycloakConfig
|
||||||
Smtp *config.SmtpConfig
|
Smtp *config.SmtpConfig
|
||||||
|
|
@ -55,11 +59,21 @@ type UsersService interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUsersService init UsersService
|
// NewUsersService init UsersService
|
||||||
func NewUsersService(repo repository.UsersRepository, userLevelsRepo userLevelsRepository.UserLevelsRepository, log zerolog.Logger, keycloak *config.KeycloakConfig, smtp *config.SmtpConfig) UsersService {
|
func NewUsersService(
|
||||||
|
repo repository.UsersRepository,
|
||||||
|
userLevelsRepo userLevelsRepository.UserLevelsRepository,
|
||||||
|
approvalWorkflowsRepo approvalWorkflowsRepo.ApprovalWorkflowsRepository,
|
||||||
|
clientApprovalSettingsRepo clientApprovalSettingsRepo.ClientApprovalSettingsRepository,
|
||||||
|
log zerolog.Logger,
|
||||||
|
keycloak *config.KeycloakConfig,
|
||||||
|
smtp *config.SmtpConfig,
|
||||||
|
) UsersService {
|
||||||
|
|
||||||
return &usersService{
|
return &usersService{
|
||||||
Repo: repo,
|
Repo: repo,
|
||||||
UserLevelsRepo: userLevelsRepo,
|
UserLevelsRepo: userLevelsRepo,
|
||||||
|
ApprovalWorkflowsRepo: approvalWorkflowsRepo,
|
||||||
|
ClientApprovalSettingsRepo: clientApprovalSettingsRepo,
|
||||||
Log: log,
|
Log: log,
|
||||||
Keycloak: keycloak,
|
Keycloak: keycloak,
|
||||||
Smtp: smtp,
|
Smtp: smtp,
|
||||||
|
|
@ -140,8 +154,63 @@ func (_i *usersService) ShowUserInfo(authToken string) (users *response.UsersRes
|
||||||
}
|
}
|
||||||
|
|
||||||
userInfo := utilSvc.GetUserInfo(_i.Log, _i.Repo, authToken)
|
userInfo := utilSvc.GetUserInfo(_i.Log, _i.Repo, authToken)
|
||||||
|
if userInfo == nil {
|
||||||
|
return nil, fmt.Errorf("user not found")
|
||||||
|
}
|
||||||
|
|
||||||
return mapper.UsersResponseMapper(userInfo, _i.UserLevelsRepo, clientId), nil
|
// Get approval workflow info
|
||||||
|
approvalWorkflowInfo, err := _i.getApprovalWorkflowInfo(clientId)
|
||||||
|
if err != nil {
|
||||||
|
_i.Log.Warn().Err(err).Msg("Failed to get approval workflow info")
|
||||||
|
// Don't return error, just log warning and continue without workflow info
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map user response with approval workflow info
|
||||||
|
usersRes := mapper.UsersResponseMapper(userInfo, _i.UserLevelsRepo, clientId)
|
||||||
|
if usersRes != nil && approvalWorkflowInfo != nil {
|
||||||
|
usersRes.ApprovalWorkflowInfo = approvalWorkflowInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
return usersRes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getApprovalWorkflowInfo retrieves approval workflow information for the client
|
||||||
|
func (_i *usersService) getApprovalWorkflowInfo(clientId *uuid.UUID) (*response.ApprovalWorkflowInfo, error) {
|
||||||
|
if clientId == nil {
|
||||||
|
return &response.ApprovalWorkflowInfo{
|
||||||
|
HasWorkflowSetup: false,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if client has approval settings
|
||||||
|
clientSettings, err := _i.ClientApprovalSettingsRepo.FindByClientId(*clientId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get client approval settings: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
workflowInfo := &response.ApprovalWorkflowInfo{
|
||||||
|
HasWorkflowSetup: clientSettings != nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
if clientSettings != nil {
|
||||||
|
workflowInfo.RequiresApproval = clientSettings.RequiresApproval
|
||||||
|
workflowInfo.AutoPublishArticles = clientSettings.AutoPublishArticles
|
||||||
|
workflowInfo.IsApprovalActive = clientSettings.IsActive
|
||||||
|
|
||||||
|
// Get default workflow info if exists
|
||||||
|
if clientSettings.DefaultWorkflowId != nil {
|
||||||
|
workflowInfo.DefaultWorkflowId = clientSettings.DefaultWorkflowId
|
||||||
|
|
||||||
|
defaultWorkflow, err := _i.ApprovalWorkflowsRepo.FindOne(clientId, *clientSettings.DefaultWorkflowId)
|
||||||
|
if err != nil {
|
||||||
|
_i.Log.Warn().Err(err).Msg("Failed to get default workflow details")
|
||||||
|
} else if defaultWorkflow != nil {
|
||||||
|
workflowInfo.DefaultWorkflowName = &defaultWorkflow.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return workflowInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *usersService) Save(authToken string, req request.UsersCreateRequest) (userReturn *users.Users, err error) {
|
func (_i *usersService) Save(authToken string, req request.UsersCreateRequest) (userReturn *users.Users, err error) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,322 @@
|
||||||
|
# Comprehensive Approval Workflow API
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
This document describes the new comprehensive API endpoint that creates approval workflows along with all their dependencies (client approval settings) in a single API call.
|
||||||
|
|
||||||
|
## Endpoint Details
|
||||||
|
|
||||||
|
### POST `/approval-workflows/with-client-settings`
|
||||||
|
|
||||||
|
**Description**: Creates a comprehensive approval workflow with workflow steps and client approval settings in a single transaction.
|
||||||
|
|
||||||
|
**Authentication**: Bearer token required
|
||||||
|
|
||||||
|
**Request Body**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "Standard Article Approval",
|
||||||
|
"description": "Standard approval workflow for articles",
|
||||||
|
"isActive": true,
|
||||||
|
"isDefault": true,
|
||||||
|
"requiresApproval": true,
|
||||||
|
"autoPublish": false,
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"stepOrder": 1,
|
||||||
|
"stepName": "Editor Review",
|
||||||
|
"requiredUserLevelId": 2,
|
||||||
|
"canSkip": false,
|
||||||
|
"autoApproveAfterHours": null,
|
||||||
|
"isActive": true,
|
||||||
|
"parentStepId": null,
|
||||||
|
"conditionType": "always",
|
||||||
|
"conditionValue": null,
|
||||||
|
"isParallel": false,
|
||||||
|
"branchName": null,
|
||||||
|
"branchOrder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stepOrder": 2,
|
||||||
|
"stepName": "Manager Approval",
|
||||||
|
"requiredUserLevelId": 3,
|
||||||
|
"canSkip": false,
|
||||||
|
"autoApproveAfterHours": 24,
|
||||||
|
"isActive": true,
|
||||||
|
"parentStepId": null,
|
||||||
|
"conditionType": "always",
|
||||||
|
"conditionValue": null,
|
||||||
|
"isParallel": false,
|
||||||
|
"branchName": null,
|
||||||
|
"branchOrder": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"clientApprovalSettings": {
|
||||||
|
"requiresApproval": true,
|
||||||
|
"autoPublishArticles": false,
|
||||||
|
"approvalExemptUsers": [],
|
||||||
|
"approvalExemptRoles": [],
|
||||||
|
"approvalExemptCategories": [],
|
||||||
|
"requireApprovalFor": ["article", "news"],
|
||||||
|
"skipApprovalFor": ["announcement"],
|
||||||
|
"isActive": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"messages": ["Comprehensive approval workflow with client settings successfully created"],
|
||||||
|
"data": {
|
||||||
|
"workflow": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "Standard Article Approval",
|
||||||
|
"description": "Standard approval workflow for articles",
|
||||||
|
"isActive": true,
|
||||||
|
"isDefault": true,
|
||||||
|
"requiresApproval": true,
|
||||||
|
"autoPublish": false,
|
||||||
|
"clientId": "uuid-here",
|
||||||
|
"createdAt": "2024-01-01T00:00:00Z",
|
||||||
|
"updatedAt": "2024-01-01T00:00:00Z"
|
||||||
|
},
|
||||||
|
"clientSettings": {
|
||||||
|
"id": 1,
|
||||||
|
"clientId": "uuid-here",
|
||||||
|
"requiresApproval": true,
|
||||||
|
"defaultWorkflowId": 1,
|
||||||
|
"autoPublishArticles": false,
|
||||||
|
"approvalExemptUsers": [],
|
||||||
|
"approvalExemptRoles": [],
|
||||||
|
"approvalExemptCategories": [],
|
||||||
|
"requireApprovalFor": ["article", "news"],
|
||||||
|
"skipApprovalFor": ["announcement"],
|
||||||
|
"isActive": true,
|
||||||
|
"createdAt": "2024-01-01T00:00:00Z",
|
||||||
|
"updatedAt": "2024-01-01T00:00:00Z"
|
||||||
|
},
|
||||||
|
"message": "Comprehensive approval workflow with client settings created successfully"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
### 1. Atomic Transaction
|
||||||
|
- Creates workflow, workflow steps, and client approval settings in a single transaction
|
||||||
|
- Automatic rollback if any step fails
|
||||||
|
- Ensures data consistency
|
||||||
|
|
||||||
|
### 2. Comprehensive Validation
|
||||||
|
- Validates workflow structure and steps
|
||||||
|
- Checks for existing client approval settings
|
||||||
|
- Validates multi-branch workflow logic
|
||||||
|
- Ensures proper step ordering
|
||||||
|
|
||||||
|
### 3. Multi-Branch Support
|
||||||
|
- Supports complex approval workflows with parallel branches
|
||||||
|
- Conditional step execution
|
||||||
|
- Parent-child step relationships
|
||||||
|
- Branch naming and ordering
|
||||||
|
|
||||||
|
### 4. Client Settings Integration
|
||||||
|
- Automatically links workflow to client approval settings
|
||||||
|
- Sets default workflow if specified
|
||||||
|
- Configures approval exemptions
|
||||||
|
- Sets content type approval rules
|
||||||
|
|
||||||
|
### 5. Error Handling
|
||||||
|
- Comprehensive error messages
|
||||||
|
- Automatic cleanup on failure
|
||||||
|
- Detailed logging for debugging
|
||||||
|
- Graceful degradation
|
||||||
|
|
||||||
|
## Request Structure Details
|
||||||
|
|
||||||
|
### Workflow Fields
|
||||||
|
- `name`: Workflow name (required)
|
||||||
|
- `description`: Workflow description (required)
|
||||||
|
- `isActive`: Whether workflow is active
|
||||||
|
- `isDefault`: Whether to set as default workflow
|
||||||
|
- `requiresApproval`: Whether workflow requires approval
|
||||||
|
- `autoPublish`: Whether to auto-publish after approval
|
||||||
|
|
||||||
|
### Step Fields
|
||||||
|
- `stepOrder`: Order of the step in workflow
|
||||||
|
- `stepName`: Name of the approval step
|
||||||
|
- `requiredUserLevelId`: User level required for this step
|
||||||
|
- `canSkip`: Whether this step can be skipped
|
||||||
|
- `autoApproveAfterHours`: Auto-approve after specified hours
|
||||||
|
- `isActive`: Whether step is active
|
||||||
|
|
||||||
|
### Multi-Branch Fields
|
||||||
|
- `parentStepId`: Parent step for branching
|
||||||
|
- `conditionType`: Condition type (user_level, user_level_hierarchy, always, custom)
|
||||||
|
- `conditionValue`: JSON condition value
|
||||||
|
- `isParallel`: Whether step runs in parallel
|
||||||
|
- `branchName`: Name of the branch
|
||||||
|
- `branchOrder`: Order within branch
|
||||||
|
|
||||||
|
### Client Settings Fields
|
||||||
|
- `requiresApproval`: Global approval requirement
|
||||||
|
- `autoPublishArticles`: Auto-publish after creation
|
||||||
|
- `approvalExemptUsers`: User IDs exempt from approval
|
||||||
|
- `approvalExemptRoles`: Role IDs exempt from approval
|
||||||
|
- `approvalExemptCategories`: Category IDs exempt from approval
|
||||||
|
- `requireApprovalFor`: Content types requiring approval
|
||||||
|
- `skipApprovalFor`: Content types skipping approval
|
||||||
|
- `isActive`: Whether settings are active
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### Basic Workflow
|
||||||
|
```bash
|
||||||
|
curl -X POST "https://api.example.com/approval-workflows/with-client-settings" \
|
||||||
|
-H "Authorization: Bearer your-token" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"name": "Simple Approval",
|
||||||
|
"description": "Two-step approval process",
|
||||||
|
"isActive": true,
|
||||||
|
"isDefault": true,
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"stepOrder": 1,
|
||||||
|
"stepName": "Editor Review",
|
||||||
|
"requiredUserLevelId": 2,
|
||||||
|
"canSkip": false,
|
||||||
|
"isActive": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stepOrder": 2,
|
||||||
|
"stepName": "Manager Approval",
|
||||||
|
"requiredUserLevelId": 3,
|
||||||
|
"canSkip": false,
|
||||||
|
"isActive": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"clientApprovalSettings": {
|
||||||
|
"requiresApproval": true,
|
||||||
|
"autoPublishArticles": false,
|
||||||
|
"isActive": true
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complex Multi-Branch Workflow
|
||||||
|
```bash
|
||||||
|
curl -X POST "https://api.example.com/approval-workflows/with-client-settings" \
|
||||||
|
-H "Authorization: Bearer your-token" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"name": "Complex Multi-Branch Approval",
|
||||||
|
"description": "Complex workflow with parallel branches",
|
||||||
|
"isActive": true,
|
||||||
|
"isDefault": false,
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"stepOrder": 1,
|
||||||
|
"stepName": "Initial Review",
|
||||||
|
"requiredUserLevelId": 2,
|
||||||
|
"canSkip": false,
|
||||||
|
"isActive": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stepOrder": 2,
|
||||||
|
"stepName": "Technical Review",
|
||||||
|
"requiredUserLevelId": 4,
|
||||||
|
"canSkip": false,
|
||||||
|
"isActive": true,
|
||||||
|
"parentStepId": 1,
|
||||||
|
"conditionType": "user_level",
|
||||||
|
"conditionValue": "{\"minLevel\": 4}",
|
||||||
|
"isParallel": true,
|
||||||
|
"branchName": "technical",
|
||||||
|
"branchOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stepOrder": 2,
|
||||||
|
"stepName": "Content Review",
|
||||||
|
"requiredUserLevelId": 3,
|
||||||
|
"canSkip": false,
|
||||||
|
"isActive": true,
|
||||||
|
"parentStepId": 1,
|
||||||
|
"conditionType": "user_level",
|
||||||
|
"conditionValue": "{\"minLevel\": 3}",
|
||||||
|
"isParallel": true,
|
||||||
|
"branchName": "content",
|
||||||
|
"branchOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stepOrder": 3,
|
||||||
|
"stepName": "Final Approval",
|
||||||
|
"requiredUserLevelId": 5,
|
||||||
|
"canSkip": false,
|
||||||
|
"isActive": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"clientApprovalSettings": {
|
||||||
|
"requiresApproval": true,
|
||||||
|
"autoPublishArticles": false,
|
||||||
|
"approvalExemptUsers": [1],
|
||||||
|
"approvalExemptRoles": [1],
|
||||||
|
"approvalExemptCategories": [1],
|
||||||
|
"requireApprovalFor": ["article", "news", "blog"],
|
||||||
|
"skipApprovalFor": ["announcement", "update"],
|
||||||
|
"isActive": true
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Responses
|
||||||
|
|
||||||
|
### Validation Error
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"messages": ["Validation failed: [\"Workflow name is required\", \"Workflow must have at least one step\"]"],
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Client Settings Already Exist
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"messages": ["client approval settings already exist for this client"],
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Authentication Error
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"messages": ["clientId not found in auth token"],
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Implementation Details
|
||||||
|
|
||||||
|
### Files Modified/Created
|
||||||
|
1. `app/module/approval_workflows/request/approval_workflows.request.go` - Added comprehensive request structs
|
||||||
|
2. `app/module/approval_workflows/service/approval_workflows.service.go` - Added service method with transaction logic
|
||||||
|
3. `app/module/approval_workflows/controller/approval_workflows.controller.go` - Added controller method
|
||||||
|
4. `app/module/approval_workflows/approval_workflows.module.go` - Added route registration
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
- Client Approval Settings Repository
|
||||||
|
- Approval Workflow Steps Repository
|
||||||
|
- Users Repository
|
||||||
|
- Validation utilities
|
||||||
|
- Response utilities
|
||||||
|
|
||||||
|
### Transaction Safety
|
||||||
|
- Automatic rollback on any failure
|
||||||
|
- Comprehensive error handling
|
||||||
|
- Detailed logging for debugging
|
||||||
|
- Data consistency guarantees
|
||||||
|
|
||||||
|
This comprehensive API endpoint provides a single, atomic way to create complete approval workflows with all necessary dependencies, ensuring data consistency and providing a better developer experience.
|
||||||
|
|
@ -0,0 +1,187 @@
|
||||||
|
# Users Info API Enhancement - Approval Workflow Information
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
This document describes the enhancement made to the `users/info` API to include approval workflow information, allowing users to know whether their client has set up approval workflows or not.
|
||||||
|
|
||||||
|
## Changes Made
|
||||||
|
|
||||||
|
### 1. Response Structure Enhancement
|
||||||
|
|
||||||
|
**File**: `app/module/users/response/users.response.go`
|
||||||
|
|
||||||
|
Added new fields to `UsersResponse` struct:
|
||||||
|
```go
|
||||||
|
type UsersResponse struct {
|
||||||
|
// ... existing fields ...
|
||||||
|
|
||||||
|
// Approval Workflow Info
|
||||||
|
ApprovalWorkflowInfo *ApprovalWorkflowInfo `json:"approvalWorkflowInfo,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ApprovalWorkflowInfo struct {
|
||||||
|
HasWorkflowSetup bool `json:"hasWorkflowSetup"`
|
||||||
|
DefaultWorkflowId *uint `json:"defaultWorkflowId,omitempty"`
|
||||||
|
DefaultWorkflowName *string `json:"defaultWorkflowName,omitempty"`
|
||||||
|
RequiresApproval *bool `json:"requiresApproval,omitempty"`
|
||||||
|
AutoPublishArticles *bool `json:"autoPublishArticles,omitempty"`
|
||||||
|
IsApprovalActive *bool `json:"isApprovalActive,omitempty"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Service Layer Enhancement
|
||||||
|
|
||||||
|
**File**: `app/module/users/service/users.service.go`
|
||||||
|
|
||||||
|
#### Added Dependencies
|
||||||
|
- `ApprovalWorkflowsRepository` - to access approval workflow data
|
||||||
|
- `ClientApprovalSettingsRepository` - to access client approval settings
|
||||||
|
|
||||||
|
#### Enhanced ShowUserInfo Method
|
||||||
|
The `ShowUserInfo` method now:
|
||||||
|
1. Retrieves user information as before
|
||||||
|
2. Calls `getApprovalWorkflowInfo()` to get workflow information
|
||||||
|
3. Combines both pieces of information in the response
|
||||||
|
|
||||||
|
#### New Method: getApprovalWorkflowInfo
|
||||||
|
```go
|
||||||
|
func (_i *usersService) getApprovalWorkflowInfo(clientId *uuid.UUID) (*response.ApprovalWorkflowInfo, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
This method:
|
||||||
|
- Checks if client has approval settings configured
|
||||||
|
- Retrieves default workflow information if available
|
||||||
|
- Returns comprehensive workflow status information
|
||||||
|
|
||||||
|
### 3. Mapper Enhancement
|
||||||
|
|
||||||
|
**File**: `app/module/users/mapper/users.mapper.go`
|
||||||
|
|
||||||
|
Updated `UsersResponseMapper` to include a comment indicating that `ApprovalWorkflowInfo` will be set by the service layer.
|
||||||
|
|
||||||
|
## API Response Examples
|
||||||
|
|
||||||
|
### Client with Workflow Setup
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"messages": ["Users successfully retrieve"],
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"username": "john.doe",
|
||||||
|
"email": "john.doe@example.com",
|
||||||
|
"fullname": "John Doe",
|
||||||
|
"userLevelId": 2,
|
||||||
|
"userLevelGroup": "Editor",
|
||||||
|
"isActive": true,
|
||||||
|
"approvalWorkflowInfo": {
|
||||||
|
"hasWorkflowSetup": true,
|
||||||
|
"defaultWorkflowId": 1,
|
||||||
|
"defaultWorkflowName": "Standard Article Approval",
|
||||||
|
"requiresApproval": true,
|
||||||
|
"autoPublishArticles": false,
|
||||||
|
"isApprovalActive": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Client without Workflow Setup
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"messages": ["Users successfully retrieve"],
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"username": "john.doe",
|
||||||
|
"email": "john.doe@example.com",
|
||||||
|
"fullname": "John Doe",
|
||||||
|
"userLevelId": 2,
|
||||||
|
"userLevelGroup": "Editor",
|
||||||
|
"isActive": true,
|
||||||
|
"approvalWorkflowInfo": {
|
||||||
|
"hasWorkflowSetup": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Client with Workflow but No Default Workflow
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"messages": ["Users successfully retrieve"],
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"username": "john.doe",
|
||||||
|
"email": "john.doe@example.com",
|
||||||
|
"fullname": "John Doe",
|
||||||
|
"userLevelId": 2,
|
||||||
|
"userLevelGroup": "Editor",
|
||||||
|
"isActive": true,
|
||||||
|
"approvalWorkflowInfo": {
|
||||||
|
"hasWorkflowSetup": true,
|
||||||
|
"requiresApproval": true,
|
||||||
|
"autoPublishArticles": false,
|
||||||
|
"isApprovalActive": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Field Descriptions
|
||||||
|
|
||||||
|
### ApprovalWorkflowInfo Fields
|
||||||
|
|
||||||
|
| Field | Type | Description |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| `hasWorkflowSetup` | `bool` | Indicates whether the client has any approval workflow configuration |
|
||||||
|
| `defaultWorkflowId` | `*uint` | ID of the default workflow (if set) |
|
||||||
|
| `defaultWorkflowName` | `*string` | Name of the default workflow (if set) |
|
||||||
|
| `requiresApproval` | `*bool` | Whether the client requires approval for articles |
|
||||||
|
| `autoPublishArticles` | `*bool` | Whether articles are auto-published after creation |
|
||||||
|
| `isApprovalActive` | `*bool` | Whether the approval system is active for this client |
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
The implementation includes robust error handling:
|
||||||
|
|
||||||
|
1. **Graceful Degradation**: If workflow information cannot be retrieved, the API still returns user information without workflow data
|
||||||
|
2. **Logging**: All errors are logged for debugging purposes
|
||||||
|
3. **Non-blocking**: Workflow information retrieval failures don't prevent user information from being returned
|
||||||
|
|
||||||
|
## Usage Scenarios
|
||||||
|
|
||||||
|
### 1. Frontend Dashboard
|
||||||
|
The frontend can now check `approvalWorkflowInfo.hasWorkflowSetup` to:
|
||||||
|
- Show/hide approval workflow setup prompts
|
||||||
|
- Display workflow status indicators
|
||||||
|
- Guide users through workflow configuration
|
||||||
|
|
||||||
|
### 2. Article Creation Flow
|
||||||
|
Before creating articles, the frontend can check:
|
||||||
|
- `requiresApproval` - to determine if approval is needed
|
||||||
|
- `autoPublishArticles` - to know if articles will be auto-published
|
||||||
|
- `isApprovalActive` - to verify the approval system is active
|
||||||
|
|
||||||
|
### 3. Workflow Management
|
||||||
|
The frontend can display:
|
||||||
|
- Current default workflow name
|
||||||
|
- Workflow configuration status
|
||||||
|
- Approval system status
|
||||||
|
|
||||||
|
## Benefits
|
||||||
|
|
||||||
|
1. **Single API Call**: Users can get both user info and workflow status in one request
|
||||||
|
2. **Real-time Status**: Always shows current workflow configuration status
|
||||||
|
3. **User Experience**: Users immediately know if they need to set up workflows
|
||||||
|
4. **Frontend Efficiency**: Reduces the need for multiple API calls
|
||||||
|
5. **Backward Compatibility**: Existing API consumers continue to work without changes
|
||||||
|
|
||||||
|
## Implementation Notes
|
||||||
|
|
||||||
|
- The `approvalWorkflowInfo` field is optional (`omitempty`) to maintain backward compatibility
|
||||||
|
- Error handling ensures the API remains stable even if workflow services are unavailable
|
||||||
|
- The implementation follows the existing code patterns and architecture
|
||||||
|
- All changes are non-breaking and additive
|
||||||
|
|
||||||
|
This enhancement provides users with immediate visibility into their approval workflow setup status, improving the overall user experience and reducing confusion about workflow configuration.
|
||||||
|
|
@ -1755,6 +1755,64 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/approval-workflows/with-client-settings": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "API for creating ApprovalWorkflows with workflow steps and client approval settings in a single call",
|
||||||
|
"tags": [
|
||||||
|
"ApprovalWorkflows"
|
||||||
|
],
|
||||||
|
"summary": "Create comprehensive ApprovalWorkflows with client settings",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Insert the Authorization",
|
||||||
|
"name": "Authorization",
|
||||||
|
"in": "header",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Comprehensive approval workflow data",
|
||||||
|
"name": "req",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/request.CreateApprovalWorkflowWithClientSettingsRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Created",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.BadRequestError"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Unauthorized",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.UnauthorizedError"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.InternalServerError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/approval-workflows/with-steps": {
|
"/approval-workflows/with-steps": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|
@ -17122,6 +17180,50 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"request.ClientApprovalSettingsRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"approvalExemptCategories": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"approvalExemptRoles": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"approvalExemptUsers": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoPublishArticles": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isActive": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"requireApprovalFor": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requiresApproval": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"skipApprovalFor": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"request.ClientWithUserCreateRequest": {
|
"request.ClientWithUserCreateRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -17286,6 +17388,51 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"request.CreateApprovalWorkflowWithClientSettingsRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"clientApprovalSettings",
|
||||||
|
"description",
|
||||||
|
"name",
|
||||||
|
"steps"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"autoPublish": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"clientApprovalSettings": {
|
||||||
|
"description": "Client approval settings",
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/request.ClientApprovalSettingsRequest"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"isActive": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isDefault": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Workflow details",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"requiresApproval": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"steps": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/request.ApprovalWorkflowStepRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"request.CreateClientApprovalSettingsRequest": {
|
"request.CreateClientApprovalSettingsRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -1744,6 +1744,64 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/approval-workflows/with-client-settings": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "API for creating ApprovalWorkflows with workflow steps and client approval settings in a single call",
|
||||||
|
"tags": [
|
||||||
|
"ApprovalWorkflows"
|
||||||
|
],
|
||||||
|
"summary": "Create comprehensive ApprovalWorkflows with client settings",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Insert the Authorization",
|
||||||
|
"name": "Authorization",
|
||||||
|
"in": "header",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Comprehensive approval workflow data",
|
||||||
|
"name": "req",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/request.CreateApprovalWorkflowWithClientSettingsRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Created",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.BadRequestError"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Unauthorized",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.UnauthorizedError"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.InternalServerError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/approval-workflows/with-steps": {
|
"/approval-workflows/with-steps": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|
@ -17111,6 +17169,50 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"request.ClientApprovalSettingsRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"approvalExemptCategories": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"approvalExemptRoles": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"approvalExemptUsers": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoPublishArticles": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isActive": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"requireApprovalFor": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requiresApproval": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"skipApprovalFor": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"request.ClientWithUserCreateRequest": {
|
"request.ClientWithUserCreateRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -17275,6 +17377,51 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"request.CreateApprovalWorkflowWithClientSettingsRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"clientApprovalSettings",
|
||||||
|
"description",
|
||||||
|
"name",
|
||||||
|
"steps"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"autoPublish": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"clientApprovalSettings": {
|
||||||
|
"description": "Client approval settings",
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/request.ClientApprovalSettingsRequest"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"isActive": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isDefault": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Workflow details",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"requiresApproval": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"steps": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/request.ApprovalWorkflowStepRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"request.CreateClientApprovalSettingsRequest": {
|
"request.CreateClientApprovalSettingsRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -693,6 +693,35 @@ definitions:
|
||||||
- id
|
- id
|
||||||
- prov_id
|
- prov_id
|
||||||
type: object
|
type: object
|
||||||
|
request.ClientApprovalSettingsRequest:
|
||||||
|
properties:
|
||||||
|
approvalExemptCategories:
|
||||||
|
items:
|
||||||
|
type: integer
|
||||||
|
type: array
|
||||||
|
approvalExemptRoles:
|
||||||
|
items:
|
||||||
|
type: integer
|
||||||
|
type: array
|
||||||
|
approvalExemptUsers:
|
||||||
|
items:
|
||||||
|
type: integer
|
||||||
|
type: array
|
||||||
|
autoPublishArticles:
|
||||||
|
type: boolean
|
||||||
|
isActive:
|
||||||
|
type: boolean
|
||||||
|
requireApprovalFor:
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
requiresApproval:
|
||||||
|
type: boolean
|
||||||
|
skipApprovalFor:
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
type: object
|
||||||
request.ClientWithUserCreateRequest:
|
request.ClientWithUserCreateRequest:
|
||||||
properties:
|
properties:
|
||||||
adminUser:
|
adminUser:
|
||||||
|
|
@ -805,6 +834,36 @@ definitions:
|
||||||
- stepOrder
|
- stepOrder
|
||||||
- workflowId
|
- workflowId
|
||||||
type: object
|
type: object
|
||||||
|
request.CreateApprovalWorkflowWithClientSettingsRequest:
|
||||||
|
properties:
|
||||||
|
autoPublish:
|
||||||
|
type: boolean
|
||||||
|
clientApprovalSettings:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/definitions/request.ClientApprovalSettingsRequest'
|
||||||
|
description: Client approval settings
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
isActive:
|
||||||
|
type: boolean
|
||||||
|
isDefault:
|
||||||
|
type: boolean
|
||||||
|
name:
|
||||||
|
description: Workflow details
|
||||||
|
type: string
|
||||||
|
requiresApproval:
|
||||||
|
type: boolean
|
||||||
|
steps:
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/request.ApprovalWorkflowStepRequest'
|
||||||
|
minItems: 1
|
||||||
|
type: array
|
||||||
|
required:
|
||||||
|
- clientApprovalSettings
|
||||||
|
- description
|
||||||
|
- name
|
||||||
|
- steps
|
||||||
|
type: object
|
||||||
request.CreateClientApprovalSettingsRequest:
|
request.CreateClientApprovalSettingsRequest:
|
||||||
properties:
|
properties:
|
||||||
approvalExemptCategories:
|
approvalExemptCategories:
|
||||||
|
|
@ -3003,6 +3062,44 @@ paths:
|
||||||
summary: Get default ApprovalWorkflows
|
summary: Get default ApprovalWorkflows
|
||||||
tags:
|
tags:
|
||||||
- ApprovalWorkflows
|
- ApprovalWorkflows
|
||||||
|
/approval-workflows/with-client-settings:
|
||||||
|
post:
|
||||||
|
description: API for creating ApprovalWorkflows with workflow steps and client
|
||||||
|
approval settings in a single call
|
||||||
|
parameters:
|
||||||
|
- description: Insert the Authorization
|
||||||
|
in: header
|
||||||
|
name: Authorization
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- description: Comprehensive approval workflow data
|
||||||
|
in: body
|
||||||
|
name: req
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/request.CreateApprovalWorkflowWithClientSettingsRequest'
|
||||||
|
responses:
|
||||||
|
"201":
|
||||||
|
description: Created
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.Response'
|
||||||
|
"400":
|
||||||
|
description: Bad Request
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.BadRequestError'
|
||||||
|
"401":
|
||||||
|
description: Unauthorized
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.UnauthorizedError'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.InternalServerError'
|
||||||
|
security:
|
||||||
|
- Bearer: []
|
||||||
|
summary: Create comprehensive ApprovalWorkflows with client settings
|
||||||
|
tags:
|
||||||
|
- ApprovalWorkflows
|
||||||
/approval-workflows/with-steps:
|
/approval-workflows/with-steps:
|
||||||
post:
|
post:
|
||||||
description: API for creating ApprovalWorkflows with steps
|
description: API for creating ApprovalWorkflows with steps
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue