package service import ( "fmt" "web-qudo-be/app/database/entity" "web-qudo-be/app/module/client_approval_settings/mapper" "web-qudo-be/app/module/client_approval_settings/repository" "web-qudo-be/app/module/client_approval_settings/request" "web-qudo-be/app/module/client_approval_settings/response" "github.com/google/uuid" "github.com/rs/zerolog" ) type clientApprovalSettingsService struct { clientApprovalSettingsRepo repository.ClientApprovalSettingsRepository Log zerolog.Logger } type ClientApprovalSettingsService interface { GetByClientId(clientId *uuid.UUID) (*response.ClientApprovalSettingsResponse, error) Create(clientId *uuid.UUID, req request.CreateClientApprovalSettingsRequest) (*response.ClientApprovalSettingsResponse, error) Update(clientId *uuid.UUID, req request.UpdateClientApprovalSettingsRequest) (*response.ClientApprovalSettingsResponse, error) Delete(clientId *uuid.UUID) error ToggleApprovalRequirement(clientId *uuid.UUID, requiresApproval bool) error SetDefaultWorkflow(clientId *uuid.UUID, workflowId *uint) error AddExemptUser(clientId *uuid.UUID, userId uint) error RemoveExemptUser(clientId *uuid.UUID, userId uint) error AddExemptRole(clientId *uuid.UUID, roleId uint) error RemoveExemptRole(clientId *uuid.UUID, roleId uint) error AddExemptCategory(clientId *uuid.UUID, categoryId uint) error RemoveExemptCategory(clientId *uuid.UUID, categoryId uint) error CheckIfApprovalRequired(clientId *uuid.UUID, userId uint, userLevelId uint, categoryId uint, contentType string) (bool, error) // Enhanced methods for dynamic approval management EnableApprovalWithTransition(clientId *uuid.UUID, defaultWorkflowId *uint) error DisableApprovalWithAutoPublish(clientId *uuid.UUID, reason string) error HandlePendingApprovalsOnDisable(clientId *uuid.UUID, action string) error // "auto_approve", "keep_pending", "reset_to_draft" } func NewClientApprovalSettingsService( clientApprovalSettingsRepo repository.ClientApprovalSettingsRepository, log zerolog.Logger, ) ClientApprovalSettingsService { return &clientApprovalSettingsService{ clientApprovalSettingsRepo: clientApprovalSettingsRepo, Log: log, } } func (_i *clientApprovalSettingsService) GetByClientId(clientId *uuid.UUID) (*response.ClientApprovalSettingsResponse, error) { settings, err := _i.clientApprovalSettingsRepo.FindByClientId(*clientId) if err != nil { return nil, err } if settings == nil { // Return default settings if none found return &response.ClientApprovalSettingsResponse{ ClientId: clientId.String(), RequiresApproval: true, // Default to requiring approval AutoPublishArticles: false, ApprovalExemptUsers: []uint{}, ApprovalExemptRoles: []uint{}, ApprovalExemptCategories: []uint{}, RequireApprovalFor: []string{}, SkipApprovalFor: []string{}, IsActive: true, }, nil } return mapper.ClientApprovalSettingsResponseMapper(_i.Log, clientId, settings), nil } func (_i *clientApprovalSettingsService) Create(clientId *uuid.UUID, req request.CreateClientApprovalSettingsRequest) (*response.ClientApprovalSettingsResponse, error) { // Check if settings already exist existing, err := _i.clientApprovalSettingsRepo.FindByClientId(*clientId) if err != nil { return nil, err } if existing != nil { return nil, fmt.Errorf("approval settings already exist for this client") } // Create new settings settings := &entity.ClientApprovalSettings{ RequiresApproval: &req.RequiresApproval, DefaultWorkflowId: req.DefaultWorkflowId, AutoPublishArticles: &req.AutoPublishArticles, ApprovalExemptUsers: req.ApprovalExemptUsers, ApprovalExemptRoles: req.ApprovalExemptRoles, ApprovalExemptCategories: req.ApprovalExemptCategories, RequireApprovalFor: req.RequireApprovalFor, SkipApprovalFor: req.SkipApprovalFor, IsActive: &req.IsActive, } createdSettings, err := _i.clientApprovalSettingsRepo.Create(clientId, settings) if err != nil { return nil, err } return mapper.ClientApprovalSettingsResponseMapper(_i.Log, clientId, createdSettings), nil } func (_i *clientApprovalSettingsService) Update(clientId *uuid.UUID, req request.UpdateClientApprovalSettingsRequest) (*response.ClientApprovalSettingsResponse, error) { // Get existing settings settings, err := _i.clientApprovalSettingsRepo.FindByClientId(*clientId) if err != nil { return nil, err } if settings == nil { return nil, fmt.Errorf("approval settings not found for this client") } // Update fields if provided if req.RequiresApproval != nil { settings.RequiresApproval = req.RequiresApproval } if req.DefaultWorkflowId != nil { settings.DefaultWorkflowId = *req.DefaultWorkflowId } if req.AutoPublishArticles != nil { settings.AutoPublishArticles = req.AutoPublishArticles } if req.ApprovalExemptUsers != nil { settings.ApprovalExemptUsers = req.ApprovalExemptUsers } if req.ApprovalExemptRoles != nil { settings.ApprovalExemptRoles = req.ApprovalExemptRoles } if req.ApprovalExemptCategories != nil { settings.ApprovalExemptCategories = req.ApprovalExemptCategories } if req.RequireApprovalFor != nil { settings.RequireApprovalFor = req.RequireApprovalFor } if req.SkipApprovalFor != nil { settings.SkipApprovalFor = req.SkipApprovalFor } if req.IsActive != nil { settings.IsActive = req.IsActive } updatedSettings, err := _i.clientApprovalSettingsRepo.Update(clientId, settings) if err != nil { return nil, err } return mapper.ClientApprovalSettingsResponseMapper(_i.Log, clientId, updatedSettings), nil } func (_i *clientApprovalSettingsService) Delete(clientId *uuid.UUID) error { return _i.clientApprovalSettingsRepo.Delete(clientId) } func (_i *clientApprovalSettingsService) ToggleApprovalRequirement(clientId *uuid.UUID, requiresApproval bool) error { settings, err := _i.clientApprovalSettingsRepo.FindByClientId(*clientId) if err != nil { return err } if settings == nil { return fmt.Errorf("approval settings not found for this client") } settings.RequiresApproval = &requiresApproval _, err = _i.clientApprovalSettingsRepo.Update(clientId, settings) return err } func (_i *clientApprovalSettingsService) SetDefaultWorkflow(clientId *uuid.UUID, workflowId *uint) error { settings, err := _i.clientApprovalSettingsRepo.FindByClientId(*clientId) if err != nil { return err } if settings == nil { return fmt.Errorf("approval settings not found for this client") } settings.DefaultWorkflowId = workflowId _, err = _i.clientApprovalSettingsRepo.Update(clientId, settings) return err } func (_i *clientApprovalSettingsService) AddExemptUser(clientId *uuid.UUID, userId uint) error { return _i.clientApprovalSettingsRepo.AddExemptUser(clientId, userId) } func (_i *clientApprovalSettingsService) RemoveExemptUser(clientId *uuid.UUID, userId uint) error { return _i.clientApprovalSettingsRepo.RemoveExemptUser(clientId, userId) } func (_i *clientApprovalSettingsService) AddExemptRole(clientId *uuid.UUID, roleId uint) error { return _i.clientApprovalSettingsRepo.AddExemptRole(clientId, roleId) } func (_i *clientApprovalSettingsService) RemoveExemptRole(clientId *uuid.UUID, roleId uint) error { return _i.clientApprovalSettingsRepo.RemoveExemptRole(clientId, roleId) } func (_i *clientApprovalSettingsService) AddExemptCategory(clientId *uuid.UUID, categoryId uint) error { return _i.clientApprovalSettingsRepo.AddExemptCategory(clientId, categoryId) } func (_i *clientApprovalSettingsService) RemoveExemptCategory(clientId *uuid.UUID, categoryId uint) error { return _i.clientApprovalSettingsRepo.RemoveExemptCategory(clientId, categoryId) } func (_i *clientApprovalSettingsService) CheckIfApprovalRequired(clientId *uuid.UUID, userId uint, userLevelId uint, categoryId uint, contentType string) (bool, error) { settings, err := _i.clientApprovalSettingsRepo.FindActiveSettings(clientId) if err != nil { return true, err // Default to requiring approval on error } if settings == nil { return true, nil // Default to requiring approval if no settings } // Check if approval is disabled if settings.RequiresApproval != nil && !*settings.RequiresApproval { return false, nil } // Check user exemption for _, exemptUserId := range settings.ApprovalExemptUsers { if exemptUserId == userId { return false, nil } } // Check role exemption for _, exemptRoleId := range settings.ApprovalExemptRoles { if exemptRoleId == userLevelId { return false, nil } } // Check category exemption for _, exemptCategoryId := range settings.ApprovalExemptCategories { if exemptCategoryId == categoryId { return false, nil } } // Check content type exemptions for _, skipType := range settings.SkipApprovalFor { if skipType == contentType { return false, nil } } // Check if content type requires approval for _, requireType := range settings.RequireApprovalFor { if requireType == contentType { return true, nil } } // Default to requiring approval return true, nil } func (_i *clientApprovalSettingsService) EnableApprovalWithTransition(clientId *uuid.UUID, defaultWorkflowId *uint) error { settings, err := _i.clientApprovalSettingsRepo.FindByClientId(*clientId) if err != nil { return err } if settings == nil { // Create new settings settings = &entity.ClientApprovalSettings{ RequiresApproval: &[]bool{true}[0], DefaultWorkflowId: defaultWorkflowId, AutoPublishArticles: &[]bool{false}[0], IsActive: &[]bool{true}[0], } _, err = _i.clientApprovalSettingsRepo.Create(clientId, settings) } else { // Update existing settings settings.RequiresApproval = &[]bool{true}[0] settings.DefaultWorkflowId = defaultWorkflowId settings.AutoPublishArticles = &[]bool{false}[0] settings.IsActive = &[]bool{true}[0] _, err = _i.clientApprovalSettingsRepo.Update(clientId, settings) } return err } func (_i *clientApprovalSettingsService) DisableApprovalWithAutoPublish(clientId *uuid.UUID, reason string) error { settings, err := _i.clientApprovalSettingsRepo.FindByClientId(*clientId) if err != nil { return err } if settings == nil { return fmt.Errorf("approval settings not found for this client") } settings.RequiresApproval = &[]bool{false}[0] settings.AutoPublishArticles = &[]bool{true}[0] settings.IsActive = &[]bool{true}[0] _, err = _i.clientApprovalSettingsRepo.Update(clientId, settings) return err } func (_i *clientApprovalSettingsService) HandlePendingApprovalsOnDisable(clientId *uuid.UUID, action string) error { // This would typically interact with article approval flows // For now, just log the action _i.Log.Info(). Str("client_id", clientId.String()). Str("action", action). Msg("Handling pending approvals on disable") // TODO: Implement actual logic based on action: // - "auto_approve": Auto approve all pending articles // - "keep_pending": Keep articles in pending state // - "reset_to_draft": Reset articles to draft state return nil }