fecr
Version:
Modulo de comprobantes electrónicos para el API del Ministerio de Hacienda de Costa Rica versión 4.3
284 lines (240 loc) • 7.82 kB
JavaScript
"use strict";
var xml2js = require("xml2js");
var moment = require("moment-timezone");
var utils = require("./utils.js");
var signer = require("./signer.js");
var Summary = require("./voucher/summary.js");
class Voucher {
constructor(voucher) {
this.cert = voucher.cert;
this.api = voucher.api;
this.date = voucher.date ? moment.tz(voucher.date, "America/Costa_Rica") : moment.tz("America/Costa_Rica");
this.issuer = voucher.issuer;
this.headquarters = voucher.headquarters ? voucher.headquarters : 1;
this.terminal = voucher.terminal ? voucher.terminal : 1;
this.number = voucher.number;
this.situation = voucher.situation ? voucher.situation : "1";
this.activityCode = voucher.activityCode;
this.securityCode = voucher.securityCode;
if (voucher.receiver) {
this.receiver = voucher.receiver;
}
this.condition = voucher.condition ? voucher.condition : "01";
this.paymentType = voucher.paymentType ? voucher.paymentType : "01";
if (voucher.creditTerm) {
this.creditTerm = voucher.creditTerm;
}
if (voucher.items) {
this.items = voucher.items;
}
if (voucher.otherCharges) {
this.otherCharges = voucher.otherCharges;
}
if (voucher.currency) {
this.currency = voucher.currency;
}
if (voucher.exchangeRate) {
this.exchangeRate = voucher.exchangeRate;
}
if (voucher.summary) {
this.summary = voucher.summary;
} else {
this.generateSummary();
}
if (voucher.references) {
this.references = voucher.references;
}
if (voucher.others) {
this.others = voucher.others;
}
if (voucher.callbackUrl) {
this.callbackUrl = voucher.callbackUrl;
}
}
buildXml() {
var voucher = {
[this.rootTag]: {
$: this.namespaces
}
};
voucher[this.rootTag].Clave = this.key;
voucher[this.rootTag].CodigoActividad = this.activityCode;
voucher[this.rootTag].NumeroConsecutivo = this.sequence;
voucher[this.rootTag].FechaEmision = this.date.format();
voucher[this.rootTag].Emisor = this.issuer.generate();
if (this.receiver) {
voucher[this.rootTag].Receptor = this.receiver.generate();
}
voucher[this.rootTag].CondicionVenta = this.condition;
if (this.creditTerm && this.condition === "02") {
voucher[this.rootTag].PlazoCredito = this.creditTerm;
}
voucher[this.rootTag].MedioPago = this.paymentType;
if (this.items) {
var lines = [];
this.items.forEach(item => {
lines.push(item.generate());
});
voucher[this.rootTag].DetalleServicio = {
LineaDetalle: lines
};
}
if (this.otherCharges) {
var charges = [];
this.otherCharges.forEach(charge => {
charges.push(charge.generate());
});
voucher[this.rootTag].OtrosCargos = charges;
}
voucher[this.rootTag].ResumenFactura = this.summary ? this.summary.generate() : this.generateSummary({
items: voucher[this.rootTag].DetalleServicio.LineaDetalle,
otherCharges: voucher[this.rootTag].OtrosCargos
});
if (this.references) {
var references = [];
this.references.forEach(reference => {
references.push(reference.generate());
});
voucher[this.rootTag].InformacionReferencia = references;
}
if (this.others) {
voucher[this.rootTag].Otros = this.others.generate();
}
var builder = new xml2js.Builder();
var xmlString = builder.buildObject(voucher);
this.data = voucher;
return xmlString.replace(/[\r\n]/g, "").replace(/\s{2,}/g, "");
}
generateSequence() {
var headquarters = utils.zfill(this.headquarters, 3);
var terminal = utils.zfill(this.terminal, 5);
var type = utils.zfill(this.voucherType, 2);
var number = utils.zfill(this.number, 10);
this.sequence = headquarters + terminal + type + number;
}
generateKey() {
var country = "506";
var day = utils.zfill(this.date.date(), 2);
var month = utils.zfill(this.date.month() + 1, 2);
var year = utils.zfill(this.date.year() - 2000, 2);
var idNumber = utils.zfill(this.issuer.id, 12);
var type = utils.zfill(this.situation, 1);
var securityCode = utils.zfill(this.securityCode, 8); // eslint-disable-next-line max-len
this.key = country + day + month + year + idNumber + this.sequence + type + securityCode;
}
generateSummary() {
var servicesTaxableTotal = 0;
var servicesExentTotal = 0;
var servicesExoneTotal = 0;
var goodsTaxableTotal = 0;
var goodsExentTotal = 0;
var goodsExoneTotal = 0;
var discountTotal = 0;
var taxTotal = 0;
var otherChargesTotal = 0;
this.otherCharges.forEach((_ref) => {
var {
amount
} = _ref;
otherChargesTotal += Number(amount);
});
this.items.forEach(item => {
if (item.taxes) {
var allowances = [];
item.taxes.forEach((_ref2) => {
var {
allowance
} = _ref2;
if (allowance) allowances.push(allowance);
});
if (item.unit === "Al" || item.unit === "Alc" || item.unit === "Cm" || item.unit === "I" || item.unit === "Os" || item.unit === "Sp" || item.unit === "Spe" || item.unit === "St") {
if (allowances.length > 0) {
servicesExoneTotal += item.total;
} else {
servicesTaxableTotal += item.total;
}
} else {
if (allowances.length > 0) {
goodsExoneTotal += item.total;
} else {
goodsTaxableTotal += item.total;
}
}
taxTotal += item.taxNet;
} else if (item.unit === "Al" || item.unit === "Alc" || item.unit === "Cm" || item.unit === "I" || item.unit === "Os" || item.unit === "Sp" || item.unit === "Spe" || item.unit === "St") {
servicesExentTotal += item.total;
} else {
goodsExentTotal += item.total;
}
if (item.discounts) {
item.discounts.forEach((_ref3) => {
var {
discountAmount
} = _ref3;
discountTotal += discountAmount;
});
}
});
this.summary = new Summary({
currency: this.currency,
exchangeRate: this.exchangeRate,
servicesTaxableTotal,
servicesExentTotal,
servicesExoneTotal,
goodsTaxableTotal,
goodsExentTotal,
goodsExoneTotal,
discountTotal,
taxTotal,
otherChargesTotal
});
}
sign() {
return new Promise((resolve, reject) => {
signer.signXmlString(this.buildXml(), this.cert).then(signedXml => {
this.signedXml = signedXml;
this.signedXmlBase64 = Buffer.from(signedXml).toString("base64");
resolve(signedXml);
}).catch(error => {
reject(error);
});
});
}
getPayload() {
if (!this.signedXmlBase64) {
throw Error("the document has not been signed yet");
}
var payload = {
clave: this.key,
fecha: this.date.format(),
emisor: {
tipoIdentificacion: this.issuer.idType,
numeroIdentificacion: this.issuer.id
}
};
if (this.receiver) {
payload.receptor = {
tipoIdentificacion: this.receiver.idType,
numeroIdentificacion: this.receiver.id
};
}
if (this.callbackUrl) {
payload.callbackUrl = this.callbackUrl;
}
payload.comprobanteXml = this.signedXmlBase64;
return payload;
}
send() {
return new Promise((resolve, reject) => {
this.sign().then(() => this.api.send(this.getPayload())).then(() => {
resolve({
data: this.data,
xml: this.signedXmlBase64
});
}).catch(error => {
reject(error);
});
});
}
}
module.exports = Voucher;