feat(meta-orcamento-consolidado): adicionando view de orcamento conso…#592
feat(meta-orcamento-consolidado): adicionando view de orcamento conso…#592lucasansei wants to merge 3 commits intohomolfrom
Conversation
…lidado e triggers
📝 WalkthroughWalkthroughAdds a consolidated per-meta budget table and Prisma model, PostgreSQL functions/triggers to aggregate and upsert totals from planned/realized budgets, a deduplicated queue task and worker service to refresh consolidations, and exposes consolidated totals in the Meta API response. Initial population and recalculation are included. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant API as Backend API
participant TaskQ as Task Queue (DB table)
participant DB as Postgres
Client->>API: create/update/delete orcamento_planejado/realizado
API->>DB: execute DML
DB->>DB: trigger tg_orcamento_*_refresh_consolidado fires
DB->>TaskQ: insert deduplicated refresh task (refresh_meta_orcamento_consolidado)
Note right of TaskQ: Task worker (TaskService) picks tasks
TaskQ->>API: TaskService executes RefreshMetaOrcamentoConsolidadoService
API->>DB: call f_refresh_meta_orcamento_consolidado(meta_id) within tx
DB->>DB: aggregate planned/realized by classification and upsert meta_orcamento_consolidado
DB-->>API: success
API-->>Client: subsequent reads include MetaOrcamentoConsolidado
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
backend/src/meta/meta.service.ts (1)
630-649: Gate MetaOrcamentoConsolidado select on both ID filter and non-permission-check flows.When
skipObjectsistrue(e.g., inassertMetaWriteOrThrow), this relation is still selected iffilters.idis set, adding unnecessary DB work. The orcamento mapping happens outside theif (!skipObjects)guard and is always returned (null or mapped), but fetching the relation remains wasteful during permission-only checks.♻️ Suggested change
MetaOrcamentoConsolidado: - filters?.id !== undefined + filters?.id !== undefined && !skipObjects ? { select: { total_previsao: true, total_empenhado: true, total_liquidado: true, total_previsao_projeto: true, total_empenhado_projeto: true, total_liquidado_projeto: true, total_previsao_atividade: true, total_empenhado_atividade: true, total_liquidado_atividade: true, total_previsao_operacao_especial: true, total_empenhado_operacao_especial: true, total_liquidado_operacao_especial: true, atualizado_em: true, }, } : undefined,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/src/meta/meta.service.ts` around lines 630 - 649, The MetaOrcamentoConsolidado relation is being selected whenever filters.id is set even when skipObjects is true (e.g., inside assertMetaWriteOrThrow), causing unnecessary DB work; update the selection logic where MetaOrcamentoConsolidado is added so it only includes the select block when skipObjects is false AND filters?.id !== undefined (i.e., gate the existing select behind a check of skipObjects), keeping the existing fields and leaving the orcamento mapping unchanged so permission-only flows avoid fetching the relation.backend/prisma/manual-copy/0056-atualiza-meta-orcamento-consolidado.pgsql (1)
262-323: Consider extracting shared meta resolution logic.The trigger functions
tg_orcamento_planejado_refresh_consolidadoandtg_orcamento_realizado_refresh_consolidadoshare nearly identical logic. Consider extracting the meta resolution into a helper function to reduce duplication and ease maintenance:CREATE OR REPLACE FUNCTION f_resolve_meta_id( p_meta_id INT, p_iniciativa_id INT, p_atividade_id INT ) RETURNS INT AS $$ DECLARE v_meta_id INT; BEGIN IF p_meta_id IS NOT NULL THEN RETURN p_meta_id; ELSIF p_iniciativa_id IS NOT NULL THEN SELECT meta_id INTO v_meta_id FROM iniciativa WHERE id = p_iniciativa_id; RETURN v_meta_id; ELSIF p_atividade_id IS NOT NULL THEN SELECT i.meta_id INTO v_meta_id FROM atividade a JOIN iniciativa i ON i.id = a.iniciativa_id WHERE a.id = p_atividade_id; RETURN v_meta_id; END IF; RETURN NULL; END; $$ LANGUAGE plpgsql STABLE;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/prisma/manual-copy/0056-atualiza-meta-orcamento-consolidado.pgsql` around lines 262 - 323, Both tg_orcamento_planejado_refresh_consolidado and tg_orcamento_realizado_refresh_consolidado duplicate the same meta resolution logic; extract that logic into a new helper function (suggested name f_resolve_meta_id(p_meta_id INT, p_iniciativa_id INT, p_atividade_id INT) RETURNS INT STABLE) and replace the repeated blocks that compute v_meta_id and v_old_meta_id with calls to f_resolve_meta_id(NEW.meta_id, NEW.iniciativa_id, NEW.atividade_id) and f_resolve_meta_id(OLD.meta_id, OLD.iniciativa_id, OLD.atividade_id) respectively, leaving the calls to f_refresh_meta_orcamento_consolidado(v_meta_id) and the UPDATE-old-vs-new comparison logic intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@backend/prisma/manual-copy/0056-atualiza-meta-orcamento-consolidado.pgsql`:
- Around line 246-249: The NULL comparison can short-circuit the IF when
v_meta_id is NULL; change the condition so a difference with NULL is
detected—e.g., in the IF that currently reads "IF v_old_meta_id IS NOT NULL AND
v_old_meta_id != v_meta_id THEN" replace the inequality check with a NULL-safe
comparison (use IS DISTINCT FROM) so it becomes "v_old_meta_id IS NOT NULL AND
v_old_meta_id IS DISTINCT FROM v_meta_id", ensuring
f_refresh_meta_orcamento_consolidado(v_old_meta_id) is called when the old meta
differs or the new meta is NULL.
- Around line 315-318: The current IF condition uses "v_old_meta_id IS NOT NULL
AND v_old_meta_id != v_meta_id" which fails when v_meta_id is NULL; update the
condition in the trigger to use SQL NULL-safe comparison so the refresh runs
when values differ or one is NULL — e.g., change the check around
f_refresh_meta_orcamento_consolidado to "IF v_old_meta_id IS NOT NULL AND
v_old_meta_id IS DISTINCT FROM v_meta_id THEN PERFORM
f_refresh_meta_orcamento_consolidado(v_old_meta_id); END IF;" so v_meta_id NULL
is handled correctly.
---
Nitpick comments:
In `@backend/prisma/manual-copy/0056-atualiza-meta-orcamento-consolidado.pgsql`:
- Around line 262-323: Both tg_orcamento_planejado_refresh_consolidado and
tg_orcamento_realizado_refresh_consolidado duplicate the same meta resolution
logic; extract that logic into a new helper function (suggested name
f_resolve_meta_id(p_meta_id INT, p_iniciativa_id INT, p_atividade_id INT)
RETURNS INT STABLE) and replace the repeated blocks that compute v_meta_id and
v_old_meta_id with calls to f_resolve_meta_id(NEW.meta_id, NEW.iniciativa_id,
NEW.atividade_id) and f_resolve_meta_id(OLD.meta_id, OLD.iniciativa_id,
OLD.atividade_id) respectively, leaving the calls to
f_refresh_meta_orcamento_consolidado(v_meta_id) and the UPDATE-old-vs-new
comparison logic intact.
In `@backend/src/meta/meta.service.ts`:
- Around line 630-649: The MetaOrcamentoConsolidado relation is being selected
whenever filters.id is set even when skipObjects is true (e.g., inside
assertMetaWriteOrThrow), causing unnecessary DB work; update the selection logic
where MetaOrcamentoConsolidado is added so it only includes the select block
when skipObjects is false AND filters?.id !== undefined (i.e., gate the existing
select behind a check of skipObjects), keeping the existing fields and leaving
the orcamento mapping unchanged so permission-only flows avoid fetching the
relation.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
backend/prisma/manual-copy/0056-atualiza-meta-orcamento-consolidado.pgsqlbackend/prisma/migrations/20260226121720_meta_orcamento_consolidado/migration.sqlbackend/prisma/schema.prismabackend/src/meta/entities/meta.entity.tsbackend/src/meta/meta.service.ts
backend/prisma/manual-copy/0056-atualiza-meta-orcamento-consolidado.pgsql
Show resolved
Hide resolved
backend/prisma/manual-copy/0056-atualiza-meta-orcamento-consolidado.pgsql
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
backend/prisma/manual-copy/0056-atualiza-meta-orcamento-consolidado.pgsql (2)
263-323: Consider extracting shared meta resolution logic.The trigger functions
tg_orcamento_planejado_refresh_consolidadoandtg_orcamento_realizado_refresh_consolidadoshare identical meta_id resolution logic. Consider extracting this into a helper function to reduce duplication:CREATE OR REPLACE FUNCTION f_resolve_meta_id_from_budget( p_meta_id INT, p_iniciativa_id INT, p_atividade_id INT ) RETURNS INT AS $$ ...This is a nice-to-have improvement and can be deferred.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/prisma/manual-copy/0056-atualiza-meta-orcamento-consolidado.pgsql` around lines 263 - 323, Extract the repeated meta_id resolution into a new function named f_resolve_meta_id_from_budget(p_meta_id INT, p_iniciativa_id INT, p_atividade_id INT) RETURNS INT that returns the resolved meta_id (use the same logic: return p_meta_id if not null, otherwise lookup iniciativa.meta_id by p_iniciativa_id, otherwise join atividade->iniciativa to get meta_id by p_atividade_id). Replace the inline resolution blocks in tg_orcamento_realizado_refresh_consolidado (both NEW and OLD resolution and v_meta_id/v_old_meta_id assignments) and the equivalent blocks in tg_orcamento_planejado_refresh_consolidado to call f_resolve_meta_id_from_budget(NEW.meta_id, NEW.iniciativa_id, NEW.atividade_id) and f_resolve_meta_id_from_budget(OLD.meta_id, OLD.iniciativa_id, OLD.atividade_id) respectively, keeping the same conditional calls to f_refresh_meta_orcamento_consolidado and the UPDATE comparison logic.
256-260: Row-level triggers may cause performance issues during bulk operations.These
FOR EACH ROWtriggers will callf_refresh_meta_orcamento_consolidadofor every affected row. During bulk inserts/updates (e.g., batch imports), this results in redundant recalculations for the samemeta_id.Consider whether bulk operations on these tables are common. If so, you might want to:
- Add a mechanism to temporarily disable triggers during bulk operations
- Or implement a deferred/batched approach using a queue table
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/prisma/manual-copy/0056-atualiza-meta-orcamento-consolidado.pgsql` around lines 256 - 260, The FOR EACH ROW trigger tg_orcamento_planejado_refresh_consolidado on table orcamento_planejado calls f_refresh_meta_orcamento_consolidado for every row and will cause redundant work in bulk operations; to fix, either convert to a FOR EACH STATEMENT trigger (so the function runs once per statement) or implement a two-step batched approach: change the trigger to collect distinct meta_id values into a queue table (e.g., refresh_meta_queue) from tg_orcamento_planejado_refresh_consolidado and create a separate worker/function that processes distinct meta_id entries and calls f_refresh_meta_orcamento_consolidado, or document adding ALTER TABLE ... DISABLE TRIGGER for controlled bulk loads — update trigger definition and related logic accordingly to avoid per-row recalculation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@backend/prisma/manual-copy/0056-atualiza-meta-orcamento-consolidado.pgsql`:
- Around line 12-14: Update the misleading inline comment near the code that
concatenates array elements into codigo: the comment currently says "índices 5 e
6" but the code uses partes[6] and partes[7], so change the comment to "índices
6 e 7" (or otherwise reword to state they refer to the 6th and 7th elements) to
accurately reflect the PostgreSQL 1-based array indices used by the partes ->
codigo concatenation.
---
Nitpick comments:
In `@backend/prisma/manual-copy/0056-atualiza-meta-orcamento-consolidado.pgsql`:
- Around line 263-323: Extract the repeated meta_id resolution into a new
function named f_resolve_meta_id_from_budget(p_meta_id INT, p_iniciativa_id INT,
p_atividade_id INT) RETURNS INT that returns the resolved meta_id (use the same
logic: return p_meta_id if not null, otherwise lookup iniciativa.meta_id by
p_iniciativa_id, otherwise join atividade->iniciativa to get meta_id by
p_atividade_id). Replace the inline resolution blocks in
tg_orcamento_realizado_refresh_consolidado (both NEW and OLD resolution and
v_meta_id/v_old_meta_id assignments) and the equivalent blocks in
tg_orcamento_planejado_refresh_consolidado to call
f_resolve_meta_id_from_budget(NEW.meta_id, NEW.iniciativa_id, NEW.atividade_id)
and f_resolve_meta_id_from_budget(OLD.meta_id, OLD.iniciativa_id,
OLD.atividade_id) respectively, keeping the same conditional calls to
f_refresh_meta_orcamento_consolidado and the UPDATE comparison logic.
- Around line 256-260: The FOR EACH ROW trigger
tg_orcamento_planejado_refresh_consolidado on table orcamento_planejado calls
f_refresh_meta_orcamento_consolidado for every row and will cause redundant work
in bulk operations; to fix, either convert to a FOR EACH STATEMENT trigger (so
the function runs once per statement) or implement a two-step batched approach:
change the trigger to collect distinct meta_id values into a queue table (e.g.,
refresh_meta_queue) from tg_orcamento_planejado_refresh_consolidado and create a
separate worker/function that processes distinct meta_id entries and calls
f_refresh_meta_orcamento_consolidado, or document adding ALTER TABLE ... DISABLE
TRIGGER for controlled bulk loads — update trigger definition and related logic
accordingly to avoid per-row recalculation.
backend/prisma/manual-copy/0056-atualiza-meta-orcamento-consolidado.pgsql
Show resolved
Hide resolved
…om fila e deduplicação para recálculo Inclui procedure e função PL/pgSQL para enfileirar tarefas de recálculo da meta orcamento consolidado com deduplicação por txid, atualiza triggers para usar essa fila, adiciona suporte no schema Prisma, cria módulo, serviço e DTO no backend para executar a tarefa de forma resiliente com retries, e integra o novo serviço ao sistema de tasks existente. Isso melhora a escalabilidade e evita execuções redundantes do recálculo, garantindo maior eficiência e consistência.
|
Como tem a importação do orçamento, achei importante mover pra um refresh async |
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@backend/prisma/manual-copy/0056-atualiza-meta-orcamento-consolidado.pgsql`:
- Around line 198-205: The NOT EXISTS dedup check in the task_queue insertion
uses an unnecessary criado_em = now() predicate; remove the criado_em = now()
conjunct so the check relies solely on "type" =
'refresh_meta_orcamento_consolidado', status = 'pending',
(params->>'meta_id')::INTEGER = p_meta_id and (params->>'current_txid')::bigint
= current_txid; update the same pattern wherever it appears (e.g. the similar
checks in 0031-trigger.meta.consolidado.pgsql and
0039-trigger.transferencia.consolidado.pgsql) to avoid coupling deduplication to
the timestamp.
In
`@backend/src/task/refresh_meta_orcamento_consolidado/refresh-meta-orcamento-consolidado.service.ts`:
- Around line 19-25: The UPDATE that marks duplicate tasks as completed must
also set the completion timestamp to keep audit consistency; in the method in
refresh-meta-orcamento-consolidado.service.ts where the raw query runs (using
task.id and inputParams.meta_id) update the SQL to include terminou_em = now()
(or the DB-equivalent timestamp function) alongside status='completed' and
output so duplicated rows get a termination time; ensure the same parameter
interpolation ( ${task.id}, ${inputParams.meta_id} ) is preserved.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
backend/prisma/manual-copy/0056-atualiza-meta-orcamento-consolidado.pgsqlbackend/prisma/schema.prismabackend/src/task/refresh_meta_orcamento_consolidado/dto/create-refresh-meta-orcamento-consolidado.dto.tsbackend/src/task/refresh_meta_orcamento_consolidado/refresh-meta-orcamento-consolidado.module.tsbackend/src/task/refresh_meta_orcamento_consolidado/refresh-meta-orcamento-consolidado.service.tsbackend/src/task/task.module.tsbackend/src/task/task.parseParams.tsbackend/src/task/task.service.ts



…lidado e triggers
Summary by CodeRabbit