feat(migrations): Harden task audit tracking and optimize article templates

- Added migration to harden task audit tracking by modifying audit_logs and related tables.
- Introduced operator_id to several tables for better tracking of actions.
- Updated article_templates with new prompt templates for various article types, enhancing content generation.
- Created prompt_rules and schedule_tasks tables to manage content generation rules and scheduling.
- Added foreign key constraints to articles for better data integrity.
This commit is contained in:
2026-04-02 00:31:28 +08:00
parent de30497f59
commit b31d8d0096
101 changed files with 16671 additions and 721 deletions
+39 -8
View File
@@ -8,16 +8,19 @@ import (
"github.com/jackc/pgx/v5/pgxpool"
"github.com/geo-platform/tenant-api/internal/shared/auditlog"
"github.com/geo-platform/tenant-api/internal/shared/auth"
"github.com/geo-platform/tenant-api/internal/shared/middleware"
"github.com/geo-platform/tenant-api/internal/shared/response"
)
type BrandService struct {
pool *pgxpool.Pool
pool *pgxpool.Pool
auditLogs *auditlog.AsyncWriter
}
func NewBrandService(pool *pgxpool.Pool) *BrandService {
return &BrandService{pool: pool}
func NewBrandService(pool *pgxpool.Pool, auditLogs *auditlog.AsyncWriter) *BrandService {
return &BrandService{pool: pool, auditLogs: auditLogs}
}
// --- Brand CRUD ---
@@ -77,8 +80,20 @@ func (s *BrandService) Create(ctx context.Context, req BrandRequest) (*BrandResp
}
afterJSON, _ := json.Marshal(map[string]interface{}{"id": id, "name": req.Name})
_, _ = s.pool.Exec(ctx, `INSERT INTO audit_logs (operator_id, tenant_id, module, action, after_json, result) VALUES ($1, $2, 'brand', 'create', $3, 'success')`,
actor.UserID, actor.TenantID, afterJSON)
result := "success"
resourceType := "brand"
requestID := middleware.RequestIDFromContext(ctx)
s.auditLogs.Log(auditlog.Entry{
OperatorID: actor.UserID,
TenantID: &actor.TenantID,
Module: "brand",
Action: "create",
ResourceType: &resourceType,
ResourceID: &id,
RequestID: nilIfEmptyString(requestID),
AfterJSON: afterJSON,
Result: &result,
})
return &BrandResponse{ID: id, Name: req.Name, Description: req.Description, Status: "active", CreatedAt: fmt.Sprintf("%v", ca)}, nil
}
@@ -130,10 +145,26 @@ func (s *BrandService) Delete(ctx context.Context, id int64) error {
_, _ = tx.Exec(ctx, `UPDATE competitors SET deleted_at = NOW(), updated_at = NOW() WHERE brand_id = $1 AND tenant_id = $2 AND deleted_at IS NULL`, id, actor.TenantID)
afterJSON, _ := json.Marshal(map[string]interface{}{"id": id, "action": "cascade_soft_delete"})
_, _ = tx.Exec(ctx, `INSERT INTO audit_logs (operator_id, tenant_id, module, action, after_json, result) VALUES ($1, $2, 'brand', 'delete', $3, 'success')`,
actor.UserID, actor.TenantID, afterJSON)
if err := tx.Commit(ctx); err != nil {
return err
}
return tx.Commit(ctx)
result := "success"
resourceType := "brand"
requestID := middleware.RequestIDFromContext(ctx)
s.auditLogs.Log(auditlog.Entry{
OperatorID: actor.UserID,
TenantID: &actor.TenantID,
Module: "brand",
Action: "delete",
ResourceType: &resourceType,
ResourceID: &id,
RequestID: nilIfEmptyString(requestID),
AfterJSON: afterJSON,
Result: &result,
})
return nil
}
// --- Keyword CRUD ---