852 lines
30 KiB
Go
852 lines
30 KiB
Go
package obtencionCodigo
|
|
|
|
//
|
|
//import (
|
|
// "context"
|
|
// "daemonService/internal/handlers"
|
|
// "daemonService/internal/models"
|
|
// svc "daemonService/internal/models"
|
|
// "daemonService/internal/models/obtencionCodigos"
|
|
// "daemonService/internal/repositories"
|
|
// "daemonService/internal/services/obtencionCodigo"
|
|
// "daemonService/internal/services/procesar"
|
|
// "daemonService/internal/services/sincronizacionDatos"
|
|
// "flag"
|
|
// "fmt"
|
|
// "github.com/robfig/cron/v3"
|
|
// "log"
|
|
// "net/http"
|
|
// "os"
|
|
// "os/signal"
|
|
// "syscall"
|
|
// "time"
|
|
//
|
|
// "daemonService/internal/api"
|
|
// "daemonService/internal/config"
|
|
// "daemonService/internal/database"
|
|
// "daemonService/internal/notifications"
|
|
// "daemonService/internal/services"
|
|
//)
|
|
//
|
|
//func main() {
|
|
// configFile := flag.String("config", "configs/config.yaml", "Ruta al archivo de configuración")
|
|
// runOnce := flag.Bool("run-once", false, "Ejecutar servicios una vez y salir")
|
|
// serviceName := flag.String("service", "", "Nombre del servicio específico a ejecutar")
|
|
// flag.Parse()
|
|
//
|
|
// // Cargar configuración
|
|
// cfg, err := config.LoadConfig(*configFile)
|
|
// if err != nil {
|
|
// log.Fatalf("Error al cargar configuración: %v", err)
|
|
// }
|
|
//
|
|
// // Inicializar la base de datos
|
|
// db, err := database.InitDB(*cfg)
|
|
// if err != nil {
|
|
// log.Fatalf("Error al inicializar la base de datos: %v", err)
|
|
// }
|
|
// defer db.Close()
|
|
//
|
|
// // Crear sistema de notificaciones
|
|
// notifier := notifications.CreateNotificationSender(cfg.Notifications.Enabled, cfg.Notifications.Method, cfg.Notifications.Config)
|
|
// if notifier != nil {
|
|
// log.Printf("Sistema de notificaciones iniciado: %s", cfg.Notifications.Method)
|
|
// }
|
|
//
|
|
// // Crear servicios a partir de la configuración
|
|
// //var cuisServices []models.CuisService
|
|
// var servicesList []models.SoapService
|
|
// var servicesList2 []obtencionCodigos.CuisService
|
|
// for _, svcCfg := range cfg.Services {
|
|
// if !svcCfg.Enabled {
|
|
// continue
|
|
// }
|
|
//
|
|
// // Crear el logger para el servicio
|
|
// serviceLogger := log.New(log.Writer(), fmt.Sprintf("[%s] ", svcCfg.Name), log.LstdFlags)
|
|
//
|
|
// log.Println(cfg.SOAP.FACTURA_SINCRONIZACION.Retries)
|
|
// baseSvc := svc.ServiceModel{
|
|
// Name: svcCfg.Name,
|
|
// Enabled: svcCfg.Enabled,
|
|
// Concurrency: svcCfg.Concurrency,
|
|
// DB: db,
|
|
// SOAPEndpoint: cfg.SOAP.FACTURA_SINCRONIZACION.Endpoint,
|
|
// SOAPTimeout: time.Duration(cfg.SOAP.FACTURA_SINCRONIZACION.Timeout) * time.Second,
|
|
// SOAPRetries: cfg.SOAP.FACTURA_SINCRONIZACION.Retries,
|
|
// NotificationSender: notifier,
|
|
// APIKey: cfg.SOAP.APIKey,
|
|
// TagNames: "",
|
|
// QueryInsert: "",
|
|
// MsgCustomResponse: "",
|
|
// }
|
|
//
|
|
// cuisServiceModel := obtencionCodigos.CuisServiceModel{
|
|
// Name: svcCfg.Name,
|
|
// Enabled: svcCfg.Enabled,
|
|
// Concurrency: svcCfg.Concurrency,
|
|
// DB: db,
|
|
// SOAPEndpoint: cfg.SOAP.FACTURA_CODIGO.Endpoint,
|
|
// SOAPTimeout: time.Duration(cfg.SOAP.FACTURA_CODIGO.Timeout) * time.Second,
|
|
// SOAPRetries: cfg.SOAP.FACTURA_CODIGO.Retries,
|
|
// NotificationSender: notifier,
|
|
// APIKey: cfg.SOAP.APIKey,
|
|
// TagNames: "",
|
|
// QueryInsert: "",
|
|
// MsgCustomResponse: "",
|
|
// }
|
|
//
|
|
// //registrar-empresa solo para registrar empresa
|
|
// cuisServiceModel.TagNames = "cuis"
|
|
// cuisServiceModel.QueryInsert = "INSERT INTO registroEmpresa (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
|
|
// cuisServiceModel.MsgCustomResponse = "Registrar Empresa"
|
|
//
|
|
// procesarRegistro := procesar.NewProcesarRegistro(cuisServiceModel)
|
|
// empresaRepository := repositories.NewEmpresaRepository(cuisServiceModel)
|
|
// cuisService := services.NewCuisService(cuisServiceModel, serviceLogger)
|
|
// cuisRepository := repositories.NewCuisRepository(baseSvc, cuisService)
|
|
// cronHandler := handlers.NewCronHandler(cuisService, empresaRepository, cuisRepository, procesarRegistro)
|
|
// apiHandler := handlers.NewApiHandler(cuisService, cuisRepository, procesarRegistro)
|
|
//
|
|
// // Llamar a NewObtencionCodigoService correctamente
|
|
// obtencionCodigoSvc := obtencionCodigo.NewObtencionCodigoService(
|
|
// cuisServiceModel,
|
|
// cuisService,
|
|
// cronHandler,
|
|
// apiHandler,
|
|
// )
|
|
//
|
|
// switch svcCfg.Name {
|
|
// case "registrar-empresa":
|
|
// servicesList2 = append(servicesList2, obtencionCodigoSvc)
|
|
// break
|
|
// case "leyendas_factura":
|
|
// baseSvc.TagNames = "sincronizarListaLeyendasFactura"
|
|
// baseSvc.QueryInsert = "INSERT INTO leyendas_factura (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
|
|
// baseSvc.MsgCustomResponse = "Listado Leyendas de Facturas"
|
|
// servicesList = append(servicesList, &sincronizacionDatos.SincronizacionDatosService{
|
|
// ServiceModel: baseSvc,
|
|
// })
|
|
// case "producto-servicio":
|
|
// baseSvc.TagNames = "sincronizarListaProductosServicios"
|
|
// baseSvc.QueryInsert = "INSERT INTO productos_servicios (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
|
|
// baseSvc.MsgCustomResponse = "Listado Producto Servicio"
|
|
// servicesList = append(servicesList, &sincronizacionDatos.SincronizacionDatosService{
|
|
// ServiceModel: baseSvc,
|
|
// })
|
|
// case "tipo_documento_identidad":
|
|
// baseSvc.TagNames = "sincronizarParametricaTipoDocumentoIdentidad"
|
|
// baseSvc.QueryInsert = "INSERT INTO tipo_documento_identidad (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
|
|
// baseSvc.MsgCustomResponse = "Listado tipos de documento de identidad"
|
|
// servicesList = append(servicesList, &sincronizacionDatos.SincronizacionDatosService{
|
|
// ServiceModel: baseSvc,
|
|
// })
|
|
// case "tipo_documento_sector":
|
|
// baseSvc.TagNames = "sincronizarParametricaTipoDocumentoSector"
|
|
// baseSvc.QueryInsert = "INSERT INTO tipo_documento_sector (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
|
|
// baseSvc.MsgCustomResponse = "Listado tipos de documento de identidad"
|
|
// servicesList = append(servicesList, &sincronizacionDatos.SincronizacionDatosService{
|
|
// ServiceModel: baseSvc,
|
|
// })
|
|
// case "tipo_metodo_pago":
|
|
// baseSvc.TagNames = "sincronizarParametricaTipoMetodoPago"
|
|
// baseSvc.QueryInsert = "INSERT INTO tipo_metodo_pago (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
|
|
// baseSvc.MsgCustomResponse = "Listado tipos metodo de pago"
|
|
// servicesList = append(servicesList, &sincronizacionDatos.SincronizacionDatosService{
|
|
// ServiceModel: baseSvc,
|
|
// })
|
|
// case "tipo_moneda":
|
|
// baseSvc.TagNames = "sincronizarParametricaTipoMoneda"
|
|
// baseSvc.QueryInsert = "INSERT INTO tipo_moneda (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
|
|
// baseSvc.MsgCustomResponse = "Listado tipos de moneda"
|
|
// servicesList = append(servicesList, &sincronizacionDatos.SincronizacionDatosService{
|
|
// ServiceModel: baseSvc,
|
|
// })
|
|
// case "tipo_punto_venta":
|
|
// baseSvc.TagNames = "sincronizarParametricaTipoPuntoVenta"
|
|
// baseSvc.QueryInsert = "INSERT INTO tipo_punto_venta (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
|
|
// baseSvc.MsgCustomResponse = "Listado tipos de punto de venta"
|
|
// servicesList = append(servicesList, &sincronizacionDatos.SincronizacionDatosService{
|
|
// ServiceModel: baseSvc,
|
|
// })
|
|
// case "tipo_unidad_medida":
|
|
// baseSvc.TagNames = "sincronizarParametricaUnidadMedida"
|
|
// baseSvc.QueryInsert = "INSERT INTO tipo_unidad_medida (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
|
|
// baseSvc.MsgCustomResponse = "Listado tipos de unidad de medida"
|
|
// servicesList = append(servicesList, &sincronizacionDatos.SincronizacionDatosService{
|
|
// ServiceModel: baseSvc,
|
|
// })
|
|
// default:
|
|
// log.Printf("Servicio desconocido: %s", svcCfg.Name)
|
|
// }
|
|
// }
|
|
//
|
|
// // Si se especifica un servicio específico, filtrar la lista.
|
|
// if *serviceName != "" {
|
|
// var filtered []models.SoapService
|
|
// for _, s := range servicesList {
|
|
// if s.GetName() == *serviceName {
|
|
// filtered = append(filtered, s)
|
|
// break
|
|
// }
|
|
// }
|
|
// if len(filtered) == 0 {
|
|
// log.Fatalf("No se encontró el servicio: %s", *serviceName)
|
|
// }
|
|
// servicesList = filtered
|
|
// log.Printf("Ejecutando solo el servicio: %s", *serviceName)
|
|
// }
|
|
//
|
|
// // Crear contexto con cancelación para manejar señales de terminación.
|
|
// ctx, cancel := context.WithCancel(context.Background())
|
|
// defer cancel()
|
|
//
|
|
// // Canal para capturar señales del sistema.
|
|
// sigChan := make(chan os.Signal, 1)
|
|
// signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
|
|
//
|
|
// // Iniciar servidor HTTP si se configura puerto para API.
|
|
// var httpServer *http.Server
|
|
// if cfg.API.Port > 0 {
|
|
// httpServer = api.StartAPIServer(cfg.API.Port, servicesList, servicesList2, false)
|
|
// }
|
|
//
|
|
// // Goroutine para manejar señales.
|
|
// go func() {
|
|
// sig := <-sigChan
|
|
// log.Printf("Recibida señal: %v. Cerrando...", sig)
|
|
// if notifier != nil {
|
|
// notifier.SendNotification("Servicio detenido", fmt.Sprintf("El servicio fue detenido por la señal: %v", sig))
|
|
// }
|
|
// cancel()
|
|
// if httpServer != nil {
|
|
// log.Println("Cerrando servidor HTTP...")
|
|
// shutdownCtx, cancelServer := context.WithTimeout(context.Background(), 10*time.Second)
|
|
// defer cancelServer()
|
|
// if err := httpServer.Shutdown(shutdownCtx); err != nil {
|
|
// log.Printf("Error al cerrar servidor HTTP: %v", err)
|
|
// }
|
|
// }
|
|
// }()
|
|
//
|
|
// // Si se debe ejecutar solo una vez.
|
|
// if *runOnce {
|
|
// errors := services.RunAllServices(ctx, servicesList, false)
|
|
// if len(errors) > 0 {
|
|
// for _, e := range errors {
|
|
// log.Printf("Error: %v", e)
|
|
// }
|
|
// os.Exit(1)
|
|
// }
|
|
// return
|
|
// }
|
|
//
|
|
// // Configurar primer cron
|
|
// c := cron.New(cron.WithSeconds())
|
|
// _, err = c.AddFunc(cfg.Schedule.FACTURA_SINCRONIZACION.Cron, func() {
|
|
// log.Println("Iniciando ejecución programada de servicios")
|
|
// execCtx, execCancel := context.WithCancel(ctx)
|
|
// defer execCancel()
|
|
//
|
|
// errors := services.RunAllServices(execCtx, servicesList, true)
|
|
// if len(errors) > 0 {
|
|
// errMsg := "Errores durante la ejecución programada:"
|
|
// for _, err := range errors {
|
|
// errMsg += "\n- " + err.Error()
|
|
// }
|
|
// if notifier != nil {
|
|
// notifier.SendNotification("Errores en ejecución programada", errMsg)
|
|
// }
|
|
// log.Println(errMsg)
|
|
// } else {
|
|
// log.Println("Ejecución programada completada exitosamente")
|
|
// }
|
|
// })
|
|
//
|
|
// if err != nil {
|
|
// log.Fatalf("Error al programar tareas: %v", err)
|
|
// }
|
|
//
|
|
// // Configurar segundo cron
|
|
// cronGetCode := cron.New(cron.WithSeconds())
|
|
// _, err = cronGetCode.AddFunc(cfg.Schedule.FACTURA_CODIGO.Cron, func() {
|
|
// log.Println("Iniciando ejecución programada para Obtener Codigos")
|
|
// execCtx, cancel := context.WithCancel(context.Background())
|
|
// defer cancel()
|
|
// //execCtx, execCancel := context.WithCancel(ctx)
|
|
// //defer execCancel()
|
|
//
|
|
// errors := services.RunAllGetCodeServices(execCtx, servicesList2, true)
|
|
// if len(errors) > 0 {
|
|
// errMsg := "Errores durante la ejecución programada Obtener Codigos:"
|
|
// for _, err := range errors {
|
|
// errMsg += "\n- " + err.Error()
|
|
// }
|
|
// if notifier != nil {
|
|
// notifier.SendNotification("Errores en ejecución programada Obtener Codigos", errMsg)
|
|
// }
|
|
// log.Println(errMsg)
|
|
// } else {
|
|
// log.Println("Ejecución programada completada exitosamente Obtener Codigos")
|
|
// }
|
|
// })
|
|
//
|
|
// if err != nil {
|
|
// log.Fatalf("Error al programar tareas Obtener Codigos: %v", err)
|
|
// }
|
|
//
|
|
// // Iniciar ambos cron
|
|
// c.Start()
|
|
// cronGetCode.Start()
|
|
//
|
|
// log.Printf("Demonio de servicios iniciado. Programación: %s", cfg.Schedule.FACTURA_SINCRONIZACION.Cron)
|
|
// log.Printf("Demonio de obtención de códigos iniciado. Programación: %s", cfg.Schedule.FACTURA_CODIGO.Cron)
|
|
//
|
|
// if notifier != nil {
|
|
// notifier.SendNotification("Servicios iniciados",
|
|
// fmt.Sprintf("Los servicios SOAP han sido iniciados con programación: %s", cfg.Schedule.FACTURA_SINCRONIZACION.Cron))
|
|
// }
|
|
//
|
|
// // Esperar a que el contexto termine y luego detener ambos cron
|
|
// <-ctx.Done()
|
|
// c.Stop()
|
|
// cronGetCode.Stop()
|
|
// log.Println("Demonios detenidos correctamente")
|
|
//}
|
|
|
|
//package obtencionCodigo
|
|
|
|
//
|
|
//import (
|
|
// "context"
|
|
// "daemonService/internal/services/procesar"
|
|
// "database/sql"
|
|
// "encoding/json"
|
|
// "errors"
|
|
// "fmt"
|
|
// "log"
|
|
// "net/http"
|
|
// "strconv"
|
|
// "time"
|
|
//
|
|
// "daemonService/internal/models/obtencionCodigos"
|
|
// "daemonService/internal/models/obtencionCodigos/request"
|
|
// "daemonService/internal/models/obtencionCodigos/response"
|
|
//)
|
|
//
|
|
//// Constantes para la configuración general
|
|
//const (
|
|
// maxBodySize = 1 * 1024 * 1024 // 1MB
|
|
// defaultTimeZone = "America/La_Paz"
|
|
// logServiceStart = "Iniciando servicio %s"
|
|
// logServiceEnd = "Finalizado servicio %s"
|
|
// logErrorProcessing = "Error procesando registro %s: %v"
|
|
//)
|
|
//
|
|
//// Errores comunes
|
|
//var (
|
|
// ErrAllFieldsRequired = errors.New("todos los campos son requeridos")
|
|
// ErrUnexpectedRespType = errors.New("tipo de respuesta inesperado")
|
|
//)
|
|
//
|
|
//// mapea toda la tabla registroEmpresa
|
|
//type RegistroEmpresa struct {
|
|
// ID int `sql:"id"`
|
|
// CodigoAmbiente int `sql:"codigo_ambiente"`
|
|
// CodigoModalidad int `sql:"codigo_modalidad"`
|
|
// CodigoPuntoVenta int `sql:"codigo_punto_venta"`
|
|
// CodigoSistema string `sql:"codigo_sistema"`
|
|
// CodigoSucursal int `sql:"codigo_sucursal"`
|
|
// Nit string `sql:"nit"`
|
|
// FechaCreacion time.Time `sql:"fecha_creacion"`
|
|
// FechaActualizacion time.Time `sql:"fecha_actualizacion"`
|
|
//}
|
|
//
|
|
//// solo tiene los dos campos que quieres de la tabla cuis
|
|
//type CuisMinimal struct {
|
|
// Cuis_id int64 `sql:"id"`
|
|
// Cuis string `sql:"cuis"`
|
|
// FechaVigencia time.Time `sql:"fecha_vigencia"`
|
|
//}
|
|
//
|
|
//// EmpresaConCuis agrupa una empresa con sus cuis mínimos
|
|
//type EmpresaConCuis struct {
|
|
// RegistroEmpresa
|
|
// Cuis []CuisMinimal
|
|
//}
|
|
//
|
|
//type ObtencionCodigoService struct {
|
|
// obtencionCodigos.CuisServiceModel
|
|
// procesar.Procesar
|
|
// Logger *log.Logger
|
|
//}
|
|
//
|
|
//// retorna el nombre del servicio
|
|
//func (s *ObtencionCodigoService) GetName() string {
|
|
// return s.Name
|
|
//}
|
|
//
|
|
//// registra un mensaje con el prefijo del servicio
|
|
//func (s *ObtencionCodigoService) logMessage(format string, v ...interface{}) {
|
|
// if s.Logger != nil {
|
|
// s.Logger.Printf(format, v...)
|
|
// }
|
|
//}
|
|
//
|
|
//// registra un error y devuelve el mismo error
|
|
//func (s *ObtencionCodigoService) logError(format string, err error, v ...interface{}) error {
|
|
// args := append([]interface{}{err}, v...)
|
|
// if s.Logger != nil {
|
|
// s.Logger.Printf(format, args...)
|
|
// }
|
|
// return fmt.Errorf(format, args...)
|
|
//}
|
|
//
|
|
//// maneja la obtención de códigos CUIS
|
|
//func (s *ObtencionCodigoService) ExecuteGetCode(dbCtx context.Context, w http.ResponseWriter, req *http.Request, isCron bool) (interface{}, error) {
|
|
// s.logMessage(logServiceStart, s.Name)
|
|
// defer s.logMessage(logServiceEnd, s.Name)
|
|
//
|
|
// var respCuis interface{}
|
|
// var err error
|
|
//
|
|
// if isCron {
|
|
// respCuis, err = s.processCronMode(dbCtx)
|
|
// } else {
|
|
// respCuis, err = s.processAPIMode(dbCtx, w, req)
|
|
// }
|
|
//
|
|
// if err != nil {
|
|
// return nil, err
|
|
// }
|
|
// return respCuis, nil
|
|
//}
|
|
//
|
|
//// procesa la ejecución en modo cron
|
|
//func (s *ObtencionCodigoService) processCronMode(dbCtx context.Context) (interface{}, error) {
|
|
// empresasConCuis, err := s.GetEmpresasConCuisMinimal(dbCtx)
|
|
// if err != nil {
|
|
// return nil, s.logError("Error al obtener empresas con CUIS: %v", err)
|
|
// }
|
|
//
|
|
// var lastResponse interface{}
|
|
// for _, ec := range empresasConCuis {
|
|
// s.logMessage("Procesando empresa ID: %d", ec.ID)
|
|
//
|
|
// if len(ec.Cuis) == 0 {
|
|
// s.logMessage("Empresa ID %d sin CUIS registrados", ec.ID)
|
|
// continue
|
|
// }
|
|
//
|
|
// for _, c := range ec.Cuis {
|
|
// s.logMessage("Procesando CUIS ID: %d", c.Cuis_id)
|
|
//
|
|
// cuisRequest := s.buildCuisRequestFromEmpresa(ec)
|
|
// respCuis, err := s.CodigoProcesarRegistro(&s.CuisServiceModel, cuisRequest, 0)
|
|
//
|
|
// if err != nil {
|
|
// s.logError(logErrorProcessing, err, cuisRequest.CodigoSistema)
|
|
// continue
|
|
// }
|
|
//
|
|
// if err := s.actualizarRegistro(dbCtx, ec.ID, c.Cuis_id, cuisRequest, respCuis); err != nil {
|
|
// s.logError("Error actualizando registro: %v", err)
|
|
// continue
|
|
// }
|
|
//
|
|
// lastResponse = respCuis
|
|
// }
|
|
// }
|
|
//
|
|
// return lastResponse, nil
|
|
//}
|
|
//
|
|
//// procesa la ejecución en modo API
|
|
//func (s *ObtencionCodigoService) processAPIMode(dbCtx context.Context, w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
|
// cuisRequest, err := s.parseCuisRequest(w, req)
|
|
// if err != nil {
|
|
// return nil, err
|
|
// }
|
|
//
|
|
// if err := s.validateCuisRequest(cuisRequest); err != nil {
|
|
// return nil, s.logError("Datos inválidos: %v", err)
|
|
// }
|
|
//
|
|
// respCuis, err := s.CodigoProcesarRegistro(&s.CuisServiceModel, cuisRequest, 0)
|
|
// if err != nil {
|
|
// return nil, s.logError(logErrorProcessing, err, cuisRequest.CodigoSistema)
|
|
// }
|
|
//
|
|
// if err := s.crearNuevoRegistro(dbCtx, cuisRequest, respCuis); err != nil {
|
|
// return nil, s.logError("Error creando nuevo registro: %v", err)
|
|
// }
|
|
//
|
|
// return respCuis, nil
|
|
//}
|
|
//
|
|
//// parsea la solicitud de CUIS desde el body del request
|
|
//func (s *ObtencionCodigoService) parseCuisRequest(w http.ResponseWriter, req *http.Request) (request.SolicitudCuis, error) {
|
|
// var cuisRequest request.SolicitudCuis
|
|
//
|
|
// // Limitar el tamaño del body para prevenir ataques DoS
|
|
// req.Body = http.MaxBytesReader(w, req.Body, maxBodySize)
|
|
//
|
|
// decoder := json.NewDecoder(req.Body)
|
|
// decoder.DisallowUnknownFields() // Rechazar campos desconocidos
|
|
//
|
|
// if err := decoder.Decode(&cuisRequest); err != nil {
|
|
// return cuisRequest, s.logError("Error al decodificar JSON: %v", err)
|
|
// }
|
|
//
|
|
// return cuisRequest, nil
|
|
//}
|
|
//
|
|
//// valida los datos de la solicitud CUIS
|
|
//func (s *ObtencionCodigoService) validateCuisRequest(request request.SolicitudCuis) error {
|
|
// if request.CodigoAmbiente == "" ||
|
|
// request.CodigoModalidad == "" ||
|
|
// request.CodigoPuntoVenta == "" ||
|
|
// request.CodigoSistema == "" ||
|
|
// request.CodigoSucursal == "" ||
|
|
// request.Nit == "" {
|
|
// return ErrAllFieldsRequired
|
|
// }
|
|
// return nil
|
|
//}
|
|
//
|
|
//// crea una solicitud CUIS a partir de datos de empresa
|
|
//func (s *ObtencionCodigoService) buildCuisRequestFromEmpresa(ec EmpresaConCuis) request.SolicitudCuis {
|
|
// return request.SolicitudCuis{
|
|
// CodigoAmbiente: strconv.Itoa(ec.CodigoAmbiente),
|
|
// CodigoModalidad: strconv.Itoa(ec.CodigoModalidad),
|
|
// CodigoPuntoVenta: strconv.Itoa(ec.CodigoPuntoVenta),
|
|
// CodigoSistema: ec.CodigoSistema,
|
|
// CodigoSucursal: strconv.Itoa(ec.CodigoSucursal),
|
|
// Nit: ec.Nit,
|
|
// }
|
|
//}
|
|
//
|
|
//// obtiene todas las empresas con sus CUIS
|
|
//func (s *ObtencionCodigoService) GetEmpresasConCuisMinimal(ctx context.Context) ([]EmpresaConCuis, error) {
|
|
// const query = `
|
|
// SELECT
|
|
// -- columnas de registroEmpresa
|
|
// re.id, re.codigo_ambiente, re.codigo_modalidad, re.codigo_punto_venta,
|
|
// re.codigo_sistema, re.codigo_sucursal, re.nit,
|
|
// re.fecha_creacion, re.fecha_actualizacion,
|
|
// -- columnas específicas de cuis
|
|
// c.id, c.cuis, c.fecha_vigencia
|
|
// FROM registroEmpresa re
|
|
// LEFT JOIN cuis c ON c.registro_empresa_id = re.id
|
|
// ORDER BY re.id;
|
|
// `
|
|
//
|
|
// rows, err := s.DB.QueryContext(ctx, query)
|
|
// if err != nil {
|
|
// return nil, fmt.Errorf("consulta empresas con cuis minimal: %w", err)
|
|
// }
|
|
// defer rows.Close()
|
|
//
|
|
// // Mapa temporal para agrupar por empresa.ID
|
|
// empresasMap := make(map[int]*EmpresaConCuis)
|
|
//
|
|
// for rows.Next() {
|
|
// // Variables temporales de escaneo
|
|
// var (
|
|
// id int
|
|
// codigoAmbiente int
|
|
// codigoModalidad int
|
|
// codigoPuntoVenta int
|
|
// codigoSistema string
|
|
// codigoSucursal int
|
|
// nit string
|
|
// fechaCreacion time.Time
|
|
// fechaActualizacion time.Time
|
|
//
|
|
// idCuis sql.NullInt64
|
|
// cuis sql.NullString
|
|
// fechaVigencia sql.NullTime
|
|
// )
|
|
//
|
|
// // Leer la fila
|
|
// if err := rows.Scan(
|
|
// &id, &codigoAmbiente, &codigoModalidad, &codigoPuntoVenta,
|
|
// &codigoSistema, &codigoSucursal, &nit,
|
|
// &fechaCreacion, &fechaActualizacion,
|
|
// &idCuis, &cuis, &fechaVigencia,
|
|
// ); err != nil {
|
|
// return nil, fmt.Errorf("scan fila: %w", err)
|
|
// }
|
|
//
|
|
// // ¿Ya existe la empresa en el mapa?
|
|
// ent, ok := empresasMap[id]
|
|
// if !ok {
|
|
// // Si no existe, la creamos y rellenamos datos de registroEmpresa
|
|
// ent = &EmpresaConCuis{
|
|
// RegistroEmpresa: RegistroEmpresa{
|
|
// ID: id,
|
|
// CodigoAmbiente: codigoAmbiente,
|
|
// CodigoModalidad: codigoModalidad,
|
|
// CodigoPuntoVenta: codigoPuntoVenta,
|
|
// CodigoSistema: codigoSistema,
|
|
// CodigoSucursal: codigoSucursal,
|
|
// Nit: nit,
|
|
// FechaCreacion: fechaCreacion,
|
|
// FechaActualizacion: fechaActualizacion,
|
|
// },
|
|
// Cuis: make([]CuisMinimal, 0, 1),
|
|
// }
|
|
// empresasMap[id] = ent
|
|
// }
|
|
//
|
|
// // Si hay un CUIS válido, lo añadimos al slice
|
|
// if idCuis.Valid && cuis.Valid && fechaVigencia.Valid {
|
|
// ent.Cuis = append(ent.Cuis, CuisMinimal{
|
|
// Cuis_id: idCuis.Int64,
|
|
// Cuis: cuis.String,
|
|
// FechaVigencia: fechaVigencia.Time,
|
|
// })
|
|
// }
|
|
// }
|
|
//
|
|
// if err := rows.Err(); err != nil {
|
|
// return nil, fmt.Errorf("iteración filas: %w", err)
|
|
// }
|
|
//
|
|
// // Convertimos el mapa a slice ordenado por aparición
|
|
// resp := make([]EmpresaConCuis, 0, len(empresasMap))
|
|
// for _, ent := range empresasMap {
|
|
// resp = append(resp, *ent)
|
|
// }
|
|
// return resp, nil
|
|
//}
|
|
//
|
|
//// busca un registro de empresa por sus criterios
|
|
//func (s *ObtencionCodigoService) buscarRegistroEmpresa(ctx context.Context, request request.SolicitudCuis) (int, error) {
|
|
// query := `
|
|
// SELECT id
|
|
// FROM registroEmpresa
|
|
// WHERE codigo_sistema = $1
|
|
// AND nit = $2
|
|
// AND codigo_ambiente = $3
|
|
// AND codigo_punto_venta = $4
|
|
// AND codigo_sucursal = $5
|
|
// LIMIT 1
|
|
// `
|
|
//
|
|
// var id int
|
|
// err := s.DB.QueryRowContext(
|
|
// ctx,
|
|
// query,
|
|
// request.CodigoSistema,
|
|
// request.Nit,
|
|
// request.CodigoAmbiente,
|
|
// request.CodigoPuntoVenta,
|
|
// request.CodigoSucursal,
|
|
// ).Scan(&id)
|
|
//
|
|
// if err == sql.ErrNoRows {
|
|
// return 0, nil // No existe el registro
|
|
// }
|
|
//
|
|
// if err != nil {
|
|
// return 0, err
|
|
// }
|
|
//
|
|
// return id, nil
|
|
//}
|
|
//
|
|
//// obtiene la hora actual en la zona horaria de Bolivia
|
|
//func (s *ObtencionCodigoService) getCurrentBoliviaTime() (time.Time, error) {
|
|
// loc, err := time.LoadLocation(defaultTimeZone)
|
|
// if err != nil {
|
|
// return time.Time{}, err
|
|
// }
|
|
// return time.Now().In(loc), nil
|
|
//}
|
|
//
|
|
//// parsea la respuesta SOAP para CUIS
|
|
//func (s *ObtencionCodigoService) parseSoapCuisResponse(respSoap interface{}) (string, string, bool, error) {
|
|
// resp, ok := respSoap.(response.SoapBodyCuis)
|
|
// if !ok {
|
|
// return "", "", false, fmt.Errorf("%w: %T", ErrUnexpectedRespType, respSoap)
|
|
// }
|
|
//
|
|
// return resp.Response.Respuesta.Codigo,
|
|
// resp.Response.Respuesta.FechaVigencia,
|
|
// resp.Response.Respuesta.Transaccion,
|
|
// nil
|
|
//}
|
|
//
|
|
//// crea un nuevo registro de empresa y CUIS
|
|
//func (s *ObtencionCodigoService) crearNuevoRegistro(ctx context.Context, request request.SolicitudCuis, respSoap interface{}) error {
|
|
// currentBolivia, err := s.getCurrentBoliviaTime()
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
//
|
|
// // Parsear respuesta
|
|
// codigoCuis, fechaVigencia, transaccion, err := s.parseSoapCuisResponse(respSoap)
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
//
|
|
// // Iniciar transacción
|
|
// tx, err := s.DB.BeginTx(ctx, nil)
|
|
// if err != nil {
|
|
// return fmt.Errorf("error al iniciar transacción: %w", err)
|
|
// }
|
|
// defer tx.Rollback()
|
|
//
|
|
// // Verificar si ya existe el NIT en la base de datos
|
|
// var existeNIT bool
|
|
// queryVerificacionNIT := `
|
|
// SELECT EXISTS (
|
|
// SELECT 1 FROM registroEmpresa
|
|
// WHERE nit = $1
|
|
// )
|
|
// `
|
|
// err = tx.QueryRowContext(
|
|
// ctx,
|
|
// queryVerificacionNIT,
|
|
// request.Nit,
|
|
// ).Scan(&existeNIT)
|
|
//
|
|
// if err != nil {
|
|
// return fmt.Errorf("error al verificar existencia del NIT: %w", err)
|
|
// }
|
|
//
|
|
// // Si el NIT ya existe, verificar si la combinación de sucursal y punto de venta existe
|
|
// if existeNIT {
|
|
// var existeCombinacion bool
|
|
// queryVerificacionCombinacion := `
|
|
// SELECT EXISTS (
|
|
// SELECT 1 FROM registroEmpresa
|
|
// WHERE nit = $1
|
|
// AND codigo_sucursal = $2
|
|
// AND codigo_punto_venta = $3
|
|
// )
|
|
// `
|
|
// err = tx.QueryRowContext(
|
|
// ctx,
|
|
// queryVerificacionCombinacion,
|
|
// request.Nit,
|
|
// request.CodigoSucursal,
|
|
// request.CodigoPuntoVenta,
|
|
// ).Scan(&existeCombinacion)
|
|
//
|
|
// if err != nil {
|
|
// return fmt.Errorf("error al verificar combinación de sucursal y punto de venta: %w", err)
|
|
// }
|
|
//
|
|
// if existeCombinacion {
|
|
// return fmt.Errorf("ya existe un registro con el mismo NIT, código sucursal y código punto de venta")
|
|
// }
|
|
// }
|
|
//
|
|
// // Insertar en registroEmpresa
|
|
// query := `
|
|
// INSERT INTO registroEmpresa (
|
|
// codigo_ambiente,
|
|
// codigo_modalidad,
|
|
// codigo_punto_venta,
|
|
// codigo_sistema,
|
|
// codigo_sucursal,
|
|
// nit
|
|
// ) VALUES ($1, $2, $3, $4, $5, $6)
|
|
// RETURNING id
|
|
// `
|
|
// var registroID int
|
|
// err = tx.QueryRowContext(
|
|
// ctx,
|
|
// query,
|
|
// request.CodigoAmbiente,
|
|
// request.CodigoModalidad,
|
|
// request.CodigoPuntoVenta,
|
|
// request.CodigoSistema,
|
|
// request.CodigoSucursal,
|
|
// request.Nit,
|
|
// ).Scan(®istroID)
|
|
// if err != nil {
|
|
// return fmt.Errorf("error al insertar registro: %w", err)
|
|
// }
|
|
//
|
|
// // Insertar en cuis
|
|
// queryInsertCuis := `
|
|
// INSERT INTO cuis (cuis, fecha_vigencia, transaccion, fecha_creacion, registro_empresa_id)
|
|
// VALUES ($1, $2, $3, $4, $5)
|
|
// `
|
|
// _, err = tx.ExecContext(ctx, queryInsertCuis, codigoCuis, fechaVigencia, transaccion, currentBolivia, registroID)
|
|
// if err != nil {
|
|
// return fmt.Errorf("error al insertar CUIS: %w", err)
|
|
// }
|
|
//
|
|
// if err = tx.Commit(); err != nil {
|
|
// return fmt.Errorf("error al confirmar transacción: %w", err)
|
|
// }
|
|
//
|
|
// return nil
|
|
//}
|
|
//
|
|
//// actualiza un registro existente de empresa y CUIS
|
|
//func (s *ObtencionCodigoService) actualizarRegistro(ctx context.Context, empresaID int, cuisID int64, req request.SolicitudCuis, respRaw interface{}) error {
|
|
// currentBolivia, err := s.getCurrentBoliviaTime()
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
//
|
|
// // 1. Iniciar tx
|
|
// tx, err := s.DB.BeginTx(ctx, nil)
|
|
// if err != nil {
|
|
// return fmt.Errorf("iniciar transacción: %w", err)
|
|
// }
|
|
// defer tx.Rollback()
|
|
//
|
|
// // 2. Parsear respuesta
|
|
// nuevoCuis, fechaVigencia, _, err := s.parseSoapCuisResponse(respRaw)
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
//
|
|
// // 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 {
|
|
// return fmt.Errorf("actualizar registroEmpresa: %w", err)
|
|
// }
|
|
//
|
|
// // 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 {
|
|
// return fmt.Errorf("consultar cuis existente: %w", err)
|
|
// }
|
|
//
|
|
// // 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 {
|
|
// return fmt.Errorf("insertar nuevo cuis: %w", err)
|
|
// }
|
|
// } 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 {
|
|
// return fmt.Errorf("actualizar cuis existente: %w", err)
|
|
// }
|
|
// }
|
|
//
|
|
// // 6. Confirmar tx
|
|
// if err := tx.Commit(); err != nil {
|
|
// return fmt.Errorf("confirmar transacción: %w", err)
|
|
// }
|
|
// return nil
|
|
//}
|