Abimael Torcate Claude commited on
Commit ·
2e30dbb
1
Parent(s): 3d7739f
Fix PostgreSQL compatibility in get_comprehensive_analysis_data
Browse files- Replace complex CTE with separate simple queries
- Eliminate potential window function conflicts
- Split data retrieval into basic process data and interactions
- Combine results in Python for better PostgreSQL compatibility
- Maintain same functionality with improved database compatibility
- Should resolve aggregate function calls cannot contain window function calls error
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- utils/database.py +57 -62
utils/database.py
CHANGED
|
@@ -530,75 +530,70 @@ def get_comprehensive_analysis_data():
|
|
| 530 |
"""Retorna dados completos para análise com IA"""
|
| 531 |
with get_db_connection() as conn:
|
| 532 |
with conn.cursor(cursor_factory=RealDictCursor) as cur:
|
| 533 |
-
#
|
| 534 |
cur.execute("""
|
| 535 |
-
WITH checklist_progress AS (
|
| 536 |
-
SELECT
|
| 537 |
-
c.id,
|
| 538 |
-
c.numero_processo,
|
| 539 |
-
c.created_at,
|
| 540 |
-
COUNT(ci.id) as total_items,
|
| 541 |
-
COUNT(CASE WHEN cis.is_checked THEN 1 END) as completed_items,
|
| 542 |
-
CASE
|
| 543 |
-
WHEN COUNT(ci.id) > 0 THEN
|
| 544 |
-
ROUND((COUNT(CASE WHEN cis.is_checked THEN 1 END)::decimal / COUNT(ci.id)) * 100, 1)
|
| 545 |
-
ELSE 0
|
| 546 |
-
END as progress_percentage
|
| 547 |
-
FROM checklists c
|
| 548 |
-
LEFT JOIN checklist_items ci ON c.id = ci.checklist_id
|
| 549 |
-
LEFT JOIN current_item_states cis ON ci.id = cis.item_id
|
| 550 |
-
WHERE c.numero_processo IS NOT NULL
|
| 551 |
-
GROUP BY c.id, c.numero_processo, c.created_at
|
| 552 |
-
),
|
| 553 |
-
process_stats AS (
|
| 554 |
-
SELECT
|
| 555 |
-
cp.numero_processo,
|
| 556 |
-
COUNT(cp.id) as total_checklists,
|
| 557 |
-
MIN(cp.created_at) as process_start_date,
|
| 558 |
-
MAX(cp.created_at) as latest_checklist_date,
|
| 559 |
-
SUM(cp.total_items) as total_items,
|
| 560 |
-
SUM(cp.completed_items) as completed_items,
|
| 561 |
-
ROUND(AVG(cp.progress_percentage), 1) as avg_progress_percentage,
|
| 562 |
-
COUNT(ii.id) as total_interactions,
|
| 563 |
-
MIN(ii.timestamp) as first_interaction,
|
| 564 |
-
MAX(ii.timestamp) as last_interaction,
|
| 565 |
-
CURRENT_DATE - MIN(cp.created_at)::date as days_elapsed,
|
| 566 |
-
(MIN(cp.created_at) + INTERVAL '180 days')::date - CURRENT_DATE as days_remaining_to_deadline
|
| 567 |
-
FROM checklist_progress cp
|
| 568 |
-
LEFT JOIN item_interactions ii ON cp.id = ii.checklist_id
|
| 569 |
-
GROUP BY cp.numero_processo
|
| 570 |
-
)
|
| 571 |
SELECT
|
| 572 |
-
numero_processo,
|
| 573 |
-
total_checklists,
|
| 574 |
-
process_start_date,
|
| 575 |
-
latest_checklist_date,
|
| 576 |
-
total_items,
|
| 577 |
-
completed_items,
|
| 578 |
-
avg_progress_percentage,
|
| 579 |
-
total_interactions,
|
| 580 |
-
first_interaction,
|
| 581 |
-
last_interaction,
|
| 582 |
-
days_elapsed,
|
| 583 |
-
days_remaining_to_deadline,
|
| 584 |
-
CASE
|
| 585 |
-
WHEN avg_progress_percentage = 100 THEN 'CONCLUIDO'
|
| 586 |
-
WHEN days_remaining_to_deadline < 0 THEN 'ATRASADO'
|
| 587 |
-
WHEN days_remaining_to_deadline < 30 THEN 'EM_RISCO'
|
| 588 |
-
ELSE 'NO_PRAZO'
|
| 589 |
-
END as status_prazo,
|
| 590 |
CASE
|
| 591 |
-
WHEN
|
| 592 |
-
ROUND((
|
| 593 |
-
ELSE
|
| 594 |
-
END as
|
| 595 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 596 |
ORDER BY days_remaining_to_deadline ASC
|
| 597 |
""")
|
| 598 |
|
| 599 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 600 |
|
| 601 |
-
# Estatísticas globais
|
| 602 |
cur.execute("""
|
| 603 |
SELECT
|
| 604 |
COUNT(DISTINCT c.id) as total_checklists_global,
|
|
|
|
| 530 |
"""Retorna dados completos para análise com IA"""
|
| 531 |
with get_db_connection() as conn:
|
| 532 |
with conn.cursor(cursor_factory=RealDictCursor) as cur:
|
| 533 |
+
# Primeira query: dados básicos dos processos
|
| 534 |
cur.execute("""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 535 |
SELECT
|
| 536 |
+
c.numero_processo,
|
| 537 |
+
COUNT(DISTINCT c.id) as total_checklists,
|
| 538 |
+
MIN(c.created_at) as process_start_date,
|
| 539 |
+
MAX(c.created_at) as latest_checklist_date,
|
| 540 |
+
COUNT(ci.id) as total_items,
|
| 541 |
+
COUNT(CASE WHEN cis.is_checked THEN 1 END) as completed_items,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 542 |
CASE
|
| 543 |
+
WHEN COUNT(ci.id) > 0 THEN
|
| 544 |
+
ROUND((COUNT(CASE WHEN cis.is_checked THEN 1 END)::decimal / COUNT(ci.id)) * 100, 1)
|
| 545 |
+
ELSE 0
|
| 546 |
+
END as avg_progress_percentage,
|
| 547 |
+
CURRENT_DATE - MIN(c.created_at)::date as days_elapsed,
|
| 548 |
+
(MIN(c.created_at) + INTERVAL '180 days')::date - CURRENT_DATE as days_remaining_to_deadline
|
| 549 |
+
FROM checklists c
|
| 550 |
+
LEFT JOIN checklist_items ci ON c.id = ci.checklist_id
|
| 551 |
+
LEFT JOIN current_item_states cis ON ci.id = cis.item_id
|
| 552 |
+
WHERE c.numero_processo IS NOT NULL
|
| 553 |
+
GROUP BY c.numero_processo
|
| 554 |
ORDER BY days_remaining_to_deadline ASC
|
| 555 |
""")
|
| 556 |
|
| 557 |
+
basic_process_data = cur.fetchall()
|
| 558 |
+
|
| 559 |
+
# Segunda query: dados de interações por processo
|
| 560 |
+
process_data = []
|
| 561 |
+
for process in basic_process_data:
|
| 562 |
+
cur.execute("""
|
| 563 |
+
SELECT
|
| 564 |
+
COUNT(ii.id) as total_interactions,
|
| 565 |
+
MIN(ii.timestamp) as first_interaction,
|
| 566 |
+
MAX(ii.timestamp) as last_interaction
|
| 567 |
+
FROM checklists c
|
| 568 |
+
LEFT JOIN item_interactions ii ON c.id = ii.checklist_id
|
| 569 |
+
WHERE c.numero_processo = %s
|
| 570 |
+
""", (process['numero_processo'],))
|
| 571 |
+
|
| 572 |
+
interaction_data = cur.fetchone()
|
| 573 |
+
|
| 574 |
+
# Combinar dados
|
| 575 |
+
combined_process = dict(process)
|
| 576 |
+
combined_process.update(interaction_data)
|
| 577 |
+
|
| 578 |
+
# Adicionar campos calculados
|
| 579 |
+
combined_process['status_prazo'] = (
|
| 580 |
+
'CONCLUIDO' if combined_process['avg_progress_percentage'] == 100
|
| 581 |
+
else 'ATRASADO' if combined_process['days_remaining_to_deadline'] < 0
|
| 582 |
+
else 'EM_RISCO' if combined_process['days_remaining_to_deadline'] < 30
|
| 583 |
+
else 'NO_PRAZO'
|
| 584 |
+
)
|
| 585 |
+
|
| 586 |
+
if combined_process['days_elapsed'] > 0 and combined_process['avg_progress_percentage'] > 0:
|
| 587 |
+
combined_process['projected_days_to_complete'] = round(
|
| 588 |
+
(combined_process['avg_progress_percentage'] / combined_process['days_elapsed']) *
|
| 589 |
+
(100 - combined_process['avg_progress_percentage'])
|
| 590 |
+
)
|
| 591 |
+
else:
|
| 592 |
+
combined_process['projected_days_to_complete'] = None
|
| 593 |
+
|
| 594 |
+
process_data.append(combined_process)
|
| 595 |
|
| 596 |
+
# Estatísticas globais - query simples
|
| 597 |
cur.execute("""
|
| 598 |
SELECT
|
| 599 |
COUNT(DISTINCT c.id) as total_checklists_global,
|