UNPKG

@aledj02/afip.js

Version:

Libreria para usar los Web Services de AFIP con JavaScript Fork de @afipsdk/afip.js

346 lines (299 loc) 9.16 kB
const AfipWebService = require('./AfipWebService'); /** * SDK for AFIP Electronic Billing (wsfe1) * * @link http://www.afip.gob.ar/fe/documentos/manual_desarrollador_COMPG_v2_10.pdf WS Specification **/ module.exports = class ElectronicBilling extends AfipWebService { constructor(afip){ const options = { soapV12: true, WSDL: 'wsfe-production.wsdl', URL: 'https://servicios1.afip.gov.ar/wsfev1/service.asmx', WSDL_TEST: 'wsfe.wsdl', URL_TEST: 'https://wswhomo.afip.gov.ar/wsfev1/service.asmx', afip } super(options); } /** * Gets last voucher number * * Asks to Afip servers for number of the last voucher created for * certain sales point and voucher type {@see WS Specification * item 4.15} * * @param int salesPoint Sales point to ask for last voucher * @param int type Voucher type to ask for last voucher * * @return int **/ async getLastVoucher(salesPoint, type) { const req = { 'PtoVta' : salesPoint, 'CbteTipo' : type }; return (await this.executeRequest('FECompUltimoAutorizado', req)).CbteNro; } /** * Create a voucher from AFIP * * Send to AFIP servers request for create a voucher and assign * CAE to them {@see WS Specification item 4.1} * * @param array data Voucher parameters {@see WS Specification * item 4.1.3}, some arrays were simplified for easy use {@example * examples/createVoucher.js Example with all allowed * attributes} * @param bool returnResponse if is TRUE returns complete response * from AFIP * * @return array if returnResponse is set to false returns * [CAE : CAE assigned to voucher, CAEFchVto : Expiration date * for CAE (yyyy-mm-dd)] else returns complete response from * AFIP {@see WS Specification item 4.1.3} **/ async createVoucher(data, returnResponse = false) { const req = { 'FeCAEReq' : { 'FeCabReq' : { 'CantReg' : data['CbteHasta'] - data['CbteDesde'] + 1, 'PtoVta' : data['PtoVta'], 'CbteTipo' : data['CbteTipo'] }, 'FeDetReq' : { 'FECAEDetRequest' : data } } }; delete data['CantReg']; delete data['PtoVta']; delete data['CbteTipo']; if (data['Tributos']) data['Tributos'] = { 'Tributo' : data['Tributos'] }; if (data['Iva']) data['Iva'] = { 'AlicIva' : data['Iva'] }; if (data['CbtesAsoc']) data['CbtesAsoc'] = { 'CbteAsoc' : data['CbtesAsoc'] }; if (data['Compradores']) data['Compradores'] = { 'Comprador' : data['Compradores'] }; if (data['Opcionales']) data['Opcionales'] = { 'Opcional' : data['Opcionales'] }; const results = await this.executeRequest('FECAESolicitar', req); if (returnResponse === true) { return results; } else{ if (Array.isArray(results.FeDetResp.FECAEDetResponse)) { results.FeDetResp.FECAEDetResponse = results.FeDetResp.FECAEDetResponse[0]; } return { 'CAE' : results.FeDetResp.FECAEDetResponse.CAE, 'CAEFchVto' : this.formatDate(results.FeDetResp.FECAEDetResponse.CAEFchVto), }; } } /** * Create next voucher from AFIP * * This method combines Afip.getLastVoucher and Afip.createVoucher * for create the next voucher * * @param array data Same to data in Afip.createVoucher except that * don't need CbteDesde and CbteHasta attributes * * @return array [CAE : CAE assigned to voucher, CAEFchVto : Expiration * date for CAE (yyyy-mm-dd), voucherNumber : Number assigned to * voucher] **/ async createNextVoucher(data) { const lastVoucher = await this.getLastVoucher(data['PtoVta'], data['CbteTipo']); const voucherNumber = lastVoucher + 1; data['CbteDesde'] = voucherNumber; data['CbteHasta'] = voucherNumber; let res = await this.createVoucher(data); res['voucherNumber'] = voucherNumber; return res; } /** * Get complete voucher information * * Asks to AFIP servers for complete information of voucher {@see WS * Specification item 4.19} * * @param int number Number of voucher to get information * @param int salesPoint Sales point of voucher to get information * @param int type Type of voucher to get information * * @return array|null returns array with complete voucher information * {@see WS Specification item 4.19} or null if there not exists **/ async getVoucherInfo(number, salesPoint, type) { const req = { 'FeCompConsReq' : { 'CbteNro' : number, 'PtoVta' : salesPoint, 'CbteTipo' : type } }; const result = await this.executeRequest('FECompConsultar', req) .catch(err => { if (err.code === 602) { return null } else { throw err }}); return result.ResultGet; } /** * Asks to AFIP Servers for sales points availables {@see WS * Specification item 4.11} * * @return array All sales points availables **/ async getSalesPoints() { return (await this.executeRequest('FEParamGetPtosVenta')).ResultGet.PtoVenta; } /** * Asks to AFIP Servers for voucher types availables {@see WS * Specification item 4.4} * * @return array All voucher types availables **/ async getVoucherTypes() { return (await this.executeRequest('FEParamGetTiposCbte')).ResultGet.CbteTipo; } /** * Asks to AFIP Servers for voucher concepts availables {@see WS * Specification item 4.5} * * @return array All voucher concepts availables **/ async getConceptTypes() { return (await this.executeRequest('FEParamGetTiposConcepto')).ResultGet.ConceptoTipo; } /** * Asks to AFIP Servers for document types availables {@see WS * Specification item 4.6} * * @return array All document types availables **/ async getDocumentTypes() { return (await this.executeRequest('FEParamGetTiposDoc')).ResultGet.DocTipo; } /** * Asks to AFIP Servers for aliquot availables {@see WS * Specification item 4.7} * * @return array All aliquot availables **/ async getAliquotTypes() { return (await this.executeRequest('FEParamGetTiposIva')).ResultGet.IvaTipo; } /** * Asks to AFIP Servers for currencies availables {@see WS * Specification item 4.8} * * @return array All currencies availables **/ async getCurrenciesTypes() { return (await this.executeRequest('FEParamGetTiposMonedas')).ResultGet.Moneda; } /** * Asks to AFIP Servers for voucher optional data available {@see WS * Specification item 4.9} * * @return array All voucher optional data available **/ async getOptionsTypes() { return (await this.executeRequest('FEParamGetTiposOpcional')).ResultGet.OpcionalTipo; } /** * Asks to AFIP Servers for tax availables {@see WS * Specification item 4.10} * * @return array All tax availables **/ async getTaxTypes() { return (await this.executeRequest('FEParamGetTiposTributos')).ResultGet.TributoTipo; } /** * Asks to web service for servers status {@see WS * Specification item 4.14} * * @return object { AppServer : Web Service status, * DbServer : Database status, AuthServer : Autentication * server status} **/ async getServerStatus() { return await this.executeRequest('FEDummy'); } /** * Change date from AFIP used format (yyyymmdd) to yyyy-mm-dd * * @param string|int date to format * * @return string date in format yyyy-mm-dd **/ formatDate(date) { return date.toString() .replace(/(\d{4})(\d{2})(\d{2})/, (string, year, month, day) => `${year}-${month}-${day}`); } /** * Sends request to AFIP servers * * @param string operation SOAP operation to do * @param array params Parameters to send * * @return mixed Operation results **/ async executeRequest(operation, params = {}) { Object.assign(params, await this.getWSInitialRequest(operation)); const results = await super.executeRequest(operation, params); await this._checkErrors(operation, results); return results[operation+'Result']; } /** * Make default request parameters for most of the operations * * @param string operation SOAP Operation to do * * @return array Request parameters **/ async getWSInitialRequest(operation, tokenAuth) { if (operation === 'FEDummy') { return {}; } const { token, sign } = tokenAuth; return { 'Auth' : { 'Token' : token, 'Sign' : sign, 'Cuit' : this.afip.CUIT } }; } /** * Check if occurs an error on Web Service request * * @param string operation SOAP operation to check * @param mixed results AFIP response * * @throws Exception if exists an error in response * * @return void **/ async _checkErrors(operation, results) { const res = results[operation+'Result']; if (operation === 'FECAESolicitar') { if (Array.isArray(res.FeDetResp.FECAEDetResponse)) { res.FeDetResp.FECAEDetResponse = res.FeDetResp.FECAEDetResponse[0]; } if (res.FeDetResp.FECAEDetResponse.Observaciones && res.FeDetResp.FECAEDetResponse.Resultado !== 'A') { res.Errors = { Err : res.FeDetResp.FECAEDetResponse.Observaciones.Obs }; } } if (res.Errors) { const err = Array.isArray(res.Errors.Err) ? res.Errors.Err[0] : res.Errors.Err; throw new Error(`(${err.Code}) ${err.Msg}`, err.Code); } } }