package automation import ( "context" ) // =========================== // Automation Execution Logging // =========================== // ExecutionLogService records automation rule and macro execution events for audit trail. // Reference: Chatwoot does not explicitly store automation execution logs — // gochat adds this for debugging, monitoring, and compliance per M6 requirements. type ExecutionLogService struct { db DBProvider } // NewExecutionLogService creates a new ExecutionLogService. func NewExecutionLogService(db DBProvider) *ExecutionLogService { return &ExecutionLogService{db: db} } // LogRuleExecution records an automation rule execution event. func (s *ExecutionLogService) LogRuleExecution(ctx context.Context, accountID, ruleID, conversationID uint, status string, actionsExecuted, actionsFailed int, errorMsg string) error { record := &AutomationExecution{ AccountID: accountID, RuleID: ruleID, ConversationID: conversationID, Status: status, ActionsExecuted: actionsExecuted, ActionsFailed: actionsFailed, ErrorMessage: errorMsg, } return s.db.DB().WithContext(ctx).Select( "AccountID", "RuleID", "ConversationID", "Status", "ActionsExecuted", "ActionsFailed", "ErrorMessage", ).Create(record).Error } // ListRuleExecutions retrieves execution logs for an automation rule, ordered by most recent. func (s *ExecutionLogService) ListRuleExecutions(ctx context.Context, accountID, ruleID uint, limit int) ([]AutomationExecution, error) { var logs []AutomationExecution query := s.db.DB().WithContext(ctx). Where("account_id = ? AND rule_id = ?", accountID, ruleID). Order("created_at DESC") if limit > 0 { query = query.Limit(limit) } if err := query.Find(&logs).Error; err != nil { return nil, err } return logs, nil } // ListConversationExecutions retrieves execution logs for a conversation, ordered by most recent. func (s *ExecutionLogService) ListConversationExecutions(ctx context.Context, accountID, conversationID uint, limit int) ([]AutomationExecution, error) { var logs []AutomationExecution query := s.db.DB().WithContext(ctx). Where("account_id = ? AND conversation_id = ?", accountID, conversationID). Order("created_at DESC") if limit > 0 { query = query.Limit(limit) } if err := query.Find(&logs).Error; err != nil { return nil, err } return logs, nil } // LogMacroExecution records a macro execution event (uses MacroExecution model). func (s *ExecutionLogService) LogMacroExecution(ctx context.Context, macroID, conversationID, userID uint) error { record := &MacroExecution{ MacroID: macroID, ConversationID: conversationID, ExecutedByID: userID, } return s.db.DB().WithContext(ctx).Create(record).Error } // ListMacroExecutions retrieves execution logs for a macro, ordered by most recent. func (s *ExecutionLogService) ListMacroExecutions(ctx context.Context, macroID uint, limit int) ([]MacroExecution, error) { var logs []MacroExecution query := s.db.DB().WithContext(ctx). Where("macro_id = ?", macroID). Order("id DESC") if limit > 0 { query = query.Limit(limit) } if err := query.Find(&logs).Error; err != nil { return nil, err } return logs, nil } // ExecutionStatus constants. const ( ExecutionStatusSuccess = "success" ExecutionStatusPartial = "partial" // some actions succeeded, some failed ExecutionStatusFailed = "failed" )