forked from icd/mt940-mbank-ts
Compare commits
No commits in common. "7826f1bef4650e3bdcc32e2fea12f4c1533d8196" and "76db8ce9c465a154456b5589a5c21e1248037271" have entirely different histories.
7826f1bef4
...
76db8ce9c4
15
.arcconfig
15
.arcconfig
@ -1,7 +1,12 @@
|
||||
{
|
||||
"phabricator.uri": "https://hub.sealcode.org/",
|
||||
"arc.land.onto.default": "hotwire",
|
||||
"load": ["arcanist-linters", "arc-unit-mocha/src"],
|
||||
"unit.engine": "MochaEngine",
|
||||
"unit.mocha.include": [".test/**/*.ts"]
|
||||
"phabricator.uri": "https://hub.sealcode.org/",
|
||||
"arc.land.onto.default": "hotwire",
|
||||
"load": [
|
||||
"arcanist-linters",
|
||||
"arc-unit-mocha/src"
|
||||
],
|
||||
"unit.engine": "MochaEngine",
|
||||
"unit.mocha.include": [
|
||||
".test/**/*.ts"
|
||||
]
|
||||
}
|
7
.gitignore
vendored
7
.gitignore
vendored
@ -6,8 +6,5 @@ lib
|
||||
coverage
|
||||
@types
|
||||
|
||||
public/bundle.*
|
||||
public/*.woff
|
||||
public/*.woff2
|
||||
|
||||
.DS_Store
|
||||
public/*.js
|
||||
/public/bundle.js.map
|
||||
|
25
.prettierrc
25
.prettierrc
@ -1,7 +1,22 @@
|
||||
{
|
||||
"useTabs": true,
|
||||
"tabWidth": 4,
|
||||
"trailingComma": "es5",
|
||||
"printWidth": 120,
|
||||
"htmlWhitespaceSensitivity": "ignore"
|
||||
"useTabs": true,
|
||||
"tabWidth": 4,
|
||||
"trailingComma": "es5",
|
||||
"printWidth": 100,
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.yml",
|
||||
"options": {
|
||||
"tabWidth": 2,
|
||||
"useTabs": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": "*.html",
|
||||
"options": {
|
||||
"printWidth": 120,
|
||||
"htmlWhitespaceSensitivity": "ignore"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
93
package-lock.json
generated
93
package-lock.json
generated
@ -10,7 +10,6 @@
|
||||
"hasInstallScript": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@fontsource/atkinson-hyperlegible": "^5.2.6",
|
||||
"@types/mocha": "^10.0.1",
|
||||
"@types/node": "^20.10.4",
|
||||
"@types/yargs": "^17.0.32",
|
||||
@ -25,7 +24,6 @@
|
||||
"@types/diff": "^5.2.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.58.0",
|
||||
"@typescript-eslint/parser": "^5.58.0",
|
||||
"concurrently": "^9.2.0",
|
||||
"diff": "^5.2.0",
|
||||
"eslint": "^8.38.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
@ -902,15 +900,6 @@
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fontsource/atkinson-hyperlegible": {
|
||||
"version": "5.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/atkinson-hyperlegible/-/atkinson-hyperlegible-5.2.6.tgz",
|
||||
"integrity": "sha512-Kfh6/UlHhotKuv4Oi9PXQIsmzwbtJIR442sSJnEHsO7TDZaDczK8cY0AlTNOB0XMDZj1j35nAlgbi2HZCdNg/Q==",
|
||||
"license": "OFL-1.1",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ayuhito"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
|
||||
@ -2116,48 +2105,6 @@
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/concurrently": {
|
||||
"version": "9.2.0",
|
||||
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.0.tgz",
|
||||
"integrity": "sha512-IsB/fiXTupmagMW4MNp2lx2cdSN2FfZq78vF90LBB+zZHArbIQZjQtzXCiXnvTxCZSvXanTqFLWBjw2UkLx1SQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.2",
|
||||
"lodash": "^4.17.21",
|
||||
"rxjs": "^7.8.1",
|
||||
"shell-quote": "^1.8.1",
|
||||
"supports-color": "^8.1.1",
|
||||
"tree-kill": "^1.2.2",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"bin": {
|
||||
"conc": "dist/bin/concurrently.js",
|
||||
"concurrently": "dist/bin/concurrently.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/concurrently/node_modules/supports-color": {
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
||||
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/convert-source-map": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
|
||||
@ -4525,23 +4472,6 @@
|
||||
"queue-microtask": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/rxjs": {
|
||||
"version": "7.8.2",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
|
||||
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rxjs/node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"dev": true,
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
@ -4655,19 +4585,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/shell-quote": {
|
||||
"version": "1.8.3",
|
||||
"resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz",
|
||||
"integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/side-channel": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
|
||||
@ -4835,16 +4752,6 @@
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tree-kill": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
|
||||
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"tree-kill": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-node": {
|
||||
"version": "10.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
|
||||
|
@ -7,16 +7,13 @@
|
||||
"test": "mocha",
|
||||
"build": "npm run build-node && npm run build-browser",
|
||||
"build-node": "tsc",
|
||||
"build-browser": "esbuild src/browser.ts --bundle --minify --sourcemap --target=firefox120 --outfile=public/bundle.js --loader:.woff=file --loader:.woff2=file",
|
||||
"watch-node": "tsc --watch",
|
||||
"watch-browser": "esbuild src/browser.ts --bundle --outfile=public/bundle.js --watch --loader:.woff=file --loader:.woff2=file",
|
||||
"build-browser": "esbuild src/browser.ts --bundle --minify --sourcemap --target=firefox120 --outfile=public/bundle.js",
|
||||
"postinstall": "npm run build",
|
||||
"clean-coverage": "rm -rf coverage .nyc_output .xunit",
|
||||
"coverage": "npm run clean-coverage && nyc mocha",
|
||||
"test-reports": "npm run clean-coverage && nyc --reporter clover mocha --reporter xunit --reporter-option output=.xunit",
|
||||
"coverage-html": "npm run test-reports && nyc report --reporter lcov && xdg-open coverage/lcov-report/index.html",
|
||||
"start": "http-server public -p 8080",
|
||||
"dev": "concurrently --names \"NODE,BROWSER,SERVER\" --prefix-colors \"blue,magenta,green\" \"npm run watch-node\" \"npm run watch-browser\" \"npm run start\"",
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check ."
|
||||
},
|
||||
@ -27,7 +24,6 @@
|
||||
"@types/diff": "^5.2.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.58.0",
|
||||
"@typescript-eslint/parser": "^5.58.0",
|
||||
"concurrently": "^9.2.0",
|
||||
"diff": "^5.2.0",
|
||||
"eslint": "^8.38.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
@ -42,7 +38,6 @@
|
||||
},
|
||||
"types": "./@types/index.d.ts",
|
||||
"dependencies": {
|
||||
"@fontsource/atkinson-hyperlegible": "^5.2.6",
|
||||
"@types/mocha": "^10.0.1",
|
||||
"@types/node": "^20.10.4",
|
||||
"@types/yargs": "^17.0.32",
|
||||
|
@ -4,23 +4,22 @@
|
||||
<title>mBank mt940 konwerter</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.classless.fuchsia.min.css" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.css" />
|
||||
<link rel="stylesheet" href="styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<section>
|
||||
<main>
|
||||
<header>
|
||||
<h1>mBank mt940 konwerter</h1>
|
||||
<button id="theme-toggle" type="button"></button>
|
||||
</section>
|
||||
</header>
|
||||
<main>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<p>
|
||||
Za pomocą tego narzędzia za darmo przekonwertujesz plik CSV wygenerowany przez mbank do formatu
|
||||
mt940. Konwersja odbywa się w przeglądarce, Twoje dane nie są nigdzie wysyłane. Dla pewności
|
||||
możesz na czas konwersji wyłączyć dostęp do Internetu na Twoim komputerze, zamknąć
|
||||
tę stronę, i włączyć dostęp do Internetu ponownie.
|
||||
Za pomocą tego narzędzia za darmo przekonwertujesz plik CSV wygenerowany przez mbank do formatu
|
||||
mt940. Konwersja odbywa się w przeglądarce, Twoje dane nie są nigdzie wysyłane. Dla pewności możesz
|
||||
na czas konwersji wyłączyć dostęp do Internetu na Twoim komputerze, zamknąć tę stronę, i włączyć
|
||||
dostęp do Internetu ponownie.
|
||||
</p>
|
||||
|
||||
<form>
|
||||
@ -34,7 +33,7 @@
|
||||
<div class="success hidden" role="alert">
|
||||
<p>
|
||||
<strong>Sukces!</strong>
|
||||
Rozpoczęto pobieranie wygenerowanego raportu mt940. Cieszymy się, że mogliśmy Ci oszczędzić
|
||||
Rozpoczęto pobieranie wygenerowanego raportu mt940. Cieszymy się, że mogliśmy Ci oszczędzić
|
||||
trochę wydatków. Jeżeli chcesz się nam odwdzięczyć, zachęcamy do
|
||||
<a target="_blank" href="https://www.internet-czas-dzialac.pl/contact/#wesprzyj-nas">
|
||||
wspierania naszej fundacji
|
||||
@ -42,34 +41,21 @@
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<section>
|
||||
<a target="_blank" href="https://www.internet-czas-dzialac.pl/">
|
||||
<figure id="icd-logo-container">
|
||||
<div id="icd-logo"></div>
|
||||
</figure>
|
||||
</a>
|
||||
|
||||
<footer>
|
||||
<p>
|
||||
Aplikacja została wykonana przez
|
||||
<a target="_blank" href="https://www.internet-czas-dzialac.pl/">
|
||||
Fundację „Internet. Czas działać!”
|
||||
</a>
|
||||
i jest utrzymywana przez
|
||||
i jest utrzymywana przez
|
||||
<a target="_blank" href="https://www.sealcode.it/">Sealcode</a>
|
||||
.
|
||||
</p>
|
||||
<p>
|
||||
<a target="_blank" href="https://git.internet-czas-dzialac.pl/icd/mt940-mbank-ts">Kod źródłowy</a>
|
||||
</p>
|
||||
|
||||
<small>
|
||||
Wykorzystuje czcionkę
|
||||
<a target="_blank" href="https://brailleinstitute.org/freefont">Atkinson Hyperlegible</a>
|
||||
na licencji SIL Open Font License
|
||||
</small>
|
||||
</section>
|
||||
</footer>
|
||||
</footer>
|
||||
</main>
|
||||
<script src="bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
BIN
public/logo.png
BIN
public/logo.png
Binary file not shown.
Before Width: | Height: | Size: 30 KiB |
@ -1,17 +1,6 @@
|
||||
:root {
|
||||
--pico-font-family: "Atkinson Hyperlegible", sans-serif;
|
||||
}
|
||||
|
||||
/* use to enforce styles for both themes */
|
||||
[data-theme="dark"],
|
||||
:not([data-theme="dark"]) {
|
||||
--noop: none;
|
||||
}
|
||||
|
||||
section {
|
||||
max-width: 800px;
|
||||
body {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
button {
|
||||
@ -30,13 +19,7 @@ button {
|
||||
color: hsl(120, 100%, 7.1%);
|
||||
}
|
||||
|
||||
header,
|
||||
footer {
|
||||
max-width: unset !important;
|
||||
background-color: var(--pico-modal-overlay-background-color);
|
||||
}
|
||||
|
||||
header section {
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
@ -55,25 +38,3 @@ header section {
|
||||
#theme-toggle[dark]::before {
|
||||
content: "🌙";
|
||||
}
|
||||
|
||||
#icd-logo {
|
||||
height: 50px;
|
||||
aspect-ratio: 1200/319;
|
||||
background-color: white;
|
||||
mask-image: url("logo.png");
|
||||
mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
mask-position: center;
|
||||
-webkit-mask-image: url("logo.png");
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
-webkit-mask-size: contain;
|
||||
-webkit-mask-position: center;
|
||||
}
|
||||
|
||||
figure#icd-logo-container {
|
||||
background-color: black;
|
||||
padding: 1rem;
|
||||
width: fit-content;
|
||||
margin: 0 auto 1em auto;
|
||||
border-radius: var(--pico-border-radius);
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { convert } from ".";
|
||||
import "@fontsource/atkinson-hyperlegible";
|
||||
|
||||
function download(data: string, filename: string, type: string) {
|
||||
var file = new Blob([data], { type: type });
|
||||
@ -31,7 +30,9 @@ async function handle() {
|
||||
const result = convert(string);
|
||||
download(
|
||||
result.output,
|
||||
`raport-${result.range.date_start.getFullYear()}-${(result.range.date_start.getMonth() + 1)
|
||||
`raport-${result.range.date_start.getFullYear()}-${(
|
||||
result.range.date_start.getMonth() + 1
|
||||
)
|
||||
.toString()
|
||||
.padStart(2, "0")}.mt940`,
|
||||
"text"
|
||||
|
@ -7,31 +7,47 @@ 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 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");
|
||||
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));
|
||||
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 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");
|
||||
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));
|
||||
console.log(
|
||||
Diff.createPatch("mt940", result.output, expected_result)
|
||||
);
|
||||
throw new Error("Texts differ");
|
||||
}
|
||||
});
|
||||
|
91
src/index.ts
91
src/index.ts
@ -1,4 +1,9 @@
|
||||
import { addLineNumbers, chunks, fillWithEmpty, removeRepeatingSpace } from "./utils";
|
||||
import {
|
||||
addLineNumbers,
|
||||
chunks,
|
||||
fillWithEmpty,
|
||||
removeRepeatingSpace,
|
||||
} from "./utils";
|
||||
|
||||
class Account {
|
||||
constructor(
|
||||
@ -30,12 +35,18 @@ class Transaction {
|
||||
})();
|
||||
|
||||
formatTitle() {
|
||||
return addLineNumbers(fillWithEmpty(chunks(this.title.trim(), 27), 9), 20).join("\n");
|
||||
return addLineNumbers(
|
||||
fillWithEmpty(chunks(this.title.trim(), 27), 9),
|
||||
20
|
||||
).join("\n");
|
||||
}
|
||||
|
||||
formatPerson() {
|
||||
const ret = addLineNumbers(
|
||||
fillWithEmpty(chunks(removeRepeatingSpace(this.person).trim(), 27), 2).slice(0, 2),
|
||||
fillWithEmpty(
|
||||
chunks(removeRepeatingSpace(this.person).trim(), 27),
|
||||
2
|
||||
).slice(0, 2),
|
||||
32
|
||||
).join("\n");
|
||||
return ret;
|
||||
@ -44,11 +55,26 @@ class Transaction {
|
||||
toMT940() {
|
||||
// just a bunch of heuristics
|
||||
const prefix_fns = [
|
||||
() => (this.description.includes("OPŁATA-PRZELEW WEWN.") ? "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.description.includes("OPŁATA-PRZELEW WEWN.")
|
||||
? "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",
|
||||
];
|
||||
@ -60,9 +86,11 @@ class Transaction {
|
||||
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}
|
||||
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}~00B${prefix}${this.description.slice(0, 23)}
|
||||
${this.formatTitle()}
|
||||
@ -107,7 +135,10 @@ class mBankParser extends CSVParser {
|
||||
this.parseAmount(lines[last - 2][7]),
|
||||
lines[18][0]
|
||||
);
|
||||
const range = new Range(this.parseDate(lines[14][0]), this.parseDate(lines[14][1]));
|
||||
const range = new Range(
|
||||
this.parseDate(lines[14][0]),
|
||||
this.parseDate(lines[14][1])
|
||||
);
|
||||
const transactions = [];
|
||||
for (let i = 38; i <= last - 5; i++) {
|
||||
const line = lines[i];
|
||||
@ -117,14 +148,29 @@ class mBankParser extends CSVParser {
|
||||
}
|
||||
if (line.length != 9) {
|
||||
console.log({ line });
|
||||
throw new Error("Wrong amount of columns! maybe a semicolon got stuck in a transaction description?");
|
||||
throw new Error(
|
||||
"Wrong amount of columns! maybe a semicolon got stuck in a transaction description?"
|
||||
);
|
||||
}
|
||||
const date_acc = new Date(line[0]);
|
||||
const date_op = new Date(line[1]);
|
||||
const [description, title, person, account_number] = line.slice(2).map(this.trimString);
|
||||
const [amount, balance_after] = line.slice(6).map((s) => this.parseAmount(s));
|
||||
const [description, title, person, account_number] = line
|
||||
.slice(2)
|
||||
.map(this.trimString);
|
||||
const [amount, balance_after] = line
|
||||
.slice(6)
|
||||
.map((s) => this.parseAmount(s));
|
||||
transactions.push(
|
||||
new Transaction(date_acc, date_op, description, title, person, account_number, amount, balance_after)
|
||||
new Transaction(
|
||||
date_acc,
|
||||
date_op,
|
||||
description,
|
||||
title,
|
||||
person,
|
||||
account_number,
|
||||
amount,
|
||||
balance_after
|
||||
)
|
||||
);
|
||||
}
|
||||
return { account, range, transactions };
|
||||
@ -154,10 +200,9 @@ class mBankParser extends CSVParser {
|
||||
}
|
||||
|
||||
function mtDate(d: Date) {
|
||||
return `${d.getFullYear() - 2000}${(d.getMonth() + 1).toString().padStart(2, "0")}${d
|
||||
.getDate()
|
||||
return `${d.getFullYear() - 2000}${(d.getMonth() + 1)
|
||||
.toString()
|
||||
.padStart(2, "0")}`;
|
||||
.padStart(2, "0")}${d.getDate().toString().padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
function mtAmount(n: number) {
|
||||
@ -170,8 +215,12 @@ export function convert(csv_utf8: string): { output: string; range: Range } {
|
||||
const string = `:20:MT940
|
||||
:25:/PL${account.number.replaceAll(/[^0-9]/g, "")}
|
||||
:28C:${mtDate(range.date_start)}
|
||||
:60F:D${mtDate(range.date_start)}${account.currency}${mtAmount(account.initial_balance)}
|
||||
:60F:D${mtDate(range.date_start)}${account.currency}${mtAmount(
|
||||
account.initial_balance
|
||||
)}
|
||||
${transactions.map((t) => t.toMT940()).join("\n")}
|
||||
:62F:D${mtDate(range.date_end)}${account.currency}${mtAmount(account.closing_balance)}`;
|
||||
:62F:D${mtDate(range.date_end)}${account.currency}${mtAmount(
|
||||
account.closing_balance
|
||||
)}`;
|
||||
return { output: string, range };
|
||||
}
|
||||
|
@ -15,7 +15,11 @@ export function fillWithEmpty(array: string[], target_length: number) {
|
||||
return a;
|
||||
}
|
||||
|
||||
export function addLineNumbers(s: string[], start_num: number, prefix = "~"): string[] {
|
||||
export function addLineNumbers(
|
||||
s: string[],
|
||||
start_num: number,
|
||||
prefix = "~"
|
||||
): string[] {
|
||||
return s.map((l, i) => `${prefix}${start_num + i}${l}`);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user