04/23 Enhance app functionalities 2
This commit is contained in:
@@ -993,7 +993,17 @@ def get_unchecked_report(target_date=None, user_id=None):
|
||||
|
||||
def get_summary_report(date_from=None, date_to=None):
|
||||
"""
|
||||
Per-user per-day summary: total sites checked vs total active sites.
|
||||
Per-user per-day summary: sites checked vs the sites that user was
|
||||
expected to check on that specific day (shift-scoped total).
|
||||
|
||||
The previous implementation used a global COUNT(*) of all active websites
|
||||
as the denominator, producing misleading percentages — a user in a 3-site
|
||||
shift who checked all 3 would show 15% against 20 global sites.
|
||||
|
||||
The corrected subquery counts the distinct websites in the shifts the user
|
||||
was assigned to that ran on the check_date's day-of-week. For historical
|
||||
dates this still uses DAYOFWEEK(check_date) to match the shift schedule.
|
||||
|
||||
Columns: check_date, username, full_name, checked_count, total_sites, pct_complete
|
||||
"""
|
||||
conn = None
|
||||
@@ -1015,16 +1025,38 @@ def get_summary_report(date_from=None, date_to=None):
|
||||
cur.execute(
|
||||
f"""
|
||||
SELECT
|
||||
DATE(sc.checked_at) AS check_date,
|
||||
DATE(sc.checked_at) AS check_date,
|
||||
u.username,
|
||||
COALESCE(u.full_name, u.username) AS full_name,
|
||||
COUNT(DISTINCT sc.website_id) AS checked_count,
|
||||
(SELECT COUNT(*) FROM websites WHERE is_active=1) AS total_sites,
|
||||
COALESCE(u.full_name, u.username) AS full_name,
|
||||
COUNT(DISTINCT sc.website_id) AS checked_count,
|
||||
(
|
||||
SELECT COUNT(DISTINCT sw2.website_id)
|
||||
FROM shift_websites sw2
|
||||
JOIN shifts s2 ON s2.id = sw2.shift_id
|
||||
JOIN shift_users su2 ON su2.shift_id = s2.id
|
||||
AND su2.user_id = u.id
|
||||
WHERE s2.is_active = 1
|
||||
AND LOCATE(
|
||||
CAST(DAYOFWEEK(DATE(sc.checked_at)) AS CHAR),
|
||||
s2.days_of_week
|
||||
) > 0
|
||||
) AS total_sites,
|
||||
ROUND(
|
||||
COUNT(DISTINCT sc.website_id) * 100.0 /
|
||||
NULLIF((SELECT COUNT(*) FROM websites WHERE is_active=1), 0),
|
||||
NULLIF((
|
||||
SELECT COUNT(DISTINCT sw2.website_id)
|
||||
FROM shift_websites sw2
|
||||
JOIN shifts s2 ON s2.id = sw2.shift_id
|
||||
JOIN shift_users su2 ON su2.shift_id = s2.id
|
||||
AND su2.user_id = u.id
|
||||
WHERE s2.is_active = 1
|
||||
AND LOCATE(
|
||||
CAST(DAYOFWEEK(DATE(sc.checked_at)) AS CHAR),
|
||||
s2.days_of_week
|
||||
) > 0
|
||||
), 0),
|
||||
1
|
||||
) AS pct_complete
|
||||
) AS pct_complete
|
||||
FROM shift_checks sc
|
||||
JOIN users u ON u.id = sc.user_id
|
||||
{where_clause}
|
||||
@@ -1430,17 +1462,22 @@ def get_unchecked_sites_for_user(user_id: int):
|
||||
# ─── AI Criteria CRUD ─────────────────────────────────────────────────────────
|
||||
|
||||
def get_all_criteria():
|
||||
"""Return all AI evaluation criteria ordered by sort_order, then id."""
|
||||
"""Return all AI evaluation criteria ordered by sort_order, then id.
|
||||
|
||||
The creator username is intentionally omitted — the criteria treeview does
|
||||
not display it and the LEFT JOIN was adding a needless per-call cost.
|
||||
If a creator column is ever added to the UI, restore the JOIN here.
|
||||
"""
|
||||
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
|
||||
SELECT id, title, description, is_active, sort_order,
|
||||
created_by, created_at, updated_at
|
||||
FROM ai_criteria
|
||||
ORDER BY sort_order, id
|
||||
"""
|
||||
)
|
||||
rows = cur.fetchall()
|
||||
|
||||
Reference in New Issue
Block a user