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 //}