118 lines
3.8 KiB
TypeScript
118 lines
3.8 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { buildM7Dataset, computeM3Counters } from "@/lib/compliance/m7";
|
|
import { ProposalWorkflowStateSchema } from "@/lib/proposals/workflow-state";
|
|
|
|
function buildWorkflowWithDeadline(dateIso: string) {
|
|
return ProposalWorkflowStateSchema.parse({
|
|
step: 5,
|
|
info: {
|
|
title: "Licitacion infraestructura",
|
|
issuingEntity: "Gobierno municipal",
|
|
procedureType: "Publica",
|
|
jurisdiction: "Estatal",
|
|
state: "Nuevo Leon",
|
|
municipality: "Monterrey",
|
|
sector: "Obra publica",
|
|
description: "Proceso de prueba",
|
|
convocatoriaUrl: "https://example.com/convocatoria",
|
|
},
|
|
requirements: [
|
|
{
|
|
id: "req-critical",
|
|
title: "Garantia critica",
|
|
description: "Incumplimiento puede descalificar la propuesta",
|
|
category: "legal",
|
|
mandatory: true,
|
|
source: "critical_requirement",
|
|
status: "pending",
|
|
note: "",
|
|
evidences: [],
|
|
},
|
|
],
|
|
technicalSections: [{ id: "tech-1", title: "Alcance tecnico", description: "Detalle tecnico", completed: true }],
|
|
economicItems: [{ id: "eco-1", concept: "Servicio", unit: "lote", quantity: 1, unitPrice: 1000 }],
|
|
milestones: [{ id: "mil-1", title: "Entrega", dateIso, location: "", note: "", source: "manual" }],
|
|
signatureCompliance: {
|
|
policyStatus: "condicionado",
|
|
policyName: "Politica piloto",
|
|
jurisdictionLabel: "Nuevo Leon",
|
|
sourceUrl: "https://www.nl.gob.mx/",
|
|
minimumEvidence: ["Acuse"],
|
|
notes: "",
|
|
validatedByLegal: false,
|
|
},
|
|
readyMarked: false,
|
|
});
|
|
}
|
|
|
|
describe("M3 -> M5 -> M7 integration", () => {
|
|
it("combines M3 preferences with active M5 workflow into M7 KPI snapshot", () => {
|
|
const now = new Date("2026-04-02T10:00:00.000Z");
|
|
const m3 = computeM3Counters({
|
|
totalOpenLicitations: 8,
|
|
preferences: [{ status: "REVIEWED" }, { status: "INTERESTED" }, { status: "INTERESTED" }],
|
|
activeLinked: 1,
|
|
});
|
|
|
|
const dataset = buildM7Dataset({
|
|
proposals: [
|
|
{
|
|
id: "proposal-1",
|
|
title: "Propuesta M5 activa",
|
|
status: "IN_PROGRESS",
|
|
sourceLicitationId: "licit-1",
|
|
workflowDraft: buildWorkflowWithDeadline("2026-04-03T09:00:00.000Z"),
|
|
updatedAt: now,
|
|
},
|
|
],
|
|
m3,
|
|
dueVerifications: [],
|
|
now,
|
|
});
|
|
|
|
expect(dataset.kpis.activeLicitations).toBe(1);
|
|
expect(dataset.m3States.consulted).toBe(1);
|
|
expect(dataset.m3States.interested).toBe(2);
|
|
expect(dataset.m3States.active).toBe(1);
|
|
expect(dataset.tabs.checklist.length).toBe(1);
|
|
expect(dataset.tabs.panelKpi.some((item) => item.label === "M3 Consultadas")).toBe(true);
|
|
});
|
|
|
|
it("raises critical pending alert when high-risk pending items meet near deadlines", () => {
|
|
const now = new Date("2026-04-02T10:00:00.000Z");
|
|
const m3 = computeM3Counters({
|
|
totalOpenLicitations: 3,
|
|
preferences: [],
|
|
activeLinked: 1,
|
|
});
|
|
|
|
const dataset = buildM7Dataset({
|
|
proposals: [
|
|
{
|
|
id: "proposal-critical",
|
|
title: "Propuesta critica",
|
|
status: "DRAFT",
|
|
sourceLicitationId: "licit-2",
|
|
workflowDraft: buildWorkflowWithDeadline("2026-04-02T12:00:00.000Z"),
|
|
updatedAt: now,
|
|
},
|
|
],
|
|
m3,
|
|
dueVerifications: [
|
|
{
|
|
sourceId: "nl-reg",
|
|
sourceTitle: "Reglamento NL",
|
|
authorityName: "Gobierno NL",
|
|
dueAt: "2026-04-02T11:00:00.000Z",
|
|
overdue: false,
|
|
},
|
|
],
|
|
now,
|
|
});
|
|
|
|
expect(dataset.kpis.criticalPending).toBeGreaterThan(0);
|
|
expect(dataset.tabs.alertas.some((item) => item.kind === "critical_requirement_pending")).toBe(true);
|
|
expect(dataset.tabs.alertas.some((item) => item.kind === "deadline_soon")).toBe(true);
|
|
});
|
|
});
|