1342 lines
49 KiB
Markdown
1342 lines
49 KiB
Markdown
# DDL-SPEC: Schema quality_management
|
|
|
|
## Identificacion
|
|
|
|
| Campo | Valor |
|
|
|-------|-------|
|
|
| **Schema** | quality_management |
|
|
| **Modulo** | MAI-006 |
|
|
| **Vertical** | Construccion |
|
|
| **Version** | 1.0 |
|
|
| **Estado** | En Diseno |
|
|
| **Autor** | Database-Agent |
|
|
| **Fecha** | 2025-12-06 |
|
|
|
|
---
|
|
|
|
## Descripcion General
|
|
|
|
El schema `quality_management` gestiona el control de calidad en proyectos de construccion, incluyendo inspecciones, no conformidades, acciones correctivas, pruebas de laboratorio y certificaciones.
|
|
|
|
### RF Cubiertos
|
|
|
|
| RF | Titulo | Tablas |
|
|
|----|--------|--------|
|
|
| RF-CAL-001 | Inspecciones de Calidad | inspections, inspection_items |
|
|
| RF-CAL-002 | No Conformidades | non_conformities, corrective_actions |
|
|
| RF-CAL-003 | Pruebas de Laboratorio | lab_tests |
|
|
| RF-CAL-004 | Certificaciones | certifications |
|
|
|
|
---
|
|
|
|
## Diagrama ER
|
|
|
|
```mermaid
|
|
erDiagram
|
|
inspections {
|
|
uuid id PK
|
|
uuid tenant_id FK
|
|
uuid project_id FK
|
|
varchar inspection_code
|
|
varchar inspection_type
|
|
varchar title
|
|
text description
|
|
uuid inspector_id FK
|
|
date inspection_date
|
|
time inspection_time
|
|
varchar status
|
|
varchar result
|
|
jsonb checklist
|
|
jsonb attachments
|
|
text observations
|
|
uuid approved_by FK
|
|
timestamptz approved_at
|
|
timestamptz created_at
|
|
timestamptz updated_at
|
|
}
|
|
|
|
inspection_items {
|
|
uuid id PK
|
|
uuid tenant_id FK
|
|
uuid inspection_id FK
|
|
int item_number
|
|
varchar item_type
|
|
varchar description
|
|
varchar requirement
|
|
varchar verification_method
|
|
varchar result
|
|
varchar conformity
|
|
text observations
|
|
jsonb measurements
|
|
jsonb attachments
|
|
timestamptz created_at
|
|
}
|
|
|
|
non_conformities {
|
|
uuid id PK
|
|
uuid tenant_id FK
|
|
uuid project_id FK
|
|
uuid inspection_id FK
|
|
varchar nc_code
|
|
varchar severity
|
|
varchar category
|
|
varchar title
|
|
text description
|
|
varchar location
|
|
text root_cause
|
|
varchar status
|
|
uuid detected_by FK
|
|
timestamptz detected_at
|
|
uuid assigned_to FK
|
|
date deadline
|
|
uuid closed_by FK
|
|
timestamptz closed_at
|
|
jsonb attachments
|
|
timestamptz created_at
|
|
timestamptz updated_at
|
|
}
|
|
|
|
corrective_actions {
|
|
uuid id PK
|
|
uuid tenant_id FK
|
|
uuid non_conformity_id FK
|
|
int action_number
|
|
varchar action_type
|
|
text description
|
|
uuid responsible_id FK
|
|
date planned_date
|
|
date completed_date
|
|
varchar status
|
|
text verification_method
|
|
text results
|
|
jsonb evidence
|
|
timestamptz created_at
|
|
timestamptz updated_at
|
|
}
|
|
|
|
lab_tests {
|
|
uuid id PK
|
|
uuid tenant_id FK
|
|
uuid project_id FK
|
|
uuid inspection_id FK
|
|
varchar test_code
|
|
varchar test_type
|
|
varchar material_type
|
|
varchar sample_id
|
|
date sample_date
|
|
varchar location
|
|
uuid lab_id FK
|
|
uuid technician_id FK
|
|
date test_date
|
|
varchar status
|
|
varchar result
|
|
jsonb test_parameters
|
|
jsonb test_results
|
|
boolean meets_spec
|
|
text observations
|
|
jsonb attachments
|
|
timestamptz created_at
|
|
timestamptz updated_at
|
|
}
|
|
|
|
certifications {
|
|
uuid id PK
|
|
uuid tenant_id FK
|
|
uuid project_id FK
|
|
varchar cert_code
|
|
varchar cert_type
|
|
varchar title
|
|
varchar issuing_body
|
|
date issue_date
|
|
date expiry_date
|
|
varchar status
|
|
text scope
|
|
jsonb requirements
|
|
jsonb documents
|
|
uuid verified_by FK
|
|
timestamptz verified_at
|
|
jsonb attachments
|
|
timestamptz created_at
|
|
timestamptz updated_at
|
|
}
|
|
|
|
inspections ||--o{ inspection_items : "contiene"
|
|
inspections ||--o{ non_conformities : "genera"
|
|
non_conformities ||--o{ corrective_actions : "requiere"
|
|
inspections ||--o{ lab_tests : "solicita"
|
|
```
|
|
|
|
---
|
|
|
|
## Tablas
|
|
|
|
### 1. inspections
|
|
|
|
Registro de inspecciones de calidad realizadas.
|
|
|
|
| Columna | Tipo | Nullable | Default | Descripcion |
|
|
|---------|------|----------|---------|-------------|
|
|
| `id` | UUID | NOT NULL | gen_random_uuid() | PK |
|
|
| `tenant_id` | UUID | NOT NULL | - | FK a tenants |
|
|
| `project_id` | UUID | NOT NULL | - | FK a projects |
|
|
| `inspection_code` | VARCHAR(50) | NOT NULL | - | Codigo unico de inspeccion |
|
|
| `inspection_type` | VARCHAR(50) | NOT NULL | - | Tipo de inspeccion (ENUM) |
|
|
| `title` | VARCHAR(255) | NOT NULL | - | Titulo de la inspeccion |
|
|
| `description` | TEXT | NULL | - | Descripcion detallada |
|
|
| `inspector_id` | UUID | NOT NULL | - | FK a users (inspector) |
|
|
| `inspection_date` | DATE | NOT NULL | - | Fecha de inspeccion |
|
|
| `inspection_time` | TIME | NULL | - | Hora de inspeccion |
|
|
| `location` | VARCHAR(255) | NULL | - | Ubicacion en obra |
|
|
| `status` | VARCHAR(20) | NOT NULL | 'scheduled' | Estado (ENUM) |
|
|
| `result` | VARCHAR(20) | NULL | - | Resultado (ENUM) |
|
|
| `checklist` | JSONB | NULL | '{}' | Checklist de verificacion |
|
|
| `attachments` | JSONB | NULL | '[]' | Fotos, documentos |
|
|
| `observations` | TEXT | NULL | - | Observaciones generales |
|
|
| `approved_by` | UUID | NULL | - | FK a users (aprobador) |
|
|
| `approved_at` | TIMESTAMPTZ | NULL | - | Fecha aprobacion |
|
|
| `created_at` | TIMESTAMPTZ | NOT NULL | NOW() | Fecha creacion |
|
|
| `updated_at` | TIMESTAMPTZ | NOT NULL | NOW() | Fecha actualizacion |
|
|
| `created_by` | UUID | NOT NULL | - | FK a users |
|
|
| `updated_by` | UUID | NULL | - | FK a users |
|
|
| `is_active` | BOOLEAN | NOT NULL | true | Soft delete |
|
|
| `deleted_at` | TIMESTAMPTZ | NULL | - | Fecha eliminacion |
|
|
| `deleted_by` | UUID | NULL | - | FK a users |
|
|
|
|
```sql
|
|
-- ============================================================================
|
|
-- Schema: quality_management
|
|
-- Tabla: inspections
|
|
-- Descripcion: Inspecciones de calidad en proyectos de construccion
|
|
-- Modulo: MAI-006
|
|
-- ============================================================================
|
|
|
|
-- ENUM: Tipos de inspeccion
|
|
CREATE TYPE quality_management.inspection_type AS ENUM (
|
|
'initial', -- Inspeccion inicial
|
|
'progress', -- Inspeccion de avance
|
|
'final', -- Inspeccion final
|
|
'structural', -- Inspeccion estructural
|
|
'electrical', -- Inspeccion electrica
|
|
'plumbing', -- Inspeccion de plomeria
|
|
'hvac', -- Inspeccion HVAC
|
|
'safety', -- Inspeccion de seguridad
|
|
'environmental', -- Inspeccion ambiental
|
|
'quality_control', -- Control de calidad
|
|
'material_reception', -- Recepcion de materiales
|
|
'equipment', -- Inspeccion de equipos
|
|
'finishing' -- Inspeccion de acabados
|
|
);
|
|
|
|
-- ENUM: Estados de inspeccion
|
|
CREATE TYPE quality_management.inspection_status AS ENUM (
|
|
'scheduled', -- Programada
|
|
'in_progress', -- En progreso
|
|
'completed', -- Completada
|
|
'approved', -- Aprobada
|
|
'rejected', -- Rechazada
|
|
'cancelled' -- Cancelada
|
|
);
|
|
|
|
-- ENUM: Resultados de inspeccion
|
|
CREATE TYPE quality_management.inspection_result AS ENUM (
|
|
'passed', -- Aprobada
|
|
'failed', -- Rechazada
|
|
'conditional', -- Condicional
|
|
'pending_review' -- Pendiente de revision
|
|
);
|
|
|
|
-- Crear tabla
|
|
CREATE TABLE IF NOT EXISTS quality_management.inspections (
|
|
-- Primary Key
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
|
|
-- Multi-tenant
|
|
tenant_id UUID NOT NULL REFERENCES core_tenants.tenants(id) ON DELETE CASCADE,
|
|
|
|
-- Relaciones
|
|
project_id UUID NOT NULL,
|
|
inspector_id UUID NOT NULL,
|
|
|
|
-- Datos de negocio
|
|
inspection_code VARCHAR(50) NOT NULL,
|
|
inspection_type quality_management.inspection_type NOT NULL,
|
|
title VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
inspection_date DATE NOT NULL,
|
|
inspection_time TIME,
|
|
location VARCHAR(255),
|
|
status quality_management.inspection_status NOT NULL DEFAULT 'scheduled',
|
|
result quality_management.inspection_result,
|
|
|
|
-- Datos estructurados
|
|
checklist JSONB DEFAULT '{}',
|
|
attachments JSONB DEFAULT '[]',
|
|
observations TEXT,
|
|
|
|
-- Aprobacion
|
|
approved_by UUID,
|
|
approved_at TIMESTAMPTZ,
|
|
|
|
-- Auditoria
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
created_by UUID NOT NULL,
|
|
updated_by UUID,
|
|
|
|
-- Soft delete
|
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
|
deleted_at TIMESTAMPTZ,
|
|
deleted_by UUID,
|
|
|
|
-- Constraints
|
|
CONSTRAINT uq_inspections_code_tenant UNIQUE (tenant_id, inspection_code),
|
|
CONSTRAINT chk_inspections_approval CHECK (
|
|
(approved_by IS NULL AND approved_at IS NULL) OR
|
|
(approved_by IS NOT NULL AND approved_at IS NOT NULL)
|
|
)
|
|
);
|
|
|
|
-- Comentarios
|
|
COMMENT ON TABLE quality_management.inspections IS 'Inspecciones de calidad en proyectos de construccion';
|
|
COMMENT ON COLUMN quality_management.inspections.inspection_code IS 'Codigo unico de inspeccion por tenant';
|
|
COMMENT ON COLUMN quality_management.inspections.inspection_type IS 'Tipo de inspeccion realizada';
|
|
COMMENT ON COLUMN quality_management.inspections.status IS 'Estado actual de la inspeccion';
|
|
COMMENT ON COLUMN quality_management.inspections.result IS 'Resultado de la inspeccion';
|
|
COMMENT ON COLUMN quality_management.inspections.checklist IS 'Lista de verificacion en formato JSON';
|
|
|
|
-- ============================================================================
|
|
-- INDICES
|
|
-- ============================================================================
|
|
|
|
CREATE INDEX idx_inspections_tenant ON quality_management.inspections(tenant_id);
|
|
CREATE INDEX idx_inspections_project ON quality_management.inspections(project_id, inspection_date DESC);
|
|
CREATE INDEX idx_inspections_inspector ON quality_management.inspections(inspector_id, inspection_date DESC);
|
|
CREATE INDEX idx_inspections_code ON quality_management.inspections(inspection_code);
|
|
CREATE INDEX idx_inspections_status ON quality_management.inspections(status) WHERE is_active = true;
|
|
CREATE INDEX idx_inspections_type ON quality_management.inspections(inspection_type, inspection_date DESC);
|
|
CREATE INDEX idx_inspections_date ON quality_management.inspections(inspection_date DESC);
|
|
CREATE INDEX idx_inspections_result ON quality_management.inspections(result) WHERE result IS NOT NULL;
|
|
|
|
-- ============================================================================
|
|
-- RLS POLICIES
|
|
-- ============================================================================
|
|
|
|
ALTER TABLE quality_management.inspections ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY tenant_isolation_select ON quality_management.inspections
|
|
FOR SELECT
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_insert ON quality_management.inspections
|
|
FOR INSERT
|
|
WITH CHECK (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_update ON quality_management.inspections
|
|
FOR UPDATE
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_delete ON quality_management.inspections
|
|
FOR DELETE
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
-- ============================================================================
|
|
-- TRIGGERS
|
|
-- ============================================================================
|
|
|
|
CREATE TRIGGER trg_inspections_update_timestamp
|
|
BEFORE UPDATE ON quality_management.inspections
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION core_shared.set_updated_at();
|
|
```
|
|
|
|
---
|
|
|
|
### 2. inspection_items
|
|
|
|
Items individuales de cada inspeccion.
|
|
|
|
| Columna | Tipo | Nullable | Default | Descripcion |
|
|
|---------|------|----------|---------|-------------|
|
|
| `id` | UUID | NOT NULL | gen_random_uuid() | PK |
|
|
| `tenant_id` | UUID | NOT NULL | - | FK a tenants |
|
|
| `inspection_id` | UUID | NOT NULL | - | FK a inspections |
|
|
| `item_number` | INTEGER | NOT NULL | - | Numero de item |
|
|
| `item_type` | VARCHAR(50) | NOT NULL | - | Tipo de item |
|
|
| `description` | VARCHAR(500) | NOT NULL | - | Descripcion del item |
|
|
| `requirement` | VARCHAR(500) | NOT NULL | - | Requisito a verificar |
|
|
| `verification_method` | VARCHAR(100) | NOT NULL | - | Metodo de verificacion |
|
|
| `result` | VARCHAR(20) | NULL | - | Resultado del item |
|
|
| `conformity` | VARCHAR(20) | NULL | - | Conformidad (ENUM) |
|
|
| `observations` | TEXT | NULL | - | Observaciones |
|
|
| `measurements` | JSONB | NULL | '{}' | Mediciones realizadas |
|
|
| `attachments` | JSONB | NULL | '[]' | Evidencias |
|
|
| `created_at` | TIMESTAMPTZ | NOT NULL | NOW() | Fecha creacion |
|
|
| `created_by` | UUID | NOT NULL | - | FK a users |
|
|
|
|
```sql
|
|
-- ============================================================================
|
|
-- Tabla: inspection_items
|
|
-- Descripcion: Items individuales de cada inspeccion
|
|
-- ============================================================================
|
|
|
|
-- ENUM: Conformidad
|
|
CREATE TYPE quality_management.conformity_status AS ENUM (
|
|
'conforming', -- Conforme
|
|
'non_conforming', -- No conforme
|
|
'partially', -- Parcialmente conforme
|
|
'not_applicable' -- No aplica
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS quality_management.inspection_items (
|
|
-- Primary Key
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
|
|
-- Multi-tenant
|
|
tenant_id UUID NOT NULL REFERENCES core_tenants.tenants(id) ON DELETE CASCADE,
|
|
|
|
-- Relaciones
|
|
inspection_id UUID NOT NULL REFERENCES quality_management.inspections(id) ON DELETE CASCADE,
|
|
|
|
-- Datos de negocio
|
|
item_number INTEGER NOT NULL,
|
|
item_type VARCHAR(50) NOT NULL,
|
|
description VARCHAR(500) NOT NULL,
|
|
requirement VARCHAR(500) NOT NULL,
|
|
verification_method VARCHAR(100) NOT NULL,
|
|
result VARCHAR(20),
|
|
conformity quality_management.conformity_status,
|
|
observations TEXT,
|
|
|
|
-- Datos estructurados
|
|
measurements JSONB DEFAULT '{}',
|
|
attachments JSONB DEFAULT '[]',
|
|
|
|
-- Auditoria
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
created_by UUID NOT NULL,
|
|
|
|
-- Constraints
|
|
CONSTRAINT uq_inspection_items_number UNIQUE (inspection_id, item_number)
|
|
);
|
|
|
|
-- Comentarios
|
|
COMMENT ON TABLE quality_management.inspection_items IS 'Items individuales de verificacion en inspecciones';
|
|
COMMENT ON COLUMN quality_management.inspection_items.item_number IS 'Numero secuencial del item dentro de la inspeccion';
|
|
COMMENT ON COLUMN quality_management.inspection_items.conformity IS 'Estado de conformidad del item';
|
|
COMMENT ON COLUMN quality_management.inspection_items.measurements IS 'Mediciones y valores registrados en formato JSON';
|
|
|
|
-- Indices
|
|
CREATE INDEX idx_inspection_items_tenant ON quality_management.inspection_items(tenant_id);
|
|
CREATE INDEX idx_inspection_items_inspection ON quality_management.inspection_items(inspection_id, item_number);
|
|
CREATE INDEX idx_inspection_items_conformity ON quality_management.inspection_items(conformity);
|
|
|
|
-- RLS
|
|
ALTER TABLE quality_management.inspection_items ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY tenant_isolation_select ON quality_management.inspection_items
|
|
FOR SELECT
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_insert ON quality_management.inspection_items
|
|
FOR INSERT
|
|
WITH CHECK (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_update ON quality_management.inspection_items
|
|
FOR UPDATE
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_delete ON quality_management.inspection_items
|
|
FOR DELETE
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
```
|
|
|
|
---
|
|
|
|
### 3. non_conformities
|
|
|
|
No conformidades detectadas durante inspecciones.
|
|
|
|
| Columna | Tipo | Nullable | Default | Descripcion |
|
|
|---------|------|----------|---------|-------------|
|
|
| `id` | UUID | NOT NULL | gen_random_uuid() | PK |
|
|
| `tenant_id` | UUID | NOT NULL | - | FK a tenants |
|
|
| `project_id` | UUID | NOT NULL | - | FK a projects |
|
|
| `inspection_id` | UUID | NULL | - | FK a inspections |
|
|
| `nc_code` | VARCHAR(50) | NOT NULL | - | Codigo de NC |
|
|
| `severity` | VARCHAR(20) | NOT NULL | - | Severidad (ENUM) |
|
|
| `category` | VARCHAR(50) | NOT NULL | - | Categoria |
|
|
| `title` | VARCHAR(255) | NOT NULL | - | Titulo |
|
|
| `description` | TEXT | NOT NULL | - | Descripcion detallada |
|
|
| `location` | VARCHAR(255) | NOT NULL | - | Ubicacion |
|
|
| `root_cause` | TEXT | NULL | - | Causa raiz |
|
|
| `status` | VARCHAR(20) | NOT NULL | 'open' | Estado (ENUM) |
|
|
| `detected_by` | UUID | NOT NULL | - | FK a users |
|
|
| `detected_at` | TIMESTAMPTZ | NOT NULL | NOW() | Fecha deteccion |
|
|
| `assigned_to` | UUID | NULL | - | FK a users |
|
|
| `deadline` | DATE | NULL | - | Fecha limite |
|
|
| `closed_by` | UUID | NULL | - | FK a users |
|
|
| `closed_at` | TIMESTAMPTZ | NULL | - | Fecha cierre |
|
|
| `attachments` | JSONB | NULL | '[]' | Evidencias |
|
|
| `created_at` | TIMESTAMPTZ | NOT NULL | NOW() | Fecha creacion |
|
|
| `updated_at` | TIMESTAMPTZ | NOT NULL | NOW() | Fecha actualizacion |
|
|
| `created_by` | UUID | NOT NULL | - | FK a users |
|
|
| `updated_by` | UUID | NULL | - | FK a users |
|
|
| `is_active` | BOOLEAN | NOT NULL | true | Soft delete |
|
|
| `deleted_at` | TIMESTAMPTZ | NULL | - | Fecha eliminacion |
|
|
| `deleted_by` | UUID | NULL | - | FK a users |
|
|
|
|
```sql
|
|
-- ============================================================================
|
|
-- Tabla: non_conformities
|
|
-- Descripcion: No conformidades detectadas
|
|
-- ============================================================================
|
|
|
|
-- ENUM: Severidad de NC
|
|
CREATE TYPE quality_management.nc_severity AS ENUM (
|
|
'critical', -- Critica
|
|
'major', -- Mayor
|
|
'minor', -- Menor
|
|
'observation' -- Observacion
|
|
);
|
|
|
|
-- ENUM: Estados de NC
|
|
CREATE TYPE quality_management.nc_status AS ENUM (
|
|
'open', -- Abierta
|
|
'assigned', -- Asignada
|
|
'in_progress', -- En progreso
|
|
'pending_review', -- Pendiente revision
|
|
'closed', -- Cerrada
|
|
'rejected' -- Rechazada
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS quality_management.non_conformities (
|
|
-- Primary Key
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
|
|
-- Multi-tenant
|
|
tenant_id UUID NOT NULL REFERENCES core_tenants.tenants(id) ON DELETE CASCADE,
|
|
|
|
-- Relaciones
|
|
project_id UUID NOT NULL,
|
|
inspection_id UUID REFERENCES quality_management.inspections(id),
|
|
|
|
-- Datos de negocio
|
|
nc_code VARCHAR(50) NOT NULL,
|
|
severity quality_management.nc_severity NOT NULL,
|
|
category VARCHAR(50) NOT NULL,
|
|
title VARCHAR(255) NOT NULL,
|
|
description TEXT NOT NULL,
|
|
location VARCHAR(255) NOT NULL,
|
|
root_cause TEXT,
|
|
status quality_management.nc_status NOT NULL DEFAULT 'open',
|
|
|
|
-- Gestion
|
|
detected_by UUID NOT NULL,
|
|
detected_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
assigned_to UUID,
|
|
deadline DATE,
|
|
closed_by UUID,
|
|
closed_at TIMESTAMPTZ,
|
|
|
|
-- Datos estructurados
|
|
attachments JSONB DEFAULT '[]',
|
|
|
|
-- Auditoria
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
created_by UUID NOT NULL,
|
|
updated_by UUID,
|
|
|
|
-- Soft delete
|
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
|
deleted_at TIMESTAMPTZ,
|
|
deleted_by UUID,
|
|
|
|
-- Constraints
|
|
CONSTRAINT uq_nc_code_tenant UNIQUE (tenant_id, nc_code),
|
|
CONSTRAINT chk_nc_closure CHECK (
|
|
(closed_by IS NULL AND closed_at IS NULL) OR
|
|
(closed_by IS NOT NULL AND closed_at IS NOT NULL)
|
|
)
|
|
);
|
|
|
|
-- Comentarios
|
|
COMMENT ON TABLE quality_management.non_conformities IS 'No conformidades detectadas en inspecciones';
|
|
COMMENT ON COLUMN quality_management.non_conformities.nc_code IS 'Codigo unico de no conformidad';
|
|
COMMENT ON COLUMN quality_management.non_conformities.severity IS 'Nivel de severidad de la NC';
|
|
COMMENT ON COLUMN quality_management.non_conformities.status IS 'Estado actual de la NC';
|
|
|
|
-- Indices
|
|
CREATE INDEX idx_nc_tenant ON quality_management.non_conformities(tenant_id);
|
|
CREATE INDEX idx_nc_project ON quality_management.non_conformities(project_id, detected_at DESC);
|
|
CREATE INDEX idx_nc_inspection ON quality_management.non_conformities(inspection_id);
|
|
CREATE INDEX idx_nc_code ON quality_management.non_conformities(nc_code);
|
|
CREATE INDEX idx_nc_status ON quality_management.non_conformities(status) WHERE is_active = true;
|
|
CREATE INDEX idx_nc_severity ON quality_management.non_conformities(severity, detected_at DESC);
|
|
CREATE INDEX idx_nc_assigned ON quality_management.non_conformities(assigned_to) WHERE status IN ('assigned', 'in_progress');
|
|
CREATE INDEX idx_nc_overdue ON quality_management.non_conformities(deadline)
|
|
WHERE status NOT IN ('closed', 'rejected') AND deadline < CURRENT_DATE;
|
|
|
|
-- RLS
|
|
ALTER TABLE quality_management.non_conformities ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY tenant_isolation_select ON quality_management.non_conformities
|
|
FOR SELECT
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_insert ON quality_management.non_conformities
|
|
FOR INSERT
|
|
WITH CHECK (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_update ON quality_management.non_conformities
|
|
FOR UPDATE
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_delete ON quality_management.non_conformities
|
|
FOR DELETE
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
-- Triggers
|
|
CREATE TRIGGER trg_nc_update_timestamp
|
|
BEFORE UPDATE ON quality_management.non_conformities
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION core_shared.set_updated_at();
|
|
```
|
|
|
|
---
|
|
|
|
### 4. corrective_actions
|
|
|
|
Acciones correctivas para resolver no conformidades.
|
|
|
|
| Columna | Tipo | Nullable | Default | Descripcion |
|
|
|---------|------|----------|---------|-------------|
|
|
| `id` | UUID | NOT NULL | gen_random_uuid() | PK |
|
|
| `tenant_id` | UUID | NOT NULL | - | FK a tenants |
|
|
| `non_conformity_id` | UUID | NOT NULL | - | FK a non_conformities |
|
|
| `action_number` | INTEGER | NOT NULL | - | Numero de accion |
|
|
| `action_type` | VARCHAR(50) | NOT NULL | - | Tipo de accion (ENUM) |
|
|
| `description` | TEXT | NOT NULL | - | Descripcion |
|
|
| `responsible_id` | UUID | NOT NULL | - | FK a users |
|
|
| `planned_date` | DATE | NOT NULL | - | Fecha planificada |
|
|
| `completed_date` | DATE | NULL | - | Fecha completada |
|
|
| `status` | VARCHAR(20) | NOT NULL | 'planned' | Estado (ENUM) |
|
|
| `verification_method` | TEXT | NULL | - | Metodo de verificacion |
|
|
| `results` | TEXT | NULL | - | Resultados obtenidos |
|
|
| `evidence` | JSONB | NULL | '[]' | Evidencias |
|
|
| `created_at` | TIMESTAMPTZ | NOT NULL | NOW() | Fecha creacion |
|
|
| `updated_at` | TIMESTAMPTZ | NOT NULL | NOW() | Fecha actualizacion |
|
|
| `created_by` | UUID | NOT NULL | - | FK a users |
|
|
| `updated_by` | UUID | NULL | - | FK a users |
|
|
|
|
```sql
|
|
-- ============================================================================
|
|
-- Tabla: corrective_actions
|
|
-- Descripcion: Acciones correctivas para NCs
|
|
-- ============================================================================
|
|
|
|
-- ENUM: Tipos de accion correctiva
|
|
CREATE TYPE quality_management.action_type AS ENUM (
|
|
'immediate', -- Accion inmediata
|
|
'corrective', -- Accion correctiva
|
|
'preventive', -- Accion preventiva
|
|
'improvement' -- Mejora
|
|
);
|
|
|
|
-- ENUM: Estados de accion
|
|
CREATE TYPE quality_management.action_status AS ENUM (
|
|
'planned', -- Planificada
|
|
'in_progress', -- En progreso
|
|
'completed', -- Completada
|
|
'verified', -- Verificada
|
|
'rejected' -- Rechazada
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS quality_management.corrective_actions (
|
|
-- Primary Key
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
|
|
-- Multi-tenant
|
|
tenant_id UUID NOT NULL REFERENCES core_tenants.tenants(id) ON DELETE CASCADE,
|
|
|
|
-- Relaciones
|
|
non_conformity_id UUID NOT NULL REFERENCES quality_management.non_conformities(id) ON DELETE CASCADE,
|
|
|
|
-- Datos de negocio
|
|
action_number INTEGER NOT NULL,
|
|
action_type quality_management.action_type NOT NULL,
|
|
description TEXT NOT NULL,
|
|
responsible_id UUID NOT NULL,
|
|
planned_date DATE NOT NULL,
|
|
completed_date DATE,
|
|
status quality_management.action_status NOT NULL DEFAULT 'planned',
|
|
verification_method TEXT,
|
|
results TEXT,
|
|
|
|
-- Datos estructurados
|
|
evidence JSONB DEFAULT '[]',
|
|
|
|
-- Auditoria
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
created_by UUID NOT NULL,
|
|
updated_by UUID,
|
|
|
|
-- Constraints
|
|
CONSTRAINT uq_actions_number UNIQUE (non_conformity_id, action_number),
|
|
CONSTRAINT chk_action_completion CHECK (
|
|
(completed_date IS NULL) OR
|
|
(completed_date >= planned_date)
|
|
)
|
|
);
|
|
|
|
-- Comentarios
|
|
COMMENT ON TABLE quality_management.corrective_actions IS 'Acciones correctivas para resolver no conformidades';
|
|
COMMENT ON COLUMN quality_management.corrective_actions.action_type IS 'Tipo de accion: inmediata, correctiva, preventiva o mejora';
|
|
COMMENT ON COLUMN quality_management.corrective_actions.status IS 'Estado actual de la accion';
|
|
|
|
-- Indices
|
|
CREATE INDEX idx_actions_tenant ON quality_management.corrective_actions(tenant_id);
|
|
CREATE INDEX idx_actions_nc ON quality_management.corrective_actions(non_conformity_id, action_number);
|
|
CREATE INDEX idx_actions_responsible ON quality_management.corrective_actions(responsible_id, status);
|
|
CREATE INDEX idx_actions_status ON quality_management.corrective_actions(status);
|
|
CREATE INDEX idx_actions_planned ON quality_management.corrective_actions(planned_date)
|
|
WHERE status IN ('planned', 'in_progress');
|
|
|
|
-- RLS
|
|
ALTER TABLE quality_management.corrective_actions ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY tenant_isolation_select ON quality_management.corrective_actions
|
|
FOR SELECT
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_insert ON quality_management.corrective_actions
|
|
FOR INSERT
|
|
WITH CHECK (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_update ON quality_management.corrective_actions
|
|
FOR UPDATE
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_delete ON quality_management.corrective_actions
|
|
FOR DELETE
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
-- Triggers
|
|
CREATE TRIGGER trg_actions_update_timestamp
|
|
BEFORE UPDATE ON quality_management.corrective_actions
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION core_shared.set_updated_at();
|
|
```
|
|
|
|
---
|
|
|
|
### 5. lab_tests
|
|
|
|
Pruebas de laboratorio de materiales.
|
|
|
|
| Columna | Tipo | Nullable | Default | Descripcion |
|
|
|---------|------|----------|---------|-------------|
|
|
| `id` | UUID | NOT NULL | gen_random_uuid() | PK |
|
|
| `tenant_id` | UUID | NOT NULL | - | FK a tenants |
|
|
| `project_id` | UUID | NOT NULL | - | FK a projects |
|
|
| `inspection_id` | UUID | NULL | - | FK a inspections |
|
|
| `test_code` | VARCHAR(50) | NOT NULL | - | Codigo de prueba |
|
|
| `test_type` | VARCHAR(50) | NOT NULL | - | Tipo de prueba (ENUM) |
|
|
| `material_type` | VARCHAR(50) | NOT NULL | - | Tipo de material |
|
|
| `sample_id` | VARCHAR(50) | NOT NULL | - | ID de muestra |
|
|
| `sample_date` | DATE | NOT NULL | - | Fecha de muestreo |
|
|
| `location` | VARCHAR(255) | NOT NULL | - | Ubicacion de muestreo |
|
|
| `lab_id` | UUID | NULL | - | FK a laboratorio |
|
|
| `technician_id` | UUID | NULL | - | FK a users (tecnico) |
|
|
| `test_date` | DATE | NULL | - | Fecha de prueba |
|
|
| `status` | VARCHAR(20) | NOT NULL | 'pending' | Estado (ENUM) |
|
|
| `result` | VARCHAR(20) | NULL | - | Resultado (ENUM) |
|
|
| `test_parameters` | JSONB | NULL | '{}' | Parametros de prueba |
|
|
| `test_results` | JSONB | NULL | '{}' | Resultados detallados |
|
|
| `meets_spec` | BOOLEAN | NULL | - | Cumple especificacion |
|
|
| `observations` | TEXT | NULL | - | Observaciones |
|
|
| `attachments` | JSONB | NULL | '[]' | Certificados, reportes |
|
|
| `created_at` | TIMESTAMPTZ | NOT NULL | NOW() | Fecha creacion |
|
|
| `updated_at` | TIMESTAMPTZ | NOT NULL | NOW() | Fecha actualizacion |
|
|
| `created_by` | UUID | NOT NULL | - | FK a users |
|
|
| `updated_by` | UUID | NULL | - | FK a users |
|
|
| `is_active` | BOOLEAN | NOT NULL | true | Soft delete |
|
|
| `deleted_at` | TIMESTAMPTZ | NULL | - | Fecha eliminacion |
|
|
| `deleted_by` | UUID | NULL | - | FK a users |
|
|
|
|
```sql
|
|
-- ============================================================================
|
|
-- Tabla: lab_tests
|
|
-- Descripcion: Pruebas de laboratorio de materiales
|
|
-- ============================================================================
|
|
|
|
-- ENUM: Tipos de prueba
|
|
CREATE TYPE quality_management.lab_test_type AS ENUM (
|
|
'concrete_compression', -- Compresion de concreto
|
|
'concrete_slump', -- Revenimiento
|
|
'steel_tensile', -- Tension de acero
|
|
'soil_compaction', -- Compactacion de suelo
|
|
'soil_bearing', -- Capacidad portante
|
|
'asphalt_density', -- Densidad de asfalto
|
|
'mortar_compression', -- Compresion de mortero
|
|
'brick_absorption', -- Absorcion de ladrillo
|
|
'aggregate_gradation', -- Granulometria
|
|
'chemical_analysis', -- Analisis quimico
|
|
'moisture_content', -- Contenido de humedad
|
|
'other' -- Otra
|
|
);
|
|
|
|
-- ENUM: Estados de prueba
|
|
CREATE TYPE quality_management.lab_test_status AS ENUM (
|
|
'pending', -- Pendiente
|
|
'sample_collected', -- Muestra recolectada
|
|
'in_lab', -- En laboratorio
|
|
'testing', -- En prueba
|
|
'completed', -- Completada
|
|
'certified' -- Certificada
|
|
);
|
|
|
|
-- ENUM: Resultados de prueba
|
|
CREATE TYPE quality_management.lab_test_result AS ENUM (
|
|
'passed', -- Aprobada
|
|
'failed', -- Rechazada
|
|
'conditional', -- Condicional
|
|
'retest' -- Re-ensayo
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS quality_management.lab_tests (
|
|
-- Primary Key
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
|
|
-- Multi-tenant
|
|
tenant_id UUID NOT NULL REFERENCES core_tenants.tenants(id) ON DELETE CASCADE,
|
|
|
|
-- Relaciones
|
|
project_id UUID NOT NULL,
|
|
inspection_id UUID REFERENCES quality_management.inspections(id),
|
|
lab_id UUID,
|
|
technician_id UUID,
|
|
|
|
-- Datos de negocio
|
|
test_code VARCHAR(50) NOT NULL,
|
|
test_type quality_management.lab_test_type NOT NULL,
|
|
material_type VARCHAR(50) NOT NULL,
|
|
sample_id VARCHAR(50) NOT NULL,
|
|
sample_date DATE NOT NULL,
|
|
location VARCHAR(255) NOT NULL,
|
|
test_date DATE,
|
|
status quality_management.lab_test_status NOT NULL DEFAULT 'pending',
|
|
result quality_management.lab_test_result,
|
|
meets_spec BOOLEAN,
|
|
observations TEXT,
|
|
|
|
-- Datos estructurados
|
|
test_parameters JSONB DEFAULT '{}',
|
|
test_results JSONB DEFAULT '{}',
|
|
attachments JSONB DEFAULT '[]',
|
|
|
|
-- Auditoria
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
created_by UUID NOT NULL,
|
|
updated_by UUID,
|
|
|
|
-- Soft delete
|
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
|
deleted_at TIMESTAMPTZ,
|
|
deleted_by UUID,
|
|
|
|
-- Constraints
|
|
CONSTRAINT uq_lab_tests_code_tenant UNIQUE (tenant_id, test_code),
|
|
CONSTRAINT chk_lab_test_dates CHECK (
|
|
(test_date IS NULL) OR (test_date >= sample_date)
|
|
)
|
|
);
|
|
|
|
-- Comentarios
|
|
COMMENT ON TABLE quality_management.lab_tests IS 'Pruebas de laboratorio de materiales de construccion';
|
|
COMMENT ON COLUMN quality_management.lab_tests.test_type IS 'Tipo de prueba de laboratorio';
|
|
COMMENT ON COLUMN quality_management.lab_tests.test_parameters IS 'Parametros de la prueba en formato JSON';
|
|
COMMENT ON COLUMN quality_management.lab_tests.test_results IS 'Resultados detallados en formato JSON';
|
|
|
|
-- Indices
|
|
CREATE INDEX idx_lab_tests_tenant ON quality_management.lab_tests(tenant_id);
|
|
CREATE INDEX idx_lab_tests_project ON quality_management.lab_tests(project_id, sample_date DESC);
|
|
CREATE INDEX idx_lab_tests_inspection ON quality_management.lab_tests(inspection_id);
|
|
CREATE INDEX idx_lab_tests_code ON quality_management.lab_tests(test_code);
|
|
CREATE INDEX idx_lab_tests_status ON quality_management.lab_tests(status) WHERE is_active = true;
|
|
CREATE INDEX idx_lab_tests_type ON quality_management.lab_tests(test_type, sample_date DESC);
|
|
CREATE INDEX idx_lab_tests_result ON quality_management.lab_tests(result) WHERE result IS NOT NULL;
|
|
CREATE INDEX idx_lab_tests_failed ON quality_management.lab_tests(project_id)
|
|
WHERE result = 'failed' AND is_active = true;
|
|
|
|
-- RLS
|
|
ALTER TABLE quality_management.lab_tests ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY tenant_isolation_select ON quality_management.lab_tests
|
|
FOR SELECT
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_insert ON quality_management.lab_tests
|
|
FOR INSERT
|
|
WITH CHECK (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_update ON quality_management.lab_tests
|
|
FOR UPDATE
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_delete ON quality_management.lab_tests
|
|
FOR DELETE
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
-- Triggers
|
|
CREATE TRIGGER trg_lab_tests_update_timestamp
|
|
BEFORE UPDATE ON quality_management.lab_tests
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION core_shared.set_updated_at();
|
|
```
|
|
|
|
---
|
|
|
|
### 6. certifications
|
|
|
|
Certificaciones de calidad de proyectos.
|
|
|
|
| Columna | Tipo | Nullable | Default | Descripcion |
|
|
|---------|------|----------|---------|-------------|
|
|
| `id` | UUID | NOT NULL | gen_random_uuid() | PK |
|
|
| `tenant_id` | UUID | NOT NULL | - | FK a tenants |
|
|
| `project_id` | UUID | NOT NULL | - | FK a projects |
|
|
| `cert_code` | VARCHAR(50) | NOT NULL | - | Codigo de certificacion |
|
|
| `cert_type` | VARCHAR(50) | NOT NULL | - | Tipo de certificacion (ENUM) |
|
|
| `title` | VARCHAR(255) | NOT NULL | - | Titulo |
|
|
| `issuing_body` | VARCHAR(255) | NOT NULL | - | Organismo emisor |
|
|
| `issue_date` | DATE | NOT NULL | - | Fecha emision |
|
|
| `expiry_date` | DATE | NULL | - | Fecha vencimiento |
|
|
| `status` | VARCHAR(20) | NOT NULL | 'pending' | Estado (ENUM) |
|
|
| `scope` | TEXT | NULL | - | Alcance |
|
|
| `requirements` | JSONB | NULL | '{}' | Requisitos |
|
|
| `documents` | JSONB | NULL | '[]' | Documentos |
|
|
| `verified_by` | UUID | NULL | - | FK a users |
|
|
| `verified_at` | TIMESTAMPTZ | NULL | - | Fecha verificacion |
|
|
| `attachments` | JSONB | NULL | '[]' | Certificados |
|
|
| `created_at` | TIMESTAMPTZ | NOT NULL | NOW() | Fecha creacion |
|
|
| `updated_at` | TIMESTAMPTZ | NOT NULL | NOW() | Fecha actualizacion |
|
|
| `created_by` | UUID | NOT NULL | - | FK a users |
|
|
| `updated_by` | UUID | NULL | - | FK a users |
|
|
| `is_active` | BOOLEAN | NOT NULL | true | Soft delete |
|
|
| `deleted_at` | TIMESTAMPTZ | NULL | - | Fecha eliminacion |
|
|
| `deleted_by` | UUID | NULL | - | FK a users |
|
|
|
|
```sql
|
|
-- ============================================================================
|
|
-- Tabla: certifications
|
|
-- Descripcion: Certificaciones de calidad
|
|
-- ============================================================================
|
|
|
|
-- ENUM: Tipos de certificacion
|
|
CREATE TYPE quality_management.certification_type AS ENUM (
|
|
'iso_9001', -- ISO 9001
|
|
'iso_14001', -- ISO 14001
|
|
'iso_45001', -- ISO 45001
|
|
'leed', -- LEED
|
|
'breeam', -- BREEAM
|
|
'well', -- WELL Building
|
|
'edge', -- EDGE
|
|
'project_completion', -- Finalizacion de proyecto
|
|
'structural', -- Estructural
|
|
'electrical', -- Electrica
|
|
'plumbing', -- Sanitaria
|
|
'fire_safety', -- Contra incendios
|
|
'seismic', -- Sismica
|
|
'environmental', -- Ambiental
|
|
'other' -- Otra
|
|
);
|
|
|
|
-- ENUM: Estados de certificacion
|
|
CREATE TYPE quality_management.certification_status AS ENUM (
|
|
'pending', -- Pendiente
|
|
'in_process', -- En proceso
|
|
'issued', -- Emitida
|
|
'expired', -- Vencida
|
|
'revoked' -- Revocada
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS quality_management.certifications (
|
|
-- Primary Key
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
|
|
-- Multi-tenant
|
|
tenant_id UUID NOT NULL REFERENCES core_tenants.tenants(id) ON DELETE CASCADE,
|
|
|
|
-- Relaciones
|
|
project_id UUID NOT NULL,
|
|
|
|
-- Datos de negocio
|
|
cert_code VARCHAR(50) NOT NULL,
|
|
cert_type quality_management.certification_type NOT NULL,
|
|
title VARCHAR(255) NOT NULL,
|
|
issuing_body VARCHAR(255) NOT NULL,
|
|
issue_date DATE NOT NULL,
|
|
expiry_date DATE,
|
|
status quality_management.certification_status NOT NULL DEFAULT 'pending',
|
|
scope TEXT,
|
|
|
|
-- Datos estructurados
|
|
requirements JSONB DEFAULT '{}',
|
|
documents JSONB DEFAULT '[]',
|
|
attachments JSONB DEFAULT '[]',
|
|
|
|
-- Verificacion
|
|
verified_by UUID,
|
|
verified_at TIMESTAMPTZ,
|
|
|
|
-- Auditoria
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
created_by UUID NOT NULL,
|
|
updated_by UUID,
|
|
|
|
-- Soft delete
|
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
|
deleted_at TIMESTAMPTZ,
|
|
deleted_by UUID,
|
|
|
|
-- Constraints
|
|
CONSTRAINT uq_certifications_code_tenant UNIQUE (tenant_id, cert_code),
|
|
CONSTRAINT chk_cert_dates CHECK (
|
|
(expiry_date IS NULL) OR (expiry_date > issue_date)
|
|
)
|
|
);
|
|
|
|
-- Comentarios
|
|
COMMENT ON TABLE quality_management.certifications IS 'Certificaciones de calidad de proyectos';
|
|
COMMENT ON COLUMN quality_management.certifications.cert_type IS 'Tipo de certificacion';
|
|
COMMENT ON COLUMN quality_management.certifications.issuing_body IS 'Organismo o entidad emisora';
|
|
COMMENT ON COLUMN quality_management.certifications.requirements IS 'Requisitos de la certificacion en formato JSON';
|
|
|
|
-- Indices
|
|
CREATE INDEX idx_certifications_tenant ON quality_management.certifications(tenant_id);
|
|
CREATE INDEX idx_certifications_project ON quality_management.certifications(project_id, issue_date DESC);
|
|
CREATE INDEX idx_certifications_code ON quality_management.certifications(cert_code);
|
|
CREATE INDEX idx_certifications_status ON quality_management.certifications(status) WHERE is_active = true;
|
|
CREATE INDEX idx_certifications_type ON quality_management.certifications(cert_type, issue_date DESC);
|
|
CREATE INDEX idx_certifications_expiry ON quality_management.certifications(expiry_date)
|
|
WHERE expiry_date IS NOT NULL AND status = 'issued';
|
|
|
|
-- RLS
|
|
ALTER TABLE quality_management.certifications ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY tenant_isolation_select ON quality_management.certifications
|
|
FOR SELECT
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_insert ON quality_management.certifications
|
|
FOR INSERT
|
|
WITH CHECK (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_update ON quality_management.certifications
|
|
FOR UPDATE
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
CREATE POLICY tenant_isolation_delete ON quality_management.certifications
|
|
FOR DELETE
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
-- Triggers
|
|
CREATE TRIGGER trg_certifications_update_timestamp
|
|
BEFORE UPDATE ON quality_management.certifications
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION core_shared.set_updated_at();
|
|
```
|
|
|
|
---
|
|
|
|
## Funciones y Triggers de Flujo
|
|
|
|
### Funcion: Auto-transicion de NC
|
|
|
|
```sql
|
|
-- ============================================================================
|
|
-- Funcion: Actualizar estado de NC basado en acciones correctivas
|
|
-- ============================================================================
|
|
|
|
CREATE OR REPLACE FUNCTION quality_management.update_nc_status_on_actions()
|
|
RETURNS TRIGGER AS $$
|
|
DECLARE
|
|
v_total_actions INTEGER;
|
|
v_completed_actions INTEGER;
|
|
BEGIN
|
|
-- Contar acciones totales y completadas
|
|
SELECT
|
|
COUNT(*),
|
|
COUNT(*) FILTER (WHERE status IN ('completed', 'verified'))
|
|
INTO v_total_actions, v_completed_actions
|
|
FROM quality_management.corrective_actions
|
|
WHERE non_conformity_id = COALESCE(NEW.non_conformity_id, OLD.non_conformity_id)
|
|
AND (SELECT is_active FROM quality_management.non_conformities WHERE id = COALESCE(NEW.non_conformity_id, OLD.non_conformity_id));
|
|
|
|
-- Si todas las acciones estan completadas, cambiar NC a pending_review
|
|
IF v_total_actions > 0 AND v_total_actions = v_completed_actions THEN
|
|
UPDATE quality_management.non_conformities
|
|
SET status = 'pending_review',
|
|
updated_at = NOW()
|
|
WHERE id = COALESCE(NEW.non_conformity_id, OLD.non_conformity_id)
|
|
AND status = 'in_progress';
|
|
END IF;
|
|
|
|
-- Si alguna accion esta en progreso, cambiar NC a in_progress
|
|
IF EXISTS (
|
|
SELECT 1 FROM quality_management.corrective_actions
|
|
WHERE non_conformity_id = COALESCE(NEW.non_conformity_id, OLD.non_conformity_id)
|
|
AND status = 'in_progress'
|
|
) THEN
|
|
UPDATE quality_management.non_conformities
|
|
SET status = 'in_progress',
|
|
updated_at = NOW()
|
|
WHERE id = COALESCE(NEW.non_conformity_id, OLD.non_conformity_id)
|
|
AND status = 'assigned';
|
|
END IF;
|
|
|
|
RETURN COALESCE(NEW, OLD);
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- Trigger para actualizar NC cuando cambian las acciones
|
|
CREATE TRIGGER trg_update_nc_on_action_change
|
|
AFTER INSERT OR UPDATE OR DELETE ON quality_management.corrective_actions
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION quality_management.update_nc_status_on_actions();
|
|
|
|
COMMENT ON FUNCTION quality_management.update_nc_status_on_actions() IS
|
|
'Actualiza automaticamente el estado de la NC basado en el progreso de sus acciones correctivas';
|
|
```
|
|
|
|
### Funcion: Validar resultado de inspeccion
|
|
|
|
```sql
|
|
-- ============================================================================
|
|
-- Funcion: Validar y actualizar resultado de inspeccion
|
|
-- ============================================================================
|
|
|
|
CREATE OR REPLACE FUNCTION quality_management.update_inspection_result()
|
|
RETURNS TRIGGER AS $$
|
|
DECLARE
|
|
v_total_items INTEGER;
|
|
v_non_conforming_items INTEGER;
|
|
v_new_result quality_management.inspection_result;
|
|
BEGIN
|
|
-- Solo ejecutar cuando se completa la inspeccion
|
|
IF NEW.status = 'completed' AND OLD.status != 'completed' THEN
|
|
-- Contar items conformes y no conformes
|
|
SELECT
|
|
COUNT(*),
|
|
COUNT(*) FILTER (WHERE conformity = 'non_conforming')
|
|
INTO v_total_items, v_non_conforming_items
|
|
FROM quality_management.inspection_items
|
|
WHERE inspection_id = NEW.id;
|
|
|
|
-- Determinar resultado
|
|
IF v_total_items = 0 THEN
|
|
v_new_result := 'pending_review';
|
|
ELSIF v_non_conforming_items = 0 THEN
|
|
v_new_result := 'passed';
|
|
ELSIF v_non_conforming_items < v_total_items THEN
|
|
v_new_result := 'conditional';
|
|
ELSE
|
|
v_new_result := 'failed';
|
|
END IF;
|
|
|
|
NEW.result := v_new_result;
|
|
END IF;
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- Trigger para validar resultado
|
|
CREATE TRIGGER trg_validate_inspection_result
|
|
BEFORE UPDATE ON quality_management.inspections
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION quality_management.update_inspection_result();
|
|
|
|
COMMENT ON FUNCTION quality_management.update_inspection_result() IS
|
|
'Calcula automaticamente el resultado de la inspeccion basado en los items verificados';
|
|
```
|
|
|
|
### Funcion: Notificar NC criticas
|
|
|
|
```sql
|
|
-- ============================================================================
|
|
-- Funcion: Crear alerta para NCs criticas
|
|
-- ============================================================================
|
|
|
|
CREATE OR REPLACE FUNCTION quality_management.notify_critical_nc()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
-- Si la NC es critica o mayor, crear notificacion
|
|
IF NEW.severity IN ('critical', 'major') THEN
|
|
-- Insertar en tabla de notificaciones (asumiendo que existe)
|
|
-- Esta funcion se implementaria con la integracion del modulo de notificaciones
|
|
PERFORM pg_notify(
|
|
'quality_alert',
|
|
json_build_object(
|
|
'type', 'critical_nc',
|
|
'nc_id', NEW.id,
|
|
'nc_code', NEW.nc_code,
|
|
'severity', NEW.severity,
|
|
'project_id', NEW.project_id,
|
|
'tenant_id', NEW.tenant_id
|
|
)::text
|
|
);
|
|
END IF;
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- Trigger para notificar
|
|
CREATE TRIGGER trg_notify_critical_nc
|
|
AFTER INSERT ON quality_management.non_conformities
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION quality_management.notify_critical_nc();
|
|
|
|
COMMENT ON FUNCTION quality_management.notify_critical_nc() IS
|
|
'Envia notificacion cuando se crea una NC critica o mayor';
|
|
```
|
|
|
|
---
|
|
|
|
## Vistas de Consulta
|
|
|
|
### Vista: Resumen de inspecciones por proyecto
|
|
|
|
```sql
|
|
CREATE OR REPLACE VIEW quality_management.v_inspection_summary AS
|
|
SELECT
|
|
i.tenant_id,
|
|
i.project_id,
|
|
i.inspection_type,
|
|
COUNT(*) as total_inspections,
|
|
COUNT(*) FILTER (WHERE i.status = 'completed') as completed,
|
|
COUNT(*) FILTER (WHERE i.status = 'approved') as approved,
|
|
COUNT(*) FILTER (WHERE i.result = 'passed') as passed,
|
|
COUNT(*) FILTER (WHERE i.result = 'failed') as failed,
|
|
COUNT(*) FILTER (WHERE i.result = 'conditional') as conditional,
|
|
MAX(i.inspection_date) as last_inspection_date
|
|
FROM quality_management.inspections i
|
|
WHERE i.is_active = true
|
|
GROUP BY i.tenant_id, i.project_id, i.inspection_type;
|
|
|
|
COMMENT ON VIEW quality_management.v_inspection_summary IS
|
|
'Resumen de inspecciones agrupadas por proyecto y tipo';
|
|
```
|
|
|
|
### Vista: NCs abiertas por severidad
|
|
|
|
```sql
|
|
CREATE OR REPLACE VIEW quality_management.v_open_nc_by_severity AS
|
|
SELECT
|
|
nc.tenant_id,
|
|
nc.project_id,
|
|
nc.severity,
|
|
COUNT(*) as total_nc,
|
|
COUNT(*) FILTER (WHERE nc.status = 'open') as open,
|
|
COUNT(*) FILTER (WHERE nc.status = 'assigned') as assigned,
|
|
COUNT(*) FILTER (WHERE nc.status = 'in_progress') as in_progress,
|
|
COUNT(*) FILTER (WHERE nc.deadline < CURRENT_DATE) as overdue,
|
|
MIN(nc.detected_at) as oldest_nc_date,
|
|
AVG(EXTRACT(EPOCH FROM (COALESCE(nc.closed_at, NOW()) - nc.detected_at))/86400)::INTEGER as avg_days_to_close
|
|
FROM quality_management.non_conformities nc
|
|
WHERE nc.is_active = true
|
|
AND nc.status NOT IN ('closed', 'rejected')
|
|
GROUP BY nc.tenant_id, nc.project_id, nc.severity;
|
|
|
|
COMMENT ON VIEW quality_management.v_open_nc_by_severity IS
|
|
'NCs abiertas agrupadas por proyecto y severidad con metricas';
|
|
```
|
|
|
|
### Vista: Pruebas de laboratorio pendientes
|
|
|
|
```sql
|
|
CREATE OR REPLACE VIEW quality_management.v_pending_lab_tests AS
|
|
SELECT
|
|
lt.id,
|
|
lt.tenant_id,
|
|
lt.project_id,
|
|
lt.test_code,
|
|
lt.test_type,
|
|
lt.material_type,
|
|
lt.sample_date,
|
|
lt.status,
|
|
CURRENT_DATE - lt.sample_date as days_pending,
|
|
lt.location,
|
|
lt.technician_id
|
|
FROM quality_management.lab_tests lt
|
|
WHERE lt.is_active = true
|
|
AND lt.status NOT IN ('completed', 'certified')
|
|
ORDER BY lt.sample_date ASC;
|
|
|
|
COMMENT ON VIEW quality_management.v_pending_lab_tests IS
|
|
'Pruebas de laboratorio pendientes ordenadas por antiguedad';
|
|
```
|
|
|
|
---
|
|
|
|
## Indices de Performance
|
|
|
|
```sql
|
|
-- Indices adicionales para reportes y analytics
|
|
CREATE INDEX idx_inspections_project_type_date ON quality_management.inspections(project_id, inspection_type, inspection_date DESC)
|
|
WHERE is_active = true;
|
|
|
|
CREATE INDEX idx_nc_project_severity_status ON quality_management.non_conformities(project_id, severity, status)
|
|
WHERE is_active = true;
|
|
|
|
CREATE INDEX idx_lab_tests_project_type_date ON quality_management.lab_tests(project_id, test_type, sample_date DESC)
|
|
WHERE is_active = true;
|
|
|
|
-- Indice para busqueda de texto en descripciones (usando trigram)
|
|
CREATE INDEX idx_nc_description_trgm ON quality_management.non_conformities
|
|
USING gin (description gin_trgm_ops)
|
|
WHERE is_active = true;
|
|
```
|
|
|
|
---
|
|
|
|
## Consideraciones de Performance
|
|
|
|
| Tabla | Volumen Esperado | Estrategia |
|
|
|-------|------------------|------------|
|
|
| inspections | Medio (miles/proyecto) | Indices por proyecto y fecha |
|
|
| inspection_items | Alto (decenas/inspeccion) | Cascade delete, indices compuestos |
|
|
| non_conformities | Medio-bajo | Indices por severidad y estado |
|
|
| corrective_actions | Medio | Indices por responsable y estado |
|
|
| lab_tests | Medio | Indices por tipo y fecha |
|
|
| certifications | Bajo | Indices simples |
|
|
|
|
---
|
|
|
|
## Validaciones Pre-Commit
|
|
|
|
- [x] Todas las tablas tienen tenant_id
|
|
- [x] RLS habilitado en todas las tablas
|
|
- [x] 4 policies RLS creadas (SELECT, INSERT, UPDATE, DELETE)
|
|
- [x] Indices en tenant_id
|
|
- [x] Columnas de auditoria completas
|
|
- [x] Comentarios en tablas y columnas
|
|
- [x] ENUMs definidos para tipos y estados
|
|
- [x] Triggers para flujo de NC
|
|
- [x] Funciones de utilidad documentadas
|
|
- [x] Vistas de consulta creadas
|
|
- [x] Nomenclatura correcta
|
|
|
|
---
|
|
|
|
## Historial
|
|
|
|
| Version | Fecha | Autor | Cambios |
|
|
|---------|-------|-------|---------|
|
|
| 1.0 | 2025-12-06 | Database-Agent | Creacion inicial del schema quality_management |
|