package ar.com.comit.factura.electronica; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.math.BigDecimal; import java.sql.Date; import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.Properties; import java.util.logging.Level; import org.compiere.model.MInvoice; import org.compiere.model.MInvoiceTax; import org.compiere.model.MPOS; import org.compiere.model.MPreference; import org.compiere.util.CLogger; import org.compiere.util.Env; import org.compiere.util.Msg; /** * @author Horacio Alvarez - SERVICIOS DIGITALES S.A. * @updated 2011-06-25 * @notes Adaptado para Factura Electronica Argentina v1.0 - Vigencia a partir del 01-07-2011 */ public abstract class Wsfe { private CLogger log = CLogger.getCLogger(Wsfe.class); private String messageError = null; private Properties m_ctx = Env.getCtx(); private String trxName = null; private MInvoice invoice = null; private String result = null; private WsfeResult wsfeResult; private String path = ""; public Wsfe(MInvoice inv) { this.invoice = inv; setTrxName(invoice.get_TrxName()); this.wsfeResult = new WsfeResult(); } /* Getters y Setters */ public String getMessageError() { return messageError; } public void setMessageError(String messageError) { this.messageError = messageError; } public Properties getM_ctx() { return m_ctx; } public void setM_ctx(Properties m_ctx) { this.m_ctx = m_ctx; } public String getTrxName(){ return trxName; } private void setTrxName(String value){ trxName = value; } public MInvoice getInvoice() { return invoice; } public void setInvoice(MInvoice invoice) { this.invoice = invoice; } protected abstract void createInputFile(); /** * @author Horacio Alvarez * @descripcion: Formatea el fecha recibida @time@ * al formato @format@. Ej: yyyyMMdd */ protected String formatTime(Timestamp time,String format){ SimpleDateFormat simpleformat = new SimpleDateFormat(format); Date date = new Date(time.getTime()); return simpleformat.format(date); } /** * @author Horacio Alvarez * @return: Devuelve el path donde se encuentra alojado el proceso wsfe.py en el * sistema de archvos local. Este path se guarda en la tabla AD_Preference (Valores Predeterminados) */ protected String getPath() { /** * El nombre de AD_Preference a consultar se forma concatenando el valor * WSFE_PV y el Nro de Punto de Venta */ if (path != "") return path; else { MPOS pos = new MPOS(m_ctx, invoice.get_ValueAsInt("C_Pos_ID"), trxName); String atributo = "WSFE_PV" + pos.get_ValueAsInt("PosNumber"); MPreference preference = MPreference.getOrgPreference(Env.getAD_Client_ID(getM_ctx()), Env.getAD_Org_ID(getM_ctx()), atributo, getM_ctx(), getTrxName()); // En el caso que no se haya encontrado ninguna preferencia // a partir del Nro de Punto de Venta se busca utilizando el valor // por defecto que es: WSFE if (preference == null) { atributo = "WSFE"; preference = MPreference.getOrgPreference(Env.getAD_Client_ID(getM_ctx()), Env.getAD_Org_ID(getM_ctx()), atributo, getM_ctx(), getTrxName()); } path = preference.getValue(); return path; } } protected void deleteExistingFiles(){ try{ File file = new File(getPath()+"entrada.txt"); if(file.exists()){ if(!file.delete()){ messageError = Msg.translate(m_ctx, "caeCannotDeleteEntradaTxt"); log.log(Level.SEVERE, messageError); } } file = new File(getPath()+"salida.txt"); if(file.exists()){ if(!file.delete()){ messageError = Msg.translate(m_ctx, "caeCannotDeleteSalidaTxt"); log.log(Level.SEVERE, messageError); } } file = new File(getPath()+"error.txt"); if(file.exists()){ if(!file.delete()){ messageError = Msg.translate(m_ctx, "caeCannotDeleteErrorTxt"); log.log(Level.SEVERE, messageError); } } } catch(Exception ex){ messageError = Msg.translate(m_ctx, "caeCannotDeleteFilesError"); log.log(Level.SEVERE, messageError,ex); } } /** * @author Horacio Alvarez * @descripcion: Invoca el ejecutable run.sh (wsfe.py) * ****************************************************************************** * #!/bin/bash * RUTAWSFE="/home/horacio/soft/Archivos" * RUTAPYTHON="/usr/bin/python" * cd $RUTAWSFE * $RUTAPYTHON $RUTAWSFE/wsfe.py >> $RUTAWSFE/log.error 2>> $RUTAWSFE/log.error * ****************************************************************************** * */ protected void callProcess(){ String aux = null; String auxE = null; try { /* directorio/ejecutable es el path del ejecutable y un nombre */ Process p = null; String osName = System.getProperty("os.name"); if(osName.equals("Linux")){ p = Runtime.getRuntime().exec ("sh "+getPath() + "run.sh"); } else{ p = Runtime.getRuntime().exec (getPath() + "run.bat"); } p.waitFor(); if(p.exitValue() != 0){ InputStream is = p.getInputStream(); InputStream ie = p.getErrorStream(); BufferedReader br = new BufferedReader (new InputStreamReader (is)); BufferedReader brE = new BufferedReader (new InputStreamReader (ie)); aux = br.readLine(); if(aux == null) aux = ""; if(auxE == null) auxE = ""; auxE = brE.readLine(); messageError = "Exit Value="+p.exitValue()+",InputStream="+aux+",ErrorStream="+auxE; //messageError = "La AFIP no aprueba el envio. Por favor corrobore los datos (CUIT, Categoria de IVA, Etc)."; log.log(Level.SEVERE,"caeErrorCallProcess:" +aux + auxE); } } catch (Exception e) { messageError = "Error callProcess(): "+aux; log.log(Level.SEVERE,messageError); e.printStackTrace(); } } /** * @author: Horacio Alvarez * @descripcion: Busca si el wsfe.py devolvió algun error, mediante el error.txt. */ protected void searchForProblems(){ String linea = null; try{ File errorFile = new File(getPath()+"error.txt"); if(errorFile.exists()){ BufferedReader reader = new BufferedReader(new FileReader(errorFile)); linea = reader.readLine(); messageError = linea; log.log(Level.SEVERE, linea); } else{ log.log(Level.WARNING, "Everything is OK"); } } catch(Exception ex){ messageError = Msg.translate(m_ctx, "caeErrorSearchForProblems"); log.log(Level.SEVERE, linea); } } /** * @author: Horacio Alvarez * @descripcion: Guarda en @resultado@ la linea del archivo de salida * generado por el WSFE, */ protected void readOutput(){ String linea = null; try { BufferedReader reader = new BufferedReader(new FileReader(getPath()+"salida.txt")); linea = reader.readLine(); log.log(Level.INFO, linea); } catch (IOException ex) { messageError = Msg.translate(m_ctx, "CaeErrorReadOutput"); log.log(Level.SEVERE, messageError+ex); } result = linea; } protected void setValues(){ try{ String[] values = getOutputLine().split(":"); wsfeResult.setAcepted(values[0]); wsfeResult.setCae(values[1]); wsfeResult.setNroCbte(values[2]); wsfeResult.setMensaje(values[3]); wsfeResult.setDateCae(values[4]); } catch(Exception ex){ messageError = Msg.translate(m_ctx, "caeErrorSetValues"); log.log(Level.SEVERE,messageError+ ":" +ex.toString()); } } protected void check(){ if(wsfeResult.getMensaje() != null & !wsfeResult.getMensaje().equals("None")){ messageError = wsfeResult.getMensaje(); } } /** * @author Horacio Alvarez * @return Devuelve la linea de salida generada por wsfe.py. */ private String getOutputLine(){ return result; } class WsfeResult{ private String accepted; private String cae; private String mensaje; private String nroCbte; private Timestamp dateCae; /** * @author Horacio Alvarez * @descripcion: Obtiene y setea el ID del CAE desde * la linea guardada del archivo de respuesta. */ public void setAcepted(String value){ accepted = value; } public String getAccepted(){ return accepted; } /** * @author Horacio Alvarez * @descripcion: Obtiene y setea el CAE desde la linea guardada del archivo de respuesta. */ public void setCae(String value){ cae = value; } public String getCAE(){ return cae; } public void setMensaje(String value){ mensaje = value; } public String getMensaje(){ return mensaje; } public void setNroCbte(String value){ nroCbte = value; } public String getNroCbte(){ return nroCbte; } /** * @author Horacio Alvarez * @descripcion: Obtiene y setea la fecha de vto. del CAE desde * la linea guardada del archivo de respuesta. */ public void setDateCae(String value){ try{ dateCae = getTimestamp(value, "yyyyMMdd"); }catch(Exception ex){ ex.printStackTrace(); } } public Timestamp getDateCae(){ return dateCae; } } public String getAccepted(){ return this.wsfeResult.getAccepted(); } public String getCAE(){ return this.wsfeResult.getCAE(); } public String getNroCbte(){ return this.wsfeResult.getNroCbte(); } public Timestamp getDateCae(){ return this.wsfeResult.getDateCae(); } public String getMensaje(){ return this.wsfeResult.getMensaje(); } /** * @author Horacio Alvarez * @descripcion: Convierte la fecha string @value@ de formato @format@ * en Timestamp. */ private Timestamp getTimestamp(String value, String format){ Timestamp time = null; try{ SimpleDateFormat dateFormat = new SimpleDateFormat(format); java.util.Date date = dateFormat.parse(value); time = new Timestamp(date.getTime()); } catch(Exception ex){ log.log(Level.SEVERE, "Error getTimestamp():"+ex); } return time; } /** * Obtener el monto total de todos los impuesto aplicados a la factura. * @param invoice * @return */ public BigDecimal getTaxesAmt(MInvoice invoice) { MInvoiceTax[] taxes = invoice.getTaxes(false); BigDecimal total = Env.ZERO; for (int i = 0; i < taxes.length; i++) { total = total.add(taxes[i].getTaxAmt()); } return total; } // getTaxesAmt }