Requirements Module: Technical Request Intake and Routing
Capture client technical needs and route them through diagnosis, quoting, and approval. Tracks priority, SLA deadlines, categories, and assigned engineers.
Use this file to discover all available pages before exploring further.
A Requirement is the primary intake record for any client technical need in B2B Import ERP. In an industrial B2B context — such as HVAC engineering, extraction systems, or duct fabrication — clients express a need that must be understood, diagnosed, scoped, and ultimately converted into a quotation and then a work order. The Requirements module orchestrates this entire journey, assigning the right engineers and commercial staff at each phase, enforcing SLAs by priority, and blocking invalid transitions at the database level.
Requirements follow a strict sequential workflow enforced by the validate_requirement_state_transitions and enforce_requirement_permissions triggers. No state can be skipped and no transition outside the matrix is permitted.
At any stage, a requirement can transition to CANCELADO provided the cancelling user supplies a cancel_code from the catalogue and a cancel_reason of at least 10 characters.
sales_user_id must be set; a DIAGNOSTIC PDF document must exist
COTIZACION → APROBACION
description ≥ 15 characters; a QUOTE PDF document must exist
APROBACION → OT_GENERADA
An APPROVAL document must exist; an APROBADA quote must be linked
ANY → CANCELADO
cancel_code + cancel_reason (≥ 10 chars) required
Physical deletion of requirements is blocked by trg_block_physical_requirement_delete. All removals must use soft-delete (deleted_at). The AUDITOR role can still read soft-deleted records via RLS.
The following TypeScript interface is exported from src/app/actions/requirements.ts and reflects the full shape of a requirement row as returned by the server actions:
requirement_code is generated transactionally using tenant_sequences as REQ-XXXXXX, ensuring no code collisions under concurrent inserts. The code is immutable after creation.
All server actions are declared with "use server" and run exclusively on the Next.js server. They resolve the tenant from tenantCode using getTenantId() and call supabaseAdmin — bypassing RLS — but rely on database-level triggers for permission enforcement.
getRequirements
getRequirements(tenantCode?)Returns all non-deleted requirements for the resolved tenant, ordered newest first. The response includes joined client (legal name, city) and engineering_user (first and last name) relations.
updateRequirementStatus(reqId, newStatus, extra?)Updates the status of a requirement along with any extra fields (e.g. engineering_user_id, cancel_code, cancel_reason). The database trigger validates the transition and RBAC before persisting.
Requirements are classified into industrial service categories defined in the requirements.category CHECK constraint:
Category Code
Description
FABRICACION
Custom fabrication of HVAC components, ducts, or equipment
VENTA
Direct product sale (equipment or materials)
MANTENIMIENTO
Scheduled or preventive maintenance services
REPARACION
Corrective repair of existing installations
OTRO
Other technical services not covered by the above
The data dictionary lists additional operational categories (HVAC, extraction, filtration, duct installation) that map to these five canonical codes in the database. Use OTRO when the client’s need does not fit the four primary categories.
Priority is set at creation and drives automatic SLA deadline calculation by the handle_requirement_traceability trigger:
Priority
SLA — Response
SLA — Close
Typical Use Case
LOW
24 business hours
240 business hours
Routine maintenance scheduling
MEDIUM
24 business hours
120 business hours
Standard service requests
HIGH
24 business hours
72 business hours
Urgent equipment repairs
CRITICAL
24 business hours
48 business hours
Production-stopping failures
SLA timestamps (sla_response_due_at, sla_diagnostic_due_at, sla_quote_due_at, sla_close_due_at) are stored in UTC and computed using the add_business_hours() function, which skips weekends.