2025-05-17 11:36:26 -04:00

293 lines
10 KiB
Go

// repository/cuis_repo.go
package repositories
import (
"context"
"daemonService/internal/models"
"daemonService/internal/models/obtencionCodigos/request"
"daemonService/internal/models/obtencionCodigos/response"
srv "daemonService/internal/services"
"daemonService/internal/utils"
"database/sql"
"fmt"
"net/http"
)
type CuisRepository struct {
CuisService *srv.CuisService
ModelService models.ServiceModel
}
// instanciamos cuisRepository
func NewCuisRepository(model models.ServiceModel, cuisService *srv.CuisService) *CuisRepository {
return &CuisRepository{ModelService: model, CuisService: cuisService}
}
func (cr *CuisRepository) CrearNuevoRegistro(ctx context.Context, request request.SolicitudCuisCufd, codigoCuis string, fechaVigencia string, transaccion bool, cufdData response.SoapBodyCufd) error {
// Obtener la hora actual de Bolivia
currentBolivia, err := utils.GetCurrentBoliviaTime()
if err != nil {
return fmt.Errorf("error al obtener hora de Bolivia: %w", err)
}
// Iniciar transacción
tx, err := cr.ModelService.DB.BeginTx(ctx, nil)
if err != nil {
cr.CuisService.LogMessage("Error al iniciar transacción: %v", err)
return utils.ErrorCustom(http.StatusBadRequest, "Error al iniciar transacción")
}
defer func() {
if err != nil {
tx.Rollback()
}
}()
// Consulta corregida para manejar actualizaciones de CUIS y CUFD
query := `
WITH empresa AS (
-- Inserta o actualiza empresa usando la clave natural
INSERT INTO registroEmpresa (
codigo_ambiente,
codigo_modalidad,
codigo_punto_venta,
codigo_sistema,
codigo_sucursal,
nit,
token_key,
token_value,
nombre_archivo_certificado,
nombre_archivo_clave_privada
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
ON CONFLICT (nit, codigo_sucursal, codigo_punto_venta)
DO UPDATE SET
codigo_ambiente = EXCLUDED.codigo_ambiente,
codigo_modalidad = EXCLUDED.codigo_modalidad,
codigo_sistema = EXCLUDED.codigo_sistema,
token_key = EXCLUDED.token_key,
token_value = EXCLUDED.token_value,
nombre_archivo_certificado = EXCLUDED.nombre_archivo_certificado,
nombre_archivo_clave_privada = EXCLUDED.nombre_archivo_clave_privada,
fecha_actualizacion = CURRENT_TIMESTAMP
RETURNING id
),
cuis_existente AS (
-- Busca si existe un CUIS para la empresa
SELECT id, cuis, registro_empresa_id
FROM cuis
WHERE registro_empresa_id = (SELECT id FROM empresa)
LIMIT 1
),
cuis_actualizado AS (
-- Si existe CUIS pero es diferente, actualízalo
UPDATE cuis
SET
cuis = $11,
fecha_vigencia = $12,
transaccion = $13,
fecha_actualizacion = CURRENT_TIMESTAMP
FROM cuis_existente
WHERE cuis.id = cuis_existente.id
AND (cuis_existente.cuis <> $11 OR cuis_existente.cuis IS NULL)
RETURNING cuis.id, cuis.registro_empresa_id
),
cuis_insertado AS (
-- Si no existe CUIS, inserta uno nuevo
INSERT INTO cuis (
cuis,
fecha_vigencia,
transaccion,
fecha_creacion,
registro_empresa_id
)
SELECT
$11, $12, $13, $14, id
FROM empresa
WHERE NOT EXISTS (SELECT 1 FROM cuis_existente)
RETURNING id, registro_empresa_id
),
cuis_final AS (
-- Usa el CUIS actualizado si existe
SELECT id, registro_empresa_id FROM cuis_actualizado
UNION ALL
-- O el insertado si no había uno previo
SELECT id, registro_empresa_id FROM cuis_insertado
UNION ALL
-- O el existente si no se actualizó (porque era igual)
SELECT id, registro_empresa_id FROM cuis_existente
WHERE NOT EXISTS (SELECT 1 FROM cuis_actualizado)
AND EXISTS (SELECT 1 FROM cuis_existente)
),
cufd_existente AS (
-- Busca si existe un CUFD para el CUIS actual
SELECT c.id, c.codigo, c.codigo_control, c.direccion, c.cuis_id
FROM cufd c
JOIN cuis_final cf ON c.cuis_id = cf.id
LIMIT 1
),
cufd_actualizado AS (
-- Si existe CUFD pero algún valor es diferente, actualízalo
UPDATE cufd
SET
codigo = $15,
codigo_control = $16,
direccion = $17,
fecha_vigencia = $18,
transaccion = $19,
fecha_actualizacion = CURRENT_TIMESTAMP
FROM cufd_existente, cuis_final
WHERE cufd.id = cufd_existente.id
AND cufd.cuis_id = cuis_final.id
AND (
cufd_existente.codigo <> $15 OR
cufd_existente.codigo_control <> $16 OR
cufd_existente.direccion <> $17 OR
cufd_existente.codigo IS NULL
)
RETURNING (SELECT registro_empresa_id FROM cuis_final LIMIT 1) as registro_id
),
cufd_insertado AS (
-- Si no existe CUFD, inserta uno nuevo
INSERT INTO cufd (
codigo,
codigo_control,
direccion,
fecha_vigencia,
transaccion,
fecha_creacion,
cuis_id
)
SELECT
$15, $16, $17, $18, $19, $20, id
FROM cuis_final
WHERE NOT EXISTS (SELECT 1 FROM cufd_existente)
RETURNING (SELECT registro_empresa_id FROM cuis_final LIMIT 1) as registro_id
),
resultado_final AS (
-- Usa el resultado de cualquiera de las operaciones
SELECT registro_id FROM cufd_actualizado
UNION ALL
SELECT registro_id FROM cufd_insertado
UNION ALL
-- O usa el ID de empresa si el CUFD ya existía y no cambió
SELECT registro_empresa_id as registro_id FROM cuis_final
WHERE NOT EXISTS (SELECT 1 FROM cufd_actualizado)
AND NOT EXISTS (SELECT 1 FROM cufd_insertado)
AND EXISTS (SELECT 1 FROM cufd_existente)
LIMIT 1
)
SELECT registro_id FROM resultado_final LIMIT 1;
`
var registroID int
err = tx.QueryRowContext(
ctx,
query,
// Parámetros para registroEmpresa
request.CodigoAmbiente,
request.CodigoModalidad,
request.CodigoPuntoVenta,
request.CodigoSistema,
request.CodigoSucursal,
request.Nit,
request.KeyToken,
request.ValueToken,
request.NombreArchivoCertificado, // Nuevo parámetro
request.NombreArchivoClavePrivada, // Nuevo parámetro
// Parámetros para cuis
codigoCuis,
fechaVigencia,
transaccion,
currentBolivia,
// Parámetros para cufd
cufdData.Response.Respuesta.Codigo,
cufdData.Response.Respuesta.CodigoControl,
cufdData.Response.Respuesta.Direccion,
cufdData.Response.Respuesta.FechaVigencia,
cufdData.Response.Respuesta.Transaccion,
currentBolivia,
).Scan(&registroID)
if err != nil {
cr.CuisService.LogMessage("Error al insertar/actualizar registros: %v", err)
return utils.ErrorCustom(http.StatusInternalServerError, "Error al procesar los registros en la base de datos")
}
// Confirmar la transacción
if err = tx.Commit(); err != nil {
cr.CuisService.LogMessage("Error al confirmar transacción: %v", err)
return utils.ErrorCustom(http.StatusInternalServerError, "Error al confirmar transacción")
}
return nil
}
// actualiza un registro existente de empresa y CUIS
func (cr *CuisRepository) ActualizarRegistro(ctx context.Context, empresaID int, cuisID int64, req request.SolicitudCuisCufd, respRaw interface{}) error {
currentBolivia, err := utils.GetCurrentBoliviaTime()
if err != nil {
return err
}
// 1. Iniciar tx
tx, err := cr.ModelService.DB.BeginTx(ctx, nil)
if err != nil {
cr.CuisService.LogMessage("Error iniciar transacción: %d", err)
return fmt.Errorf("%w", utils.ErrorCustom(http.StatusBadRequest, "Error iniciar transacción"))
}
defer tx.Rollback()
// 2. Parsear respuesta
nuevoCuis, fechaVigencia, _, err := utils.ParseSoapCuisResponse(respRaw)
if err != nil {
cr.CuisService.LogMessage("Error al parsear la respuesta: %d", err)
return fmt.Errorf("%w", utils.ErrorCustom(http.StatusBadRequest, "Error al parsear la respuesta"))
}
// 3. Actualizar empresa
_, err = tx.ExecContext(ctx, `
UPDATE registroEmpresa
SET codigo_ambiente=$1, codigo_modalidad=$2, codigo_punto_venta=$3,
codigo_sistema=$4, codigo_sucursal=$5, nit=$6, fecha_actualizacion=$7
WHERE id=$8
`,
req.CodigoAmbiente, req.CodigoModalidad, req.CodigoPuntoVenta,
req.CodigoSistema, req.CodigoSucursal, req.Nit, currentBolivia, empresaID,
)
if err != nil {
cr.CuisService.LogMessage("Error al actualizar registroEmpresa: %d", err)
return fmt.Errorf("%w", utils.ErrorCustom(http.StatusBadRequest, "Error al actualizar la tabla registroEmpresa"))
}
// 4. Comprobar si hay un CUIS existente
var existingCuis string
err = tx.QueryRowContext(ctx, `SELECT cuis FROM cuis WHERE id=$1 AND registro_empresa_id=$2`, cuisID, empresaID).Scan(&existingCuis)
if err != nil && err != sql.ErrNoRows {
cr.CuisService.LogMessage("Error al consultar cuis existente: %d", err)
return fmt.Errorf("%w", utils.ErrorCustom(http.StatusBadRequest, "Error al consultar cuis existente"))
}
// 5. Insertar o actualizar
if err == sql.ErrNoRows {
_, err = tx.ExecContext(ctx, `INSERT INTO cuis (registro_empresa_id, cuis) VALUES ($1, $2)`, empresaID, nuevoCuis)
if err != nil {
cr.CuisService.LogMessage("Error al insertar nuevo cuis: %d", err)
return fmt.Errorf("%w", utils.ErrorCustom(http.StatusBadRequest, "Error al insertar nuevo cuis"))
}
} else if existingCuis != nuevoCuis {
_, err = tx.ExecContext(ctx, `UPDATE cuis SET cuis=$1, fecha_vigencia=$2, fecha_actualizacion=$3 WHERE id=$4`,
nuevoCuis, fechaVigencia, currentBolivia, cuisID)
if err != nil {
cr.CuisService.LogMessage("Error al actualizar cuis existente: %d", err)
return fmt.Errorf("%w", utils.ErrorCustom(http.StatusBadRequest, "Error al actualizar cuis existente"))
}
}
// 6. Confirmar tx
if err := tx.Commit(); err != nil {
cr.CuisService.LogMessage("Error al confirmar transacción: %d", err)
return fmt.Errorf("%w", utils.ErrorCustom(http.StatusBadRequest, "Error al confirmar transacción"))
}
return nil
}