04/23 Add AI Analysis criteria
This commit is contained in:
@@ -309,6 +309,19 @@ def initialize_database():
|
|||||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
""",
|
""",
|
||||||
|
"""
|
||||||
|
CREATE TABLE IF NOT EXISTS ai_criteria (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
title VARCHAR(200) NOT NULL,
|
||||||
|
description TEXT NOT NULL,
|
||||||
|
is_active TINYINT(1) NOT NULL DEFAULT 1,
|
||||||
|
sort_order INT NOT NULL DEFAULT 0,
|
||||||
|
created_by INT,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
""",
|
||||||
]
|
]
|
||||||
|
|
||||||
conn = None
|
conn = None
|
||||||
|
|||||||
@@ -1386,3 +1386,119 @@ def get_unchecked_sites_for_user(user_id: int):
|
|||||||
finally:
|
finally:
|
||||||
if conn:
|
if conn:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
# ─── AI Criteria CRUD ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
def get_all_criteria():
|
||||||
|
"""Return all AI evaluation criteria ordered by sort_order, then id."""
|
||||||
|
conn = None
|
||||||
|
try:
|
||||||
|
conn = get_connection()
|
||||||
|
cur = conn.cursor(dictionary=True)
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
SELECT c.*, u.username AS creator
|
||||||
|
FROM ai_criteria c
|
||||||
|
LEFT JOIN users u ON u.id = c.created_by
|
||||||
|
ORDER BY c.sort_order, c.id
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
rows = cur.fetchall()
|
||||||
|
cur.close()
|
||||||
|
return rows
|
||||||
|
finally:
|
||||||
|
if conn:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
|
def get_active_criteria():
|
||||||
|
"""Return only active criteria for use in AI prompt construction."""
|
||||||
|
conn = None
|
||||||
|
try:
|
||||||
|
conn = get_connection()
|
||||||
|
cur = conn.cursor(dictionary=True)
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
SELECT id, title, description
|
||||||
|
FROM ai_criteria
|
||||||
|
WHERE is_active = 1
|
||||||
|
ORDER BY sort_order, id
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
rows = cur.fetchall()
|
||||||
|
cur.close()
|
||||||
|
return rows
|
||||||
|
finally:
|
||||||
|
if conn:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
|
def create_criterion(admin_id: int, title: str, description: str,
|
||||||
|
is_active: bool, sort_order: int) -> int:
|
||||||
|
"""Insert a new AI evaluation criterion. Returns the new row id."""
|
||||||
|
conn = None
|
||||||
|
try:
|
||||||
|
conn = get_connection()
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
INSERT INTO ai_criteria (title, description, is_active, sort_order, created_by)
|
||||||
|
VALUES (%s, %s, %s, %s, %s)
|
||||||
|
""",
|
||||||
|
(title, description, int(is_active), sort_order, admin_id)
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
new_id = cur.lastrowid
|
||||||
|
cur.close()
|
||||||
|
log_action(admin_id, "CREATE_AI_CRITERION", "ai_criteria", new_id,
|
||||||
|
f"Created criterion '{title}' active={is_active} order={sort_order}.")
|
||||||
|
logger.info(f"AI criterion id={new_id} '{title}' created by admin_id={admin_id}.")
|
||||||
|
return new_id
|
||||||
|
finally:
|
||||||
|
if conn:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
|
def update_criterion(admin_id: int, criterion_id: int, title: str,
|
||||||
|
description: str, is_active: bool, sort_order: int):
|
||||||
|
"""Update an existing AI evaluation criterion."""
|
||||||
|
conn = None
|
||||||
|
try:
|
||||||
|
conn = get_connection()
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
UPDATE ai_criteria
|
||||||
|
SET title=%s, description=%s, is_active=%s, sort_order=%s
|
||||||
|
WHERE id=%s
|
||||||
|
""",
|
||||||
|
(title, description, int(is_active), sort_order, criterion_id)
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
cur.close()
|
||||||
|
log_action(admin_id, "UPDATE_AI_CRITERION", "ai_criteria", criterion_id,
|
||||||
|
f"Updated criterion id={criterion_id} '{title}' active={is_active}.")
|
||||||
|
logger.info(f"AI criterion id={criterion_id} updated by admin_id={admin_id}.")
|
||||||
|
finally:
|
||||||
|
if conn:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
|
def delete_criterion(admin_id: int, criterion_id: int):
|
||||||
|
"""Hard-delete an AI evaluation criterion."""
|
||||||
|
conn = None
|
||||||
|
try:
|
||||||
|
conn = get_connection()
|
||||||
|
cur = conn.cursor(dictionary=True)
|
||||||
|
cur.execute("SELECT title FROM ai_criteria WHERE id=%s", (criterion_id,))
|
||||||
|
row = cur.fetchone()
|
||||||
|
title = row["title"] if row else str(criterion_id)
|
||||||
|
cur.execute("DELETE FROM ai_criteria WHERE id=%s", (criterion_id,))
|
||||||
|
conn.commit()
|
||||||
|
cur.close()
|
||||||
|
log_action(admin_id, "DELETE_AI_CRITERION", "ai_criteria", criterion_id,
|
||||||
|
f"Deleted criterion id={criterion_id} '{title}'.")
|
||||||
|
logger.info(f"AI criterion id={criterion_id} '{title}' deleted by admin_id={admin_id}.")
|
||||||
|
finally:
|
||||||
|
if conn:
|
||||||
|
conn.close()
|
||||||
|
|||||||
+503
-174
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user