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

348 lines
9.7 KiB
Go

package sincronizacionDatos
import (
"context"
"daemonService/internal/handlers"
"daemonService/internal/models"
"daemonService/internal/models/sincronizacionDatos/request"
"database/sql"
"errors"
"fmt"
"log"
"net/http"
"time"
)
type SincronizacionDatosService struct {
models.ServiceModel
}
func (s *SincronizacionDatosService) Execute(ctx context.Context, req *http.Request, isCron bool) (interface{}, error) {
var nit, codPuntoVenta, codSucursal, codigoSistema string
if req != nil {
//2) Recuperar los query params
nit = req.URL.Query().Get("nit")
codPuntoVenta = req.URL.Query().Get("code_point_sale")
codSucursal = req.URL.Query().Get("code_branch")
codigoSistema = req.URL.Query().Get("code_system")
log.Printf("nit: %v", nit)
log.Printf("codPuntoVenta: %v", codPuntoVenta)
log.Printf("codSucursal: %v", codSucursal)
log.Printf("codigoSistema: %v", codigoSistema)
}
// 1. Obtener datos de la base de datos
dbCtx, dbCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer dbCancel()
var rows *sql.Rows
var err error
// Verificar si los parámetros nit, codPuntoVenta y codSucursal tienen valores
if nit != "" && codPuntoVenta != "" && codSucursal != "" {
// Consulta específica con los parámetros proporcionados
query := `
SELECT
r.codigo_ambiente::text,
r.codigo_punto_venta::text,
r.codigo_sistema,
r.codigo_sucursal::text,
c.cuis,
r.nit,
r.token_key,
r.token_value,
c.id
FROM registroEmpresa r
JOIN cuis c ON r.id = c.registro_empresa_id
WHERE r.nit = $1 AND r.codigo_punto_venta = $2 AND r.codigo_sucursal = $3
ORDER BY r.id`
rows, err = s.DB.QueryContext(dbCtx, query, nit, codPuntoVenta, codSucursal)
} else if isCron || req == nil {
// Consulta para el caso de CRON (asumiendo que necesitas todos los registros)
query := `
SELECT
r.codigo_ambiente::text,
r.codigo_punto_venta::text,
r.codigo_sistema,
r.codigo_sucursal::text,
c.cuis,
r.nit,
r.token_key,
r.token_value,
c.id
FROM registroEmpresa r
JOIN cuis c ON r.id = c.registro_empresa_id
ORDER BY r.id`
rows, err = s.DB.QueryContext(dbCtx, query)
} else {
// Si no es CRON y faltan parámetros, retornar error
return nil, fmt.Errorf("parámetros incompletos: se requiere nit, code_point_sale y code_branch")
}
if err != nil {
return nil, handlers.HandleError(&s.ServiceModel, "Error en consulta SQL: %v", err)
}
defer rows.Close()
var respService interface{}
// 2. Procesar registros
success, errors := 0, 0
for rows.Next() {
var solicitud request.SolicitudSincronizacion
var cuisID int
var tokenKey string
var tokenValue string
if err := rows.Scan(
&solicitud.CodigoAmbiente,
&solicitud.CodigoPuntoVenta,
&solicitud.CodigoSistema,
&solicitud.CodigoSucursal,
&solicitud.Cuis,
&solicitud.Nit,
&tokenKey,
&tokenValue,
&cuisID,
); err != nil {
log.Printf("Error escaneando fila: %v", err)
errors++
continue
}
s.ServiceModel.KeyToken = tokenKey
s.ServiceModel.ValueToken = tokenValue
respService, err = ProcesarRegistro(&s.ServiceModel, solicitud, cuisID)
if err != nil {
log.Printf("Error procesando registro: %v", err)
errors++
} else {
success++
}
fmt.Printf("respuesta del servicio: %v", respService)
}
if err := rows.Err(); err != nil {
return nil, handlers.HandleError(&s.ServiceModel, "Error en resultados: %v", err)
}
log.Printf("Proceso completado. Éxitos: %d, Errores: %d", success, errors)
if errors > 0 {
return nil, fmt.Errorf("proceso completado con %d errores", errors)
}
return respService, nil
}
//func (s *SincronizacionDatosService) Execute(ctx context.Context, req *http.Request, isCron bool) (interface{}, error) {
//
// //2) Recuperar los query params
// nit := req.URL.Query().Get("nit")
// codPuntoVenta := req.URL.Query().Get("code_point_sale")
// codSucursal := req.URL.Query().Get("code_branch")
// codigoSistema := req.URL.Query().Get("code_system")
// log.Printf("ni: %v", nit)
// log.Printf("codPuntoVenta: %v", codPuntoVenta)
// log.Printf("codSucursal: %v", codSucursal)
// log.Printf("codigoSistema: %v", codigoSistema)
//
// // 1. Obtener datos de la base de datos
// dbCtx, dbCancel := context.WithTimeout(context.Background(), 10*time.Minute)
// defer dbCancel()
//
// ///////// cuando es CRON = true
// query := `
// SELECT
// r.codigo_ambiente::text,
// r.codigo_punto_venta::text,
// r.codigo_sistema,
// r.codigo_sucursal::text,
// c.cuis,
// r.nit,
// r.token_key,
// r.token_value,
// c.id
// FROM registroEmpresa r
// JOIN cuis c ON r.id = c.registro_empresa_id
// WHERE r.nit = $1 and r.codigo_punto_venta = $2 and r.codigo_sucursal = $3
// ORDER BY r.id`
//
// rows, err := s.DB.QueryContext(dbCtx, query, nit, codPuntoVenta, codSucursal)
// if err != nil {
// return nil, handlers.HandleError(&s.ServiceModel, "Error en consulta SQL: %v", err)
// }
// defer rows.Close()
//
// var respService interface{}
//
// // 2. Procesar registros
// success, errors := 0, 0
// for rows.Next() {
// var solicitud request.SolicitudSincronizacion
// var cuisID int
// var tokenKey string
// var tokenValue string
//
// if err := rows.Scan(
// &solicitud.CodigoAmbiente,
// &solicitud.CodigoPuntoVenta,
// &solicitud.CodigoSistema,
// &solicitud.CodigoSucursal,
// &solicitud.Cuis,
// &solicitud.Nit,
// &tokenKey,
// &tokenValue,
// &cuisID,
// ); err != nil {
// log.Printf("Error escaneando fila: %v", err)
// errors++
// continue
// }
//
// s.ServiceModel.KeyToken = tokenKey
// s.ServiceModel.ValueToken = tokenValue
// respService, err = ProcesarRegistro(&s.ServiceModel, solicitud, cuisID)
// if err != nil {
// log.Printf("Error escaneando fila: %v", err)
// }
//
// fmt.Printf("respuesta del servicio: %v", respService)
// }
//
// if err := rows.Err(); err != nil {
// return nil, handlers.HandleError(&s.ServiceModel, "Error en resultados: %v", err)
// }
//
// log.Printf("Proceso completado. Éxitos: %d, Errores: %d", success, errors)
// if errors > 0 {
// return nil, fmt.Errorf("proceso completado con %d errores", errors)
// }
// return respService, nil
//}
func (s *SincronizacionDatosService) GetName() string {
//func GetName(s models.Service) string {
return s.Name
}
// getEmpresaYCuisID busca registroEmpresa primero por NIT y luego filtra
// por puntoVenta y/o sucursal si vienen > 0.
func getEmpresaYCuisID(db *sql.DB, nit string, puntoVenta, sucursal int) (empresaID, cuisID int, err error) {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
// Construyo dinámicamente el WHERE
where := "nit = $1"
args := []interface{}{nit}
idx := 2
if puntoVenta > 0 {
where += fmt.Sprintf(" AND codigo_punto_venta = $%d", idx)
args = append(args, puntoVenta)
idx++
}
if sucursal > 0 {
where += fmt.Sprintf(" AND codigo_sucursal = $%d", idx)
args = append(args, sucursal)
idx++
}
// Si solo vino nit, dejamos where = "nit = $1"
query := fmt.Sprintf("SELECT id FROM registroEmpresa WHERE %s", where)
row := db.QueryRowContext(ctx, query, args...)
if err = row.Scan(&empresaID); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return 0, 0, fmt.Errorf("no existe registroEmpresa para %q (pv=%d, suc=%d)", nit, puntoVenta, sucursal)
}
return 0, 0, err
}
// Ahora buscamos en cuis
row2 := db.QueryRowContext(ctx,
`SELECT id FROM cuis WHERE registro_empresa_id = $1 ORDER BY fecha_vigencia DESC LIMIT 1`,
empresaID,
)
if err = row2.Scan(&cuisID); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return empresaID, 0, fmt.Errorf("no hay CUIS para registro_empresa_id=%d", empresaID)
}
return empresaID, 0, err
}
return empresaID, cuisID, nil
}
// de sincronizar_tipo_moneda para un cuis dado.
func getRespJSONTipoMoneda(db *sql.DB, cuisID int) ([]string, error) {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
rows, err := db.QueryContext(ctx,
`SELECT respJson
FROM sincronizar_tipo_moneda
WHERE cuis_id = $1`,
cuisID,
)
if err != nil {
return nil, err
}
defer rows.Close()
var respList []string
for rows.Next() {
var resp sql.NullString
if err := rows.Scan(&resp); err != nil {
return nil, err
}
if resp.Valid {
respList = append(respList, resp.String)
} else {
// si fuera NULL, podrías elegir omitirlo o añadir una cadena vacía
respList = append(respList, "")
}
}
if err := rows.Err(); err != nil {
return nil, err
}
return respList, nil
}
//// getTipoMoneda trae todas las filas de sincronizar_tipo_moneda para un cuis dado
//func getTipoMoneda(db *sql.DB, cuisID int) ([]entities.TipoMoneda, error) {
// ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
// defer cancel()
//
// rows, err := db.QueryContext(ctx,
// `SELECT id, codigo, reqSoap, respSoap, reqJson, respJson, fecha_creacion, fecha_actualizacion, cuis_id
// FROM sincronizar_tipo_moneda
// WHERE cuis_id = $1`,
// cuisID,
// )
// if err != nil {
// return nil, err
// }
// defer rows.Close()
//
// var resultados []entities.TipoMoneda
// for rows.Next() {
// var tm entities.TipoMoneda
// if err := rows.Scan(
// &tm.ID, &tm.Codigo, &tm.ReqSoap, &tm.RespSoap,
// &tm.ReqJson, &tm.RespJson, &tm.FechaCreacion,
// &tm.FechaActualizacion, &tm.CUISID,
// ); err != nil {
// return nil, err
// }
// resultados = append(resultados, tm)
// }
// if err := rows.Err(); err != nil {
// return nil, err
// }
// return resultados, nil
//}