-- ═══════════════════════════════════════════════════════════════════════
-- 2026-10-22_02 · Comprobante de retención de IVA (DTE 07)
-- ═══════════════════════════════════════════════════════════════════════
-- TINSA es agente de retención: al comprar a un proveedor que no es gran
-- contribuyente le retiene el 1 % del IVA y le emite un comprobante de
-- retención. Decisiones del usuario: se emite desde la compra (DTE del
-- proveedor o recepción de la orden) y también a mano; el IVA retenido se
-- rebaja del pago al proveedor.
--
--   · factura (tipo 07): el comprobante; receptor = el proveedor (id_proveedor).
--   · factura_retencion: los documentos del proveedor que cubre (uno o varios),
--     ligados opcionalmente a la compra por DTE y a la recepción de la orden.
--   · orden_compra_recepcion.iva_retenido: suma de lo retenido vigente; el
--     pago pendiente es monto − iva_retenido.
--   · proveedor: datos que Hacienda pide del receptor (actividad, departamento,
--     municipio) y si es gran contribuyente (a esos no se les retiene).
--
-- Respaldo previo: backups/tinsa_db_pre-retencion_2026-10-22.sql
-- Reversa: database/rollback/2026-10-22_02_comprobante_retencion.sql
-- ═══════════════════════════════════════════════════════════════════════

USE tinsa_db;

ALTER TABLE proveedor
  ADD COLUMN cod_actividad      VARCHAR(6) DEFAULT NULL COMMENT 'CAT-019' AFTER nrc,
  ADD COLUMN cod_departamento   CHAR(2)    DEFAULT NULL COMMENT 'CAT-012' AFTER direccion,
  ADD COLUMN cod_municipio      CHAR(2)    DEFAULT NULL COMMENT 'CAT-013' AFTER cod_departamento,
  ADD COLUMN gran_contribuyente TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'a los grandes contribuyentes no se les retiene' AFTER cod_municipio;

ALTER TABLE factura
  ADD COLUMN id_proveedor INT(10) UNSIGNED DEFAULT NULL COMMENT 'comprobante de retención: proveedor receptor' AFTER id_cliente,
  ADD CONSTRAINT fk_factura_proveedor FOREIGN KEY (id_proveedor) REFERENCES proveedor (id) ON DELETE RESTRICT ON UPDATE CASCADE;

ALTER TABLE factura DROP CONSTRAINT chk_factura_tipo;
ALTER TABLE factura ADD CONSTRAINT chk_factura_tipo CHECK (tipo_dte IN ('01','03','04','05','06','07','11','14'));

CREATE TABLE factura_retencion (
  id                INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  id_factura        INT(10) UNSIGNED NOT NULL COMMENT 'el comprobante de retención (tipo 07)',
  num_item          SMALLINT UNSIGNED NOT NULL,
  tipo_dte          CHAR(2)       NOT NULL COMMENT 'documento del proveedor: 01 factura, 03 crédito fiscal',
  tipo_generacion   TINYINT(1)    NOT NULL COMMENT '1 físico, 2 electrónico (DTE)',
  num_documento     VARCHAR(36)   NOT NULL COMMENT 'código de generación (electrónico) o número del documento físico',
  fecha_emision     DATE          NOT NULL,
  monto_sujeto      DECIMAL(14,2) NOT NULL COMMENT 'monto gravado sujeto a retención (sin IVA)',
  codigo_retencion  CHAR(2)       NOT NULL DEFAULT '22' COMMENT 'CAT-006: 22 = retención IVA 1 %',
  iva_retenido      DECIMAL(14,2) NOT NULL,
  descripcion       VARCHAR(1000) NOT NULL,
  id_compra_dte     INT(10) UNSIGNED DEFAULT NULL,
  id_recepcion      INT(10) UNSIGNED DEFAULT NULL,
  KEY idx_factura_retencion_factura (id_factura),
  KEY idx_factura_retencion_compra (id_compra_dte),
  KEY idx_factura_retencion_recepcion (id_recepcion),
  CONSTRAINT fk_factura_retencion_factura FOREIGN KEY (id_factura) REFERENCES factura (id) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT fk_factura_retencion_compra FOREIGN KEY (id_compra_dte) REFERENCES compra_dte (id) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT fk_factura_retencion_recepcion FOREIGN KEY (id_recepcion) REFERENCES orden_compra_recepcion (id) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT chk_factura_retencion_tipo CHECK (tipo_dte IN ('01','03')),
  CONSTRAINT chk_factura_retencion_generacion CHECK (tipo_generacion IN (1, 2)),
  CONSTRAINT chk_factura_retencion_montos CHECK (monto_sujeto > 0 AND iva_retenido > 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

ALTER TABLE orden_compra_recepcion
  ADD COLUMN iva_retenido DECIMAL(14,2) NOT NULL DEFAULT 0.00 COMMENT 'IVA retenido con comprobantes vigentes; se paga monto − iva_retenido' AFTER monto;

-- Habilitar el comprobante de retención en el emisor
UPDATE facturacion_emisor
   SET tipos_habilitados = CONCAT_WS(',', NULLIF(tipos_habilitados, ''), '07')
 WHERE FIND_IN_SET('07', tipos_habilitados) = 0;
