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
@@ -12,19 +12,36 @@ import (
)
const createAuditLog = `-- name: CreateAuditLog :exec
INSERT INTO audit_logs (operator_id, tenant_id, module, action, before_json, after_json, result)
INSERT INTO audit_logs (
operator_id,
tenant_id,
module,
action,
resource_type,
resource_id,
request_id,
before_json,
after_json,
result,
error_message
)
VALUES ($1, $2, $3, $4,
$5, $6, $7)
$5, $6, $7,
$8, $9, $10, $11)
`
type CreateAuditLogParams struct {
OperatorID int64 `json:"operator_id"`
TenantID pgtype.Int8 `json:"tenant_id"`
Module string `json:"module"`
Action string `json:"action"`
BeforeJson []byte `json:"before_json"`
AfterJson []byte `json:"after_json"`
Result pgtype.Text `json:"result"`
OperatorID int64 `json:"operator_id"`
TenantID pgtype.Int8 `json:"tenant_id"`
Module string `json:"module"`
Action string `json:"action"`
ResourceType pgtype.Text `json:"resource_type"`
ResourceID pgtype.Int8 `json:"resource_id"`
RequestID pgtype.Text `json:"request_id"`
BeforeJson []byte `json:"before_json"`
AfterJson []byte `json:"after_json"`
Result pgtype.Text `json:"result"`
ErrorMessage pgtype.Text `json:"error_message"`
}
func (q *Queries) CreateAuditLog(ctx context.Context, arg CreateAuditLogParams) error {
@@ -33,22 +50,27 @@ func (q *Queries) CreateAuditLog(ctx context.Context, arg CreateAuditLogParams)
arg.TenantID,
arg.Module,
arg.Action,
arg.ResourceType,
arg.ResourceID,
arg.RequestID,
arg.BeforeJson,
arg.AfterJson,
arg.Result,
arg.ErrorMessage,
)
return err
}
const createGenerationTask = `-- name: CreateGenerationTask :one
INSERT INTO generation_tasks (tenant_id, article_id, quota_reservation_id, task_type, input_params_json, status)
VALUES ($1, $2, $3,
$4, $5, 'queued')
INSERT INTO generation_tasks (tenant_id, operator_id, article_id, quota_reservation_id, task_type, input_params_json, status)
VALUES ($1, $2, $3, $4,
$5, $6, 'queued')
RETURNING id
`
type CreateGenerationTaskParams struct {
TenantID int64 `json:"tenant_id"`
OperatorID pgtype.Int8 `json:"operator_id"`
ArticleID pgtype.Int8 `json:"article_id"`
QuotaReservationID pgtype.Int8 `json:"quota_reservation_id"`
TaskType string `json:"task_type"`
@@ -58,6 +80,7 @@ type CreateGenerationTaskParams struct {
func (q *Queries) CreateGenerationTask(ctx context.Context, arg CreateGenerationTaskParams) (int64, error) {
row := q.db.QueryRow(ctx, createGenerationTask,
arg.TenantID,
arg.OperatorID,
arg.ArticleID,
arg.QuotaReservationID,
arg.TaskType,
@@ -20,6 +20,7 @@ type Article struct {
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
WizardStateJson []byte `json:"wizard_state_json"`
}
type ArticleTemplate struct {
@@ -55,15 +56,19 @@ type ArticleVersion struct {
}
type AuditLog struct {
ID int64 `json:"id"`
OperatorID int64 `json:"operator_id"`
TenantID pgtype.Int8 `json:"tenant_id"`
Module string `json:"module"`
Action string `json:"action"`
BeforeJson []byte `json:"before_json"`
AfterJson []byte `json:"after_json"`
Result pgtype.Text `json:"result"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
ID int64 `json:"id"`
OperatorID int64 `json:"operator_id"`
TenantID pgtype.Int8 `json:"tenant_id"`
Module string `json:"module"`
Action string `json:"action"`
BeforeJson []byte `json:"before_json"`
AfterJson []byte `json:"after_json"`
Result pgtype.Text `json:"result"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
ResourceType pgtype.Text `json:"resource_type"`
ResourceID pgtype.Int8 `json:"resource_id"`
RequestID pgtype.Text `json:"request_id"`
ErrorMessage pgtype.Text `json:"error_message"`
}
type Brand struct {
@@ -138,6 +143,7 @@ type GenerationTask struct {
CompletedAt pgtype.Timestamptz `json:"completed_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
OperatorID pgtype.Int8 `json:"operator_id"`
}
type Plan struct {
@@ -160,12 +166,37 @@ type PlatformUserRole struct {
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
}
type PromptRule struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
GroupID pgtype.Int8 `json:"group_id"`
Name string `json:"name"`
PromptContent string `json:"prompt_content"`
Scene pgtype.Text `json:"scene"`
DefaultTone pgtype.Text `json:"default_tone"`
DefaultWordCount pgtype.Int4 `json:"default_word_count"`
Status string `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
}
type PromptRuleGroup struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
Name string `json:"name"`
SortOrder int32 `json:"sort_order"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
}
type QuotaReservation struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
QuotaType string `json:"quota_type"`
ResourceType string `json:"resource_type"`
ResourceID int64 `json:"resource_id"`
ResourceID pgtype.Int8 `json:"resource_id"`
ReservedAmount int32 `json:"reserved_amount"`
ConsumedAmount int32 `json:"consumed_amount"`
RefundedAmount int32 `json:"refunded_amount"`
@@ -173,6 +204,24 @@ type QuotaReservation struct {
ExpireAt pgtype.Timestamptz `json:"expire_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
OperatorID pgtype.Int8 `json:"operator_id"`
}
type ScheduleTask struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
PromptRuleID int64 `json:"prompt_rule_id"`
BrandID pgtype.Int8 `json:"brand_id"`
Name string `json:"name"`
CronExpr string `json:"cron_expr"`
TargetPlatform pgtype.Text `json:"target_platform"`
StartAt pgtype.Timestamptz `json:"start_at"`
EndAt pgtype.Timestamptz `json:"end_at"`
NextRunAt pgtype.Timestamptz `json:"next_run_at"`
Status string `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
}
type TaskRecord struct {
@@ -187,6 +236,23 @@ type TaskRecord struct {
ErrorMessage pgtype.Text `json:"error_message"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
OperatorID pgtype.Int8 `json:"operator_id"`
}
type TemplateAssistTask struct {
ID string `json:"id"`
TenantID int64 `json:"tenant_id"`
TemplateID int64 `json:"template_id"`
Status string `json:"status"`
RequestJson []byte `json:"request_json"`
ResultJson []byte `json:"result_json"`
ErrorMessage pgtype.Text `json:"error_message"`
StartedAt pgtype.Timestamptz `json:"started_at"`
CompletedAt pgtype.Timestamptz `json:"completed_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
TaskType string `json:"task_type"`
OperatorID pgtype.Int8 `json:"operator_id"`
}
type Tenant struct {
@@ -231,6 +297,7 @@ type TenantQuotaLedger struct {
ReferenceType pgtype.Text `json:"reference_type"`
ReferenceID pgtype.Int8 `json:"reference_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
OperatorID pgtype.Int8 `json:"operator_id"`
}
type User struct {
@@ -0,0 +1,499 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: prompt_rule.sql
package generated
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const countPromptRules = `-- name: CountPromptRules :one
SELECT COUNT(*)
FROM prompt_rules
WHERE tenant_id = $1
AND deleted_at IS NULL
AND ($2::bigint IS NULL OR group_id = $2)
AND ($3::text IS NULL OR status = $3)
AND ($4::text IS NULL OR name ILIKE '%' || $4 || '%')
`
type CountPromptRulesParams struct {
TenantID int64 `json:"tenant_id"`
GroupID pgtype.Int8 `json:"group_id"`
Status pgtype.Text `json:"status"`
Keyword pgtype.Text `json:"keyword"`
}
func (q *Queries) CountPromptRules(ctx context.Context, arg CountPromptRulesParams) (int64, error) {
row := q.db.QueryRow(ctx, countPromptRules,
arg.TenantID,
arg.GroupID,
arg.Status,
arg.Keyword,
)
var count int64
err := row.Scan(&count)
return count, err
}
const countPromptRulesUngrouped = `-- name: CountPromptRulesUngrouped :one
SELECT COUNT(*)
FROM prompt_rules
WHERE tenant_id = $1
AND deleted_at IS NULL
AND group_id IS NULL
`
func (q *Queries) CountPromptRulesUngrouped(ctx context.Context, tenantID int64) (int64, error) {
row := q.db.QueryRow(ctx, countPromptRulesUngrouped, tenantID)
var count int64
err := row.Scan(&count)
return count, err
}
const createPromptRule = `-- name: CreatePromptRule :one
INSERT INTO prompt_rules (tenant_id, group_id, name, prompt_content, scene, default_tone, default_word_count)
VALUES ($1, $2, $3, $4,
$5, $6, $7)
RETURNING id, created_at
`
type CreatePromptRuleParams struct {
TenantID int64 `json:"tenant_id"`
GroupID pgtype.Int8 `json:"group_id"`
Name string `json:"name"`
PromptContent string `json:"prompt_content"`
Scene pgtype.Text `json:"scene"`
DefaultTone pgtype.Text `json:"default_tone"`
DefaultWordCount pgtype.Int4 `json:"default_word_count"`
}
type CreatePromptRuleRow struct {
ID int64 `json:"id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
func (q *Queries) CreatePromptRule(ctx context.Context, arg CreatePromptRuleParams) (CreatePromptRuleRow, error) {
row := q.db.QueryRow(ctx, createPromptRule,
arg.TenantID,
arg.GroupID,
arg.Name,
arg.PromptContent,
arg.Scene,
arg.DefaultTone,
arg.DefaultWordCount,
)
var i CreatePromptRuleRow
err := row.Scan(&i.ID, &i.CreatedAt)
return i, err
}
const createPromptRuleGroup = `-- name: CreatePromptRuleGroup :one
INSERT INTO prompt_rule_groups (tenant_id, name, sort_order)
VALUES ($1, $2, $3)
RETURNING id, created_at
`
type CreatePromptRuleGroupParams struct {
TenantID int64 `json:"tenant_id"`
Name string `json:"name"`
SortOrder int32 `json:"sort_order"`
}
type CreatePromptRuleGroupRow struct {
ID int64 `json:"id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
func (q *Queries) CreatePromptRuleGroup(ctx context.Context, arg CreatePromptRuleGroupParams) (CreatePromptRuleGroupRow, error) {
row := q.db.QueryRow(ctx, createPromptRuleGroup, arg.TenantID, arg.Name, arg.SortOrder)
var i CreatePromptRuleGroupRow
err := row.Scan(&i.ID, &i.CreatedAt)
return i, err
}
const getPromptRuleByID = `-- name: GetPromptRuleByID :one
SELECT id, tenant_id, group_id, name, prompt_content,
scene, default_tone, default_word_count, status,
created_at, updated_at
FROM prompt_rules
WHERE id = $1 AND tenant_id = $2 AND deleted_at IS NULL
`
type GetPromptRuleByIDParams struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
}
type GetPromptRuleByIDRow struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
GroupID pgtype.Int8 `json:"group_id"`
Name string `json:"name"`
PromptContent string `json:"prompt_content"`
Scene pgtype.Text `json:"scene"`
DefaultTone pgtype.Text `json:"default_tone"`
DefaultWordCount pgtype.Int4 `json:"default_word_count"`
Status string `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
func (q *Queries) GetPromptRuleByID(ctx context.Context, arg GetPromptRuleByIDParams) (GetPromptRuleByIDRow, error) {
row := q.db.QueryRow(ctx, getPromptRuleByID, arg.ID, arg.TenantID)
var i GetPromptRuleByIDRow
err := row.Scan(
&i.ID,
&i.TenantID,
&i.GroupID,
&i.Name,
&i.PromptContent,
&i.Scene,
&i.DefaultTone,
&i.DefaultWordCount,
&i.Status,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const listAllPromptRulesSimple = `-- name: ListAllPromptRulesSimple :many
SELECT id, name, status
FROM prompt_rules
WHERE tenant_id = $1 AND deleted_at IS NULL AND status = 'enabled'
ORDER BY name
`
type ListAllPromptRulesSimpleRow struct {
ID int64 `json:"id"`
Name string `json:"name"`
Status string `json:"status"`
}
func (q *Queries) ListAllPromptRulesSimple(ctx context.Context, tenantID int64) ([]ListAllPromptRulesSimpleRow, error) {
rows, err := q.db.Query(ctx, listAllPromptRulesSimple, tenantID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListAllPromptRulesSimpleRow
for rows.Next() {
var i ListAllPromptRulesSimpleRow
if err := rows.Scan(&i.ID, &i.Name, &i.Status); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listPromptRuleGroups = `-- name: ListPromptRuleGroups :many
SELECT id, tenant_id, name, sort_order, created_at, updated_at
FROM prompt_rule_groups
WHERE tenant_id = $1 AND deleted_at IS NULL
ORDER BY sort_order, created_at
`
type ListPromptRuleGroupsRow struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
Name string `json:"name"`
SortOrder int32 `json:"sort_order"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
// ============================================================
// Prompt Rule Groups
// ============================================================
func (q *Queries) ListPromptRuleGroups(ctx context.Context, tenantID int64) ([]ListPromptRuleGroupsRow, error) {
rows, err := q.db.Query(ctx, listPromptRuleGroups, tenantID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListPromptRuleGroupsRow
for rows.Next() {
var i ListPromptRuleGroupsRow
if err := rows.Scan(
&i.ID,
&i.TenantID,
&i.Name,
&i.SortOrder,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listPromptRules = `-- name: ListPromptRules :many
SELECT pr.id, pr.tenant_id, pr.group_id, pr.name, pr.prompt_content,
pr.scene, pr.default_tone, pr.default_word_count, pr.status,
pr.created_at, pr.updated_at,
COUNT(a.id)::INT AS article_count
FROM prompt_rules pr
LEFT JOIN articles a ON a.prompt_rule_id = pr.id AND a.deleted_at IS NULL
WHERE pr.tenant_id = $1
AND pr.deleted_at IS NULL
AND ($2::bigint IS NULL OR pr.group_id = $2)
AND ($3::text IS NULL OR pr.status = $3)
AND ($4::text IS NULL OR pr.name ILIKE '%' || $4 || '%')
GROUP BY pr.id
ORDER BY pr.created_at DESC
LIMIT $6 OFFSET $5
`
type ListPromptRulesParams struct {
TenantID int64 `json:"tenant_id"`
GroupID pgtype.Int8 `json:"group_id"`
Status pgtype.Text `json:"status"`
Keyword pgtype.Text `json:"keyword"`
PageOffset int32 `json:"page_offset"`
PageSize int32 `json:"page_size"`
}
type ListPromptRulesRow struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
GroupID pgtype.Int8 `json:"group_id"`
Name string `json:"name"`
PromptContent string `json:"prompt_content"`
Scene pgtype.Text `json:"scene"`
DefaultTone pgtype.Text `json:"default_tone"`
DefaultWordCount pgtype.Int4 `json:"default_word_count"`
Status string `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ArticleCount int32 `json:"article_count"`
}
// ============================================================
// Prompt Rules
// ============================================================
func (q *Queries) ListPromptRules(ctx context.Context, arg ListPromptRulesParams) ([]ListPromptRulesRow, error) {
rows, err := q.db.Query(ctx, listPromptRules,
arg.TenantID,
arg.GroupID,
arg.Status,
arg.Keyword,
arg.PageOffset,
arg.PageSize,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListPromptRulesRow
for rows.Next() {
var i ListPromptRulesRow
if err := rows.Scan(
&i.ID,
&i.TenantID,
&i.GroupID,
&i.Name,
&i.PromptContent,
&i.Scene,
&i.DefaultTone,
&i.DefaultWordCount,
&i.Status,
&i.CreatedAt,
&i.UpdatedAt,
&i.ArticleCount,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listPromptRulesUngrouped = `-- name: ListPromptRulesUngrouped :many
SELECT pr.id, pr.tenant_id, pr.group_id, pr.name, pr.prompt_content,
pr.scene, pr.default_tone, pr.default_word_count, pr.status,
pr.created_at, pr.updated_at,
COUNT(a.id)::INT AS article_count
FROM prompt_rules pr
LEFT JOIN articles a ON a.prompt_rule_id = pr.id AND a.deleted_at IS NULL
WHERE pr.tenant_id = $1
AND pr.deleted_at IS NULL
AND pr.group_id IS NULL
GROUP BY pr.id
ORDER BY pr.created_at DESC
LIMIT $3 OFFSET $2
`
type ListPromptRulesUngroupedParams struct {
TenantID int64 `json:"tenant_id"`
PageOffset int32 `json:"page_offset"`
PageSize int32 `json:"page_size"`
}
type ListPromptRulesUngroupedRow struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
GroupID pgtype.Int8 `json:"group_id"`
Name string `json:"name"`
PromptContent string `json:"prompt_content"`
Scene pgtype.Text `json:"scene"`
DefaultTone pgtype.Text `json:"default_tone"`
DefaultWordCount pgtype.Int4 `json:"default_word_count"`
Status string `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ArticleCount int32 `json:"article_count"`
}
func (q *Queries) ListPromptRulesUngrouped(ctx context.Context, arg ListPromptRulesUngroupedParams) ([]ListPromptRulesUngroupedRow, error) {
rows, err := q.db.Query(ctx, listPromptRulesUngrouped, arg.TenantID, arg.PageOffset, arg.PageSize)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListPromptRulesUngroupedRow
for rows.Next() {
var i ListPromptRulesUngroupedRow
if err := rows.Scan(
&i.ID,
&i.TenantID,
&i.GroupID,
&i.Name,
&i.PromptContent,
&i.Scene,
&i.DefaultTone,
&i.DefaultWordCount,
&i.Status,
&i.CreatedAt,
&i.UpdatedAt,
&i.ArticleCount,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const softDeletePromptRule = `-- name: SoftDeletePromptRule :exec
UPDATE prompt_rules SET deleted_at = NOW(), updated_at = NOW()
WHERE id = $1 AND tenant_id = $2 AND deleted_at IS NULL
`
type SoftDeletePromptRuleParams struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
}
func (q *Queries) SoftDeletePromptRule(ctx context.Context, arg SoftDeletePromptRuleParams) error {
_, err := q.db.Exec(ctx, softDeletePromptRule, arg.ID, arg.TenantID)
return err
}
const softDeletePromptRuleGroup = `-- name: SoftDeletePromptRuleGroup :exec
UPDATE prompt_rule_groups SET deleted_at = NOW(), updated_at = NOW()
WHERE id = $1 AND tenant_id = $2 AND deleted_at IS NULL
`
type SoftDeletePromptRuleGroupParams struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
}
func (q *Queries) SoftDeletePromptRuleGroup(ctx context.Context, arg SoftDeletePromptRuleGroupParams) error {
_, err := q.db.Exec(ctx, softDeletePromptRuleGroup, arg.ID, arg.TenantID)
return err
}
const updatePromptRule = `-- name: UpdatePromptRule :exec
UPDATE prompt_rules
SET name = $1, group_id = $2,
prompt_content = $3,
scene = $4, default_tone = $5,
default_word_count = $6, updated_at = NOW()
WHERE id = $7 AND tenant_id = $8 AND deleted_at IS NULL
`
type UpdatePromptRuleParams struct {
Name string `json:"name"`
GroupID pgtype.Int8 `json:"group_id"`
PromptContent string `json:"prompt_content"`
Scene pgtype.Text `json:"scene"`
DefaultTone pgtype.Text `json:"default_tone"`
DefaultWordCount pgtype.Int4 `json:"default_word_count"`
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
}
func (q *Queries) UpdatePromptRule(ctx context.Context, arg UpdatePromptRuleParams) error {
_, err := q.db.Exec(ctx, updatePromptRule,
arg.Name,
arg.GroupID,
arg.PromptContent,
arg.Scene,
arg.DefaultTone,
arg.DefaultWordCount,
arg.ID,
arg.TenantID,
)
return err
}
const updatePromptRuleGroup = `-- name: UpdatePromptRuleGroup :exec
UPDATE prompt_rule_groups SET name = $1, sort_order = $2, updated_at = NOW()
WHERE id = $3 AND tenant_id = $4 AND deleted_at IS NULL
`
type UpdatePromptRuleGroupParams struct {
Name string `json:"name"`
SortOrder int32 `json:"sort_order"`
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
}
func (q *Queries) UpdatePromptRuleGroup(ctx context.Context, arg UpdatePromptRuleGroupParams) error {
_, err := q.db.Exec(ctx, updatePromptRuleGroup,
arg.Name,
arg.SortOrder,
arg.ID,
arg.TenantID,
)
return err
}
const updatePromptRuleStatus = `-- name: UpdatePromptRuleStatus :exec
UPDATE prompt_rules SET status = $1, updated_at = NOW()
WHERE id = $2 AND tenant_id = $3 AND deleted_at IS NULL
`
type UpdatePromptRuleStatusParams struct {
Status string `json:"status"`
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
}
func (q *Queries) UpdatePromptRuleStatus(ctx context.Context, arg UpdatePromptRuleStatusParams) error {
_, err := q.db.Exec(ctx, updatePromptRuleStatus, arg.Status, arg.ID, arg.TenantID)
return err
}
@@ -13,7 +13,10 @@ type Querier interface {
CountArticles(ctx context.Context, arg CountArticlesParams) (int64, error)
CountArticlesByTenant(ctx context.Context, tenantID int64) (int64, error)
CountBrandsByTenant(ctx context.Context, tenantID int64) (int64, error)
CountPromptRules(ctx context.Context, arg CountPromptRulesParams) (int64, error)
CountPromptRulesUngrouped(ctx context.Context, tenantID int64) (int64, error)
CountPublishedArticlesByTenant(ctx context.Context, tenantID int64) (int64, error)
CountScheduleTasks(ctx context.Context, arg CountScheduleTasksParams) (int64, error)
CreateArticle(ctx context.Context, arg CreateArticleParams) (int64, error)
CreateArticleVersion(ctx context.Context, arg CreateArticleVersionParams) (int64, error)
CreateAuditLog(ctx context.Context, arg CreateAuditLogParams) error
@@ -21,9 +24,12 @@ type Querier interface {
CreateCompetitor(ctx context.Context, arg CreateCompetitorParams) (CreateCompetitorRow, error)
CreateGenerationTask(ctx context.Context, arg CreateGenerationTaskParams) (int64, error)
CreateKeyword(ctx context.Context, arg CreateKeywordParams) (CreateKeywordRow, error)
CreatePromptRule(ctx context.Context, arg CreatePromptRuleParams) (CreatePromptRuleRow, error)
CreatePromptRuleGroup(ctx context.Context, arg CreatePromptRuleGroupParams) (CreatePromptRuleGroupRow, error)
CreateQuestion(ctx context.Context, arg CreateQuestionParams) (int64, error)
CreateQuestionVersion(ctx context.Context, arg CreateQuestionVersionParams) (int64, error)
CreateQuotaReservation(ctx context.Context, arg CreateQuotaReservationParams) (int64, error)
CreateScheduleTask(ctx context.Context, arg CreateScheduleTaskParams) (CreateScheduleTaskRow, error)
DeactivateQuestionVersion(ctx context.Context, questionID int64) error
GetActivePlanForTenant(ctx context.Context, tenantID int64) (GetActivePlanForTenantRow, error)
GetArticleByID(ctx context.Context, arg GetArticleByIDParams) (GetArticleByIDRow, error)
@@ -31,8 +37,10 @@ type Querier interface {
GetBrandByID(ctx context.Context, arg GetBrandByIDParams) (GetBrandByIDRow, error)
GetCurrentBalance(ctx context.Context, arg GetCurrentBalanceParams) (int32, error)
GetLatestQuestionVersionNo(ctx context.Context, questionID int64) (int32, error)
GetPromptRuleByID(ctx context.Context, arg GetPromptRuleByIDParams) (GetPromptRuleByIDRow, error)
GetQuotaSummary(ctx context.Context, tenantID int64) (int32, error)
GetRecentArticles(ctx context.Context, tenantID int64) ([]GetRecentArticlesRow, error)
GetScheduleTaskByID(ctx context.Context, arg GetScheduleTaskByIDParams) (GetScheduleTaskByIDRow, error)
GetTemplateByID(ctx context.Context, arg GetTemplateByIDParams) (GetTemplateByIDRow, error)
GetTemplateSchema(ctx context.Context, id int64) (GetTemplateSchemaRow, error)
GetTenantMembership(ctx context.Context, userID int64) (GetTenantMembershipRow, error)
@@ -40,12 +48,23 @@ type Querier interface {
GetUserByEmail(ctx context.Context, email string) (GetUserByEmailRow, error)
GetUserByID(ctx context.Context, id int64) (GetUserByIDRow, error)
InsertQuotaLedger(ctx context.Context, arg InsertQuotaLedgerParams) (int64, error)
ListAllPromptRulesSimple(ctx context.Context, tenantID int64) ([]ListAllPromptRulesSimpleRow, error)
ListArticles(ctx context.Context, arg ListArticlesParams) ([]ListArticlesRow, error)
ListBrands(ctx context.Context, tenantID int64) ([]ListBrandsRow, error)
ListCompetitors(ctx context.Context, arg ListCompetitorsParams) ([]ListCompetitorsRow, error)
ListKeywords(ctx context.Context, arg ListKeywordsParams) ([]ListKeywordsRow, error)
// ============================================================
// Prompt Rule Groups
// ============================================================
ListPromptRuleGroups(ctx context.Context, tenantID int64) ([]ListPromptRuleGroupsRow, error)
// ============================================================
// Prompt Rules
// ============================================================
ListPromptRules(ctx context.Context, arg ListPromptRulesParams) ([]ListPromptRulesRow, error)
ListPromptRulesUngrouped(ctx context.Context, arg ListPromptRulesUngroupedParams) ([]ListPromptRulesUngroupedRow, error)
ListQuestionVersions(ctx context.Context, arg ListQuestionVersionsParams) ([]BrandQuestionVersion, error)
ListQuestions(ctx context.Context, arg ListQuestionsParams) ([]ListQuestionsRow, error)
ListScheduleTasks(ctx context.Context, arg ListScheduleTasksParams) ([]ListScheduleTasksRow, error)
ListTemplates(ctx context.Context, tenantID int64) ([]ListTemplatesRow, error)
RefundReservation(ctx context.Context, arg RefundReservationParams) error
SoftDeleteArticle(ctx context.Context, arg SoftDeleteArticleParams) error
@@ -54,16 +73,24 @@ type Querier interface {
SoftDeleteCompetitorsByBrand(ctx context.Context, arg SoftDeleteCompetitorsByBrandParams) error
SoftDeleteKeyword(ctx context.Context, arg SoftDeleteKeywordParams) error
SoftDeleteKeywordsByBrand(ctx context.Context, arg SoftDeleteKeywordsByBrandParams) error
SoftDeletePromptRule(ctx context.Context, arg SoftDeletePromptRuleParams) error
SoftDeletePromptRuleGroup(ctx context.Context, arg SoftDeletePromptRuleGroupParams) error
SoftDeleteQuestion(ctx context.Context, arg SoftDeleteQuestionParams) error
SoftDeleteQuestionsByBrand(ctx context.Context, arg SoftDeleteQuestionsByBrandParams) error
SoftDeleteScheduleTask(ctx context.Context, arg SoftDeleteScheduleTaskParams) error
UpdateArticleCurrentVersion(ctx context.Context, arg UpdateArticleCurrentVersionParams) error
UpdateArticleGenerateStatus(ctx context.Context, arg UpdateArticleGenerateStatusParams) error
UpdateBrand(ctx context.Context, arg UpdateBrandParams) error
UpdateCompetitor(ctx context.Context, arg UpdateCompetitorParams) error
UpdateGenerationTaskStatus(ctx context.Context, arg UpdateGenerationTaskStatusParams) error
UpdateKeyword(ctx context.Context, arg UpdateKeywordParams) error
UpdatePromptRule(ctx context.Context, arg UpdatePromptRuleParams) error
UpdatePromptRuleGroup(ctx context.Context, arg UpdatePromptRuleGroupParams) error
UpdatePromptRuleStatus(ctx context.Context, arg UpdatePromptRuleStatusParams) error
UpdateQuestionCurrentVersion(ctx context.Context, arg UpdateQuestionCurrentVersionParams) error
UpdateQuotaReservationResource(ctx context.Context, arg UpdateQuotaReservationResourceParams) error
UpdateScheduleTask(ctx context.Context, arg UpdateScheduleTaskParams) error
UpdateScheduleTaskStatus(ctx context.Context, arg UpdateScheduleTaskStatusParams) error
}
var _ Querier = (*Queries)(nil)
@@ -27,17 +27,18 @@ func (q *Queries) ConfirmReservation(ctx context.Context, arg ConfirmReservation
}
const createQuotaReservation = `-- name: CreateQuotaReservation :one
INSERT INTO quota_reservations (tenant_id, quota_type, resource_type, resource_id, reserved_amount, status, expire_at)
VALUES ($1, $2, $3, $4,
$5, 'pending', $6)
INSERT INTO quota_reservations (tenant_id, operator_id, quota_type, resource_type, resource_id, reserved_amount, status, expire_at)
VALUES ($1, $2, $3, $4, $5,
$6, 'pending', $7)
RETURNING id
`
type CreateQuotaReservationParams struct {
TenantID int64 `json:"tenant_id"`
OperatorID pgtype.Int8 `json:"operator_id"`
QuotaType string `json:"quota_type"`
ResourceType string `json:"resource_type"`
ResourceID int64 `json:"resource_id"`
ResourceID pgtype.Int8 `json:"resource_id"`
ReservedAmount int32 `json:"reserved_amount"`
ExpireAt pgtype.Timestamptz `json:"expire_at"`
}
@@ -45,6 +46,7 @@ type CreateQuotaReservationParams struct {
func (q *Queries) CreateQuotaReservation(ctx context.Context, arg CreateQuotaReservationParams) (int64, error) {
row := q.db.QueryRow(ctx, createQuotaReservation,
arg.TenantID,
arg.OperatorID,
arg.QuotaType,
arg.ResourceType,
arg.ResourceID,
@@ -77,14 +79,15 @@ func (q *Queries) GetCurrentBalance(ctx context.Context, arg GetCurrentBalancePa
}
const insertQuotaLedger = `-- name: InsertQuotaLedger :one
INSERT INTO tenant_quota_ledgers (tenant_id, quota_type, delta, balance_after, reason, reference_type, reference_id)
VALUES ($1, $2, $3, $4,
$5, $6, $7)
INSERT INTO tenant_quota_ledgers (tenant_id, operator_id, quota_type, delta, balance_after, reason, reference_type, reference_id)
VALUES ($1, $2, $3, $4, $5,
$6, $7, $8)
RETURNING id
`
type InsertQuotaLedgerParams struct {
TenantID int64 `json:"tenant_id"`
OperatorID pgtype.Int8 `json:"operator_id"`
QuotaType string `json:"quota_type"`
Delta int32 `json:"delta"`
BalanceAfter int32 `json:"balance_after"`
@@ -96,6 +99,7 @@ type InsertQuotaLedgerParams struct {
func (q *Queries) InsertQuotaLedger(ctx context.Context, arg InsertQuotaLedgerParams) (int64, error) {
row := q.db.QueryRow(ctx, insertQuotaLedger,
arg.TenantID,
arg.OperatorID,
arg.QuotaType,
arg.Delta,
arg.BalanceAfter,
@@ -129,9 +133,9 @@ WHERE id = $2 AND tenant_id = $3
`
type UpdateQuotaReservationResourceParams struct {
ResourceID int64 `json:"resource_id"`
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
ResourceID pgtype.Int8 `json:"resource_id"`
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
}
func (q *Queries) UpdateQuotaReservationResource(ctx context.Context, arg UpdateQuotaReservationResourceParams) error {
@@ -0,0 +1,290 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: schedule_task.sql
package generated
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const countScheduleTasks = `-- name: CountScheduleTasks :one
SELECT COUNT(*)
FROM schedule_tasks
WHERE tenant_id = $1
AND deleted_at IS NULL
AND ($2::text IS NULL OR status = $2)
AND ($3::bigint IS NULL OR prompt_rule_id = $3)
`
type CountScheduleTasksParams struct {
TenantID int64 `json:"tenant_id"`
Status pgtype.Text `json:"status"`
PromptRuleID pgtype.Int8 `json:"prompt_rule_id"`
}
func (q *Queries) CountScheduleTasks(ctx context.Context, arg CountScheduleTasksParams) (int64, error) {
row := q.db.QueryRow(ctx, countScheduleTasks, arg.TenantID, arg.Status, arg.PromptRuleID)
var count int64
err := row.Scan(&count)
return count, err
}
const createScheduleTask = `-- name: CreateScheduleTask :one
INSERT INTO schedule_tasks (tenant_id, prompt_rule_id, brand_id, name, cron_expr,
target_platform, start_at, end_at, next_run_at)
VALUES ($1, $2, $3, $4,
$5, $6, $7, $8,
$9)
RETURNING id, created_at
`
type CreateScheduleTaskParams struct {
TenantID int64 `json:"tenant_id"`
PromptRuleID int64 `json:"prompt_rule_id"`
BrandID pgtype.Int8 `json:"brand_id"`
Name string `json:"name"`
CronExpr string `json:"cron_expr"`
TargetPlatform pgtype.Text `json:"target_platform"`
StartAt pgtype.Timestamptz `json:"start_at"`
EndAt pgtype.Timestamptz `json:"end_at"`
NextRunAt pgtype.Timestamptz `json:"next_run_at"`
}
type CreateScheduleTaskRow struct {
ID int64 `json:"id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
func (q *Queries) CreateScheduleTask(ctx context.Context, arg CreateScheduleTaskParams) (CreateScheduleTaskRow, error) {
row := q.db.QueryRow(ctx, createScheduleTask,
arg.TenantID,
arg.PromptRuleID,
arg.BrandID,
arg.Name,
arg.CronExpr,
arg.TargetPlatform,
arg.StartAt,
arg.EndAt,
arg.NextRunAt,
)
var i CreateScheduleTaskRow
err := row.Scan(&i.ID, &i.CreatedAt)
return i, err
}
const getScheduleTaskByID = `-- name: GetScheduleTaskByID :one
SELECT st.id, st.tenant_id, st.prompt_rule_id, st.brand_id, st.name,
st.cron_expr, st.target_platform, st.start_at, st.end_at,
st.next_run_at, st.status, st.created_at, st.updated_at,
pr.name AS prompt_rule_name,
b.name AS brand_name
FROM schedule_tasks st
LEFT JOIN prompt_rules pr ON pr.id = st.prompt_rule_id
LEFT JOIN brands b ON b.id = st.brand_id
WHERE st.id = $1 AND st.tenant_id = $2 AND st.deleted_at IS NULL
`
type GetScheduleTaskByIDParams struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
}
type GetScheduleTaskByIDRow struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
PromptRuleID int64 `json:"prompt_rule_id"`
BrandID pgtype.Int8 `json:"brand_id"`
Name string `json:"name"`
CronExpr string `json:"cron_expr"`
TargetPlatform pgtype.Text `json:"target_platform"`
StartAt pgtype.Timestamptz `json:"start_at"`
EndAt pgtype.Timestamptz `json:"end_at"`
NextRunAt pgtype.Timestamptz `json:"next_run_at"`
Status string `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
PromptRuleName pgtype.Text `json:"prompt_rule_name"`
BrandName pgtype.Text `json:"brand_name"`
}
func (q *Queries) GetScheduleTaskByID(ctx context.Context, arg GetScheduleTaskByIDParams) (GetScheduleTaskByIDRow, error) {
row := q.db.QueryRow(ctx, getScheduleTaskByID, arg.ID, arg.TenantID)
var i GetScheduleTaskByIDRow
err := row.Scan(
&i.ID,
&i.TenantID,
&i.PromptRuleID,
&i.BrandID,
&i.Name,
&i.CronExpr,
&i.TargetPlatform,
&i.StartAt,
&i.EndAt,
&i.NextRunAt,
&i.Status,
&i.CreatedAt,
&i.UpdatedAt,
&i.PromptRuleName,
&i.BrandName,
)
return i, err
}
const listScheduleTasks = `-- name: ListScheduleTasks :many
SELECT st.id, st.tenant_id, st.prompt_rule_id, st.brand_id, st.name,
st.cron_expr, st.target_platform, st.start_at, st.end_at,
st.next_run_at, st.status, st.created_at, st.updated_at,
pr.name AS prompt_rule_name,
b.name AS brand_name
FROM schedule_tasks st
LEFT JOIN prompt_rules pr ON pr.id = st.prompt_rule_id
LEFT JOIN brands b ON b.id = st.brand_id
WHERE st.tenant_id = $1
AND st.deleted_at IS NULL
AND ($2::text IS NULL OR st.status = $2)
AND ($3::bigint IS NULL OR st.prompt_rule_id = $3)
ORDER BY st.created_at DESC
LIMIT $5 OFFSET $4
`
type ListScheduleTasksParams struct {
TenantID int64 `json:"tenant_id"`
Status pgtype.Text `json:"status"`
PromptRuleID pgtype.Int8 `json:"prompt_rule_id"`
PageOffset int32 `json:"page_offset"`
PageSize int32 `json:"page_size"`
}
type ListScheduleTasksRow struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
PromptRuleID int64 `json:"prompt_rule_id"`
BrandID pgtype.Int8 `json:"brand_id"`
Name string `json:"name"`
CronExpr string `json:"cron_expr"`
TargetPlatform pgtype.Text `json:"target_platform"`
StartAt pgtype.Timestamptz `json:"start_at"`
EndAt pgtype.Timestamptz `json:"end_at"`
NextRunAt pgtype.Timestamptz `json:"next_run_at"`
Status string `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
PromptRuleName pgtype.Text `json:"prompt_rule_name"`
BrandName pgtype.Text `json:"brand_name"`
}
func (q *Queries) ListScheduleTasks(ctx context.Context, arg ListScheduleTasksParams) ([]ListScheduleTasksRow, error) {
rows, err := q.db.Query(ctx, listScheduleTasks,
arg.TenantID,
arg.Status,
arg.PromptRuleID,
arg.PageOffset,
arg.PageSize,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListScheduleTasksRow
for rows.Next() {
var i ListScheduleTasksRow
if err := rows.Scan(
&i.ID,
&i.TenantID,
&i.PromptRuleID,
&i.BrandID,
&i.Name,
&i.CronExpr,
&i.TargetPlatform,
&i.StartAt,
&i.EndAt,
&i.NextRunAt,
&i.Status,
&i.CreatedAt,
&i.UpdatedAt,
&i.PromptRuleName,
&i.BrandName,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const softDeleteScheduleTask = `-- name: SoftDeleteScheduleTask :exec
UPDATE schedule_tasks SET deleted_at = NOW(), updated_at = NOW()
WHERE id = $1 AND tenant_id = $2 AND deleted_at IS NULL
`
type SoftDeleteScheduleTaskParams struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
}
func (q *Queries) SoftDeleteScheduleTask(ctx context.Context, arg SoftDeleteScheduleTaskParams) error {
_, err := q.db.Exec(ctx, softDeleteScheduleTask, arg.ID, arg.TenantID)
return err
}
const updateScheduleTask = `-- name: UpdateScheduleTask :exec
UPDATE schedule_tasks
SET prompt_rule_id = $1, brand_id = $2,
name = $3, cron_expr = $4,
target_platform = $5,
start_at = $6, end_at = $7,
next_run_at = $8, updated_at = NOW()
WHERE id = $9 AND tenant_id = $10 AND deleted_at IS NULL
`
type UpdateScheduleTaskParams struct {
PromptRuleID int64 `json:"prompt_rule_id"`
BrandID pgtype.Int8 `json:"brand_id"`
Name string `json:"name"`
CronExpr string `json:"cron_expr"`
TargetPlatform pgtype.Text `json:"target_platform"`
StartAt pgtype.Timestamptz `json:"start_at"`
EndAt pgtype.Timestamptz `json:"end_at"`
NextRunAt pgtype.Timestamptz `json:"next_run_at"`
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
}
func (q *Queries) UpdateScheduleTask(ctx context.Context, arg UpdateScheduleTaskParams) error {
_, err := q.db.Exec(ctx, updateScheduleTask,
arg.PromptRuleID,
arg.BrandID,
arg.Name,
arg.CronExpr,
arg.TargetPlatform,
arg.StartAt,
arg.EndAt,
arg.NextRunAt,
arg.ID,
arg.TenantID,
)
return err
}
const updateScheduleTaskStatus = `-- name: UpdateScheduleTaskStatus :exec
UPDATE schedule_tasks SET status = $1, updated_at = NOW()
WHERE id = $2 AND tenant_id = $3 AND deleted_at IS NULL
`
type UpdateScheduleTaskStatusParams struct {
Status string `json:"status"`
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
}
func (q *Queries) UpdateScheduleTaskStatus(ctx context.Context, arg UpdateScheduleTaskStatusParams) error {
_, err := q.db.Exec(ctx, updateScheduleTaskStatus, arg.Status, arg.ID, arg.TenantID)
return err
}
@@ -94,7 +94,7 @@ func (q *Queries) GetQuotaSummary(ctx context.Context, tenantID int64) (int32, e
const getRecentArticles = `-- name: GetRecentArticles :many
SELECT a.id, a.generate_status, a.publish_status, a.source_type, a.created_at,
av.title, av.word_count, av.source_label,
av.title, av.markdown_content, av.word_count, av.source_label,
t.template_name
FROM articles a
LEFT JOIN article_versions av ON av.id = a.current_version_id
@@ -105,15 +105,16 @@ LIMIT 10
`
type GetRecentArticlesRow struct {
ID int64 `json:"id"`
GenerateStatus string `json:"generate_status"`
PublishStatus string `json:"publish_status"`
SourceType string `json:"source_type"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
Title pgtype.Text `json:"title"`
WordCount pgtype.Int4 `json:"word_count"`
SourceLabel pgtype.Text `json:"source_label"`
TemplateName pgtype.Text `json:"template_name"`
ID int64 `json:"id"`
GenerateStatus string `json:"generate_status"`
PublishStatus string `json:"publish_status"`
SourceType string `json:"source_type"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
Title pgtype.Text `json:"title"`
MarkdownContent pgtype.Text `json:"markdown_content"`
WordCount pgtype.Int4 `json:"word_count"`
SourceLabel pgtype.Text `json:"source_label"`
TemplateName pgtype.Text `json:"template_name"`
}
func (q *Queries) GetRecentArticles(ctx context.Context, tenantID int64) ([]GetRecentArticlesRow, error) {
@@ -132,6 +133,7 @@ func (q *Queries) GetRecentArticles(ctx context.Context, tenantID int64) ([]GetR
&i.SourceType,
&i.CreatedAt,
&i.Title,
&i.MarkdownContent,
&i.WordCount,
&i.SourceLabel,
&i.TemplateName,