swissqrbill
Advanced tools
Comparing version 1.0.4 to 1.0.5
@@ -41,2 +41,3 @@ /// <reference types="pdfkit" /> | ||
private _autoGenerate; | ||
private _referenceType; | ||
static translations: { | ||
@@ -188,2 +189,20 @@ DE: { | ||
/** | ||
* Removes line breaks from user provided data. | ||
* | ||
* @private | ||
* @param {SwissQRBill.data} data object containing the billing data | ||
* @returns {SwissQRBill.data} | ||
* @memberof PDF | ||
*/ | ||
private _cleanData; | ||
/** | ||
* Removes \n and \r from the passed string | ||
* | ||
* @private | ||
* @param {string} data string to be escaped | ||
* @returns {string} string without \n and \r | ||
* @memberof PDF | ||
*/ | ||
private _removeLinebreaks; | ||
/** | ||
* Formats the amount with spaces and decimals. | ||
@@ -197,3 +216,22 @@ * | ||
private _formatAmount; | ||
private _formatReference; | ||
/** | ||
* Formats the IBAN number according to the defintions | ||
* | ||
* @private | ||
* @param {string} iban string containing the IBAN number | ||
* @returns {(string | undefined)} string containing the formatted IBAN number if successfull, undefined otherwise | ||
* @memberof PDF | ||
*/ | ||
private _formatIBAN; | ||
/** | ||
* Checks if the provided IBAN is a QR-IBAN or a normal IBAN | ||
* | ||
* @private | ||
* @param {string} iban string containing the IBAN to be checked | ||
* @returns {boolean} boolean Whether the IBAN is a QR-IBAN or not | ||
* @memberof PDF | ||
*/ | ||
private _isQRIBAN; | ||
/** | ||
* Draws a rectangle which is used when data is to be filled in by hand. | ||
@@ -200,0 +238,0 @@ * |
251
lib/index.js
@@ -11,2 +11,3 @@ "use strict"; | ||
var svgpath_1 = __importDefault(require("svgpath")); | ||
var iban_1 = __importDefault(require("iban")); | ||
var SwissQRBill; | ||
@@ -30,3 +31,28 @@ (function (SwissQRBill) { | ||
this._autoGenerate = true; | ||
this._cleanData(data); | ||
this._data = data; | ||
//-- Validate data | ||
if (iban_1.default.isValid(this._data.creditor.account) === false) { | ||
throw new Error("The provided IBAN number '" + this._data.creditor.account + "' is not valid."); | ||
} | ||
if (this._data.creditor.account.substr(0, 2) !== "CH" && this._data.creditor.account.substr(0, 2) !== "LI") { | ||
throw new Error("Only CH and LI IBAN numbers are allowed"); | ||
} | ||
if (this._isQRIBAN(this._data.creditor.account)) { | ||
this._referenceType = "QRR"; | ||
if (this._data.reference === undefined) { | ||
throw new Error("QR-IBAN numbers must have a reference"); | ||
} | ||
} | ||
else { | ||
if (this._data.reference === undefined) { | ||
this._referenceType = "NON"; | ||
} | ||
else { | ||
this._referenceType = "SCOR"; | ||
} | ||
} | ||
if (this._data.creditor.name.length > 70) { | ||
throw new Error("Creditor name can be a maximum of 70 characters"); | ||
} | ||
if (options !== undefined) { | ||
@@ -94,5 +120,13 @@ if (options.language !== undefined) { | ||
PDF.prototype._drawOutlines = function () { | ||
this.document.moveTo(0, this.mmToPoints(this._paddingTop)) | ||
.lineTo(this.mmToPoints(210), this.mmToPoints(this._paddingTop)) | ||
.moveTo(this.mmToPoints(62), this.mmToPoints(this._paddingTop)) | ||
//-- Horizontal line | ||
if (this._size === "A4") { | ||
this.document.moveTo(0, this.mmToPoints(this._paddingTop)) | ||
.lineTo(this.mmToPoints(210), this.mmToPoints(this._paddingTop)) | ||
.lineWidth(.75) | ||
.dash(1, { size: 1 }) | ||
.strokeColor("black") | ||
.stroke(); | ||
} | ||
//-- Vertical line | ||
this.document.moveTo(this.mmToPoints(62), this.mmToPoints(this._paddingTop)) | ||
.lineTo(this.mmToPoints(62), this.mmToPoints(this._paddingTop + 105)) | ||
@@ -139,2 +173,3 @@ .lineWidth(.75) | ||
PDF.prototype._drawReceipt = function () { | ||
var _a; | ||
this.document.fontSize(11); | ||
@@ -154,3 +189,3 @@ this.document.font("Helvetica-Bold"); | ||
this.document.font("Helvetica"); | ||
this.document.text(this._data.creditor.account + "\n" + this._formatAddress(this._data.creditor), { | ||
this.document.text(((_a = this._formatIBAN(this._data.creditor.account)) !== null && _a !== void 0 ? _a : this._data.creditor.account) + "\n" + this._formatAddress(this._data.creditor), { | ||
width: this.mmToPoints(52) | ||
@@ -168,3 +203,3 @@ }); | ||
this.document.font("Helvetica"); | ||
this.document.text(this._data.reference, { | ||
this.document.text(this._formatReference(this._data.reference), { | ||
width: this.mmToPoints(52) | ||
@@ -197,3 +232,4 @@ }); | ||
//-- Draw rectangle | ||
this._drawRectangle(5, 38, 52, 20); | ||
var posY = this._data.reference === undefined ? 38 : 43; | ||
this._drawRectangle(5, posY, 52, 20); | ||
} | ||
@@ -235,2 +271,3 @@ this.document.fontSize(6); | ||
PDF.prototype._drawPaymentPart = function () { | ||
var _a; | ||
this.document.fontSize(11); | ||
@@ -254,7 +291,7 @@ this.document.font("Helvetica-Bold"); | ||
this.document.font("Helvetica"); | ||
this.document.text(this._data.currency, this.mmToPoints(67), this.mmToPoints(this._paddingTop + 71), { | ||
this.document.text(this._data.currency, this.mmToPoints(67), this.mmToPoints(this._paddingTop + 72), { | ||
width: this.mmToPoints(15) | ||
}); | ||
if (this._data.amount !== undefined) { | ||
this.document.text(this._formatAmount(this._data.amount), this.mmToPoints(87), this.mmToPoints(this._paddingTop + 71), { | ||
this.document.text(this._formatAmount(this._data.amount), this.mmToPoints(87), this.mmToPoints(this._paddingTop + 72), { | ||
width: this.mmToPoints(36) | ||
@@ -264,3 +301,3 @@ }); | ||
else { | ||
this._drawRectangle(80, 71, 40, 15); | ||
this._drawRectangle(80, 72, 40, 15); | ||
} | ||
@@ -299,3 +336,3 @@ //-- AV1 and AV2 | ||
this.document.font("Helvetica"); | ||
this.document.text(this._data.creditor.account + "\n" + this._formatAddress(this._data.creditor), this.mmToPoints(118), this.mmToPoints(this._paddingTop + 9.5), { | ||
this.document.text(((_a = this._formatIBAN(this._data.creditor.account)) !== null && _a !== void 0 ? _a : this._data.creditor.account) + "\n" + this._formatAddress(this._data.creditor), this.mmToPoints(118), this.mmToPoints(this._paddingTop + 9.5), { | ||
width: this.mmToPoints(87) | ||
@@ -312,3 +349,3 @@ }); | ||
this.document.font("Helvetica"); | ||
this.document.text(this._data.reference, { | ||
this.document.text(this._formatReference(this._data.reference), { | ||
width: this.mmToPoints(87) | ||
@@ -350,3 +387,4 @@ }); | ||
}); | ||
this._drawRectangle(118, 34, 65, 25); | ||
var posY = this._data.reference === undefined ? 34 : 45; | ||
this._drawRectangle(118, posY, 65, 25); | ||
} | ||
@@ -361,3 +399,3 @@ }; | ||
PDF.prototype._generateQRCode = function () { | ||
var _a; | ||
var _a, _b; | ||
var qrString = ""; | ||
@@ -367,9 +405,24 @@ qrString += "SPC\n"; // Swiss Payments Code | ||
qrString += "1\n"; // Coding Type UTF-8 | ||
qrString += this._data.creditor.account + "\n"; // IBAN | ||
qrString += (_a = this._formatIBAN(this._data.creditor.account)) !== null && _a !== void 0 ? _a : this._data.creditor.account + "\n"; // IBAN | ||
if (this._data.creditor.houseNumber !== undefined) { | ||
qrString += "S\n"; // Adress Type | ||
if (this._data.creditor.name.length > 70) { | ||
throw new Error("Creditor name must be a maximum of 70 characters"); | ||
} | ||
qrString += this._data.creditor.name + "\n"; // Name | ||
if (this._data.creditor.address.length > 70) { | ||
throw new Error("Creditor address must be a maximum of 70 characters"); | ||
} | ||
qrString += this._data.creditor.address + "\n"; // Address | ||
if (this._data.creditor.address.length > 16) { | ||
throw new Error("Creditor house number can be a maximum of 16 characters"); | ||
} | ||
qrString += this._data.creditor.houseNumber + "\n"; // House number | ||
if (this._data.creditor.address.length > 16) { | ||
throw new Error("Creditor zip must be a maximum of 16 characters"); | ||
} | ||
qrString += this._data.creditor.zip + "\n"; // Zip code | ||
if (this._data.creditor.address.length > 35) { | ||
throw new Error("Creditor city must be a maximum of 35 characters"); | ||
} | ||
qrString += this._data.creditor.city + "\n"; // City | ||
@@ -379,6 +432,18 @@ } | ||
qrString += "K\n"; // Adress Type | ||
if (this._data.creditor.name.length > 70) { | ||
throw new Error("Creditor name must be a maximum of 70 characters"); | ||
} | ||
qrString += this._data.creditor.name + "\n"; // Name | ||
if (this._data.creditor.address.length > 70) { | ||
throw new Error("Creditor address must be a maximum of 70 characters"); | ||
} | ||
qrString += this._data.creditor.address + "\n"; // Address | ||
if ((this._data.creditor.zip + " " + this._data.creditor.city).length > 70) { | ||
throw new Error("Creditor zip plus city must be a maximum of 70 characters"); | ||
} | ||
qrString += this._data.creditor.zip + " " + this._data.creditor.city + "\n"; // Zip code + city | ||
} | ||
if (this._data.creditor.country.length !== 2) { | ||
throw new Error("Creditor country must be 2 characters"); | ||
} | ||
qrString += this._data.creditor.country + "\n"; // Country | ||
@@ -393,3 +458,8 @@ //-- 7 x empty | ||
qrString += "\n"; // 7 | ||
qrString += ((_a = this._data.amount) !== null && _a !== void 0 ? _a : "") + "\n"; // Amount | ||
if (this._data.amount !== undefined) { | ||
if (this._data.amount.toString().length > 12) { | ||
throw new Error("Creditor country must be 2 characters"); | ||
} | ||
} | ||
qrString += ((_b = this._data.amount) !== null && _b !== void 0 ? _b : "") + "\n"; // Amount | ||
qrString += this._data.currency + "\n"; // Currency | ||
@@ -399,6 +469,21 @@ if (this._data.debitor !== undefined) { | ||
qrString += "S\n"; // Adress Type | ||
if (this._data.debitor.name.length > 70) { | ||
throw new Error("Debitor name must be a maximum of 70 characters"); | ||
} | ||
qrString += this._data.debitor.name + "\n"; // Name | ||
if (this._data.debitor.address.length > 70) { | ||
throw new Error("Debitor address must be a maximum of 70 characters"); | ||
} | ||
qrString += this._data.debitor.address + "\n"; // Address | ||
if (this._data.debitor.address.length > 16) { | ||
throw new Error("Debitor house number can be a maximum of 16 characters"); | ||
} | ||
qrString += this._data.debitor.houseNumber + "\n"; // House number | ||
if (this._data.debitor.address.length > 16) { | ||
throw new Error("Debitor zip must be a maximum of 16 characters"); | ||
} | ||
qrString += this._data.debitor.zip + "\n"; // Zip code | ||
if (this._data.debitor.address.length > 35) { | ||
throw new Error("Debitor city must be a maximum of 35 characters"); | ||
} | ||
qrString += this._data.debitor.city + "\n"; // City | ||
@@ -408,11 +493,31 @@ } | ||
qrString += "K\n"; // Adress Type | ||
if (this._data.debitor.name.length > 70) { | ||
throw new Error("Debitor name must be a maximum of 70 characters"); | ||
} | ||
qrString += this._data.debitor.name + "\n"; // Name | ||
if (this._data.debitor.address.length > 70) { | ||
throw new Error("Debitor address must be a maximum of 70 characters"); | ||
} | ||
qrString += this._data.debitor.address + "\n"; // Address | ||
qrString += this._data.debitor.zip + " " + this._data.creditor.city + "\n"; // Zip code + city | ||
if ((this._data.debitor.zip + " " + this._data.debitor.city).length > 70) { | ||
throw new Error("Debitor zip plus city must be a maximum of 70 characters"); | ||
} | ||
qrString += this._data.debitor.zip + " " + this._data.debitor.city + "\n"; // Zip code + city | ||
} | ||
qrString += this._data.debitor.country + "\n"; // Country | ||
} | ||
qrString += "QRR" + "\n"; // Referencetype Todo: calculate | ||
qrString += this._data.reference + "\n"; // Reference | ||
qrString += this._referenceType + "\n"; // Referencetype | ||
if (this._data.reference !== undefined) { | ||
if (this._data.reference.replace(/ /g, "").length > 27) { | ||
throw new Error("Reference must be a maximum of 27 characters"); | ||
} | ||
qrString += this._data.reference + "\n"; // Reference | ||
} | ||
else { | ||
qrString += "" + "\n"; // Reference | ||
} | ||
if (this._data.message !== undefined) { | ||
if (this._data.message.length > 140) { | ||
throw new Error("Message must be a maximum of 140 characters"); | ||
} | ||
qrString += this._data.message + "\n"; // Unstructured message | ||
@@ -422,8 +527,17 @@ } | ||
if (this._data.additionalInformation !== undefined) { | ||
if (this._data.additionalInformation.length > 140) { | ||
throw new Error("AdditionalInfromation must be a maximum of 27 characters"); | ||
} | ||
qrString += this._data.additionalInformation + "\n"; // Bill infromation | ||
} | ||
if (this._data.additionalInformation !== undefined) { | ||
if (this._data.av1 !== undefined) { | ||
if (this._data.av1.length > 100) { | ||
throw new Error("AV1 must be a maximum of 27 characters"); | ||
} | ||
qrString += this._data.av1 + "\n"; // AV1 | ||
} | ||
if (this._data.additionalInformation !== undefined) { | ||
if (this._data.av2 !== undefined) { | ||
if (this._data.av2.length > 100) { | ||
throw new Error("AV2 must be a maximum of 27 characters"); | ||
} | ||
qrString += this._data.av2 + "\n"; // AV2 | ||
@@ -440,4 +554,3 @@ } | ||
if (svgPath === undefined) { | ||
console.error("Could not convert svg image to path"); | ||
return; | ||
throw new Error("Could not convert svg image to path"); | ||
} | ||
@@ -536,2 +649,38 @@ this.document.moveTo(this.mmToPoints(67), this.mmToPoints(this._paddingTop + 17)); | ||
/** | ||
* Removes line breaks from user provided data. | ||
* | ||
* @private | ||
* @param {SwissQRBill.data} data object containing the billing data | ||
* @returns {SwissQRBill.data} | ||
* @memberof PDF | ||
*/ | ||
PDF.prototype._cleanData = function (data) { | ||
var _this = this; | ||
var _cleanObject = function (object) { | ||
var keys = Object.keys(object); | ||
for (var k = 0; k < keys.length; k++) { | ||
if (typeof object[keys[k]] === "string") { | ||
object[keys[k]] = _this._removeLinebreaks(object[keys[k]]); | ||
} | ||
else { | ||
if (typeof object[keys[k]] === "object") { | ||
_cleanObject(object[keys[k]]); | ||
} | ||
} | ||
} | ||
}; | ||
_cleanObject(data); | ||
}; | ||
/** | ||
* Removes \n and \r from the passed string | ||
* | ||
* @private | ||
* @param {string} data string to be escaped | ||
* @returns {string} string without \n and \r | ||
* @memberof PDF | ||
*/ | ||
PDF.prototype._removeLinebreaks = function (data) { | ||
return data.replace(/\n/g, "").replace(/\r/g, ""); | ||
}; | ||
/** | ||
* Formats the amount with spaces and decimals. | ||
@@ -557,3 +706,51 @@ * | ||
}; | ||
PDF.prototype._formatReference = function (reference) { | ||
reference = this._removeLinebreaks(reference); | ||
var referenceArray = []; | ||
if (this._referenceType === "QRR") { | ||
var match = reference.replace(/ /g, "").split("").reverse().join("").match(/.{1,5}/g); | ||
if (match !== null) { | ||
referenceArray = match.reverse(); | ||
} | ||
} | ||
else if (this._referenceType === "SCOR") { | ||
var match = reference.replace(/ /g, "").match(/.{1,4}/g); | ||
if (match !== null) { | ||
referenceArray = match; | ||
} | ||
} | ||
else { | ||
return reference; | ||
} | ||
return referenceArray.join(" "); | ||
}; | ||
/** | ||
* Formats the IBAN number according to the defintions | ||
* | ||
* @private | ||
* @param {string} iban string containing the IBAN number | ||
* @returns {(string | undefined)} string containing the formatted IBAN number if successfull, undefined otherwise | ||
* @memberof PDF | ||
*/ | ||
PDF.prototype._formatIBAN = function (iban) { | ||
iban = this._removeLinebreaks(iban); | ||
var ibanArray = iban.replace(/ /g, "").match(/.{1,4}/g); | ||
if (ibanArray === null) { | ||
return undefined; | ||
} | ||
return ibanArray.join(" "); | ||
}; | ||
/** | ||
* Checks if the provided IBAN is a QR-IBAN or a normal IBAN | ||
* | ||
* @private | ||
* @param {string} iban string containing the IBAN to be checked | ||
* @returns {boolean} boolean Whether the IBAN is a QR-IBAN or not | ||
* @memberof PDF | ||
*/ | ||
PDF.prototype._isQRIBAN = function (iban) { | ||
var QRIID = iban.substr(4, 5); | ||
return (+QRIID >= 30000 && +QRIID <= 31999); | ||
}; | ||
/** | ||
* Draws a rectangle which is used when data is to be filled in by hand. | ||
@@ -636,10 +833,10 @@ * | ||
account: "Compte / Payable à", | ||
reference: "Référence", | ||
reference: "Référence", | ||
additionalInformation: "Informations additionnelles", | ||
furtherInformation: "Informations supplémentaires", | ||
furtherInformation: "Informations supplémentaires", | ||
currency: "Monnaie", | ||
amount: "Montant", | ||
receipt: "Récépissé", | ||
acceptancePoint: "Point de dépôt", | ||
separate: "A détacher avant le versement", | ||
receipt: "Récépissé", | ||
acceptancePoint: "Point de dépôt", | ||
separate: "A détacher avant le versement", | ||
payableBy: "Payable par", | ||
@@ -646,0 +843,0 @@ payableByName: "Payable par (nom/adresse)", |
{ | ||
"name": "swissqrbill", | ||
"version": "1.0.4", | ||
"description": "Node implementation for the swiss QR bill", | ||
"version": "1.0.5", | ||
"description": "Swiss QR Bill generation in node.js ", | ||
"main": "./index.js", | ||
@@ -34,2 +34,3 @@ "types": "./lib/index.d.ts", | ||
"devDependencies": { | ||
"@types/iban": "0.0.30", | ||
"@types/node": "^13.7.7", | ||
@@ -46,2 +47,3 @@ "@types/pdfkit": "^0.10.5", | ||
"dependencies": { | ||
"iban": "0.0.14", | ||
"pdfkit": "^0.11.0", | ||
@@ -48,0 +50,0 @@ "qrcode-svg": "^1.1.0", |
@@ -37,2 +37,3 @@ # SwissQRBill | ||
amount: 1199.95, | ||
reference: "21 00000 00003 13947 14300 09017", | ||
creditor: { | ||
@@ -83,4 +84,4 @@ name: "Robert Schneider AG", | ||
- size - string: Either `"A4" | "A6/5"`. Default `"A6/5"`. | ||
- scissors - boolean: Wether you want to show the scissor icons or the text `Separate before paying in`. Default `true`. | ||
- autoGenerate - boolean: Wether you want to atomatically finalize the PDF. When set to false you are able to add your own content to the PDF using PDFKit. Default `true`; | ||
- scissors - boolean: Whether you want to show the scissor icons or the text `Separate before paying in`. Default `true`. | ||
- autoGenerate - boolean: Whether you want to atomatically finalize the PDF. When set to false you are able to add your own content to the PDF using PDFKit. Default `true`. | ||
@@ -117,2 +118,3 @@ #### addPage() | ||
amount: 1199.95, | ||
reference: "21 00000 00003 13947 14300 09017", | ||
creditor: { | ||
@@ -119,0 +121,0 @@ name: "Robert Schneider AG", |
55576
1077
161
5
10
+ Addediban@0.0.14
+ Addediban@0.0.14(transitive)