"""Regras de classificação de vencimento/prazo/categoria de ação — porta as regras de negócio da skill "analise-ncs" (ver `projects/Controladoria - Analise NCs/analise-ncs_SKILL.md`). IMPORTANTE: `status_prazo()`/`dias_para_vencer()` dependem da data de hoje — NUNCA persistir o resultado no banco, sempre calcular em tempo de leitura (serializer/dashboard). Só `vencimento_efetivo()` é seguro cachear num model (só muda com uma importação nova).""" from __future__ import annotations from datetime import date STATUS_VENCIDA = "vencida" STATUS_VENCE_7 = "vence_7_dias" STATUS_VENCE_30 = "vence_30_dias" STATUS_NO_PRAZO = "no_prazo" STATUS_SEM_VENCIMENTO = "sem_vencimento" STATUS_PRAZO_LABELS = { STATUS_VENCIDA: "Vencida", STATUS_VENCE_7: "Vence em ≤7 dias", STATUS_VENCE_30: "Vence em ≤30 dias", STATUS_NO_PRAZO: "No prazo", STATUS_SEM_VENCIMENTO: "Sem vencimento", } CATEGORIA_CORRETIVA = "Ação Corretiva" CATEGORIA_CORRECAO = "Correção" CATEGORIA_OUTROS = "Outros" # Tipos de ocorrência que exigem Correção + Ação Corretiva (regra #9 da skill). TIPOS_NC = ("Não Conformidade", "Reclamação de Cliente") def vencimento_efetivo(prazo_prorrogado: date | None, data_conclusao: date | None) -> date | None: """Prazo Prorrogado se preenchido, senão Data da Conclusão da Ação (que no export é a data-limite prevista, não a conclusão real).""" return prazo_prorrogado or data_conclusao def categoria_acao(tipo_acao: str) -> str: tl = (tipo_acao or "").lower() if "corretiva" in tl: return CATEGORIA_CORRETIVA if "correç" in tl or "correc" in tl: return CATEGORIA_CORRECAO return CATEGORIA_OUTROS def status_prazo(venc: date | None, hoje: date) -> str: if venc is None: return STATUS_SEM_VENCIMENTO if venc < hoje: return STATUS_VENCIDA dias = (venc - hoje).days if dias <= 7: return STATUS_VENCE_7 if dias <= 30: return STATUS_VENCE_30 return STATUS_NO_PRAZO def dias_para_vencer(venc: date | None, hoje: date) -> int | None: if venc is None: return None return (venc - hoje).days