Differentiate credits and debts
This commit is contained in:
parent
06c08ef93b
commit
9fb888c59d
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -7,3 +7,4 @@ coverage
|
||||||
@types
|
@types
|
||||||
|
|
||||||
public/*.js
|
public/*.js
|
||||||
|
/public/bundle.js.map
|
||||||
|
|
27
package-lock.json
generated
27
package-lock.json
generated
|
@ -7,6 +7,7 @@
|
||||||
"": {
|
"": {
|
||||||
"name": "mbank-mt940",
|
"name": "mbank-mt940",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
|
"hasInstallScript": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/mocha": "^10.0.1",
|
"@types/mocha": "^10.0.1",
|
||||||
|
@ -20,8 +21,10 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@istanbuljs/nyc-config-typescript": "^1.0.2",
|
"@istanbuljs/nyc-config-typescript": "^1.0.2",
|
||||||
|
"@types/diff": "^5.2.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.58.0",
|
"@typescript-eslint/eslint-plugin": "^5.58.0",
|
||||||
"@typescript-eslint/parser": "^5.58.0",
|
"@typescript-eslint/parser": "^5.58.0",
|
||||||
|
"diff": "^5.2.0",
|
||||||
"eslint": "^8.38.0",
|
"eslint": "^8.38.0",
|
||||||
"eslint-config-prettier": "^8.8.0",
|
"eslint-config-prettier": "^8.8.0",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
|
@ -1144,6 +1147,13 @@
|
||||||
"integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
|
"integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/diff": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-uxpcuwWJGhe2AR1g8hD9F5OYGCqjqWnBUQFD8gMZsDbv8oPHzxJF6iMO6n8Tk0AdzlxoaaoQhOYlIg/PukVU8g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/json-schema": {
|
"node_modules/@types/json-schema": {
|
||||||
"version": "7.0.11",
|
"version": "7.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
|
||||||
|
@ -2190,10 +2200,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/diff": {
|
"node_modules/diff": {
|
||||||
"version": "5.0.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz",
|
||||||
"integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
|
"integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.3.1"
|
"node": ">=0.3.1"
|
||||||
}
|
}
|
||||||
|
@ -3696,6 +3707,16 @@
|
||||||
"wrap-ansi": "^7.0.0"
|
"wrap-ansi": "^7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mocha/node_modules/diff": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mocha/node_modules/js-yaml": {
|
"node_modules/mocha/node_modules/js-yaml": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||||
|
|
|
@ -19,8 +19,10 @@
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@istanbuljs/nyc-config-typescript": "^1.0.2",
|
"@istanbuljs/nyc-config-typescript": "^1.0.2",
|
||||||
|
"@types/diff": "^5.2.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.58.0",
|
"@typescript-eslint/eslint-plugin": "^5.58.0",
|
||||||
"@typescript-eslint/parser": "^5.58.0",
|
"@typescript-eslint/parser": "^5.58.0",
|
||||||
|
"diff": "^5.2.0",
|
||||||
"eslint": "^8.38.0",
|
"eslint": "^8.38.0",
|
||||||
"eslint-config-prettier": "^8.8.0",
|
"eslint-config-prettier": "^8.8.0",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
|
@ -40,7 +42,7 @@
|
||||||
"esbuild": "^0.19.9",
|
"esbuild": "^0.19.9",
|
||||||
"http-server": "^14.1.1",
|
"http-server": "^14.1.1",
|
||||||
"iconv-lite": "^0.6.3",
|
"iconv-lite": "^0.6.3",
|
||||||
"yargs": "^17.7.2",
|
"typescript": "^5.0.4",
|
||||||
"typescript": "^5.0.4"
|
"yargs": "^17.7.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
54
src/index.test.ts
Normal file
54
src/index.test.ts
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import { promises as fs } from "fs";
|
||||||
|
import path from "node:path";
|
||||||
|
import iconv from "iconv-lite";
|
||||||
|
import { convert } from ".";
|
||||||
|
import assert from "node:assert";
|
||||||
|
import * as Diff from "diff";
|
||||||
|
|
||||||
|
describe("mt940 converter", () => {
|
||||||
|
it("converts properly", async () => {
|
||||||
|
const content = await fs.readFile(
|
||||||
|
path.resolve(__dirname, "../tests/real_csv.csv"),
|
||||||
|
{
|
||||||
|
encoding: null,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const result = convert(iconv.decode(content, "cp1250"));
|
||||||
|
const expected_result = await fs.readFile(
|
||||||
|
path.resolve(__dirname, "../tests/real_mt940.txt"),
|
||||||
|
"utf-8"
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
assert.strictEqual(result.output, expected_result);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("There was a difference. Fixes to apply:");
|
||||||
|
console.log(
|
||||||
|
Diff.createPatch("mt940", result.output, expected_result)
|
||||||
|
);
|
||||||
|
throw new Error("Texts differ");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it.only("converts properly", async () => {
|
||||||
|
const content = await fs.readFile(
|
||||||
|
path.resolve(__dirname, "../tests/real_csv_2.csv"),
|
||||||
|
{
|
||||||
|
encoding: null,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const result = convert(iconv.decode(content, "cp1250"));
|
||||||
|
const expected_result = await fs.readFile(
|
||||||
|
path.resolve(__dirname, "../tests/real_mt940_2.txt"),
|
||||||
|
"utf-8"
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
assert.strictEqual(result.output, expected_result);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("There was a difference. Fixes to apply:");
|
||||||
|
console.log(
|
||||||
|
Diff.createPatch("mt940", result.output, expected_result)
|
||||||
|
);
|
||||||
|
throw new Error("Texts differ");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
49
src/index.ts
49
src/index.ts
|
@ -42,21 +42,55 @@ class Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
formatPerson() {
|
formatPerson() {
|
||||||
return addLineNumbers(
|
const ret = addLineNumbers(
|
||||||
fillWithEmpty(
|
fillWithEmpty(
|
||||||
chunks(removeRepeatingSpace(this.person).trim(), 27),
|
chunks(removeRepeatingSpace(this.person).trim(), 27),
|
||||||
2
|
2
|
||||||
).slice(0, 2),
|
).slice(0, 2),
|
||||||
32
|
32
|
||||||
).join("\n");
|
).join("\n");
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
toMT940() {
|
toMT940() {
|
||||||
const prefixes = { incoming: "150", outcoming: "169" };
|
// just a bunch of heuristics
|
||||||
const prefix = this.amount > 0 ? prefixes.incoming : prefixes.outcoming;
|
const prefix_fns = [
|
||||||
return `:61:${mtDate(this.acc_date)}${mtDate(this.op_date).slice(
|
() =>
|
||||||
2
|
this.description.includes("OPŁATA-PRZELEW WEWN.")
|
||||||
)}C${mtAmount(this.amount)}S${prefix}${Transaction.counter.next().value}
|
? "169"
|
||||||
|
: false,
|
||||||
|
() =>
|
||||||
|
this.description.includes("PRZELEW WEWNĘTRZNY PRZY")
|
||||||
|
? "160"
|
||||||
|
: false,
|
||||||
|
() =>
|
||||||
|
this.description.includes("OPŁATA-PRZELEW WEWN. DO")
|
||||||
|
? "755"
|
||||||
|
: false,
|
||||||
|
() =>
|
||||||
|
this.description.includes("PRZELEW ZEWNĘTRZNY WYCH")
|
||||||
|
? "152"
|
||||||
|
: false,
|
||||||
|
() =>
|
||||||
|
this.description.includes("OPŁATA PRZELEW ZEW.DOWO")
|
||||||
|
? "771"
|
||||||
|
: false,
|
||||||
|
() => (this.amount > 0 ? "150" : false),
|
||||||
|
() => "169",
|
||||||
|
];
|
||||||
|
let prefix = "";
|
||||||
|
for (const fn of prefix_fns) {
|
||||||
|
const result = fn();
|
||||||
|
if (result !== false) {
|
||||||
|
prefix = result;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = `:61:${mtDate(this.acc_date)}${mtDate(
|
||||||
|
this.op_date
|
||||||
|
).slice(2)}${this.amount > 0 ? "C" : "D"}${mtAmount(
|
||||||
|
this.amount
|
||||||
|
)}S${prefix}${Transaction.counter.next().value}
|
||||||
:86:${prefix}
|
:86:${prefix}
|
||||||
:86:${prefix}~00B${prefix}${this.description.slice(0, 23)}
|
:86:${prefix}~00B${prefix}${this.description.slice(0, 23)}
|
||||||
${this.formatTitle()}
|
${this.formatTitle()}
|
||||||
|
@ -68,6 +102,7 @@ ${this.formatPerson()}
|
||||||
~38PL${this.account_number}
|
~38PL${this.account_number}
|
||||||
~62
|
~62
|
||||||
~63`;
|
~63`;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +201,7 @@ function mtDate(d: Date) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function mtAmount(n: number) {
|
function mtAmount(n: number) {
|
||||||
return Math.abs(n).toString().replace(".", ",");
|
return Math.abs(n).toFixed(2).replace(".", ",");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convert(csv_utf8: string): { output: string; range: Range } {
|
export function convert(csv_utf8: string): { output: string; range: Range } {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user