263 lines
6.9 KiB
Go
263 lines
6.9 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
|
|
"eslogad-be/internal/contract"
|
|
"eslogad-be/internal/entities"
|
|
"eslogad-be/internal/repository"
|
|
|
|
"github.com/google/uuid"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type ApprovalFlowService interface {
|
|
CreateApprovalFlow(ctx context.Context, req *contract.ApprovalFlowRequest) (*contract.ApprovalFlowResponse, error)
|
|
GetApprovalFlow(ctx context.Context, id uuid.UUID) (*contract.ApprovalFlowResponse, error)
|
|
GetApprovalFlowByDepartment(ctx context.Context, departmentID uuid.UUID) (*contract.ApprovalFlowResponse, error)
|
|
UpdateApprovalFlow(ctx context.Context, id uuid.UUID, req *contract.ApprovalFlowRequest) (*contract.ApprovalFlowResponse, error)
|
|
DeleteApprovalFlow(ctx context.Context, id uuid.UUID) error
|
|
ListApprovalFlows(ctx context.Context, req *contract.ListApprovalFlowsRequest) (*contract.ListApprovalFlowsResponse, error)
|
|
}
|
|
|
|
type ApprovalFlowServiceImpl struct {
|
|
db *gorm.DB
|
|
flowRepo *repository.ApprovalFlowRepository
|
|
stepRepo *repository.ApprovalFlowStepRepository
|
|
txManager *repository.TxManager
|
|
}
|
|
|
|
func NewApprovalFlowService(
|
|
db *gorm.DB,
|
|
flowRepo *repository.ApprovalFlowRepository,
|
|
stepRepo *repository.ApprovalFlowStepRepository,
|
|
txManager *repository.TxManager,
|
|
) *ApprovalFlowServiceImpl {
|
|
return &ApprovalFlowServiceImpl{
|
|
db: db,
|
|
flowRepo: flowRepo,
|
|
stepRepo: stepRepo,
|
|
txManager: txManager,
|
|
}
|
|
}
|
|
|
|
func (s *ApprovalFlowServiceImpl) CreateApprovalFlow(ctx context.Context, req *contract.ApprovalFlowRequest) (*contract.ApprovalFlowResponse, error) {
|
|
flow := &entities.ApprovalFlow{
|
|
DepartmentID: req.DepartmentID,
|
|
Name: req.Name,
|
|
Description: req.Description,
|
|
IsActive: req.IsActive,
|
|
}
|
|
|
|
err := s.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
|
|
if err := s.flowRepo.Create(txCtx, flow); err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(req.Steps) > 0 {
|
|
steps := make([]entities.ApprovalFlowStep, len(req.Steps))
|
|
for i, stepReq := range req.Steps {
|
|
if stepReq.ApproverRoleID == nil && stepReq.ApproverUserID == nil {
|
|
return gorm.ErrInvalidData
|
|
}
|
|
|
|
steps[i] = entities.ApprovalFlowStep{
|
|
FlowID: flow.ID,
|
|
StepOrder: stepReq.StepOrder,
|
|
ParallelGroup: stepReq.ParallelGroup,
|
|
ApproverRoleID: stepReq.ApproverRoleID,
|
|
ApproverUserID: stepReq.ApproverUserID,
|
|
Required: stepReq.Required,
|
|
}
|
|
}
|
|
|
|
if err := s.stepRepo.CreateBulk(txCtx, steps); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
result, err := s.flowRepo.Get(ctx, flow.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return transformApprovalFlowToResponse(result), nil
|
|
}
|
|
|
|
func (s *ApprovalFlowServiceImpl) GetApprovalFlow(ctx context.Context, id uuid.UUID) (*contract.ApprovalFlowResponse, error) {
|
|
flow, err := s.flowRepo.Get(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return transformApprovalFlowToResponse(flow), nil
|
|
}
|
|
|
|
func (s *ApprovalFlowServiceImpl) GetApprovalFlowByDepartment(ctx context.Context, departmentID uuid.UUID) (*contract.ApprovalFlowResponse, error) {
|
|
flow, err := s.flowRepo.GetByDepartment(ctx, departmentID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return transformApprovalFlowToResponse(flow), nil
|
|
}
|
|
|
|
func (s *ApprovalFlowServiceImpl) UpdateApprovalFlow(ctx context.Context, id uuid.UUID, req *contract.ApprovalFlowRequest) (*contract.ApprovalFlowResponse, error) {
|
|
flow, err := s.flowRepo.Get(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
flow.DepartmentID = req.DepartmentID
|
|
flow.Name = req.Name
|
|
flow.Description = req.Description
|
|
flow.IsActive = req.IsActive
|
|
|
|
err = s.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
|
|
if err := s.flowRepo.Update(txCtx, flow); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := s.stepRepo.DeleteByFlow(txCtx, id); err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(req.Steps) > 0 {
|
|
steps := make([]entities.ApprovalFlowStep, len(req.Steps))
|
|
for i, stepReq := range req.Steps {
|
|
if stepReq.ApproverRoleID == nil && stepReq.ApproverUserID == nil {
|
|
return gorm.ErrInvalidData
|
|
}
|
|
|
|
steps[i] = entities.ApprovalFlowStep{
|
|
FlowID: flow.ID,
|
|
StepOrder: stepReq.StepOrder,
|
|
ParallelGroup: stepReq.ParallelGroup,
|
|
ApproverRoleID: stepReq.ApproverRoleID,
|
|
ApproverUserID: stepReq.ApproverUserID,
|
|
Required: stepReq.Required,
|
|
}
|
|
}
|
|
|
|
if err := s.stepRepo.CreateBulk(txCtx, steps); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
result, err := s.flowRepo.Get(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return transformApprovalFlowToResponse(result), nil
|
|
}
|
|
|
|
func (s *ApprovalFlowServiceImpl) DeleteApprovalFlow(ctx context.Context, id uuid.UUID) error {
|
|
return s.flowRepo.Delete(ctx, id)
|
|
}
|
|
|
|
func (s *ApprovalFlowServiceImpl) ListApprovalFlows(ctx context.Context, req *contract.ListApprovalFlowsRequest) (*contract.ListApprovalFlowsResponse, error) {
|
|
filter := repository.ListApprovalFlowsFilter{
|
|
DepartmentID: req.DepartmentID,
|
|
Search: req.Search,
|
|
IsActive: req.IsActive,
|
|
}
|
|
|
|
page := req.Page
|
|
if page <= 0 {
|
|
page = 1
|
|
}
|
|
|
|
limit := req.Limit
|
|
if limit <= 0 {
|
|
limit = 10
|
|
}
|
|
if limit > 100 {
|
|
limit = 100 // Max limit to prevent performance issues
|
|
}
|
|
|
|
offset := (page - 1) * limit
|
|
|
|
flows, total, err := s.flowRepo.List(ctx, filter, limit, offset)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
items := make([]*contract.ApprovalFlowResponse, len(flows))
|
|
for i, flow := range flows {
|
|
items[i] = transformApprovalFlowToResponse(&flow)
|
|
}
|
|
|
|
return &contract.ListApprovalFlowsResponse{
|
|
Items: items,
|
|
Total: total,
|
|
}, nil
|
|
}
|
|
|
|
func transformApprovalFlowToResponse(flow *entities.ApprovalFlow) *contract.ApprovalFlowResponse {
|
|
resp := &contract.ApprovalFlowResponse{
|
|
ID: flow.ID,
|
|
DepartmentID: flow.DepartmentID,
|
|
Name: flow.Name,
|
|
Description: flow.Description,
|
|
IsActive: flow.IsActive,
|
|
CreatedAt: flow.CreatedAt,
|
|
UpdatedAt: flow.UpdatedAt,
|
|
}
|
|
|
|
if flow.Department != nil {
|
|
resp.Department = &contract.DepartmentResponse{
|
|
ID: flow.Department.ID,
|
|
Name: flow.Department.Name,
|
|
}
|
|
}
|
|
|
|
if len(flow.Steps) > 0 {
|
|
resp.Steps = make([]contract.ApprovalFlowStepResponse, len(flow.Steps))
|
|
for i, step := range flow.Steps {
|
|
stepResp := contract.ApprovalFlowStepResponse{
|
|
ID: step.ID,
|
|
StepOrder: step.StepOrder,
|
|
ParallelGroup: step.ParallelGroup,
|
|
ApproverRoleID: step.ApproverRoleID,
|
|
ApproverUserID: step.ApproverUserID,
|
|
Required: step.Required,
|
|
CreatedAt: step.CreatedAt,
|
|
UpdatedAt: step.UpdatedAt,
|
|
}
|
|
|
|
if step.ApproverRole != nil {
|
|
stepResp.ApproverRole = &contract.RoleResponse{
|
|
ID: step.ApproverRole.ID,
|
|
Name: step.ApproverRole.Name,
|
|
}
|
|
}
|
|
|
|
if step.ApproverUser != nil {
|
|
stepResp.ApproverUser = &contract.UserResponse{
|
|
ID: step.ApproverUser.ID,
|
|
Name: step.ApproverUser.Name,
|
|
Email: step.ApproverUser.Email,
|
|
}
|
|
}
|
|
|
|
resp.Steps[i] = stepResp
|
|
}
|
|
}
|
|
|
|
return resp
|
|
} |