ejemplo de comandos vfp con impresoras fiscales

697 views
Skip to first unread message

Juanerge Hung

unread,
Nov 21, 2022, 1:38:30 PM11/21/22
to publice...@googlegroups.com
Hola gente, por favor tengo un sistema de facturación pero ahora los clientes me piden que las facturas se hagan con impresoras fiscales epson, pnp, bematech, vmax, thefactory, etc para Venezuela; pero no se como hacerlo, les agradeceria

José Antonio Peña Martínez

unread,
Nov 21, 2022, 1:40:04 PM11/21/22
to publice...@googlegroups.com
Pues solo tienes que crear el reporte de la factura a tamaño del ticket ... solo eso

El lun, 21 nov 2022 a las 12:38, Juanerge Hung (<juan...@gmail.com>) escribió:
Hola gente, por favor tengo un sistema de facturación pero ahora los clientes me piden que las facturas se hagan con impresoras fiscales epson, pnp, bematech, vmax, thefactory, etc para Venezuela; pero no se como hacerlo, les agradeceria

--
Blog de la Comunidad Visual FoxPro en Español: http://comunidadvfp.blogspot.com
---
Has recibido este mensaje porque estás suscrito al grupo "Comunidad de Visual Foxpro en Español" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a publicesvfoxp...@googlegroups.com.
Para ver esta conversación en el sitio web, visita https://groups.google.com/d/msgid/publicesvfoxpro/CAFZUJ0tbueow2w_3UxN%2BcjyAnGAnf1A5%3Dpb1MD6%3D40Y22OSKJA%40mail.gmail.com.


--
Desarrollo de Sistemas TecnoPro
José Antonio Peña

Saludos!

Victor Espina

unread,
Nov 21, 2022, 2:35:55 PM11/21/22
to Comunidad de Visual Foxpro en Español
Nada que ver.  Una impresora fiscal no es como cualquier otra impresora.  Tu te comunicas con ella enviándole comandos específicos para abrir un documento fiscal, añadir cada item, enviar las formas de pago y luego cerrar el documento.  Esto se hace normalmente utilizando algun tipo de DLL o ActiveX que es particular para cada fabricante.  Adicionalmente a eso, hay comandos especiales para hacer los cierres diarios, etc.

En respuesta a la pregunta original, debes ver los manuales de cada fabricante para saber como comunicarte con la impresora  y que comandos debes enviar.

Saludos

Victor Espina

HernanCano

unread,
Nov 21, 2022, 2:47:31 PM11/21/22
to Comunidad de Visual Foxpro en Español
De acuerdo con Víctor.

José Antonio Peña Martínez

unread,
Nov 21, 2022, 3:05:40 PM11/21/22
to publice...@googlegroups.com
Victor por supuesto que si, instalas el driver sobretodo si vas a imprimir logotipos y codigos qr . yo tmb las he usado con comandos de escape pero para imprimir tickets, pero la persona dice facturas ...

Saludos!

José Antonio Peña Martínez

unread,
Nov 21, 2022, 3:08:25 PM11/21/22
to publice...@googlegroups.com
Anexo comprobante ..

Saludos!

--
Blog de la Comunidad Visual FoxPro en Español: http://comunidadvfp.blogspot.com
---
Has recibido este mensaje porque estás suscrito al grupo "Comunidad de Visual Foxpro en Español" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a publicesvfoxp...@googlegroups.com.
ticket80.pdf

Jose Antonio Peña Martínez

unread,
Nov 21, 2022, 3:09:24 PM11/21/22
to Comunidad de Visual Foxpro en Español
Anexo ejemplo

Saludos!
ticket80.pdf

Jose Antonio Peña Martínez

unread,
Nov 21, 2022, 3:11:48 PM11/21/22
to Comunidad de Visual Foxpro en Español
Tambien imprimo tickets en modo texto:

anexo archivo
TICKET.TXT

Victor Espina

unread,
Nov 21, 2022, 3:29:52 PM11/21/22
to Comunidad de Visual Foxpro en Español
Quizás sea un tema de terminología. Lo que yo entiendo por "impresora fiscal" es una impresora autorizada por la autoridad de impuestos de cada país, que tiene un disco duro interno y un programa certificado que es el que se encarga de generar la impresión física.  La idea es que la impresora no solo imprima la factura sino que REGISTRE los datos de la venta internamente, para efectos de auditoria fiscal.   

Al menos yo, hasta ahora, he trabajado con varios modelos de Hassar, Epson y Bixolon, y en TODOS los casos el proceso era el mismo:

a) Cargar funciones de una librería o crear una instancia de un ActiveX 
b) Abrir conexión con la impresora
c) Iniciar documento fiscal indicando los datos del comprador
d) Enviar items del documento, indicando descripción, precio, dcto y tipo de Iva (no la alicuota, sino el tipo)
e) Enviar una o mas formas de pago
f) Cerrar el documento fiscal (en este momento es que se genera la impresión)
g) Cerrar conexión con la impresora

Notese que en las impresoras fiscales tu no envias la impresion; envias los datos de la factura y es la impresora la que genera la impresion.  Los datos de la empresa, de hecho, estan quemados en la impresora por el vendedor de la impresora.

Saludos

Victor Espina

José Antonio Peña Martínez

unread,
Nov 21, 2022, 3:38:07 PM11/21/22
to publice...@googlegroups.com
Si Victor es probable, Saludos!

Juanerge Hung

unread,
Nov 21, 2022, 7:27:30 PM11/21/22
to Comunidad de Visual Foxpro en Español
lo que dice Víctor es correcto 

Juanerge Hung

unread,
Nov 21, 2022, 7:35:48 PM11/21/22
to publice...@googlegroups.com
Puedes enviarme como seria los datos que debo enviar, por favor

Juanerge Hung

unread,
Nov 21, 2022, 8:00:27 PM11/21/22
to publice...@googlegroups.com
Porfa Victor un ejemplo por favor


Victor Espina

unread,
Nov 22, 2022, 9:00:07 AM11/22/22
to Comunidad de Visual Foxpro en Español
Este es un codigo super antiguo que encontre, para impresoras fiscales BMC Camel.  Quizás sirva para darte una idea.

* BMCCAMEL.PRG
* Manejo de la impresora BMC Camel
*
#DEFINE  CRLF     CHR(13)+CHR(10)

DEFINE CLASS bmccamel AS Plugin

 Description = "Controlador para la impresora fiscal BMC Camel"
 Hooks = "controladorImpresoraFiscal"
 
 Puerto = "COM1"
 lastErrorCode = 0
 lastStatusCode = 0
 DIMENSION errorCodes[1,1]
 DIMENSION statusCodes[1,1]
 
 
 PROCEDURE Init
  *
  * Se registra la interfaz del plugin
  WITH pluginsHelper.Hooks
   .Register("controladorImpresoraFiscal","","","Controlador para la impresora fiscal")  
   .Register("CIFVerificarDriver","","","Verificar si el driver requerido para la impresora esta presente")      
   .Register("CIFCargarDriver","","","Cargar el driver para la impresora fiscal")
   .Register("CIFAbrirPuerto","","estatus,error","Abrir el puerto de la impresora fiscal")
   .Register("CIFCerrarPuerto","","estatus,error","Cerrar el puerto de la impresora fiscal")  
   .Register("CIFReiniciarImpresora","","estatus,error","Reiniciar la impresora")      
   .Register("CIFCancelarTransaccion","","error,estatus","Cancelar la transaccion en proceso")
   .Register("CIFEnviarComando","comando","estatus,error","Enviar un comando a la impresora fiscal")
   .Register("CIFConsultarEstatus","","estatus,error","Consultar el estatus de la impresora")
   .Register("CIFImpLineaCabezera","linea,data","estatus,error","Imprimir una linea de cabezera")
   .Register("CIFImpLineaDetalle","codart,nomart,precio,cantidad,iva,dcto","estatus,error","Imprimir linea de detalle")  
   .Register("CIFImpLineaDevolucion","codart,nomart,precio,cantidad,iva,dcto","estatus,error","Imprimir linea de devolucion")      
   .Register("CIFImprimirSubtotal","","estatus,error","Imprimir el subtotal del documento")
   .Register("CIFImprimirTotalFA","","estatus,error","Imprimir el total de la factura")
   .Register("CIFImprimirTotalNC","","estatus,error","Imprimir el total de la NC")
   .Register("CIFUltimaFactura","","numero,estatus,error","Ultimo numero de factura generado por la impresora")
   .Register("CIFReporteX","","estatus,error","Emitir el reporte X")
   .Register("CIFReporteY","","estatus,error","Emitir el reporte Y")  
   .Register("CIFReporteZ","","estatus,error","Emitir el reporte Z")
   .Register("CIFFirmware","","estatus,error","Imprimir informacion del firmware")
   .Register("CIFSerial","","serial,estatus,error","Obtener el serial de la impresora")
   .Register("CIFImpLineaNF","data","estatus,error","Imprimir una linea en modo no fiscal")
   .Register("CIFCerrarNF","data","estatus,error","Cerrar el modo no fiscal")
  ENDWITH
 
  * Se define la lista de codigos de estatus
  DIMENSION THIS.statusCodes[13]
  FOR i = 1 TO ALEN(THIS.statusCodes,1)
   THIS.statusCodes[i] = "0x" + THIS.dec2HEx(i) + ": Sin información"
  ENDFOR  
  THIS.statusCodes[ 1]="Estatus desconocido"
  THIS.statusCodes[ 2]="En Modo Prueba y en Espera"
  THIS.statusCodes[ 3]="En Modo Prueba y Emisión de Documentos Fiscales"
  THIS.statusCodes[ 4]="En Modo Prueba y Emisión de Documentos No Fiscales"
  THIS.statusCodes[ 5]="En Modo Fiscal y en Espera"
  THIS.statusCodes[ 6]="En Modo Fiscal y Emisión de Documentos Fiscales"
  THIS.statusCodes[ 7]="En Modo Fiscal y Emisión de Documentos No Fiscales"
  THIS.statusCodes[ 8]="En Modo Fiscal y Cercana Carga Completa De La Memoria Fiscal Y en Espera"
  THIS.statusCodes[ 9]="En Modo Fiscal y Cercana Carga Completa De La Memoria Fiscal Y en Emisión de Documentos Fiscales"
  THIS.statusCodes[10]="En Modo Fiscal y Cercana Carga Completa De La Memoria Fiscal Y en Emisión de Documentos No Fiscales"
  THIS.statusCodes[11]="En Modo Fiscal y Carga Completa De La Memoria Fiscal Y en Espera"
  THIS.statusCodes[12]="En Modo Fiscal y Carga Completa De La Memoria Fiscal Y en Emisión de Documentos Fiscales"
  THIS.statusCodes[13]="En Modo Fiscal y Carga Completa De La Memoria Fiscal Y en Emisión de Documentos No Fiscales"
 
  THIS.statusCodes[0x0 + 1] = [Status Desconocido]
  THIS.statusCodes[0x1 + 1] = [En modo Entrenamiento y en Espera]
  THIS.statusCodes[0x2 + 1] = [En modo Entrenamiento Emitiendo Documento Fiscal]
  THIS.statusCodes[0x3 + 1] = [En modo Entrenamiento Emitiendo Documento NO Fiscal]
  THIS.statusCodes[0x4 + 1] = [En modo Fiscal y en Espera]
  THIS.statusCodes[0x5 + 1] = [En modo Fiscal Emitiendo Documento Fiscal]
  THIS.statusCodes[0x6 + 1] = [En modo Fiscal Emitiendo Documento NO Fiscal]
  THIS.statusCodes[0x7 + 1] = [En modo Fiscal, Memoria Fiscal casi llena y en Espera]
  THIS.statusCodes[0x8 + 1] = [En modo Fiscal, Memoria Fiscal casi llena y Emitiendo Documento Fiscal]
  THIS.statusCodes[0x9 + 1] = [En modo Fiscal, Memoria Fiscal casi llena y Emitiendo Documento NO Fiscal]
  THIS.statusCodes[0xA + 1] = [En modo Fiscal, Memoria Fiscal llena y en Espera]
  THIS.statusCodes[0xB + 1] = [En modo Fiscal, Memoria Fiscal llena y Emitiendo Documento Fiscal]                      
  THIS.statusCodes[0xC + 1] = [En modo Fiscal, Memoria Fiscal llena y Emitiendo Documento NO Fiscal]

  * Se define la lista de codigos de error
  DIMENSION THIS.errorCodes[0x99 + 1]
  FOR i = 1 TO ALEN(THIS.errorCodes,1)
   THIS.errorCodes[i] = "0x" + THIS.dec2HEx(i) + ": Sin información"
  ENDFOR  
  THIS.errorCodes[0x00 + 1] = [OK]
  THIS.errorCodes[0x01 + 1] = [Sin papel interno]
  THIS.errorCodes[0x02 + 1] = [Error mecánico de la impresora]
  THIS.errorCodes[0x03 + 1] = [Sin papel y error mecánico de la impresora]
  THIS.errorCodes[0x50 + 1] = [Comando o valor inválido]
  THIS.errorCodes[0x54 + 1] = [IVA inválido]
  THIS.errorCodes[0x58 + 1] = [Cajero no asignado]
  THIS.errorCodes[0x5C + 1] = [Sin papel]
  THIS.errorCodes[0x60 + 1] = [Error fiscal]
  THIS.errorCodes[0x64 + 1] = [Error en memoria fiscal]
  THIS.errorCodes[0x6C + 1] = [Memoria fiscal llena]
  THIS.errorCodes[0x70 + 1] = [Buffer lleno (debe enviar el comando RESTART)]
  THIS.errorCodes[0x80 + 1] = [Error de comunicación]
  THIS.errorCodes[0x89 + 1] = [Sin respuesta]
  THIS.errorCodes[0x90 + 1] = [Error LRC]
  THIS.errorCodes[0x91 + 1] = [Error interno del API]
  THIS.errorCodes[0x99 + 1] = [Error abriendo archivo]
 
 
  * Se verifica que se disponga del driver
  THIS.CIFVerificarDriver()
 
 
  * Se carga el driver
  THIS.CIFCargarDriver()
  *
 ENDPROC
 
 
 
 ***********************************
 **
 **   I M P L E M E N T A C I O N
 **
 ***********************************
 
 PROCEDURE CIFVerificarDriver(poParams)
  *
  LOCAL cFile
  cFile = "TFHKAIF.DLL"
  IF NOT FILE(cFile)
   ThrowCustomEx("cifNoDriverException",cFile)
  ENDIF
  *
 ENDPROC
 
 PROCEDURE CIFCargarDriver(poParams)
    DECLARE INTEGER  OpenFpctrl IN c:\eposdp\TFHKAIF.DLL  String lpPortName
    DECLARE INTEGER  CloseFpctrl IN c:\eposdp\TFHKAIF.DLL  
    DECLARE INTEGER  CheckFprinter IN c:\eposdp\TFHKAIF.DLL  
    DECLARE INTEGER  ReadFpStatus IN c:\eposdp\TFHKAIF.DLL  LONG @lStatus ,LONG @lError
    DECLARE INTEGER  SendCmd IN c:\eposdp\TFHKAIF.DLL  LONG @lStatus ,LONG @lError,STRING @cmd
    DECLARE INTEGER  SendNCmd IN c:\eposdp\TFHKAIF.DLL  LONG @lStatus ,LONG @lError,STRING @bufferCmd
    DECLARE INTEGER  SendFileCmd IN c:\eposdp\TFHKAIF.DLL  LONG @lStatus ,LONG @lError,STRING @fileCmd
    DECLARE INTEGER  UploadReportCmd IN c:\eposdp\TFHKAIF.DLL  LONG @lStatus ,LONG @lError,STRING @cmd,string @fileCmd
    DECLARE INTEGER  UploadStatusCmd IN c:\eposdp\TFHKAIF.DLL  LONG @lStatus ,LONG @lError,STRING @cmd,string @fileCmd
 ENDPROC
 
 PROCEDURE CIFAbrirPuerto(poParams)
  *
  LOCAL nResult
  STORE "" TO THIS.OUT.Error,THIS.OUT.Estatus
  nResult = OPENFPCTRL(THIS.Puerto)
 
  IF nResult<>1
   PRIVATE uError, uStatus
   STORE 0 TO uError, uStatus
   THIS.readPrinterStatus(@uStatus, @uError)
   THIS.OUT.Estatus = THIS.getDescEstatus(uStatus)
   THIS.OUT.Error = THIS.getDescError(uError)
   ThrowCustomEx("cifAperturaPuertoException",THIS.getErrorEstatus(@uError, @uStatus))
   RETURN False
  ENDIF
  *
 ENDPROC


 PROCEDURE CIFCerrarPuerto(poParams)
  *
  LOCAL nResult
  STORE "" TO THIS.OUT.Error,THIS.OUT.Estatus  
  nResult = CLOSEFPCTRL()
 
  IF nResult<>1
   PRIVATE uError, uStatus
   STORE 0 TO uError, uStatus
   THIS.readPrinterStatus(@uStatus, @uError)
   THIS.OUT.Estatus = THIS.getDescEstatus(uStatus)
   THIS.OUT.Error = THIS.getDescError(uError)
   ThrowCustomEx("cifCierrePuertoException",THIS.getErrorEstatus(@uError, @uStatus))
   RETURN False
  ENDIF
  *
 ENDPROC
 
 
 PROCEDURE CIFReiniciarImpresora(poParams)
  THIS.sendToPrinter("e", THIS.Params.OUT)
 ENDPROC

 PROCEDURE CIFCancelarTransaccion(poParams)
  *
  LOCAL lOk
  lOk = True
  STORE "" TO THIS.OUT.Error,THIS.OUT.Estatus  
  TRY
      THIS.sendToPrinter("7", THIS.Params.OUT)
  CATCH TO ex
   lOk = False
  ENDTRY      
 
  RETURN lOk
  *
 ENDPROC
 
 
 PROCEDURE CIFEnviarComando(poParams)
  THIS.sendToPrinter(poParams.comando, THIS.Params.OUT)
 ENDPROC
 
 
 PROCEDURE CIFImpLineaCabezera(poParams)
  *
  *-- Se validan los parametros
  IF VARTYPE(poParams.linea)<>"N" OR NOT BETWEEN(poParams.linea,1,12)
   ThrowCustomEx("cifLineaIncorrectaException",TRANSFORM(poParams.linea,""))
   RETURN
  ENDIF
 
  IF VARTYPE(poParams.Data)<>"C"
   ThrowCustomEx("cifParametroIncorrectoException","CIFImpLineaCabezera(DATA), linea #"+ALLTRIM(STR(poParams.linea))+"  Data: "+TRANSFORM(poParams.data,""))
   RETURN
  ENDIF
 
 
  *-- Se envia el comando
  THIS.sendToPrinter("i" + PADL(poParams.linea,2,"0") + PADR(poPArams.data,40,SPACE(1)), THIS.Params.OUT)
  *
 ENDPROC
 
 
 PROCEDURE CIFImpLineaDetalle(poParams, plDevolucion)
  *
  *-- Se valida los parametros
  IF VARTYPE(poParams.CodArt)<>"C"
   ThrowCustomEx("cifParametroIncorrectoException","CIFImprimirLineaDetalle(codart)")        
   RETURN False
  ENDIF
  IF VARTYPE(poParams.NomArt)<>"C"
   ThrowCustomEx("cifParametroIncorrectoException","CIFImprimirLineaDetalle(nomart)")        
   RETURN False
  ENDIF
  IF VARTYPE(poParams.Precio)<>"N"
   ThrowCustomEx("cifParametroIncorrectoException","CIFImprimirLineaDetalle(precio)")        
   RETURN False
  ENDIF
  IF VARTYPE(poParams.Cantidad)<>"N"
   ThrowCustomEx("cifParametroIncorrectoException","CIFImprimirLineaDetalle(cantidad)")        
   RETURN False
  ENDIF
  IF VARTYPE(poParams.IVA)<>"C"
   ThrowCustomEx("cifParametroIncorrectoException","CIFImprimirLineaDetalle(IVA)")        
   RETURN False
  ENDIF
  IF VARTYPE(poParams.DCTO)<>"N"
   ThrowCustomEx("cifParametroIncorrectoException","CIFImprimirLineaDetalle(Dcto)")        
   RETURN False
  ENDIF
 
 
  IF !plDevolucion AND False
   *
   *-- Se envia el codigo de articulo
   THIS.sendToPrinter("@" + poParams.codArt, THIS.PArams.OUT)
 
   *-- Se envia el nombre, divido en dos strings de 20
   THIS.sendToPrinter("@" + LEFT(poParams.nomArt,20), THIS.Params.OUT)
   IF LEN(RTRIM(poParams.nomArt)) > 20
    THIS.sendToPrinter("@" + SUBSTR(poParams.nomArt,21,20), THIS.Params.OUT)
   ENDIF
   *
  ENDIF
 
 
  *-- Se prepara el comando para el resto de los datos del item
  LOCAL cComando
  cComando = IIF(plDevolucion,"d","") + CHRTRAN(poParams.IVA,[ ABCD],[ !"#$]) + CHRTRAN(PADL(poParams.Precio,11,"0"),".","")

  SET DECIMALS TO 3
  cComando = cComando + STRTRAN(STRTRAN(STR(poParams.Cantidad,9,3),SPACE(1),'0'),'.')  
  SET DECIMALS TO 2
 
  IF plDevolucion Or True
   cComando = cComando + PADR(RTRIM(poParams.codArt)+" "+poParams.NomArt,40)
  ELSE
   cComando = cComando + PADR(".",40)
  ENDIF
 
 
  *-- Se envia el comando
  THIS.sendToPrinter(cComando,THIS.Params.OUT)
 
 
  *-- Si se indico un descuento, se envia
  IF poPArams.Dcto > 0
    cComando = [p-] + STRTRAN(STRTRAN(STR(poParams.Dcto,6,2),SPACE(1),'0'),'.')
    THIS.sendToPrinter(cComando,THIS.Params.OUT)
  ENDIF
  *
 ENDPROC



 PROCEDURE CIFImpLineaDevolucion(poParams)
  THIS.CIFImpLineaDetalle(poParams,True)
 ENDPROC
 
 
 PROCEDURE CIFImprimirSubTotal(poParams)
  THIS.sendToPrinter([3],THIS.Params.OUT)
 ENDPROC

 PROCEDURE CIFImprimirTotalFA(poParams)
  THIS.sendToPrinter([101],THIS.Params.OUT)
 ENDPROC
 
 PROCEDURE CIFImprimirTotalNC(poParams)
  THIS.sendToPrinter([f01000000000000],THIS.Params.OUT)
 ENDPROC
 
 
 
 PROCEDURE CIFConsultarEstatus(poParams)
  PRIVATE nStatus,nERror
  STORE 0 TO nStatus, nError
  STORE "" TO THIS.OUT.Error,THIS.OUT.Estatus  
  IF WST.Name<>"VES"
   THIS.readPrinterStatus(@nStatus, @nError)
  ELSE
   nStatus = 0
   nError = 0
  ENDIF
  THIS.OUT.estatus = THIS.getDescEstatus(nstatus)
  THIS.OUT.error = THIS.getDescError(nerror)
  RETURN nStatus
 ENDPROC
 


 PROCEDURE CIFUltimaFactura(poParams)
  LOCAL cNumDoc,nPos
  cNumDoc = "00000000"
  *RETURN PADL(SECONDS(),9,"0")  && SOLO mientras duran las pruebas
  TRY
   nPos = 1
   THIS.CIFAbrirPuerto()
   nPos = 2
   cNumDoc = NVL(THIS.readS1("NUMULTFAC"),"")
   nPos = 3
   THIS.CIFCerrarPuerto()
  CATCH TO ex
   cNumDoc = ex.Message + " (" + STR(nPos)+")"
   msgHelper.Warning("Error",cNumDoc)
   cNumdoc = foox
  ENDTRY
  RETURN cNumDoc
 ENDPROC
 
 
 
 PROCEDURE CIFReporteX(poParams)
  *
  *-- Se abre el puerto  
  THIS.CIFAbrirPuerto()
 
  *-- Se emite el reporte X
  THIS.sendToPrinter("I0X",THIS.OUT)
  doPause(5)  && La pausa es necesaria para permitir que se cargue el archivo completamente
     
  *-- Se descarga el reporte a un archivo temporal
  LOCAL cTempFile,cBuff
  cTempFile = getTempFile("PTF")
  cBuff = FILETOSTR(cTempFile)
  ERASE (cTempFile)
 
  *-- Se obtiene el valor de "CAJERO" en el informe y se incrementa en 1
  LOCAL cCajero
  cCajero=SUBST(cbuff,AT('S1',cBuff)+2,2)
  cCajero=PADL(INT(VAL(cCajero)) + 1,5,"0")
  THIS.sendToPrinter("5" + cCajero, THIS.PArams.OUT)
 
  *-- Se cierra el puerto
  THIS.CIFCerrarPuerto()
  *
 ENDPROC


 PROCEDURE CIFReporteY(poParams)
  THIS.CIFReporteZ(poParams)
 ENDPROC
 PROCEDURE CIFReporteZ(poParams)
  *
  DOEVENTS

  *-- Se abre el puerto  
  THIS.CIFAbrirPuerto()
 
  *-- Se emite el reporte Z
  THIS.sendToPrinter("I0Z",THIS.OUT)

  *-- Se restablece el contador de cajeros
  THIS.sendToPrinter("6",THIS.OUT)

  LOCAL nLastStatusCode, nLastErrorCode
  nLastStatusCode = THIS.lastStatusCode
  nLastErrorCode = THIS.lastErrorCode

  *-- Se actualiza la informacion del reporte en EM
  IF INLIST(nLastStatusCode,0,4) AND nLastErrorCode = 0
   THIS.actualizarTablaZ()
  ELSE
   AUD.addEntry("No se actualizo historicoZ. LastStatusCode={0}, LastErrorCode={1}","CIF","REPORTEZ",AUD.Severity.Critical,nLastStatusCode,nLastErrorCode)
  ENDIF

  *-- Se actualiza la fecha del ultimo reporte Z para la estacion
  dictHelper.addEntry("POS.FiscalPrinter.{WST.Name}.FechaUltimoReporteZ",DATE())

  *-- Se cierra el puerto
  THIS.CIFCerrarPuerto()
  *
 ENDPROC
 

 PROCEDURE CIFFirmware(poParams)
  THIS.CIFAbrirPuerto()
  THIS.sendToPrinter("x",THIS.OUT)
  THIS.CIFCerrarPuerto()
 ENDPROC


 PROCEDURE CIFSerial(poParams)
  LOCAL cSerial
  cSerial = "000000"
  TRY
   THIS.CIFAbrirPuerto()
   cSerial = NVL(THIS.readS1("SERIAL"),"")
   THIS.CIFCerrarPuerto()
  CATCH
  ENDTRY
  RETURN cSerial
 ENDPROC
 
 
 PROCEDURE CIFImpLineaNF(poParams)
  *
  *-- Se validan los parametros
  IF VARTYPE(poParams.Data)<>"C"
   ThrowCustomEx("cifParametroIncorrectoException","CIFImpLineaNF(DATA), linea #"+ALLTRIM(STR(poParams.linea))+"  Data: "+TRANSFORM(poParams.data,""))
   RETURN
  ENDIF
 
 
  *-- Se envia el comando
  THIS.sendToPrinter([800] + LEFT(poPArams.data,35), THIS.Params.OUT)
  *
 ENDPROC

 PROCEDURE CIFCerrarNF(poParams)
  THIS.sendToPrinter([810]+LEFT(NVL(poParams.data,SPACE(35)),35),THIS.Params.OUT)
 ENDPROC
 
 
 
 *************************************
 **     METODOS DE SOPORTE
 *************************************
 
 PROCEDURE sendToPrinter(pcComando, poOUT)
  *
  PRIVATE uStatus,uError,nResult
  STORE 0 TO uStatus,uError
  IF TYPE("THIS.PArams.OUT.Error")<>"U"
   STORE "" TO THIS.Params.OUT.Error,THIS.Params.OUT.Estatus
  ENDIF
 
  poOUT.Error = ""
  poOUT.Estatus = ""
 
  nResult = SENDCMD(@uStatus,@uError,pcComando)
 
  IF nResult <> 1
   THIS.lastErrorCode = uError
   THIS.lastStatusCode = uStatus
   poOUT.Error = THIS.getDescError(uError)
   poOUT.Estatus = THIS.getDescEstatus(uStatus)
   ThrowCustomEx("cifGeneralException",THIS.getErrorEstatus(uError,uStatus,pcComando))
   RETURN False
  ENDIF
  *
 ENDPROC

 PROCEDURE downloadFromPrinter(pcComando, pcOutFile, poOut)
  *
  PRIVATE uStatus,uError,nResult
  STORE 0 TO uStatus,uError
  IF TYPE("THIS.PArams.OUT.Error")<>"U"
   STORE "" TO THIS.Params.OUT.Error,THIS.Params.OUT.Estatus
  ENDIF
 
  poOUT.Error = ""
  poOUT.Estatus = ""
 
  nResult = UPLOADREPORTCMD(@uStatus,@uError,pcComando,pcOutFile)
 
  IF nResult <> 1
   THIS.lastErrorCode = uError
   THIS.lastStatusCode = uStatus
   poOUT.Error = THIS.getDescError(uError)
   poOUT.Estatus = THIS.getDescEstatus(uStatus)
   ThrowCustomEx("cifGeneralException",THIS.getErrorEstatus(uError,uStatus,pcComando))
   RETURN False
  ENDIF
  *
 ENDPROC
 
 PROCEDURE getDescError(pnError)
  RETURN THIS.errorCodes[pnError + 1]
 ENDPROC
 
 PROCEDURE getDescEstatus(pnEstatus)
  RETURN THIS.statusCodes[pnEstatus + 1]
 ENDPROC

 PROCEDURE getErrorEstatus(pnError, pnEstatus, pcComando)
  RETURN "Error  : " + THIS.getDescError(pnError) + CRLF + ;
         "Estatus: " + THIS.getDescEstatus(pnEstatus) + CRLF + ;
         IIF(VARTYPE(pcComando)="C","Comando: "+pcComando,"")
 ENDPROC
 
 PROCEDURE readPrinterStatus(pnStatus, pnError)
  LOCAL nREsult
  nResult=READFPSTATUS(@pnStatus, @pnError)
  IF nREsult<>1
   ThrowCustomEx("cifStatusImpresoraException",THIS.getDescError(pnError))
   RETURN False
  ENDIF
 ENDPROC


 PROCEDURE readS1(pcClave)
  *
  *-- Se obtiene el estado S1 de la impresora
  PRIVATE nResult,nError,nStatus,cBuff,uValor
  STORE 0 TO nResult,nError,nStatus
  STORE "" TO cBuff
  STORE NULL TO uValor
 
 
  IF WST.NAme <> "VES"
   PRIVATE cTmpFile,cCommand
   cTmpFile = CONFIG.Folders.Temp + "\" + WST.Name + "_S1.TMP"
   cCommand = "S1"
   nResult = UPLOADSTATUSCMD(@nStatus,@nError,cCommand,cTmpFile)
   IF nResult = 1
    COPY FILE (cTmpFile) TO ("C:\EPOSDP\SALIDA.TXT")
    cBuff = FILETOSTR(cTmpFile)
    ERASE (cTmpFile)
   ENDIF
  ELSE
   cBuff = SPACE(2) + "foo" + CHR(10) + "foo" + CHR(10) + TRANSFORM(SECONDS(),"@L 9999999")
   nResult = 1
  ENDIF

  IF nResult<>1
   msgHelper.Notify("Test","Error="+STR(nError)+" Status: "+STR(nStatus))
   ThrowCustomEx("cifGeneralException",THIS.getErrorEstatus(nError,nStatus))
   RETURN NULL
  ENDIF
 
  cBuff = SUBSTR(cBuff,3)
  cBuff = SUBS(cBuff,1,2) + CHR(10) + ;
          SUBS(cBuff,3,17) + CHR(10) + ;
          SUBS(cBuff,20,8) + CHR(10) + ;
          SUBS(cBuff,28,5) + CHR(10) + ;
          SUBS(cBuff,33,8) + CHR(10) + ;
          SUBS(cBuff,41,5) + CHR(10) + ;
          SUBS(cBuff,46,4) + CHR(10) + ;
          SUBS(cBuff,50,4) + CHR(10) + ;
          SUBS(cBuff,54,11) + CHR(10) + ;
          SUBS(cBuff,65,10) + CHR(10) + ;
          SUBS(cBuff,75,6) + CHR(10) + ;
          SUBS(cBuff,81,6) + CHR(10)
  STRTOFILE(CHRT(cBuff,CHR(10),"-"),"C:\TEMP\BUFF.TXT")
  DO CASE
          **\/** Número de Cajero
     CASE pcClave=[CAJERO]
          uValor=GETWORDNUM(cBuff,1,CHR(10))
          **\/** Ventas del Dia
     CASE pcClave=[VENTAS]
          uValor=GETWORDNUM(cBuff,2,CHR(10))
          uValor=VAL(uValor)/100
          **\/** Número de la última factura
     CASE pcClave=[NUMULTFAC]
          uValor=GETWORDNUM(cBuff,3,CHR(10))
          **\** Cantidad de Facturas del Día
     CASE pcClave=[CANTFACDIA]
          uValor=GETWORDNUM(cBuff,4,CHR(10))
          uValor=VAL(uValor)
          **\/** Número del Documento No Fiscal
     CASE pcClave=[NUMDOCNOFIS]
          uValor=GETWORDNUM(cBuff,5,CHR(10))
          **\/** Cantidad de Documentos No Fiscales
     CASE pcClave=[CANTDOCNOFIS]
          uValor=GETWORDNUM(cBuff,6,CHR(10))
          uValor=VAL(uValor)
          **\/** Contador de Cierres Diarios
     CASE pcClave=[CANTCIERREZ]
          uValor=GETWORDNUM(cBuff,7,CHR(10))
          uValor=VAL(uValor)
          **\/** Contador de Reportes de Auditoria
     CASE pcClave=[CONTREPAUD]
          uValor=GETWORDNUM(cBuff,8,CHR(10))
          **\/** Nro de RIF
     CASE pcClave=[RIF]
          uValor=GETWORDNUM(cBuff,9,CHR(10))
          **\/** Serial de la Impresora
     CASE pcClave=[SERIAL]
          uValor=GETWORDNUM(cBuff,10,CHR(10))
          **\/** Hora actual de la impresora
     CASE pcClave=[HORAACT]
          uValor=GETWORDNUM(cBuff,11,CHR(10))
          **\/** Fecha actual de la impresora
     CASE pcClave=[FECHAACT]
          uValor=GETWORDNUM(cBuff,12,CHR(10))
          uValor=SUBST(uValor,1,2) + [-] + SUBST(uValor,3,2) + [-] + SUBST(uValor,5,2)
          uValor=CTOD(uValor)
  ENDCASE
 
  RETURN uValor
  *
 ENDPROC


 

 PROCEDURE dec2Hex(nDecimal)
  LOCAL lcHexa, lcChr, lnResto
  lcHexa=''
  DO WHILE nDecimal > 0
    lnResto = MOD(nDecimal,16)
    nDecimal = INT(nDecimal / 16)
    lcChr = IIF(lnResto < 10,STR(lnResto,1),CHR(lnResto + 55))
    lcHexa = lcChr + lcHexa
  ENDDO
  RETURN lcHexa
 ENDPROC
 
 
 
 PROCEDURE actualizarTablaZ(pcDateRange, pcSerial, pcBuff)
  *
  LOCAL cToday
  SET CENTURY OFF
  cToday = CHRT(DTOC(DATE()),"-/.","")
  SET CENTURY ON
  IF VARTYPE(pcDateRange)<>"C"
   pcDateRange=cToday + cToday
  ENDIF
 
  *-- Se descarga la informacion de los reportes Z emitidos durante el dia actual
  LOCAL cBuff  
  IF EMPTY(pcBuff)
   LOCAL cTempFile,cBAKFile,cCmd
   cTempFile = getTempFile("PTF")
   cBAKFile = ADDBS(CONFIG.Folders.Temp) + "REPZ_"+cToday+".TXT"
   cCmd = "U2A" + pcDateRange
   THIS.downloadFromPrinter(cCmd, cTempFile, THIS.Params.OUT)
   doPause(5)
 
   cBuff = FILETOSTR(cTempFile)
   COPY FILE (cTempFile) TO (cBAKFile)
   ERASE (cTempFile)
  ELSE
   cBuff = pcBuff
  ENDIF
 
 
  *-- Se separa el contenido del archivo en lineas, donde cada linea corresponde a los datos
  *   de un reporte Z particular
  *
  LOCAL ARRAY aZReports[1]
  LOCAL nZReportCount,nZReport
  nZReportCount = ALINES(aZReports,cBuff)

  LOCAL cNumero,tFecha,cNumUltFac,tFecUltFac,nVentasEx,nVentas1,nIVA1,nVentas2,nIVA2,nVentas3,nIVA3,nDevEx,nDev1,nIVADev1,nDev2,nIVADev2,nDev3,nIVADev3,cNumUltDev
  LOCAL oReporteZ,oSP
  oReporteZ = CreateBuffer("hizSerialIF,hizNumeroReporte,hizFecha,hizNumUltFac,hizFecUltFac,"+;
                           "hizVentasEx,hizVentas1,hizIVA1,hizVentas2,hizIVA2,hizVentas3,hizIVA3,"+;
                           "hizDevEx,hizDev1,hizIVADev1,hizDev2,hizIVADev2,hizDev3,hizIVADev3,hizNumUltDev")
  oSP = newSP("spUpdHistoricoZ")                          
                           
 
  FOR nZReport = 1 TO nZReportCount
   *
   STORE "" TO cNumero,cNumUltFac,cNumUltDev
   STORE 0.0 TO nVentasEx,nVentas1,nIVA1,nVentas2,nIVA2,nVentas3,nIVA3,nDevEx,nDev1,nIVADev1,nDev2,nIVADev2,nDev3,nIVADev3
   STORE {//::} TO tFecha,tFecUltFac
   
   cBuff = aZReports[nZReport]
   IF LEFT(cBuff,4)='S101' OR AT(" ",cbuff) = 0
    EXIT
   ENDIF
   
 
   *-- Se extraen los datos del reporte Z
   SET DATE DMY
   WITH oReporteZ
    .hizSerialIF = EVL(pcSerial,POSCONF.Local.SerialIF)
    .hizNumeroReporte = SUBSTR(cBuff,1,4)
    .hizFecha = DTOT(CTOD(TRANSFORM(SUBSTR(cBuff,5,6),"@R 99-99-2099")))
    .hizFecUltFac = .hizFecha
    .hizVentas1  = VAL(SUBSTR(cBuff,16,13)) / 100  
    .hizVentas2  = VAL(SUBSTR(cBuff,30,13)) / 100  
    .hizVentas3  = VAL(SUBSTR(cBuff,44,13)) / 100  
    .hizVentasEx = VAL(SUBSTR(cBuff,58,13)) / 100    
    .hizIVA1     = VAL(SUBSTR(cBuff,72,13)) / 100    
    .hizIVA2     = VAL(SUBSTR(cBuff,86,13)) / 100
    .hizIVA3     = VAL(SUBSTR(cBuff,100,13)) / 100
    .hizDev1     = VAL(SUBSTR(cBuff,114,13)) / 100      
    .hizDev2     = VAL(SUBSTR(cBuff,128,13)) / 100          
    .hizDev3     = VAL(SUBSTR(cBuff,142,13)) / 100      
    .hizDevEx    = VAL(SUBSTR(cBuff,156,13)) / 100      
    .hizIVADev1  = VAL(SUBSTR(cBuff,170,13)) / 100      
    .hizIVADev2  = VAL(SUBSTR(cBuff,184,13)) / 100      
    .hizIVADev3  = VAL(SUBSTR(cBuff,198,13)) / 100          
    .hizNumUltFac = SUBSTR(cBuff,211,8)    
    .hizNumUltDev = SUBSTR(cBuff,219,8)  
   ENDWITH
   SET DATE ITALIAN  
   
   
   *-- Se registran/actualizan los datos del reporte Z en el historico
   oSP.importParams(oReporteZ)
   oSP.Params.usrId = Usuario.usrId
   oSP.ExecuteNonQuery()
   
   
   *-- Se analiza el siguiente reporte en la lista
   *
  ENDFOR
 
  *
 ENDPROC


ENDDEFINE



***************************************************
**
**         E X C E P C I O N E S
**
***************************************************

DEFINE CLASS cifGeneralException AS baseException
 Message = "Ocurrió un error al intentar enviar un comando a la impresora fiscal"
ENDDEFINE


DEFINE CLASS cifLineaIncorrectaException AS baseException
 Message = "El nro. de linea indicado es incorrecto"
ENDDEFINE

DEFINE CLASS cifParametroIncorrectoException AS baseException
 Message = "El parametro es incorrecto o no se indicó"
ENDDEFINE

DEFINE CLASS cifAperturaPuertoException AS baseException
 Message = "Ocurrió un error al intentar abrir el puerto de la impresora"
ENDDEFINE

DEFINE CLASS cifStatusImpresoraException AS baseException
 Message = "Ocurrio un error al intentar leer el estado de la impresora"
ENDDEFINE

DEFINE CLASS cifCierrePuertoException AS baseException
 Message = "Ocurrió un error al intentar cerrar el puerto de la impresora"
ENDDEFINE

DEFINE CLASS cifNoDriveException AS baseException
 Message = "No se encontró la libreria DLL para la comunicación con la impresora fiscal"
ENDDEFINE


****************************************** FIN DEL DOCUMENTO *********************************************************


* FACTURAVENTA.PRG
* Plugin para manejar la impresion de una factura de venta
*
DEFINE CLASS facturaVenta AS Plugin
 *
 Description = "Imprimir una factura de venta"
 hooks = "imprimirFacturaVenta"
 
 PROCEDURE onInvoke(pcHook,poParams)
  *
  *-- Se obtienen los datos del ticket
  PRIVATE sp,oTicket
  sp = newSP("spSMGetTicketInfoById")
  sp.Params.tckId = poParams.tckId
  oTicket = sp.executeRow()
 
  *-- Se obtiene una referencia al driver de la impresora
  LOCAL oIF
  oIF = pluginsHelper.getPlugin("controladorImpresoraFiscal")
  IF ISNULL(oIF)
   ThrowCustomEx("fvNoCIFException")
   RETURN
  ENDIF
 

  *-- Se cierra el puerto (por si quedo abierto)
  TRY
   oIF.Invoke("CIFCerrarPuerto")
  CATCH
  ENDTRY


  *-- Se inicia un ciclo para permitir repetir la impresion en caso
  *   que ocurriera un error durante el proceso
  *
  LOCAL lOk,lRetry
  lOk = False
  lRetry = False
  DO WHILE True
   *
   
   TRY
 
   
    *-- Se abre el puerto de la impresora
    oIF.Invoke("CIFAbrirPuerto")
   
    *-- Se genera la cabezera de la factura
      IF NOT lRetry
     oIF.Invoke("CIFReiniciarImpresora")
      ENDIF

    oIF.Invoke("CIFImpLineaCabezera",1,'Doc.: '+oTicket.tckNumFacBO)
    oIF.Invoke("CIFImpLineaCabezera",2,RTRIM(Usuario.usrNombre)+" "+WST.Name)
    oIF.Invoke("CIFImpLineaCabezera",3,'CI/RIF : '+oTicket.cliCedRIF)
    oIF.Invoke("CIFImpLineaCabezera",4,'Cliente: '+oTicket.cliNombre)
    oIF.Invoke("CIFImpLineaCabezera",5,'Telf.  : '+oTicket.cliTelefono)
    oIF.Invoke("CIFImpLineaCabezera",6,'Direc. : '+LEFT(oTicket.cliDireccion,40))
    oIF.Invoke("CIFImpLineaCabezera",7,SUBSTR(oTicket.cliDireccion,41))
   
   
    *-- Se obtiene el detalle de la factura
    sp = newSP("spSMListTicketById")
    sp.Params.tckId = poParams.tckId
    sp.Execute("QITEMS")
   
    SELECT QITEMS
    SCAN
     IF comTipo = "01"
      oIF.Invoke("CIFImpLineaDetalle",comPLU,comTexto,comPrecio,comCant,comIVA,comPctDcto)
     ENDIF
     IF comTipo = "03"
       oIF.Invoke("CIFImpLineaDevolucion",comPLU,comTexto,comPrecio,comCant,comIVA,comPctDcto)
     ENDIF
    ENDSCAN
    USE IN QITEMS
   
    *-- Se imprime el subtotal y el total
    oIF.Invoke("CIFImprimirSubTotal")
    oIF.Invoke("CIFImprimirTotalFA")  
 
   
    *-- Se imprime el ticket de promocion (si esta definido)
    THIS.imprimirPromocion(oIF)  
 
    lOk = True
   
   CATCH TO ex
     lOk = False
     lRetry = True
     ex = getInnerEx(ex)
     IF LEFT(LOWER(ex.class),3) == "cif"
      LOCAL cResponse
      cResponse = ""
      IF INLIST(oIF.lastErrorCode,0x5C,0x01)
       cResponse = msgHelper.Custom("Error de impresion",;
                          "Falta papel en la impresora. Por favor reponga el papel, reinicie la impresora y pulse el botón REIMPRIMIR...",;
                          "Reimprimir,Cancelar","REPRINT,CANCEL",;
                          "IMG\PrinterError.PNG",TSGUI.panelColorStyles.Normal)
      ELSE
       cResponse = msgHelper.Custom("Error de impresion",;
                          "Ocurrió el siguiente error durante el proceso de impresión:\n\n"+;
                          ex.Message + "\n\n" + ;
                          "Estatus: " + oIF.OUT.Estatus + "\n"+;
                          "Condición: " + oIF.OUT.Error,;
                          "Reimprimir,Cancelar","REPRINT,CANCEL",;
                          "IMG\ErrorIcon.PNG",TSGUI.panelColorStyles.Critical)
      ENDIF
      IF cResponse = "CANCEL"                          
       lRetry = False                        
      ENDIF                          
     ELSE
      THROW
     ENDIF

 
   ENDTRY
   
   IF lOk OR (NOT lRetry)
    EXIT
   ENDIF

   TRY
    oIF.Invoke("CIFReiniciarImpresora")
    oIF.Invoke("CIFCancelarTransaccion")  
   CATCH
   ENDTRY

   TRY
    oIF.Invoke("CIFCerrarPuerto")
   CATCH
   ENDTRY
 
   *
  ENDDO

  TRY
   oIF.Invoke("CIFCerrarPuerto")
  CATCH
  ENDTRY

  THIS.OUT.OK = lOk  
 
 
  *-- Se obtiene el nro. de control asignado
  IF lOk
   THIS.OUT.numcontrol = oIF.Invoke("CIFUltimaFactura")
  ENDIF
  *
 ENDPROC
 
 PROCEDURE imprimirPromocion(poIF)
  *
  IF NOT FILE("PROMOCION.TXT")
   RETURN
  ENDIF
 
  PRIVATE cBuff,oIF
  cBuff = FILETOSTR("PROMOCION.TXT")
  oIF = poIF
 
 
  *-- Se imprime el contenido del archivo  
  LOCAL ARRAY aTicket[1]
  LOCAL nCount, i, cLine
  nCount = ALINES(aTicket,cBuff)
  FOR i = 1 TO nCount
   cLine = Expand(aTicket[i])
   oIF.Invoke("CIFImpLineaNF",cLine)
  ENDFOR
  oIF.Invoke("CIFCerrarNF",SPACE(35))  
  *
 ENDPROC
 
 *
ENDDEFINE



DEFINE CLASS fvNoCIFException AS baseException
 MEssage = "No se encontró una controladora para impresora fiscal instalada"
ENDDEFINE

****************************************** FIN DEL DOCUMENTO *********************************************************


Espero te sirva


Victor Espina

Juanerge Hung

unread,
Nov 22, 2022, 3:59:42 PM11/22/22
to publice...@googlegroups.com
Ok voy a ver que le saco, gracias por tu tiempo

Reply all
Reply to author
Forward
0 new messages