# JSONB Schemas Documentation - ERP Construccion **Version:** 1.0.0 **Fecha:** 2026-02-03 **Proyecto:** erp-construccion --- ## Descripcion Este documento define los schemas esperados para los campos JSONB en la base de datos de ERP Construccion. Los campos JSONB almacenan datos flexibles/extensibles sin estructura rigida de tablas relacionales. --- ## Convenciones ### Notacion - `{}` - Objeto JSON - `[]` - Array JSON - `?` - Campo opcional - `type` - Tipo esperado (string, number, boolean, date) ### Validacion Los schemas deben validarse en el backend antes de insertar datos. Se recomienda usar JSON Schema o Zod para validacion. --- ## Schema: construction ### fraccionamientos.metadata ```typescript interface FraccionamientoMetadata { // Informacion legal escritura_publica?: string; notario?: string; numero_registro_publico?: string; fecha_registro?: string; // YYYY-MM-DD // Permisos permiso_uso_suelo?: string; fecha_permiso_uso_suelo?: string; permiso_construccion?: string; fecha_permiso_construccion?: string; // Urbanizacion porcentaje_urbanizacion?: number; // 0-100 servicios_instalados?: string[]; // ['agua', 'luz', 'drenaje', 'gas'] // Contacto contacto_nombre?: string; contacto_telefono?: string; contacto_email?: string; // Financiamiento credito_puente?: boolean; banco_financiador?: string; monto_credito?: number; // Seguros poliza_rc?: string; vigencia_poliza_rc?: string; // Custom fields [key: string]: any; } ``` ### prototipos.metadata ```typescript interface PrototipoMetadata { // Especificaciones tecnicas estructura?: string; // 'concreto', 'acero', 'mixta' acabados?: { pisos?: string; muros?: string; plafones?: string; cocina?: string; banos?: string; }; // Equipamiento incluido equipamiento?: string[]; // ['calentador', 'tinaco', 'hidroneumatico'] // Renders y materiales de venta fotos_galeria?: string[]; // URLs video_recorrido?: string; brochure_pdf?: string; // Precios por concepto desglose_precio?: { terreno?: number; construccion?: number; equipamiento?: number; gastos_escrituracion?: number; }; // Custom fields [key: string]: any; } ``` --- ## Schema: finance ### bank_accounts.metadata ```typescript interface BankAccountMetadata { // Acceso banca electronica banca_electronica?: { url?: string; usuario_consulta?: string; tiene_transferencias?: boolean; limite_diario?: number; limite_mensual?: number; }; // Documentos contrato_url?: string; estado_cuenta_url?: string; // Autorizadores firmas_autorizadas?: Array<{ nombre: string; cargo: string; limite_firma?: number; }>; // Integraciones api_config?: { provider?: string; api_key_ref?: string; // Referencia a secret manager webhook_url?: string; }; // Custom fields [key: string]: any; } ``` ### bank_movements.raw_data ```typescript interface BankMovementRawData { // Datos originales del banco referencia_banco?: string; concepto_banco?: string; tipo_movimiento_banco?: string; codigo_movimiento?: string; // Datos de importacion imported_from?: 'api' | 'csv' | 'pdf' | 'manual'; import_date?: string; original_row?: Record; // Matching info auto_matched?: boolean; match_score?: number; match_candidates?: string[]; // IDs de posibles matches } ``` ### bank_reconciliation.reconciliation_items ```typescript interface ReconciliationItems { matched: Array<{ bank_movement_id: string; erp_movement_id: string; match_date: string; match_type: 'auto' | 'manual'; amount: number; }>; unmatched_bank: Array<{ bank_movement_id: string; amount: number; date: string; description: string; }>; unmatched_erp: Array<{ erp_movement_id: string; amount: number; date: string; description: string; }>; adjustments: Array<{ type: 'charge' | 'commission' | 'interest' | 'other'; amount: number; description: string; date: string; }>; } ``` ### cash_flow_projection.income_breakdown / expense_breakdown ```typescript interface CashFlowBreakdown { categories: Array<{ category: string; subcategories: Array<{ name: string; projected: number; actual?: number; variance?: number; notes?: string; }>; total_projected: number; total_actual?: number; }>; total: number; currency: string; } ``` --- ## Schema: hse ### programa_seguridad.metas ```typescript interface ProgramaSeguridad_Metas { indicadores: Array<{ indicador_id: string; meta_anual: number; metas_mensuales?: number[]; // 12 valores tolerancia_inferior?: number; tolerancia_superior?: number; }>; objetivos: Array<{ descripcion: string; fecha_limite: string; responsable_id?: string; estado?: 'pendiente' | 'en_progreso' | 'completado'; evidencia_url?: string; }>; } ``` ### documento_stps.datos_documento ```typescript interface DocumentoSTPS_DatosDocumento { // Para DC-3 (Constancias) dc3?: { folio_constancia: string; nombre_curso: string; duracion_horas: number; fecha_capacitacion: string; nombre_instructor: string; registro_stps_instructor: string; agente_capacitador: string; registro_agente: string; }; // Para ST-7 (Dictamen) st7?: { numero_dictamen: string; unidad_verificacion: string; fecha_verificacion: string; resultado: 'favorable' | 'condicionado' | 'negativo'; vigencia_hasta: string; observaciones?: string[]; }; // Campos genericos [key: string]: any; } ``` ### tipo_permiso_trabajo.documentos_requeridos ```typescript interface PermisoTrabajo_DocumentosRequeridos { documentos: Array<{ nombre: string; descripcion?: string; obligatorio: boolean; formato_aceptado?: string[]; // ['pdf', 'jpg', 'png'] plantilla_url?: string; }>; } ``` ### tipo_permiso_trabajo.requisitos_personal ```typescript interface PermisoTrabajo_RequisitosPersonal { roles: Array<{ rol: 'ejecutor' | 'supervisor' | 'vigia' | 'operador'; cantidad_minima: number; capacitaciones_requeridas?: string[]; // IDs de capacitaciones certificaciones_requeridas?: string[]; }>; epp_obligatorio?: string[]; // IDs de EPP del catalogo examen_medico_requerido?: boolean; } ``` ### tipo_permiso_trabajo.equipos_requeridos ```typescript interface PermisoTrabajo_EquiposRequeridos { equipos: Array<{ descripcion: string; cantidad: number; especificaciones?: string; certificacion_requerida?: boolean; }>; herramientas: Array<{ descripcion: string; cantidad: number; }>; } ``` --- ## Schema: assets ### equipment.specifications ```typescript interface EquipmentSpecifications { // Motor motor?: { tipo?: string; marca?: string; modelo?: string; potencia_hp?: number; combustible?: string; capacidad_tanque_lt?: number; }; // Dimensiones dimensiones?: { largo_m?: number; ancho_m?: number; alto_m?: number; peso_kg?: number; }; // Capacidades capacidades?: { carga_max_kg?: number; volumen_m3?: number; alcance_m?: number; }; // Llantas/Rodamiento rodamiento?: { tipo?: string; // 'neumatico', 'orugas', 'mixto' cantidad?: number; medida?: string; }; // Custom fields [key: string]: any; } ``` ### maintenance_plan.activities ```typescript interface MaintenancePlanActivities { activities: Array<{ sequence: number; name: string; description?: string; duration_minutes?: number; skill_required?: string; checklist: Array<{ item: string; type: 'check' | 'measurement' | 'photo'; required: boolean; expected_value?: string | number; tolerance?: number; }>; safety_notes?: string[]; }>; } ``` ### maintenance_plan.required_parts / required_tools ```typescript interface MaintenancePlanParts { parts: Array<{ part_number?: string; description: string; quantity: number; unit: string; estimated_cost?: number; supplier_id?: string; }>; } interface MaintenancePlanTools { tools: Array<{ name: string; specification?: string; quantity: number; }>; } ``` ### maintenance_order.activities_checklist ```typescript interface MaintenanceOrderChecklist { completed_activities: Array<{ activity_index: number; completed_at: string; completed_by: string; checklist_results: Array<{ item_index: number; passed: boolean; value?: string | number; photo_url?: string; notes?: string; }>; }>; overall_result: 'pass' | 'fail' | 'partial'; technician_notes?: string; } ``` ### maintenance_order.photos_before / photos_after / documents ```typescript interface MaintenanceOrderPhotos { photos: Array<{ url: string; description?: string; taken_at?: string; taken_by?: string; location?: string; }>; } interface MaintenanceOrderDocuments { documents: Array<{ url: string; name: string; type: 'report' | 'invoice' | 'warranty' | 'other'; uploaded_at?: string; uploaded_by?: string; }>; } ``` ### equipment_telemetry.raw_data ```typescript interface EquipmentTelemetryRawData { // Datos crudos del dispositivo device_id: string; timestamp: string; signal_strength?: number; battery_level?: number; // Payload del sensor payload: Record; // Procesamiento processed?: boolean; processing_errors?: string[]; } ``` --- ## Schema: documents ### document_types.metadata ```typescript interface DocumentTypeMetadata { // Reglas de nomenclatura naming_convention?: { prefix?: string; separator?: string; include_date?: boolean; date_format?: string; sequence_length?: number; }; // Restricciones max_file_size_mb?: number; allowed_extensions?: string[]; max_versions?: number; // Workflow por defecto default_workflow_id?: string; auto_start_workflow?: boolean; // Retencion retention_years?: number; auto_archive?: boolean; } ``` ### documents.custom_fields ```typescript interface DocumentCustomFields { // Campos dinamicos segun tipo de documento [field_name: string]: { value: any; label?: string; type?: 'text' | 'number' | 'date' | 'select' | 'boolean'; }; } ``` ### document_versions.extracted_metadata ```typescript interface DocumentExtractedMetadata { // Metadatos extraidos del archivo author?: string; title?: string; subject?: string; keywords?: string[]; creation_date?: string; modification_date?: string; // Para PDFs pdf_version?: string; page_count?: number; is_encrypted?: boolean; has_forms?: boolean; // Para imagenes width?: number; height?: number; color_space?: string; dpi?: number; // GPS si disponible gps_coordinates?: { latitude: number; longitude: number; }; // OCR ocr_text?: string; ocr_confidence?: number; } ``` ### approval_workflows.steps ```typescript interface ApprovalWorkflowSteps { steps: Array<{ step_number: number; name: string; type: 'single' | 'any' | 'all' | 'percentage'; // Aprobadores approvers: Array<{ type: 'user' | 'role' | 'department'; id: string; }>; // Para type='percentage' required_percentage?: number; // Para type='any' o 'all' required_count?: number; // Tiempo limite deadline_hours?: number; reminder_hours?: number; escalation_user_id?: string; // Acciones permitidas allow_comments?: boolean; allow_attachments?: boolean; require_signature?: boolean; }>; } ``` ### annotations.style ```typescript interface AnnotationStyle { // Para todas las anotaciones color?: string; // Hex color opacity?: number; // 0-1 // Para lineas stroke_width?: number; stroke_style?: 'solid' | 'dashed' | 'dotted'; arrow_start?: boolean; arrow_end?: boolean; // Para formas fill_color?: string; fill_opacity?: number; border_radius?: number; // Para texto font_family?: string; font_size?: number; font_weight?: 'normal' | 'bold'; text_align?: 'left' | 'center' | 'right'; text_decoration?: 'none' | 'underline' | 'strikethrough'; // Para stamps stamp_text?: string; stamp_rotation?: number; } ``` ### document_audit.action_details ```typescript interface DocumentAuditActionDetails { // Contexto de la accion ip_address?: string; user_agent?: string; session_id?: string; // Datos especificos por tipo de accion view?: { page_viewed?: number; duration_seconds?: number; }; download?: { format?: string; }; edit?: { fields_changed?: string[]; previous_values?: Record; new_values?: Record; }; share?: { shared_with?: string[]; permissions?: string[]; expires_at?: string; }; workflow?: { action?: 'approve' | 'reject' | 'request_changes'; step_number?: number; comments?: string; }; } ``` --- ## Schema: infonavit ### derechohabiente.metadata ```typescript interface DerechohabienteMetadata { // Datos adicionales INFONAVIT puntos_infonavit?: number; monto_credito_aprobado?: number; subsidio_aprobado?: number; // Documentos identificacion_url?: string; constancia_situacion_fiscal_url?: string; comprobante_domicilio_url?: string; acta_nacimiento_url?: string; // Historial crediticio score_buro?: number; fecha_consulta_buro?: string; // Referencias referencias_personales?: Array<{ nombre: string; telefono: string; parentesco: string; }>; // Custom fields [key: string]: any; } ``` ### lote_infonavit.metadata ```typescript interface LoteInfonavitMetadata { // Especificaciones vivienda tipo_vivienda?: string; valor_vivienda?: number; ecotecnologias?: string[]; // Avaluo numero_avaluo?: string; fecha_avaluo?: string; valor_avaluo?: number; valuador?: string; // ROC roc_asignado?: string; fecha_asignacion_roc?: string; // Custom fields [key: string]: any; } ``` --- ## Validacion con Zod (Ejemplo) ```typescript import { z } from 'zod'; // Schema para bank_accounts.metadata export const BankAccountMetadataSchema = z.object({ banca_electronica: z.object({ url: z.string().url().optional(), usuario_consulta: z.string().optional(), tiene_transferencias: z.boolean().optional(), limite_diario: z.number().positive().optional(), limite_mensual: z.number().positive().optional(), }).optional(), contrato_url: z.string().url().optional(), estado_cuenta_url: z.string().url().optional(), firmas_autorizadas: z.array(z.object({ nombre: z.string(), cargo: z.string(), limite_firma: z.number().optional(), })).optional(), api_config: z.object({ provider: z.string().optional(), api_key_ref: z.string().optional(), webhook_url: z.string().url().optional(), }).optional(), }).passthrough(); // Allow additional fields // Uso const validateMetadata = (data: unknown) => { return BankAccountMetadataSchema.parse(data); }; ``` --- ## Referencias - `DDL-EXECUTION-ORDER.md` - Orden de ejecucion DDL - `@ESTANDAR-DATABASE` - Estandares de base de datos - TypeScript interfaces en backend --- *Documentacion creada: 2026-02-03 - ST-P2-003*