# WARNING: Locale must be UTF-8! IMPORT util IMPORT com IMPORT os TYPE t_sync_cmd RECORD oper STRING, data STRING END RECORD DEFINE r_cmd t_sync_cmd -- el comando recibido por el server SCHEMA mbs DEFINE start_time DATETIME YEAR TO SECOND DEFINE logs DYNAMIC ARRAY OF STRING DEFINE last_request, last_response STRING DEFINE last_date DATETIME YEAR TO SECOND, pcodn CHAR(4) CONSTANT dpy_verb = TRUE -- send messages to standard output CONSTANT log_verb = TRUE -- send messages to the errorlog MAIN DEFINE tout, n, x INTEGER DEFINE d0 DATETIME YEAR TO SECOND DEFINE url, msg STRING DEFINE method, version, headers STRING DEFINE req com.HTTPServiceRequest CALL startlog("err_sync_server.log") CALL check_utf8() RETURNING x, msg IF x != 0 THEN DISPLAY "ERROR: ", msg EXIT PROGRAM 1 END IF CALL show_verb("Starting dbsync server: ...") -- Normally, the port is set by the GAS for load balancing -- For standalone tests you can set FGLAPPSERVER environment variable CALL show_verb( "Listening on port : " || NVL(fgl_getenv("FGLAPPSERVER"), "GAS")) CALL com.WebServiceEngine.Start() LET start_time = CURRENT --LET tout=-1 -- timeout: infinite wait --LET tout=5 -- timeout: 5 seconds LET tout = -1 -- timeout: 10 seconds IF tout = -1 THEN LET msg = "The dbsync server is listening (timeout = infinite wait)." ELSE LET msg = "The dbsync server is listening (timeout =", tout USING "-<<<<<<&", " seconds)." END IF CALL show_verb(msg) LET n = 0 # WHENEVER ERROR CONTINUE WHILE TRUE IF int_flag <> 0 THEN LET int_flag = 0 EXIT WHILE END IF LET req = com.WebServiceEngine.getHTTPServiceRequest(tout) IF req IS NULL THEN -- timeout CALL show_verb( SFMT("HTTP request timeout...: %1", CURRENT YEAR TO FRACTION)) CONTINUE WHILE END IF LET url = req.getURL() LET method = req.getMethod() DISPLAY "llega data: ", req DISPLAY "url ", url DISPLAY "metodo ", method IF method != 'OPTIONS' THEN IF method IS NULL OR method != "POST" THEN IF method == "GET" THEN -- TODO: Send server status page back CALL req.sendTextResponse( 200, NULL, "Welcome to dbsync server for MBS PRODUCCION...") ELSE CALL show_err(SFMT("Unexpected HTTP request: %1", method)) CALL req.sendTextResponse( 400, NULL, "Only POST requests supported") END IF CONTINUE WHILE END IF END IF IF method = 'OPTIONS' THEN CALL req.sendTextResponse(200, NULL, "Welcome") END IF LET version = req.getRequestVersion() IF version IS NULL OR version != "1.1" THEN CALL show_err(SFMT("Unexpected HTTP request version: %1", version)) CONTINUE WHILE END IF LET headers = req.getRequestHeader("DBSync-Client") DISPLAY "header: DBSync-Clent=> ", headers IF headers IS NULL OR headers != "mbs" THEN CALL show_err( SFMT("Unexpected HTTP request header DBSync-Client: %1", headers)) DISPLAY "HEADER: ", headers CALL req.sendTextResponse( 400, NULL, "Bad request in Header DBSync-Client") CONTINUE WHILE END IF LET headers = req.getRequestHeader("Content-Type") DISPLAY "content: ", headers IF headers IS NULL OR headers NOT MATCHES "dbsync/json*" THEN -- ;Charset=UTF-8 CALL show_err( SFMT("Unexpected HTTP request header Content-Type: %1", headers)) CALL req.sendTextResponse( 400, NULL, "Bad request, in Header Content-Type") CONTINUE WHILE END IF IF NOT (read_request(req)) THEN -- si el procesamiento del request da error vuelve al loop CONTINUE WHILE END IF LET n = n + 1 LET d0 = CURRENT CALL show_verb(SFMT("oper [%1]: %2", d0, r_cmd.oper)) --CALL show_verb( SFMT("data: %1", r_cmd.data) ) DISPLAY "opera ", r_cmd.oper CASE r_cmd.oper WHEN "get_status" CALL send_response(req, "SERVER OK") WHEN "info" CALL send_response(req, info()) WHEN "show_logs" CALL send_response(req, show_logs()) WHEN "last_request" CALL send_response(req, last_request()) WHEN "geoposicion" LET last_request = r_cmd.data WHEN "clientes" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := clientes(r_cmd.data)) WHEN "clientes_insert" LET last_response = clientes_insert(r_cmd.data) LET last_date = CURRENT CALL send_response(req, last_response) WHEN "clientes_contactos" LET last_response = contactos(r_cmd.data) LET last_date = CURRENT CALL send_response(req, last_response) WHEN "monedas" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := monedas()) WHEN "envia_info" LET last_response = oportunidades(r_cmd.data) LET last_date = CURRENT CALL send_response(req, last_response) WHEN "clientes_update" LET last_response = clientes_update(r_cmd.data) LET last_date = CURRENT CALL send_response(req, last_response) WHEN "clases" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := clases(r_cmd.data)) WHEN "itbis" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := itbis_descuento()) WHEN "grupos" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := grupos(r_cmd.data)) WHEN "areas" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := areas()) WHEN "usuarios" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := usuarios()) WHEN "tipos" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := tipos(r_cmd.data)) WHEN "precios" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := precios()) WHEN "tipo_negocios" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := tipo_negocios()) WHEN "condiciones" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := condiciones()) WHEN "medidas" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := medidas()) WHEN "productos_display" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := productos_display(r_cmd.data)) WHEN "api_productos" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := api_productos(r_cmd.data)) WHEN "requisicion" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := requisiciondespacho(r_cmd.data)) WHEN "envia_parametro_p" LET last_response = r_cmd.data LET pcodn = r_cmd.data CLIPPED # DISPLAY "data pcodn ",pcodn LET last_date = CURRENT CALL send_response(req, last_response) WHEN "productosconteo" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := productosconteo(last_request)) WHEN "productos" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := productos(last_request)) WHEN "productostodos" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := productostodos(last_request)) WHEN "productosnoonline" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := productosnoonline(last_request)) WHEN "oportunidades" LET last_request = oportunidades(r_cmd.data) LET last_date = CURRENT CALL send_response(req, last_response) WHEN "valida_avance" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := valida_avance(r_cmd.data)) WHEN "rnc" LET last_request = r_cmd.data LET last_date = CURRENT DISPLAY "rnc ", r_cmd.oper CALL send_response(req, last_response := rnc(r_cmd.data)) WHEN "ip_movimientos" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := ip_movimientos(r_cmd.data)) WHEN "cotizacion" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := cotizacion()) WHEN "rep_cotizacion" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := rep_cotizacion(r_cmd.data)) WHEN "orden_insert" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := orden_insert(r_cmd.data)) WHEN "orden_anular" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := orden_anular(r_cmd.data)) WHEN "produccion" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := produccion(r_cmd.data)) WHEN "gestion_gastos" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := gestion_gastos(r_cmd.data)) WHEN "produccion_elimina" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := produccion_eliminar(r_cmd.data)) WHEN "producida" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := orden_cantidad(r_cmd.data)) WHEN "requisiciones_compra" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := requisiciones_compra(r_cmd.data)) WHEN "requisicion_doc" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := requisicion_doc(r_cmd.data)) WHEN "requisiciones_compra_d" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := requisiciones_compra_d(r_cmd.data)) WHEN "ip_transportistas" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := ip_transportistas()) WHEN "ip_bodegas" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := ip_bodegas(last_request)) WHEN "ordenes_agente" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := ordenes_ia(last_request)) WHEN "ordenes_display" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := ordenes_display(last_request)) WHEN "orden_cliente" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := ordenes_cliente(last_request)) WHEN "orden_cocinas" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := ordenesCocinas(last_request)) WHEN "datos_cocinas" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := datosCocina(last_request)) WHEN "respuesta_clientes" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := respuesta_cliente(last_request)) WHEN "orden" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := orden(last_request)) WHEN "departamento" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := departamentos(last_request)) WHEN "ip_existencia" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := existencia()) WHEN "ip_secciones" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := ip_secciones(last_request)) WHEN "ip_secciones2" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := ip_secciones2(last_request)) WHEN "ip_filas" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := ip_filas(last_request)) WHEN "ip_filas2" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := ip_filas2(last_request)) WHEN "ip_posicion" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := ip_posicion(last_request)) WHEN "ip_posicion2" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := ip_posicion2(last_request)) WHEN "ip_fechaConteo" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := ip_fechaconteo(last_request)) WHEN "ip_tramos" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := ip_tramos(last_request)) WHEN "ip_tramos2" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := ip_tramos2(last_request)) WHEN "ip_data_conteo" LET last_response = ip_descarga_conteo(r_cmd.data) LET last_date = CURRENT CALL send_response(req, last_response) WHEN "ip_etiquetas" LET last_response = ip_etiquetas(r_cmd.data) LET last_date = CURRENT CALL send_response(req, last_response) WHEN "ip_documentos" LET last_response = ip_documentos(r_cmd.data) LET last_date = CURRENT CALL send_response(req, last_response) WHEN "factura" LET last_response = factura(r_cmd.data) LET last_date = CURRENT CALL send_response(req, last_response) WHEN "orden_e" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response(req, last_response := orden_e(r_cmd.data)) WHEN "imp_factura" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := imprime_factura(r_cmd.data)) WHEN "v_usuarios" LET last_request = v_usuario(r_cmd.data) LET last_date = CURRENT CALL send_response(req, last_request) WHEN "parametros_generales" LET last_request = r_cmd.data DISPLAY "last re ", last_request LET last_date = CURRENT CALL send_response(req, last_response := parametros_generales()) WHEN "requisiciones" LET last_request = r_cmd.data DISPLAY "last re ", last_request LET last_date = CURRENT CALL send_response(req, last_response := requisiciones()) WHEN "empleados" LET last_request = r_cmd.data DISPLAY "last re ", last_request LET last_date = CURRENT CALL send_response( req, last_response := empleados_data(last_request)) WHEN "cedula" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := busca_emp(last_request)) WHEN "pregunta" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := preguntas(last_request)) WHEN "respuesta" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := respuestas(last_request)) WHEN "respuesta_laboral" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := respuesta_laboral(last_request)) WHEN "respuesta_ref" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := respuestas_ref(last_request)) WHEN "disponible" LET last_request = r_cmd.data LET last_date = CURRENT CALL send_response( req, last_response := disponible_movil(r_cmd.data)) OTHERWISE LET msg = "invalid operation: " || NVL(r_cmd.oper, " ") CALL show_err(msg) CALL req.sendTextResponse(404, NULL, msg) CONTINUE WHILE END CASE LET logs[logs.getLength() + 1] = "n:", n USING "<<<<", " ", d0, ' "', r_cmd.oper, '" ' END WHILE END MAIN #------------------------------------------------------------------------------- # Operacion "disponible" (app movil ConsultaDisponible). # Recibe JSON {credenciales,codid,cod_n..cod_sec,fecha}, resuelve el codigo por # iptb00016 (maestro productos terminados), llama disponibles() (lib funciones) y devuelve # JSON con existencia(m2) + pedidos de cliente abiertos(m2) + reservado/transito. # disponibles() devuelve 5 valores: cantidad_orden,conduce,transito,existencia,reservado #------------------------------------------------------------------------------- FUNCTION disponible_movil(pdata) DEFINE pdata STRING DEFINE p RECORD credenciales RECORD usuario STRING, clave STRING END RECORD, codid INTEGER, cod_n SMALLINT, cod_grupo SMALLINT, cod_tipo SMALLINT, cod_sec SMALLINT, fecha CHAR(10) END RECORD DEFINE r RECORD perror STRING, cod_n SMALLINT, cod_grupo SMALLINT, cod_tipo SMALLINT, cod_sec SMALLINT, descripcion VARCHAR(120), unidad_med VARCHAR(10), existencia DEC(12,5), ordenes DEC(12,5), reservado DEC(12,5), transito DEC(12,5), disponible DEC(12,5), fecha CHAR(10) END RECORD DEFINE q_orden, q_conduce, q_transito, q_exist, q_reserv DEC(12,5) LET r.perror = "OK" LET r.descripcion = "" LET r.unidad_med = "" LET r.existencia = 0 LET r.ordenes = 0 LET r.reservado = 0 LET r.transito = 0 LET r.disponible = 0 TRY CALL util.JSON.parse(pdata, p) CATCH LET r.perror = "ERROR_JSON" RETURN util.JSON.stringify(r) END TRY # limpiar cualquier conexion "smarmotech" que quedara abierta de un request previo # (evita el -1802 "connection name in use" que tumbaba el server) WHENEVER ERROR CONTINUE DISCONNECT "smarmotech" WHENEVER ERROR STOP # conectar con las credenciales del request (igual que orden.4gl y demas handlers) WHENEVER ERROR CONTINUE CONNECT TO "smarmotech" USER p.credenciales.usuario USING p.credenciales.clave WHENEVER ERROR STOP IF SQLCA.SQLCODE < 0 THEN LET r.perror = "NO_VALIDO" RETURN util.JSON.stringify(r) END IF # a partir de aqui, pase lo que pase, SIEMPRE se desconecta al final TRY IF p.codid > 0 THEN SELECT cod_n, cod_grupo, cod_tipo, cod_sec, descrip_esp, unidad_med INTO p.cod_n, p.cod_grupo, p.cod_tipo, p.cod_sec, r.descripcion, r.unidad_med FROM iptb00002 WHERE codid = p.codid AND status_t IS NULL ELSE SELECT descrip_esp, unidad_med INTO r.descripcion, r.unidad_med FROM iptb00002 WHERE cod_n = p.cod_n AND cod_grupo = p.cod_grupo AND cod_tipo = p.cod_tipo AND cod_sec = p.cod_sec AND status_t IS NULL END IF IF SQLCA.SQLCODE = NOTFOUND THEN LET r.perror = "NO_EXISTE" ELSE LET r.cod_n = p.cod_n LET r.cod_grupo = p.cod_grupo LET r.cod_tipo = p.cod_tipo LET r.cod_sec = p.cod_sec CALL disponibles(p.cod_n, p.cod_grupo, p.cod_tipo, p.cod_sec, TODAY) RETURNING q_orden, q_conduce, q_transito, q_exist, q_reserv LET r.existencia = q_exist LET r.ordenes = q_orden LET r.reservado = q_reserv LET r.transito = q_transito LET r.disponible = q_exist - (q_orden - q_conduce) - q_reserv LET r.fecha = TODAY USING "yyyy-mm-dd" END IF CATCH LET r.perror = SFMT("ERROR_SQL %1", SQLCA.SQLCODE) END TRY # SIEMPRE liberar la conexion (por nombre), aunque haya habido error WHENEVER ERROR CONTINUE DISCONNECT "smarmotech" WHENEVER ERROR STOP RETURN util.JSON.stringify(r) END FUNCTION FUNCTION read_request(req) DEFINE req com.HTTPServiceRequest DEFINE cmd STRING, p RECORD oper STRING, data RECORD usuario STRING, clave STRING, codigo STRING END RECORD END RECORD INITIALIZE r_cmd.* TO NULL TRY CALL req.readTextRequest() RETURNING cmd CATCH CALL show_err( SFMT("Unexpected HTTP request read exception: %1", STATUS)) RETURN FALSE END TRY #LET cmd='{"oper":"rnc","data":{"usuario":"crm_user","clave":"XMarmotech2019","tipo_Documento":1,"rnc":"130337391"}}' IF LENGTH(cmd) == 0 THEN -- la operacion va a estar vacia y va dar error por invalida RETURN TRUE END IF TRY CALL util.JSON.parse(cmd, r_cmd) CATCH CALL show_err(SFMT("JSON parse error: %1", STATUS)) RETURN FALSE END TRY RETURN TRUE END FUNCTION FUNCTION send_response(req, res) DEFINE req com.HTTPServiceRequest DEFINE res STRING # DISPLAY "response ",res IF res.getLength() > 50 THEN CALL show_verb( SFMT("Response [%1] -> Length: %2", CURRENT YEAR TO SECOND, LENGTH(res))) ELSE CALL show_verb( SFMT("Response [%1] -> %2.", CURRENT YEAR TO SECOND, res.trim())) END IF CALL req.setResponseCharset("UTF-8") CALL req.setResponseHeader("dbsync-server", "result") CALL req.setResponseHeader("Content-Type", "dbsync/json") CALL req.sendTextResponse(200, NULL, res) END FUNCTION FUNCTION check_utf8() IF ORD("€") == 8364 AND LENGTH("€") == 1 THEN RETURN 0, NULL ELSE RETURN -1, "Application locale must be UTF-8, with char length semantics" END IF END FUNCTION FUNCTION show_verb(msg) DEFINE msg STRING IF dpy_verb THEN DISPLAY msg END IF # IF log_verb THEN # CALL errorlog(msg CLIPPED) # END IF END FUNCTION FUNCTION show_err(msg) DEFINE msg STRING DISPLAY "ERROR:", msg # CALL errorlog(msg CLIPPED) END FUNCTION FUNCTION info() DEFINE b base.StringBuffer LET b = base.StringBuffer.create() CALL b.append("") CALL b.append( "[top][logs][last request]") CALL b.append( "

Servidor de sincronizacion para dispositivos moviles

") CALL b.append("local time: " || CURRENT YEAR TO SECOND || "
") CALL b.append("uptime: " || CURRENT YEAR TO SECOND - start_time || "
") CALL b.append("Logs
") CALL b.append("Last request
") CALL b.append("") RETURN b.toString() END FUNCTION FUNCTION show_logs() DEFINE b base.StringBuffer DEFINE i INT LET b = base.StringBuffer.create() CALL b.append("") CALL b.append( "[top][logs][last request]") CALL b.append("

JSON Sync: Logs

") FOR i = 1 TO logs.getLength() CALL b.append(logs[i]) CALL b.append("
") END FOR CALL b.append("") RETURN b.toString() END FUNCTION FUNCTION last_request() DEFINE b base.StringBuffer LET b = base.StringBuffer.create() CALL b.append("") CALL b.append( "[top][logs][last request]") CALL b.append("

JSON Sync: Last Request

") CALL b.append("Date:" || last_date) CALL b.append("

Request:

") IF last_request IS NOT NULL THEN CALL b.append("
")
        CALL b.append(util.JSON.format(last_request))
        CALL b.append("
") END IF CALL b.append("

Response:

") IF last_response IS NOT NULL THEN CALL b.append("
")
        CALL b.append(util.JSON.format(last_response))
        CALL b.append("
") END IF CALL b.append("") RETURN b.toString() END FUNCTION {FUNCTION usuarios() DEFINE pusuarios DYNAMIC ARRAY OF RECORD usuarios VARCHAR(50), password VARCHAR(50), ocupacion VARCHAR(100), sec_vend INT, nombre VARCHAR(30), email VARCHAR(50) END RECORD DEFINE pusuario RECORD usuarios VARCHAR(50), password VARCHAR(50), ocupacion VARCHAR(100), sec_vend INT, nombre VARCHAR(30), email VARCHAR(50) END RECORD, i SMALLINT, selec STRING LET selec ="SELECT a.email,' ',a.ocupacion,a.sec_vend,a.nombre,a.email FROM CRMindata.dbo.vendedores a" PREPARE comando FROM selec DECLARE u1 CURSOR FOR comando LET i=0 FOREACH u1 INTO pusuario.* LET i=i+1 LET pusuarios[i].*=pusuario.* DISPLAY "SUBIENDO USUARIOS...." END FOREACH; FREE u1 RETURN util.JSON.stringify(pusuarios) END FUNCTION } { FUNCTION geolocalizacion(s) DEFINE s STRING DEFINE file_out RECORD contenido STRING, nomb_arch STRING, lat FLOAT, long FLOAT, i BYTE, file_ext STRING END RECORD DEFINE file_out_mov RECORD contenido STRING, nomb_arch STRING, lat FLOAT, long FLOAT, i BYTE, file_ext STRING END RECORD, s_out STRING, archivo STRING, borrar INT DEFINE r RECORD ERROR STRING END RECORD LOCATE file_out.i IN MEMORY TRY CALL util.JSON.parse(s, file_out) CATCH LET r.error = "FGL ERROR: ", err_get(status) RETURN util.JSON.stringify(r) END TRY IF os.Path.exists(file_out.nomb_arch) THEN CALL os.Path.delete(file_out.nomb_arch) RETURNING borrar END IF CALL file_out.i.writeFile(file_out.nomb_arch) FREE file_out.i IF os.Path.size(file_out.nomb_arch)>0 THEN CALL get_exif_latlong_bdl(file_out.nomb_arch) RETURNING file_out_mov.lat,file_out_mov.long DISPLAY "latitudes ", file_out_mov.lat," LONG ",file_out_mov.long ELSE LET file_out_mov.contenido="NO PUEDO GEOLOCALIZAR ESTA FOTO" END IF LET s_out = UTIL.JSON.stringify(file_out_mov) RETURN s_out END FUNCTION }