mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 05:21:57 +00:00
240 lines
6.6 KiB
Go
240 lines
6.6 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
|
approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type ApprovalService interface {
|
|
RegisterWorkflowSteps(workflow approvalutils.ApprovalWorkflowKey, steps map[approvalutils.ApprovalStep]string) error
|
|
WorkflowSteps(workflow approvalutils.ApprovalWorkflowKey) map[approvalutils.ApprovalStep]string
|
|
WorkflowStepName(workflow approvalutils.ApprovalWorkflowKey, step approvalutils.ApprovalStep) (string, bool)
|
|
CreateApproval(ctx context.Context, workflow approvalutils.ApprovalWorkflowKey, approvableID uint, step approvalutils.ApprovalStep, action *entity.ApprovalAction, actorID uint, note *string) (*entity.Approval, error)
|
|
List(ctx context.Context, module string, approvableID *uint, page, limit int, search string, orderByDate string) ([]entity.Approval, int64, error)
|
|
ListByTarget(ctx context.Context, workflow approvalutils.ApprovalWorkflowKey, approvableID uint, modifier func(*gorm.DB) *gorm.DB) ([]entity.Approval, error)
|
|
LatestByTarget(ctx context.Context, workflow approvalutils.ApprovalWorkflowKey, approvableID uint, modifier func(*gorm.DB) *gorm.DB) (*entity.Approval, error)
|
|
LatestByTargets(ctx context.Context, workflow approvalutils.ApprovalWorkflowKey, approvableIDs []uint, modifier func(*gorm.DB) *gorm.DB) (map[uint]*entity.Approval, error)
|
|
}
|
|
|
|
type approvalService struct {
|
|
repo commonRepo.ApprovalRepository
|
|
}
|
|
|
|
func NewApprovalService(repo commonRepo.ApprovalRepository) ApprovalService {
|
|
return &approvalService{repo: repo}
|
|
}
|
|
|
|
func (s *approvalService) RegisterWorkflowSteps(workflow approvalutils.ApprovalWorkflowKey, steps map[approvalutils.ApprovalStep]string) error {
|
|
return approvalutils.RegisterWorkflowSteps(workflow, steps)
|
|
}
|
|
|
|
func (s *approvalService) WorkflowSteps(workflow approvalutils.ApprovalWorkflowKey) map[approvalutils.ApprovalStep]string {
|
|
return approvalutils.WorkflowSteps(workflow)
|
|
}
|
|
|
|
func (s *approvalService) WorkflowStepName(workflow approvalutils.ApprovalWorkflowKey, step approvalutils.ApprovalStep) (string, bool) {
|
|
return approvalutils.ApprovalStepName(workflow, step)
|
|
}
|
|
|
|
func (s *approvalService) CreateApproval(
|
|
ctx context.Context,
|
|
workflow approvalutils.ApprovalWorkflowKey,
|
|
approvableID uint,
|
|
step approvalutils.ApprovalStep,
|
|
action *entity.ApprovalAction,
|
|
actorID uint,
|
|
note *string,
|
|
) (*entity.Approval, error) {
|
|
record, err := approvalutils.NewApproval(workflow, approvableID, step, action, actorID, note)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := s.repo.CreateOne(ctx, record, nil); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
s.decorateApproval(workflow, record)
|
|
|
|
return record, nil
|
|
}
|
|
|
|
func (s *approvalService) List(
|
|
ctx context.Context,
|
|
module string,
|
|
approvableID *uint,
|
|
page, limit int,
|
|
search string,
|
|
orderByDate string,
|
|
) ([]entity.Approval, int64, error) {
|
|
module = strings.TrimSpace(strings.ToUpper(module))
|
|
search = strings.TrimSpace(search)
|
|
orderByDate = strings.TrimSpace(strings.ToUpper(orderByDate))
|
|
if orderByDate != "ASC" && orderByDate != "DESC" {
|
|
orderByDate = "DESC"
|
|
}
|
|
|
|
if limit <= 0 {
|
|
limit = 10
|
|
}
|
|
if page <= 0 {
|
|
page = 1
|
|
}
|
|
|
|
offset := (page - 1) * limit
|
|
|
|
records, total, err := s.repo.GetAll(
|
|
ctx,
|
|
offset,
|
|
limit,
|
|
func(db *gorm.DB) *gorm.DB {
|
|
query := db.
|
|
Where("approvable_type = ?", module).
|
|
Order("action_at " + orderByDate).
|
|
Preload("ActionUser")
|
|
|
|
if approvableID != nil {
|
|
query = query.Where("approvable_id = ?", *approvableID)
|
|
}
|
|
|
|
if search != "" {
|
|
like := "%" + strings.ToLower(search) + "%"
|
|
query = query.Where("(LOWER(step_name) LIKE ? OR LOWER(action) LIKE ? OR LOWER(notes) LIKE ?)", like, like, like)
|
|
}
|
|
|
|
return query
|
|
},
|
|
)
|
|
if err != nil {
|
|
if s.isApprovalTableMissing(err) {
|
|
return nil, 0, nil
|
|
}
|
|
return nil, 0, err
|
|
}
|
|
if len(records) == 0 {
|
|
return nil, total, nil
|
|
}
|
|
|
|
workflow := approvalutils.ApprovalWorkflowKey(module)
|
|
for i := range records {
|
|
s.decorateApproval(workflow, &records[i])
|
|
}
|
|
|
|
return records, total, nil
|
|
}
|
|
|
|
func (s *approvalService) ListByTarget(
|
|
ctx context.Context,
|
|
workflow approvalutils.ApprovalWorkflowKey,
|
|
approvableID uint,
|
|
modifier func(*gorm.DB) *gorm.DB,
|
|
) ([]entity.Approval, error) {
|
|
records, err := s.repo.FindByTarget(ctx, workflow.String(), approvableID, modifier)
|
|
if err != nil {
|
|
if s.isApprovalTableMissing(err) {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
for i := range records {
|
|
s.decorateApproval(workflow, &records[i])
|
|
}
|
|
|
|
return records, nil
|
|
}
|
|
|
|
func (s *approvalService) LatestByTarget(
|
|
ctx context.Context,
|
|
workflow approvalutils.ApprovalWorkflowKey,
|
|
approvableID uint,
|
|
modifier func(*gorm.DB) *gorm.DB,
|
|
) (*entity.Approval, error) {
|
|
record, err := s.repo.LatestByTarget(ctx, workflow.String(), approvableID, modifier)
|
|
if err != nil {
|
|
if s.isApprovalTableMissing(err) {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
if record == nil {
|
|
return nil, nil
|
|
}
|
|
s.decorateApproval(workflow, record)
|
|
return record, nil
|
|
}
|
|
|
|
func (s *approvalService) LatestByTargets(
|
|
ctx context.Context,
|
|
workflow approvalutils.ApprovalWorkflowKey,
|
|
approvableIDs []uint,
|
|
modifier func(*gorm.DB) *gorm.DB,
|
|
) (map[uint]*entity.Approval, error) {
|
|
records, err := s.repo.LatestByTargets(ctx, workflow.String(), approvableIDs, modifier)
|
|
if err != nil {
|
|
if s.isApprovalTableMissing(err) {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
if len(records) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
result := make(map[uint]*entity.Approval, len(records))
|
|
for approvableID, approval := range records {
|
|
approvalCopy := approval
|
|
s.decorateApproval(workflow, &approvalCopy)
|
|
result[approvableID] = &approvalCopy
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (s *approvalService) decorateApproval(workflow approvalutils.ApprovalWorkflowKey, approval *entity.Approval) {
|
|
if approval == nil {
|
|
return
|
|
}
|
|
currentName := strings.TrimSpace(approval.StepName)
|
|
if currentName == "" {
|
|
if name, ok := approvalutils.ApprovalStepName(workflow, approvalutils.ApprovalStep(approval.StepNumber)); ok {
|
|
approval.StepName = name
|
|
}
|
|
} else {
|
|
approval.StepName = currentName
|
|
}
|
|
}
|
|
|
|
func (s *approvalService) isApprovalTableMissing(err error) bool {
|
|
if err == nil {
|
|
return false
|
|
}
|
|
|
|
errMsg := strings.ToLower(err.Error())
|
|
|
|
if strings.Contains(errMsg, "no such table: approvals") {
|
|
return true
|
|
}
|
|
|
|
schemaIssues := []string{
|
|
`relation "approvals" does not exist`,
|
|
`column "step_name" does not exist`,
|
|
`column "step_number" does not exist`,
|
|
`column "action" does not exist`,
|
|
`column "status" does not exist`,
|
|
`column "step" does not exist`,
|
|
}
|
|
for _, issue := range schemaIssues {
|
|
if strings.Contains(errMsg, issue) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|