feat(core): Add support for CI workflows and update gitignore
This commit is contained in:
commit
7fc8f04be9
66
.gitea/workflows/default_nottags.yaml
Normal file
66
.gitea/workflows/default_nottags.yaml
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
name: Default (not tags)
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags-ignore:
|
||||||
|
- '**'
|
||||||
|
|
||||||
|
env:
|
||||||
|
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||||
|
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
|
||||||
|
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
||||||
|
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
||||||
|
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
||||||
|
NPMCI_URL_CLOUDLY: ${{secrets.NPMCI_URL_CLOUDLY}}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
security:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
continue-on-error: true
|
||||||
|
container:
|
||||||
|
image: ${{ env.IMAGE }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install pnpm and npmci
|
||||||
|
run: |
|
||||||
|
pnpm install -g pnpm
|
||||||
|
pnpm install -g @shipzone/npmci
|
||||||
|
|
||||||
|
- name: Run npm prepare
|
||||||
|
run: npmci npm prepare
|
||||||
|
|
||||||
|
- name: Audit production dependencies
|
||||||
|
run: |
|
||||||
|
npmci command npm config set registry https://registry.npmjs.org
|
||||||
|
npmci command pnpm audit --audit-level=high --prod
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
- name: Audit development dependencies
|
||||||
|
run: |
|
||||||
|
npmci command npm config set registry https://registry.npmjs.org
|
||||||
|
npmci command pnpm audit --audit-level=high --dev
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
test:
|
||||||
|
if: ${{ always() }}
|
||||||
|
needs: security
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: ${{ env.IMAGE }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Test stable
|
||||||
|
run: |
|
||||||
|
npmci node install stable
|
||||||
|
npmci npm install
|
||||||
|
npmci npm test
|
||||||
|
|
||||||
|
- name: Test build
|
||||||
|
run: |
|
||||||
|
npmci node install stable
|
||||||
|
npmci npm install
|
||||||
|
npmci npm build
|
124
.gitea/workflows/default_tags.yaml
Normal file
124
.gitea/workflows/default_tags.yaml
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
name: Default (tags)
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
env:
|
||||||
|
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||||
|
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
|
||||||
|
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
||||||
|
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
||||||
|
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
||||||
|
NPMCI_URL_CLOUDLY: ${{secrets.NPMCI_URL_CLOUDLY}}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
security:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
continue-on-error: true
|
||||||
|
container:
|
||||||
|
image: ${{ env.IMAGE }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Prepare
|
||||||
|
run: |
|
||||||
|
pnpm install -g pnpm
|
||||||
|
pnpm install -g @shipzone/npmci
|
||||||
|
npmci npm prepare
|
||||||
|
|
||||||
|
- name: Audit production dependencies
|
||||||
|
run: |
|
||||||
|
npmci command npm config set registry https://registry.npmjs.org
|
||||||
|
npmci command pnpm audit --audit-level=high --prod
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
- name: Audit development dependencies
|
||||||
|
run: |
|
||||||
|
npmci command npm config set registry https://registry.npmjs.org
|
||||||
|
npmci command pnpm audit --audit-level=high --dev
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
test:
|
||||||
|
if: ${{ always() }}
|
||||||
|
needs: security
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: ${{ env.IMAGE }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Prepare
|
||||||
|
run: |
|
||||||
|
pnpm install -g pnpm
|
||||||
|
pnpm install -g @shipzone/npmci
|
||||||
|
npmci npm prepare
|
||||||
|
|
||||||
|
- name: Test stable
|
||||||
|
run: |
|
||||||
|
npmci node install stable
|
||||||
|
npmci npm install
|
||||||
|
npmci npm test
|
||||||
|
|
||||||
|
- name: Test build
|
||||||
|
run: |
|
||||||
|
npmci node install stable
|
||||||
|
npmci npm install
|
||||||
|
npmci npm build
|
||||||
|
|
||||||
|
release:
|
||||||
|
needs: test
|
||||||
|
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: ${{ env.IMAGE }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Prepare
|
||||||
|
run: |
|
||||||
|
pnpm install -g pnpm
|
||||||
|
pnpm install -g @shipzone/npmci
|
||||||
|
npmci npm prepare
|
||||||
|
|
||||||
|
- name: Release
|
||||||
|
run: |
|
||||||
|
npmci node install stable
|
||||||
|
npmci npm publish
|
||||||
|
|
||||||
|
metadata:
|
||||||
|
needs: test
|
||||||
|
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: ${{ env.IMAGE }}
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Prepare
|
||||||
|
run: |
|
||||||
|
pnpm install -g pnpm
|
||||||
|
pnpm install -g @shipzone/npmci
|
||||||
|
npmci npm prepare
|
||||||
|
|
||||||
|
- name: Code quality
|
||||||
|
run: |
|
||||||
|
npmci command npm install -g typescript
|
||||||
|
npmci npm install
|
||||||
|
|
||||||
|
- name: Trigger
|
||||||
|
run: npmci trigger
|
||||||
|
|
||||||
|
- name: Build docs and upload artifacts
|
||||||
|
run: |
|
||||||
|
npmci node install stable
|
||||||
|
npmci npm install
|
||||||
|
pnpm install -g @git.zone/tsdoc
|
||||||
|
npmci command tsdoc
|
||||||
|
continue-on-error: true
|
20
.gitignore
vendored
Normal file
20
.gitignore
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
.nogit/
|
||||||
|
|
||||||
|
# artifacts
|
||||||
|
coverage/
|
||||||
|
public/
|
||||||
|
pages/
|
||||||
|
|
||||||
|
# installs
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# caches
|
||||||
|
.yarn/
|
||||||
|
.cache/
|
||||||
|
.rpt2_cache
|
||||||
|
|
||||||
|
# builds
|
||||||
|
dist/
|
||||||
|
dist_*/
|
||||||
|
|
||||||
|
# custom
|
138
.gitlab-ci.yml
Normal file
138
.gitlab-ci.yml
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
# gitzone ci_default_private
|
||||||
|
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||||
|
|
||||||
|
cache:
|
||||||
|
paths:
|
||||||
|
- .npmci_cache/
|
||||||
|
key: '$CI_BUILD_STAGE'
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- security
|
||||||
|
- test
|
||||||
|
- release
|
||||||
|
- metadata
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- npm install -g @shipzone/npmci
|
||||||
|
|
||||||
|
# ====================
|
||||||
|
# security stage
|
||||||
|
# ====================
|
||||||
|
|
||||||
|
auditProductionDependencies:
|
||||||
|
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||||
|
stage: security
|
||||||
|
script:
|
||||||
|
- npmci npm prepare
|
||||||
|
- npmci command npm install --production --ignore-scripts
|
||||||
|
- npmci command npm config set registry https://registry.npmjs.org
|
||||||
|
- npmci command npm audit --audit-level=high --only=prod --production
|
||||||
|
tags:
|
||||||
|
- metadatacompany
|
||||||
|
- docker
|
||||||
|
allow_failure: true
|
||||||
|
|
||||||
|
auditDevDependencies:
|
||||||
|
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||||
|
stage: security
|
||||||
|
script:
|
||||||
|
- npmci npm prepare
|
||||||
|
- npmci command npm install --ignore-scripts
|
||||||
|
- npmci command npm config set registry https://registry.npmjs.org
|
||||||
|
- npmci command npm audit --audit-level=high --only=dev
|
||||||
|
tags:
|
||||||
|
- metadatacompany
|
||||||
|
- docker
|
||||||
|
allow_failure: true
|
||||||
|
|
||||||
|
# ====================
|
||||||
|
# test stage
|
||||||
|
# ====================
|
||||||
|
|
||||||
|
testStable:
|
||||||
|
stage: test
|
||||||
|
script:
|
||||||
|
- npmci npm prepare
|
||||||
|
- npmci node install stable
|
||||||
|
- npmci npm install
|
||||||
|
- npmci npm test
|
||||||
|
coverage: /\d+.?\d+?\%\s*coverage/
|
||||||
|
tags:
|
||||||
|
- metadatacompany
|
||||||
|
- docker
|
||||||
|
|
||||||
|
|
||||||
|
testBuild:
|
||||||
|
stage: test
|
||||||
|
script:
|
||||||
|
- npmci npm prepare
|
||||||
|
- npmci node install stable
|
||||||
|
- npmci npm install
|
||||||
|
- npmci command npm run build
|
||||||
|
coverage: /\d+.?\d+?\%\s*coverage/
|
||||||
|
tags:
|
||||||
|
- metadatacompany
|
||||||
|
- docker
|
||||||
|
|
||||||
|
|
||||||
|
release:
|
||||||
|
stage: release
|
||||||
|
script:
|
||||||
|
- npmci npm prepare
|
||||||
|
- npmci node install stable
|
||||||
|
- npmci npm publish
|
||||||
|
only:
|
||||||
|
- tags
|
||||||
|
tags:
|
||||||
|
- metadatacompany
|
||||||
|
- docker
|
||||||
|
|
||||||
|
|
||||||
|
# ====================
|
||||||
|
# metadata stage
|
||||||
|
# ====================
|
||||||
|
codequality:
|
||||||
|
stage: metadata
|
||||||
|
allow_failure: true
|
||||||
|
only:
|
||||||
|
- tags
|
||||||
|
script:
|
||||||
|
- npmci command npm install -g tslint typescript
|
||||||
|
- npmci npm prepare
|
||||||
|
- npmci npm install
|
||||||
|
- npmci command "tslint -c tslint.json ./ts/**/*.ts"
|
||||||
|
tags:
|
||||||
|
- metadatacompany
|
||||||
|
- docker
|
||||||
|
- priv
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
stage: metadata
|
||||||
|
script:
|
||||||
|
- npmci trigger
|
||||||
|
only:
|
||||||
|
- tags
|
||||||
|
tags:
|
||||||
|
- metadatacompany
|
||||||
|
- docker
|
||||||
|
|
||||||
|
|
||||||
|
pages:
|
||||||
|
stage: metadata
|
||||||
|
script:
|
||||||
|
- npmci node install lts
|
||||||
|
- npmci command npm install -g @gitzone/tsdoc
|
||||||
|
- npmci npm prepare
|
||||||
|
- npmci npm install
|
||||||
|
- npmci command tsdoc
|
||||||
|
tags:
|
||||||
|
- metadatacompany
|
||||||
|
- docker
|
||||||
|
|
||||||
|
only:
|
||||||
|
- tags
|
||||||
|
artifacts:
|
||||||
|
expire_in: 1 week
|
||||||
|
paths:
|
||||||
|
- public
|
||||||
|
allow_failure: true
|
11
.vscode/launch.json
vendored
Normal file
11
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"command": "npm test",
|
||||||
|
"name": "Run npm test",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "node-terminal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
26
.vscode/settings.json
vendored
Normal file
26
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"json.schemas": [
|
||||||
|
{
|
||||||
|
"fileMatch": ["/npmextra.json"],
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"npmci": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "settings for npmci"
|
||||||
|
},
|
||||||
|
"gitzone": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "settings for gitzone",
|
||||||
|
"properties": {
|
||||||
|
"projectType": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["website", "element", "service", "npm", "wcc"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
51
changelog.md
Normal file
51
changelog.md
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 2024-07-05 - 1.1.0 - feat(core)
|
||||||
|
Add support for CI workflows and update gitignore
|
||||||
|
|
||||||
|
- Added `.gitea/workflows/default_nottags.yaml` for non-tag workflows.
|
||||||
|
- Added `.gitea/workflows/default_tags.yaml` for tag workflows.
|
||||||
|
- Updated `.gitignore` to include standard and custom ignore rules.
|
||||||
|
- Added `.gitlab-ci.yml` for GitLab CI/CD integration.
|
||||||
|
- Added `.npmrc` with a custom registry URL.
|
||||||
|
- Added VSCode configuration files for debugging and settings.
|
||||||
|
- Added `changelog.md` to document project changes.
|
||||||
|
- Added `license` file with MIT License.
|
||||||
|
- Updated scripts in `package.json` for building, testing, and documentation.
|
||||||
|
- Added test file `test/test.ts`.
|
||||||
|
- Added core CSV parsing files and structures for Spendesk, PayPal, Fidor, and Commerzbank.
|
||||||
|
|
||||||
|
## 2024-07-02 - 1.0.9 - fix(core)
|
||||||
|
No changes detected
|
||||||
|
|
||||||
|
|
||||||
|
## 2023-11-17 - 1.0.8 - Core
|
||||||
|
Main version update
|
||||||
|
|
||||||
|
- Miscellaneous fixes
|
||||||
|
|
||||||
|
## 2023-11-17 - 1.0.7 - Core
|
||||||
|
Minor fixes
|
||||||
|
|
||||||
|
- Core update
|
||||||
|
|
||||||
|
## 2023-11-17 - 1.0.6 - Core
|
||||||
|
Minor fixes
|
||||||
|
|
||||||
|
- Core update
|
||||||
|
|
||||||
|
## 2022-01-03 - 1.0.5 to 1.0.6 - Core
|
||||||
|
Multiple minor fixes and updates
|
||||||
|
|
||||||
|
- Core updates
|
||||||
|
|
||||||
|
## 2022-01-03 - 1.0.4 - Core
|
||||||
|
Minor fixes
|
||||||
|
|
||||||
|
- Core update
|
||||||
|
|
||||||
|
## 2022-01-03 - 1.0.3 - Commerzbank
|
||||||
|
Commerzbank specific fix
|
||||||
|
|
||||||
|
- Fixed Commerzbank to comply with spec
|
||||||
|
|
19
license
Normal file
19
license
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2022 Lossless GmbH (hello@lossless.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
32
npmextra.json
Normal file
32
npmextra.json
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"gitzone": {
|
||||||
|
"projectType": "npm",
|
||||||
|
"module": {
|
||||||
|
"githost": "gitlab.com",
|
||||||
|
"gitscope": "fin.cx",
|
||||||
|
"gitrepo": "csvparser",
|
||||||
|
"description": "A TypeScript-based parser for CSV files from various financial service providers.",
|
||||||
|
"npmPackagename": "@fin.cx/csvparser",
|
||||||
|
"license": "MIT",
|
||||||
|
"projectDomain": "fin.cx",
|
||||||
|
"keywords": [
|
||||||
|
"CSV",
|
||||||
|
"parser",
|
||||||
|
"finance",
|
||||||
|
"TypeScript",
|
||||||
|
"PayPal",
|
||||||
|
"Spendesk",
|
||||||
|
"Commerzbank",
|
||||||
|
"Fidor",
|
||||||
|
"financial data",
|
||||||
|
"data processing",
|
||||||
|
"import",
|
||||||
|
"export"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"npmci": {
|
||||||
|
"npmGlobalTools": [],
|
||||||
|
"npmAccessLevel": "private"
|
||||||
|
}
|
||||||
|
}
|
70
package.json
Normal file
70
package.json
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"name": "@fin.cx/csvparser",
|
||||||
|
"version": "1.0.9",
|
||||||
|
"private": false,
|
||||||
|
"description": "A TypeScript-based parser for CSV files from various financial service providers.",
|
||||||
|
"main": "dist_ts/index.js",
|
||||||
|
"typings": "dist_ts/index.d.ts",
|
||||||
|
"author": "Lossless GmbH",
|
||||||
|
"license": "UNLICENSED",
|
||||||
|
"scripts": {
|
||||||
|
"test": "(tstest test/ --web)",
|
||||||
|
"build": "(tsbuild --web)",
|
||||||
|
"buildDocs": "tsdoc"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@gitzone/tsbuild": "^2.1.25",
|
||||||
|
"@gitzone/tsbundle": "^2.0.8",
|
||||||
|
"@gitzone/tstest": "^1.0.44",
|
||||||
|
"@push.rocks/tapbundle": "^5.0.8",
|
||||||
|
"@types/node": "^20.9.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@fin.cx/portablefinance": "^1.0.25",
|
||||||
|
"@push.rocks/smartcsv": "^2.0.2",
|
||||||
|
"@push.rocks/smartfile": "^11.0.0",
|
||||||
|
"@push.rocks/smarthash": "^3.0.2",
|
||||||
|
"@push.rocks/smartmoney": "^1.0.6",
|
||||||
|
"@push.rocks/smartstring": "^4.0.7",
|
||||||
|
"@push.rocks/smarttime": "^4.0.1",
|
||||||
|
"@tsclass/tsclass": "^4.0.46"
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"last 1 chrome versions"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
"ts/**/*",
|
||||||
|
"ts_web/**/*",
|
||||||
|
"dist/**/*",
|
||||||
|
"dist_*/**/*",
|
||||||
|
"dist_ts/**/*",
|
||||||
|
"dist_ts_web/**/*",
|
||||||
|
"assets/**/*",
|
||||||
|
"cli.js",
|
||||||
|
"npmextra.json",
|
||||||
|
"readme.md"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://gitlab.com/fin.cx/csvparser.git"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://gitlab.com/fin.cx/csvparser/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://gitlab.com/fin.cx/csvparser#readme",
|
||||||
|
"type": "module",
|
||||||
|
"keywords": [
|
||||||
|
"CSV",
|
||||||
|
"parser",
|
||||||
|
"finance",
|
||||||
|
"TypeScript",
|
||||||
|
"PayPal",
|
||||||
|
"Spendesk",
|
||||||
|
"Commerzbank",
|
||||||
|
"Fidor",
|
||||||
|
"financial data",
|
||||||
|
"data processing",
|
||||||
|
"import",
|
||||||
|
"export"
|
||||||
|
]
|
||||||
|
}
|
5756
pnpm-lock.yaml
generated
Normal file
5756
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
0
readme.hints.md
Normal file
0
readme.hints.md
Normal file
258
readme.md
Normal file
258
readme.md
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
```markdown
|
||||||
|
# @fin.cx/csvparser
|
||||||
|
a csvparser for fin2021
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
To install the `@fin.cx/csvparser` module, you can use npm. Simply run the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @fin.cx/csvparser
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
The `@fin.cx/csvparser` module provides tools to parse CSV files from various financial institutions such as Commerzbank, Fidor Bank, PayPal, and Spendesk. This helps in extracting and managing financial transaction data efficiently.
|
||||||
|
|
||||||
|
Here's a guide to showcase various functionalities along with comprehensive TypeScript code examples.
|
||||||
|
|
||||||
|
### Getting Started
|
||||||
|
|
||||||
|
First, make sure to import the necessary components from the `@fin.cx/csvparser` module.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { CsvSpendesk, CsvPayPal, CsvFidor, CsvCommerzbank } from '@fin.cx/csvparser';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Spendesk CSV Parsing
|
||||||
|
|
||||||
|
#### Parsing Spendesk CSV from File
|
||||||
|
|
||||||
|
The `CsvSpendesk` class provides methods to parse Spendesk CSV files.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { CsvSpendesk } from '@fin.cx/csvparser';
|
||||||
|
|
||||||
|
async function parseSpendeskFile(filePath: string) {
|
||||||
|
try {
|
||||||
|
const spendeskData = await CsvSpendesk.fromFile(filePath);
|
||||||
|
const transactions = await spendeskData.getTransactions();
|
||||||
|
console.log(transactions);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error parsing Spendesk file:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage example
|
||||||
|
parseSpendeskFile('./path/to/spendesk.csv');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Parsing Spendesk CSV from Directory
|
||||||
|
|
||||||
|
You might have multiple Spendesk CSV files in a directory. The `fromDir` method helps in parsing all of them.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { CsvSpendesk } from '@fin.cx/csvparser';
|
||||||
|
|
||||||
|
async function parseSpendeskDirectory(dirPath: string) {
|
||||||
|
try {
|
||||||
|
const spendeskData = await CsvSpendesk.fromDir(dirPath);
|
||||||
|
const transactions = await spendeskData.getTransactions();
|
||||||
|
console.log(transactions);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error parsing Spendesk directory:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage example
|
||||||
|
parseSpendeskDirectory('./path/to/spendesk_dir');
|
||||||
|
```
|
||||||
|
|
||||||
|
### PayPal CSV Parsing
|
||||||
|
|
||||||
|
The `CsvPayPal` class is used to parse PayPal CSV files.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { CsvPayPal } from '@fin.cx/csvparser';
|
||||||
|
|
||||||
|
async function parsePayPalFile(filePath: string) {
|
||||||
|
try {
|
||||||
|
const payPalData = new CsvPayPal();
|
||||||
|
const csvDescriptor = {
|
||||||
|
filename: 'paypal.csv',
|
||||||
|
contentString: await fs.promises.readFile(filePath, 'utf8')
|
||||||
|
}
|
||||||
|
payPalData.addCsvDecriptor(csvDescriptor);
|
||||||
|
const transactions = await payPalData.getTransactions();
|
||||||
|
console.log(transactions);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error parsing PayPal file:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage example
|
||||||
|
parsePayPalFile('./path/to/paypal.csv');
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fidor Bank CSV Parsing
|
||||||
|
|
||||||
|
The `CsvFidor` class is used to parse Fidor Bank CSV files.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { CsvFidor } from '@fin.cx/csvparser';
|
||||||
|
|
||||||
|
async function parseFidorFile(filePath: string) {
|
||||||
|
try {
|
||||||
|
const fidorData = new CsvFidor();
|
||||||
|
const csvDescriptor = {
|
||||||
|
filename: 'fidor.csv',
|
||||||
|
contentString: await fs.promises.readFile(filePath, 'utf8')
|
||||||
|
}
|
||||||
|
fidorData.addCsvDecriptor(csvDescriptor);
|
||||||
|
const transactions = await fidorData.getTransactions();
|
||||||
|
console.log(transactions);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error parsing Fidor file:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage example
|
||||||
|
parseFidorFile('./path/to/fidor.csv');
|
||||||
|
```
|
||||||
|
|
||||||
|
### Commerzbank CSV Parsing
|
||||||
|
|
||||||
|
The `CsvCommerzbank` class is used to parse Commerzbank CSV files.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { CsvCommerzbank } from '@fin.cx/csvparser';
|
||||||
|
|
||||||
|
async function parseCommerzbankFile(filePath: string) {
|
||||||
|
try {
|
||||||
|
const commerzbankData = new CsvCommerzbank();
|
||||||
|
const csvDescriptor = {
|
||||||
|
filename: 'commerzbank.csv',
|
||||||
|
contentString: await fs.promises.readFile(filePath, 'utf8')
|
||||||
|
}
|
||||||
|
commerzbankData.addCsvDecriptor(csvDescriptor);
|
||||||
|
const transactions = await commerzbankData.getTransactions();
|
||||||
|
console.log(transactions);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error parsing Commerzbank file:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage example
|
||||||
|
parseCommerzbankFile('./path/to/commerzbank.csv');
|
||||||
|
```
|
||||||
|
|
||||||
|
### Advanced Usage
|
||||||
|
|
||||||
|
#### Merging Spendesk Data
|
||||||
|
|
||||||
|
You may need to merge multiple Spendesk CSV data instances.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { CsvSpendesk } from '@fin.cx/csvparser';
|
||||||
|
|
||||||
|
async function mergeSpendeskData(filePaths: string[]) {
|
||||||
|
try {
|
||||||
|
const spendeskInstances = await Promise.all(filePaths.map(CsvSpendesk.fromFile));
|
||||||
|
const mergedInstance = spendeskInstances.reduce(
|
||||||
|
(merged, currentInstance) => merged.concat(currentInstance),
|
||||||
|
spendeskInstances[0]
|
||||||
|
);
|
||||||
|
console.log(await mergedInstance.getTransactions());
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error merging Spendesk data:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage example
|
||||||
|
mergeSpendeskData([
|
||||||
|
'./path/to/spendesk1.csv',
|
||||||
|
'./path/to/spendesk2.csv'
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Working with PayPal Linked Transactions
|
||||||
|
|
||||||
|
PayPal CSV data contains linked transactions, which you may need to handle specifically.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { CsvPayPal } from '@fin.cx/csvparser';
|
||||||
|
|
||||||
|
async function handlePayPalLinkedTransactions(filePath: string) {
|
||||||
|
try {
|
||||||
|
const payPalData = new CsvPayPal();
|
||||||
|
const csvDescriptor = {
|
||||||
|
filename: 'paypal.csv',
|
||||||
|
contentString: await fs.promises.readFile(filePath, 'utf8')
|
||||||
|
}
|
||||||
|
payPalData.addCsvDecriptor(csvDescriptor);
|
||||||
|
const transactions = await payPalData.getTransactions();
|
||||||
|
|
||||||
|
const linkedTransactions = transactions.filter(tx => tx.linkedTransactionCode);
|
||||||
|
console.log(linkedTransactions);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error handling linked transactions:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage example
|
||||||
|
handlePayPalLinkedTransactions('./path/to/paypal.csv');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Parsing Multiple File Types
|
||||||
|
|
||||||
|
You may need to parse CSV files from different financial service providers.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { CsvSpendesk, CsvPayPal, CsvFidor, CsvCommerzbank } from '@fin.cx/csvparser';
|
||||||
|
|
||||||
|
async function parseMultipleFiles(filePaths: {spendesk: string, paypal: string, fidor: string, commerzbank: string}) {
|
||||||
|
try {
|
||||||
|
const spendeskData = await CsvSpendesk.fromFile(filePaths.spendesk);
|
||||||
|
const payPalData = new CsvPayPal();
|
||||||
|
const csvDescriptorPayPal = {
|
||||||
|
filename: 'paypal.csv',
|
||||||
|
contentString: await fs.promises.readFile(filePaths.paypal, 'utf8')
|
||||||
|
}
|
||||||
|
payPalData.addCsvDecriptor(csvDescriptorPayPal);
|
||||||
|
|
||||||
|
const fidorData = new CsvFidor();
|
||||||
|
const csvDescriptorFidor = {
|
||||||
|
filename: 'fidor.csv',
|
||||||
|
contentString: await fs.promises.readFile(filePaths.fidor, 'utf8')
|
||||||
|
}
|
||||||
|
fidorData.addCsvDecriptor(csvDescriptorFidor);
|
||||||
|
|
||||||
|
const commerzbankData = new CsvCommerzbank();
|
||||||
|
const csvDescriptorCommerzbank = {
|
||||||
|
filename: 'commerzbank.csv',
|
||||||
|
contentString: await fs.promises.readFile(filePaths.commerzbank, 'utf8')
|
||||||
|
}
|
||||||
|
commerzbankData.addCsvDecriptor(csvDescriptorCommerzbank);
|
||||||
|
|
||||||
|
console.log(await spendeskData.getTransactions());
|
||||||
|
console.log(await payPalData.getTransactions());
|
||||||
|
console.log(await fidorData.getTransactions());
|
||||||
|
console.log(await commerzbankData.getTransactions());
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error parsing multiple files:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage example
|
||||||
|
parseMultipleFiles({
|
||||||
|
spendesk: './path/to/spendesk.csv',
|
||||||
|
paypal: './path/to/paypal.csv',
|
||||||
|
fidor: './path/to/fidor.csv',
|
||||||
|
commerzbank: './path/to/commerzbank.csv'
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
By covering multiple use cases and providing comprehensive documentation and code samples, this readme should help developers integrate and utilize the `@fin.cx/csvparser` module effectively.
|
||||||
|
```
|
||||||
|
undefined
|
8
test/test.ts
Normal file
8
test/test.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { expect, tap } from '@push.rocks/tapbundle';
|
||||||
|
import * as csvparser from '../ts/index';
|
||||||
|
|
||||||
|
tap.test('first test', async () => {
|
||||||
|
console.log(csvparser.standardExport);
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.start();
|
8
ts/00_commitinfo_data.ts
Normal file
8
ts/00_commitinfo_data.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* autocreated commitinfo by @push.rocks/commitinfo
|
||||||
|
*/
|
||||||
|
export const commitinfo = {
|
||||||
|
name: '@fin.cx/csvparser',
|
||||||
|
version: '1.1.0',
|
||||||
|
description: 'A TypeScript-based parser for CSV files from various financial service providers.'
|
||||||
|
}
|
98
ts/commerzbank/csv-commerzbank.classes.csvcommerzbank.ts
Normal file
98
ts/commerzbank/csv-commerzbank.classes.csvcommerzbank.ts
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import * as plugins from '../csvparser.plugins.js';
|
||||||
|
import * as interfaces from './interfaces/index.js';
|
||||||
|
|
||||||
|
export class CsvCommerzbank extends plugins.portablefinance
|
||||||
|
.AcCsvParser<interfaces.ICommerzbankTransaction> {
|
||||||
|
// INSTANCE
|
||||||
|
public paymentProviderName = 'Commerzbank';
|
||||||
|
public description: string = `a csv parser for parsing downloaded csv transaction files from Commerzbank`;
|
||||||
|
private csvDescriptorArray: plugins.portablefinance.ICsvDescriptor[] = [];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
addCsvDecriptor(csvDescriptorArg: plugins.portablefinance.ICsvDescriptor): void {
|
||||||
|
this.csvDescriptorArray.push(csvDescriptorArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getTransactions(): Promise<plugins.portablefinance.IMonetaryTransaction[]> {
|
||||||
|
const payments: interfaces.ICommerzbankOriginalTransaction[] = [];
|
||||||
|
|
||||||
|
for (const csvDescriptor of this.csvDescriptorArray) {
|
||||||
|
const csvInstance = await plugins.smartcsv.Csv.createCsvFromString(csvDescriptor.contentString, {
|
||||||
|
headers: true,
|
||||||
|
unquote: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
payments.push(
|
||||||
|
...(await csvInstance.exportAsObject())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const finalTransactionArray: interfaces.ICommerzbankTransaction[] = [];
|
||||||
|
for (const transaction of payments) {
|
||||||
|
// transaction.Buchungstag = transaction.Wertstellung;
|
||||||
|
console.log(transaction);
|
||||||
|
const finalTransaction: interfaces.ICommerzbankTransaction = {
|
||||||
|
simpleTransaction: null,
|
||||||
|
transactionHash: null,
|
||||||
|
original: transaction,
|
||||||
|
amount: plugins.smartmoney.parseEuropeanNumberString(transaction.Betrag),
|
||||||
|
currency: transaction.Währung,
|
||||||
|
description: transaction.Buchungstext,
|
||||||
|
transactionDate: plugins.smarttime.ExtendedDate.fromEuropeanDate(transaction.Buchungstag),
|
||||||
|
valuationDate: plugins.smarttime.ExtendedDate.fromEuropeanDate(transaction.Wertstellung),
|
||||||
|
transactionType: ((): interfaces.TTransactionType => {
|
||||||
|
switch (transaction.Umsatzart) {
|
||||||
|
case 'Gutschrift':
|
||||||
|
return 'Credit';
|
||||||
|
case 'Lastschrift':
|
||||||
|
return 'Debit';
|
||||||
|
case 'Zinsen/Entgelte':
|
||||||
|
return 'BankFees';
|
||||||
|
case 'Überweisung':
|
||||||
|
return 'ActiveTransfer';
|
||||||
|
default:
|
||||||
|
throw new Error(`unknown transactiontype ${transaction.Umsatzart}`);
|
||||||
|
}
|
||||||
|
})(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// lets assign the transactionHash
|
||||||
|
finalTransaction.transactionHash = await plugins.smarthash.sha265FromObject({
|
||||||
|
description: finalTransaction.description,
|
||||||
|
amount: finalTransaction.amount,
|
||||||
|
date: finalTransaction.valuationDate,
|
||||||
|
});
|
||||||
|
|
||||||
|
finalTransaction.simpleTransaction = {
|
||||||
|
id: finalTransaction.transactionHash,
|
||||||
|
accountId: null,
|
||||||
|
name: finalTransaction.description,
|
||||||
|
amount: finalTransaction.amount,
|
||||||
|
description: finalTransaction.description,
|
||||||
|
date: finalTransaction.transactionDate,
|
||||||
|
};
|
||||||
|
finalTransactionArray.push(finalTransaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
return finalTransactionArray.map((commerzbankTransaction) => {
|
||||||
|
const fin2021Transaction: plugins.portablefinance.IMonetaryTransaction = {
|
||||||
|
id: null,
|
||||||
|
data: {
|
||||||
|
additionalIds: [],
|
||||||
|
amount: commerzbankTransaction.amount,
|
||||||
|
date: commerzbankTransaction.transactionDate.getTime(),
|
||||||
|
description: commerzbankTransaction.description,
|
||||||
|
name: commerzbankTransaction.description,
|
||||||
|
originAccountId: null,
|
||||||
|
originTransactionId: commerzbankTransaction.transactionHash,
|
||||||
|
paymentAccountId: null,
|
||||||
|
justForLooks: null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return fin2021Transaction;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
1
ts/commerzbank/index.ts
Normal file
1
ts/commerzbank/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './csv-commerzbank.classes.csvcommerzbank.js';
|
1
ts/commerzbank/interfaces/index.ts
Normal file
1
ts/commerzbank/interfaces/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './interfaces.commerzbanktransaction.js';
|
@ -0,0 +1,30 @@
|
|||||||
|
import * as plugins from '../../csvparser.plugins.js';
|
||||||
|
|
||||||
|
export interface ICommerzbankOriginalTransaction {
|
||||||
|
Buchungstag: string;
|
||||||
|
Wertstellung: string;
|
||||||
|
Umsatzart: 'Überweisung' | 'Gutschrift' | 'Lastschrift' | 'Zinsen/Entgelte';
|
||||||
|
Buchungstext: string;
|
||||||
|
Betrag: string;
|
||||||
|
Währung: string;
|
||||||
|
Auftraggeberkonto: string;
|
||||||
|
'Bankleitzahl Auftraggeberkonto': string;
|
||||||
|
'IBAN Auftraggeberkonto': string;
|
||||||
|
Kategorie: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TTransactionType = 'Credit' | 'Debit' | 'ActiveTransfer' | 'BankFees';
|
||||||
|
|
||||||
|
export interface ICommerzbankTransaction {
|
||||||
|
simpleTransaction: plugins.tsclass.finance.ITransaction;
|
||||||
|
transactionHash: string;
|
||||||
|
original: ICommerzbankOriginalTransaction;
|
||||||
|
|
||||||
|
// translated to English
|
||||||
|
transactionDate: plugins.smarttime.ExtendedDate;
|
||||||
|
valuationDate: plugins.smarttime.ExtendedDate;
|
||||||
|
transactionType: TTransactionType;
|
||||||
|
description: string;
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
26
ts/csvparser.plugins.ts
Normal file
26
ts/csvparser.plugins.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// node native scope
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
export { path };
|
||||||
|
|
||||||
|
// fin.cx scope
|
||||||
|
import * as portablefinance from '@fin.cx/portablefinance';
|
||||||
|
|
||||||
|
export {
|
||||||
|
portablefinance
|
||||||
|
}
|
||||||
|
|
||||||
|
// pushrocks scope
|
||||||
|
import * as smartcsv from '@push.rocks/smartcsv';
|
||||||
|
import * as smartfile from '@push.rocks/smartfile';
|
||||||
|
import * as smarthash from '@push.rocks/smarthash';
|
||||||
|
import * as smartmoney from '@push.rocks/smartmoney';
|
||||||
|
import * as smartstring from '@push.rocks/smartstring';
|
||||||
|
import * as smarttime from '@push.rocks/smarttime';
|
||||||
|
|
||||||
|
export { smartcsv, smartfile, smarthash, smartmoney, smartstring, smarttime };
|
||||||
|
|
||||||
|
// tsclass scope
|
||||||
|
import * as tsclass from '@tsclass/tsclass';
|
||||||
|
|
||||||
|
export { tsclass };
|
55
ts/fidor/csv-fidor.classes.csvfidor.ts
Normal file
55
ts/fidor/csv-fidor.classes.csvfidor.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import * as plugins from '../csvparser.plugins.js';
|
||||||
|
|
||||||
|
import { ExtendedDate } from '@push.rocks/smarttime';
|
||||||
|
|
||||||
|
import * as interfaces from './interfaces/index.js';
|
||||||
|
|
||||||
|
export class CsvFidor extends plugins.portablefinance.AcCsvParser<plugins.portablefinance.IMonetaryTransaction> {
|
||||||
|
|
||||||
|
// INSTANCE
|
||||||
|
public paymentProviderName: string = 'Fidor Bank AG';
|
||||||
|
public description: string = 'a csv parser optimized for csv files from Fidor.';
|
||||||
|
public csvDescriptorArray: plugins.portablefinance.ICsvDescriptor[] = [];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
addCsvDecriptor (csvDescriptorArg: plugins.portablefinance.ICsvDescriptor): void {
|
||||||
|
this.csvDescriptorArray.push(csvDescriptorArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the transactions
|
||||||
|
*/
|
||||||
|
public async getTransactions(): Promise<plugins.portablefinance.IMonetaryTransaction[]> {
|
||||||
|
const payments: plugins.portablefinance.IMonetaryTransaction[] = [];
|
||||||
|
|
||||||
|
for (const csvDescriptor of this.csvDescriptorArray) {
|
||||||
|
const csvInstance = new plugins.smartcsv.Csv(csvDescriptor.contentString, {
|
||||||
|
headers: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const fidorTransactionArray: interfaces.IFidorOriginalTransaction[] = await csvInstance.exportAsObject();
|
||||||
|
for (const transaction of fidorTransactionArray) {
|
||||||
|
payments.push({
|
||||||
|
id: await plugins.smarthash.sha265FromObject(transaction),
|
||||||
|
data: {
|
||||||
|
additionalIds: [],
|
||||||
|
amount: parseFloat(transaction.Wert.replace('.', '').replace(',', '.')),
|
||||||
|
date: plugins.smarttime.ExtendedDate.fromEuropeanDate(transaction.Datum).getTime(),
|
||||||
|
name: transaction.Beschreibung,
|
||||||
|
description: transaction.Beschreibung2,
|
||||||
|
originAccountId: null,
|
||||||
|
originTransactionId: null,
|
||||||
|
paymentAccountId: null,
|
||||||
|
justForLooks: null,
|
||||||
|
voucherData: null,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return payments;
|
||||||
|
}
|
||||||
|
}
|
1
ts/fidor/index.ts
Normal file
1
ts/fidor/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './csv-fidor.classes.csvfidor.js';
|
1
ts/fidor/interfaces/index.ts
Normal file
1
ts/fidor/interfaces/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './interfaces.fidortransaction.js';
|
6
ts/fidor/interfaces/interfaces.fidortransaction.ts
Normal file
6
ts/fidor/interfaces/interfaces.fidortransaction.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export interface IFidorOriginalTransaction {
|
||||||
|
Datum: string;
|
||||||
|
Beschreibung: string;
|
||||||
|
Beschreibung2: string;
|
||||||
|
Wert: string;
|
||||||
|
}
|
4
ts/index.ts
Normal file
4
ts/index.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export * from './commerzbank/index.js';
|
||||||
|
export * from './fidor/index.js';
|
||||||
|
export * from './paypal/index.js';
|
||||||
|
export * from './spendesk/index.js';
|
147
ts/paypal/csv-paypal.classes.csvpaypal.ts
Normal file
147
ts/paypal/csv-paypal.classes.csvpaypal.ts
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
import * as plugins from '../csvparser.plugins.js';
|
||||||
|
|
||||||
|
import * as interfaces from './interfaces/index.js';
|
||||||
|
|
||||||
|
export class CsvPayPal extends plugins.portablefinance
|
||||||
|
.AcCsvParser<plugins.portablefinance.IMonetaryTransaction> {
|
||||||
|
// INSTANCE
|
||||||
|
public paymentProviderName = 'PayPal';
|
||||||
|
public description: string = 'a csv parser optimized for PayPal obtained csv files.';
|
||||||
|
public csvDescriptorArray: plugins.portablefinance.ICsvDescriptor[] = [];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets transactions
|
||||||
|
*/
|
||||||
|
public async getTransactions() {
|
||||||
|
const payments: plugins.portablefinance.IMonetaryTransaction[] = [];
|
||||||
|
for (const csvDescriptor of this.csvDescriptorArray) {
|
||||||
|
let stringToParse = csvDescriptor.contentString;
|
||||||
|
stringToParse = stringToParse.replace(/"(.*?)"/gi, (match, p1, offset, originalString) => {
|
||||||
|
return plugins.smartstring.base64.encodeUri(match);
|
||||||
|
});
|
||||||
|
const smartCsvInstance = new plugins.smartcsv.Csv(stringToParse, {
|
||||||
|
headers: true,
|
||||||
|
});
|
||||||
|
const payPalTransactions: interfaces.IPayPalCsvOriginalTransaction[] = (
|
||||||
|
await smartCsvInstance.exportAsObject()
|
||||||
|
).map((originalTransaction) => {
|
||||||
|
// tslint:disable-next-line: no-object-literal-type-assertion
|
||||||
|
const decodedTransaction = {} as interfaces.IPayPalCsvOriginalTransaction;
|
||||||
|
for (const key in originalTransaction) {
|
||||||
|
if (originalTransaction[key]) {
|
||||||
|
let finalKey = plugins.smartstring.base64.decode(key);
|
||||||
|
finalKey = finalKey.replace(/['"]+/g, '');
|
||||||
|
let finalValue = plugins.smartstring.base64.decode(originalTransaction[key]);
|
||||||
|
finalValue = finalValue.replace(/['"]+/g, '');
|
||||||
|
decodedTransaction[finalKey] = finalValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// pushing the ready transaction
|
||||||
|
return decodedTransaction;
|
||||||
|
});
|
||||||
|
|
||||||
|
// adjust numberFormat
|
||||||
|
const anf = (numberString: string): number => {
|
||||||
|
return parseFloat(numberString.replace(/\,/g, '.'));
|
||||||
|
};
|
||||||
|
|
||||||
|
const monetaryTransactions: interfaces.IPayPalTransaction[] = [];
|
||||||
|
for (const originalTransaction of payPalTransactions) {
|
||||||
|
const paypalTransaction: interfaces.IPayPalTransaction = {
|
||||||
|
// assigned later
|
||||||
|
transactionHash: null,
|
||||||
|
simpleTransaction: null,
|
||||||
|
|
||||||
|
// assigned now
|
||||||
|
originalTransaction,
|
||||||
|
transactionDate: plugins.smarttime.ExtendedDate.fromEuropeanDateAndTime(
|
||||||
|
originalTransaction.Datum,
|
||||||
|
originalTransaction.Uhrzeit,
|
||||||
|
'Europe/Berlin'
|
||||||
|
),
|
||||||
|
transactionCode: originalTransaction.Transaktionscode,
|
||||||
|
linkedTransactionCode: originalTransaction['Zugehöriger Transaktionscode'],
|
||||||
|
timezone: originalTransaction.Zeitzone,
|
||||||
|
bankAccount: originalTransaction.Bankkonto,
|
||||||
|
bankName: originalTransaction['Name der Bank'],
|
||||||
|
brutto: anf(originalTransaction.Brutto),
|
||||||
|
netto: anf(originalTransaction.Netto),
|
||||||
|
credit: anf(originalTransaction.Guthaben),
|
||||||
|
fee: anf(originalTransaction.Gebühr),
|
||||||
|
processingAndShippingFee: anf(originalTransaction['Versand- und Bearbeitungsgebühr']),
|
||||||
|
currency: originalTransaction.Währung,
|
||||||
|
description: originalTransaction.Beschreibung,
|
||||||
|
invoiceNumber: originalTransaction.Rechnungsnummer,
|
||||||
|
name: originalTransaction.Name,
|
||||||
|
payeeEmail: originalTransaction['Absender E-Mail-Adresse'],
|
||||||
|
transactionTime: originalTransaction.Uhrzeit,
|
||||||
|
vatAmount: anf(originalTransaction.Umsatzsteuer),
|
||||||
|
};
|
||||||
|
|
||||||
|
monetaryTransactions.push(paypalTransaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
const foreignTransactions: interfaces.IPayPalTransaction[] = [];
|
||||||
|
const eurTransactions: interfaces.IPayPalTransaction[] = monetaryTransactions.filter(
|
||||||
|
(payPalTransaction: interfaces.IPayPalTransaction) => {
|
||||||
|
const isEur = payPalTransaction.currency === 'EUR';
|
||||||
|
if (isEur) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
foreignTransactions.push(payPalTransaction);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
let finalReturnTransactions = eurTransactions.map((transaction) => {
|
||||||
|
if (transaction.brutto > 0) {
|
||||||
|
return transaction; // lets don't bother with payments from the bank
|
||||||
|
}
|
||||||
|
const eurTime = transaction.transactionDate.getTime();
|
||||||
|
const foreignCandidates: interfaces.IPayPalTransaction[] = [];
|
||||||
|
for (const foreignTransaction of foreignTransactions) {
|
||||||
|
const foreignTime = foreignTransaction.transactionDate.getTime();
|
||||||
|
if (eurTime === foreignTime) {
|
||||||
|
foreignCandidates.push(foreignTransaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foreignCandidates.length !== 2 && foreignCandidates.length !== 0) {
|
||||||
|
console.log('error! Found a weird amoun of corresponding foreign transactions');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foreignCandidates.length === 2) {
|
||||||
|
const wantedForeignTransaction = foreignCandidates.find((foreignTransaction) => {
|
||||||
|
return foreignTransaction.brutto < 0;
|
||||||
|
});
|
||||||
|
transaction.description = wantedForeignTransaction.description;
|
||||||
|
transaction.payeeEmail = wantedForeignTransaction.payeeEmail;
|
||||||
|
transaction.name = wantedForeignTransaction.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return transaction;
|
||||||
|
});
|
||||||
|
|
||||||
|
// lets assign simple transactions at last
|
||||||
|
finalReturnTransactions = finalReturnTransactions.map((transaction) => {
|
||||||
|
transaction.simpleTransaction = {
|
||||||
|
accountId: null,
|
||||||
|
id: transaction.transactionCode,
|
||||||
|
amount: transaction.brutto,
|
||||||
|
date: transaction.transactionDate,
|
||||||
|
description: transaction.description,
|
||||||
|
name: transaction.name,
|
||||||
|
};
|
||||||
|
return transaction;
|
||||||
|
});
|
||||||
|
|
||||||
|
const csvPayPalInstance = new CsvPayPal(finalReturnTransactions);
|
||||||
|
return csvPayPalInstance;
|
||||||
|
}
|
||||||
|
return payments;
|
||||||
|
}
|
||||||
|
}
|
1
ts/paypal/index.ts
Normal file
1
ts/paypal/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './csv-paypal.classes.csvpaypal';
|
1
ts/paypal/interfaces/index.ts
Normal file
1
ts/paypal/interfaces/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './interfaces.paypaltransaction.js';
|
49
ts/paypal/interfaces/interfaces.paypaltransaction.ts
Normal file
49
ts/paypal/interfaces/interfaces.paypaltransaction.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import * as plugins from '../../csvparser.plugins.js';
|
||||||
|
|
||||||
|
export interface IPayPalCsvOriginalTransaction {
|
||||||
|
Datum: string;
|
||||||
|
Uhrzeit: string;
|
||||||
|
Zeitzone: string;
|
||||||
|
Beschreibung: string;
|
||||||
|
Währung: string;
|
||||||
|
Brutto: string;
|
||||||
|
Gebühr: string;
|
||||||
|
Netto: string;
|
||||||
|
Guthaben: string;
|
||||||
|
Transaktionscode: string;
|
||||||
|
'Absender E-Mail-Adresse': string;
|
||||||
|
Name: string;
|
||||||
|
'Name der Bank': string;
|
||||||
|
Bankkonto: string;
|
||||||
|
'Versand- und Bearbeitungsgebühr': string;
|
||||||
|
Umsatzsteuer: string;
|
||||||
|
Rechnungsnummer: string;
|
||||||
|
'Zugehöriger Transaktionscode': string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPayPalTransaction {
|
||||||
|
// standardised
|
||||||
|
simpleTransaction: plugins.tsclass.finance.ITransaction;
|
||||||
|
originalTransaction;
|
||||||
|
transactionHash: string;
|
||||||
|
|
||||||
|
// specific
|
||||||
|
transactionCode: string;
|
||||||
|
transactionDate: Date;
|
||||||
|
transactionTime: string;
|
||||||
|
timezone: string;
|
||||||
|
description: string;
|
||||||
|
currency: string;
|
||||||
|
brutto: number;
|
||||||
|
fee: number;
|
||||||
|
netto: number;
|
||||||
|
credit: number;
|
||||||
|
payeeEmail: string;
|
||||||
|
name: string;
|
||||||
|
bankName: string;
|
||||||
|
bankAccount: string;
|
||||||
|
processingAndShippingFee: number;
|
||||||
|
vatAmount: number;
|
||||||
|
invoiceNumber: string;
|
||||||
|
linkedTransactionCode: string;
|
||||||
|
}
|
205
ts/spendesk/csv-spendesk.classes.csvspendesk.ts
Normal file
205
ts/spendesk/csv-spendesk.classes.csvspendesk.ts
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
import * as plugins from '../csvparser.plugins.js';
|
||||||
|
|
||||||
|
import * as interfaces from './interfaces/index.js';
|
||||||
|
|
||||||
|
export class CsvSpendesk extends plugins.portablefinance.AcCsvParser<any> {
|
||||||
|
// ========= STATIC ================
|
||||||
|
/**
|
||||||
|
* get the SpendeskData from an extracted direcotory
|
||||||
|
* @param dirPath
|
||||||
|
*/
|
||||||
|
public static async fromFile(filePath: string): Promise<CsvSpendesk> {
|
||||||
|
const reresolvedPath = plugins.path.resolve(filePath);
|
||||||
|
const fileString = plugins.smartfile.fs.toStringSync(reresolvedPath);
|
||||||
|
const csvSpendesk = await CsvSpendesk.fromCsvString(fileString);
|
||||||
|
return csvSpendesk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the SpendeskData from an extracted direcotory
|
||||||
|
* @param dirPath
|
||||||
|
*/
|
||||||
|
public static async fromDir(dirPath: string): Promise<CsvSpendesk> {
|
||||||
|
const foundFiles: string[] = await plugins.smartfile.fs.listFileTree(
|
||||||
|
dirPath,
|
||||||
|
'**/Spendesk*',
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
if (foundFiles.length === 0) {
|
||||||
|
throw new Error('no files found!');
|
||||||
|
}
|
||||||
|
|
||||||
|
const csvSpendesks: CsvSpendesk[] = [];
|
||||||
|
|
||||||
|
for (const foundFile of foundFiles) {
|
||||||
|
const fileString = plugins.smartfile.fs.toStringSync(plugins.path.resolve(foundFile));
|
||||||
|
plugins.path.join(dirPath, foundFile);
|
||||||
|
csvSpendesks.push(await this.fromFile(foundFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
let returnCsvSpendesk: CsvSpendesk;
|
||||||
|
for (const csvSpendeskInstance of csvSpendesks) {
|
||||||
|
if (!returnCsvSpendesk) {
|
||||||
|
returnCsvSpendesk = csvSpendeskInstance;
|
||||||
|
} else {
|
||||||
|
await returnCsvSpendesk.concat(csvSpendeskInstance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnCsvSpendesk;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async fromCsvString(csvStringArg: string): Promise<CsvSpendesk> {
|
||||||
|
// lets parse the data from the directory
|
||||||
|
const csvInstance = await plugins.smartcsv.Csv.createCsvFromString(csvStringArg, {
|
||||||
|
headers: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// lets differentiate between payments and credits
|
||||||
|
const originalTransactionArray: interfaces.ISpendeskOriginalTransaction[] = (await csvInstance.exportAsObject()) as interfaces.ISpendeskOriginalTransaction[];
|
||||||
|
const paymentsArray: interfaces.ISpendeskTransaction[] = [];
|
||||||
|
for (const originalTransaction of originalTransactionArray) {
|
||||||
|
const finalTransaction: interfaces.ISpendeskTransaction = {
|
||||||
|
// the original transaction
|
||||||
|
original: originalTransaction,
|
||||||
|
|
||||||
|
// assigned later
|
||||||
|
paymentType: null,
|
||||||
|
amount: null,
|
||||||
|
simpleTransaction: null,
|
||||||
|
transactionHash: null,
|
||||||
|
|
||||||
|
// assigned now
|
||||||
|
currency: originalTransaction.Currency as interfaces.TAvailableCurrencies,
|
||||||
|
description: originalTransaction.Description,
|
||||||
|
expenseAccount: originalTransaction['Expense account'],
|
||||||
|
month: originalTransaction.Month,
|
||||||
|
payer: originalTransaction.Payer,
|
||||||
|
paymentDate: new Date(originalTransaction['Payment date']),
|
||||||
|
paymentMethod: originalTransaction['Payment method'],
|
||||||
|
paymentState: originalTransaction.State as interfaces.TPaymentState,
|
||||||
|
settlementDate: new Date(originalTransaction['Settlement date']),
|
||||||
|
receiptAvailable: (() => {
|
||||||
|
if ((originalTransaction['Receipt?'] as any) === 'Yes') {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})(),
|
||||||
|
receiptNames: [],
|
||||||
|
supplier: originalTransaction.Supplier,
|
||||||
|
team: originalTransaction.Team,
|
||||||
|
vatAmount: parseFloat(originalTransaction.VAT),
|
||||||
|
vatPercentage: ((): number => {
|
||||||
|
if (!originalTransaction.VAT || originalTransaction.VAT === '0') {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
const vatAmount = parseFloat(originalTransaction.VAT);
|
||||||
|
const debitAmount = parseFloat(originalTransaction.Debit);
|
||||||
|
return Math.round((vatAmount / (debitAmount - vatAmount)) * 100);
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
};
|
||||||
|
|
||||||
|
// type
|
||||||
|
finalTransaction.paymentType = (() => {
|
||||||
|
let paymentType: interfaces.TPaymentType;
|
||||||
|
if (parseFloat(finalTransaction.original.Credit) !== 0) {
|
||||||
|
paymentType = 'Load';
|
||||||
|
} else if (parseFloat(originalTransaction.Debit) !== 0) {
|
||||||
|
paymentType = 'Payment';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (originalTransaction.Description.startsWith('FX fee')) {
|
||||||
|
paymentType = 'FXfee';
|
||||||
|
}
|
||||||
|
return paymentType;
|
||||||
|
})();
|
||||||
|
|
||||||
|
// amount
|
||||||
|
finalTransaction.amount = (() => {
|
||||||
|
switch (parseFloat(originalTransaction.Credit)) {
|
||||||
|
case 0:
|
||||||
|
return -parseFloat(originalTransaction.Debit);
|
||||||
|
default:
|
||||||
|
return parseFloat(originalTransaction.Credit);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
// transaction hash
|
||||||
|
finalTransaction.transactionHash = await plugins.smarthash.sha265FromObject({
|
||||||
|
amount: finalTransaction.amount,
|
||||||
|
transactionDate: finalTransaction.paymentDate,
|
||||||
|
settlementDate: finalTransaction.settlementDate,
|
||||||
|
supplier: finalTransaction.supplier
|
||||||
|
});
|
||||||
|
|
||||||
|
// simple transaction
|
||||||
|
finalTransaction.simpleTransaction = {
|
||||||
|
accountId: null,
|
||||||
|
id: finalTransaction.transactionHash,
|
||||||
|
amount: finalTransaction.amount,
|
||||||
|
date: finalTransaction.settlementDate,
|
||||||
|
description: finalTransaction.description,
|
||||||
|
name: finalTransaction.supplier
|
||||||
|
};
|
||||||
|
paymentsArray.push(finalTransaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
const csvSpendeskInstance = new CsvSpendesk(paymentsArray);
|
||||||
|
return csvSpendeskInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the SpendeskData from Spendesk.com
|
||||||
|
* @param dirPath
|
||||||
|
*/
|
||||||
|
public static async fromSpendeskCom(dirPath: string) {
|
||||||
|
// TODO: implement spendesk API
|
||||||
|
throw new Error(`method is not yet implemented`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========= INSTANCE ================
|
||||||
|
public paymentProviderName: string = 'Spendesk';
|
||||||
|
public origin: 'api' | 'file' | 'dir';
|
||||||
|
public updateFunction: (
|
||||||
|
fromTimeStamp: plugins.smarttime.TimeStamp,
|
||||||
|
untilTimeStamp: plugins.smarttime.TimeStamp
|
||||||
|
) => interfaces.ISpendeskTransaction[];
|
||||||
|
public transactionArray: interfaces.ISpendeskTransaction[];
|
||||||
|
|
||||||
|
constructor(transactionArrayArg: interfaces.ISpendeskTransaction[]) {
|
||||||
|
super();
|
||||||
|
this.transactionArray = transactionArrayArg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets all transactions
|
||||||
|
*/
|
||||||
|
public async getTransactions() {
|
||||||
|
return this.transactionArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets all loads
|
||||||
|
*/
|
||||||
|
public async getLoads() {
|
||||||
|
return this.transactionArray.filter(payment => {
|
||||||
|
return payment.paymentType === 'Load';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getDebits() {
|
||||||
|
return this.transactionArray.filter(payment => {
|
||||||
|
return payment.paymentType === 'Payment';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* concat this instance's transactions with those of another one
|
||||||
|
*/
|
||||||
|
public async concat(csvSpendeskInstance: CsvSpendesk): Promise<CsvSpendesk> {
|
||||||
|
this.transactionArray = this.transactionArray.concat(csvSpendeskInstance.transactionArray);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
1
ts/spendesk/index.ts
Normal file
1
ts/spendesk/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './csv-spendesk.classes.csvspendesk.js';
|
1
ts/spendesk/interfaces/index.ts
Normal file
1
ts/spendesk/interfaces/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './interface.spendesktransaction';
|
55
ts/spendesk/interfaces/interface.spendesktransaction.ts
Normal file
55
ts/spendesk/interfaces/interface.spendesktransaction.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import * as plugins from '../csv-spendesk.plugins';
|
||||||
|
|
||||||
|
export type TAvailableCurrencies = 'EUR';
|
||||||
|
export type TPaymentState = 'Settled';
|
||||||
|
export type TPaymentType = 'Load' | 'Credit' | 'Payment' | 'FXfee';
|
||||||
|
|
||||||
|
export interface ISpendeskOriginalTransaction {
|
||||||
|
simpleTransaction: plugins.tsclass.ITransaction;
|
||||||
|
original: any;
|
||||||
|
'Payment date': string;
|
||||||
|
'Settlement date': string;
|
||||||
|
Month: string;
|
||||||
|
Payer: string;
|
||||||
|
Team: string;
|
||||||
|
Description: string;
|
||||||
|
Supplier: string;
|
||||||
|
'Expense account': string;
|
||||||
|
'Payment method': string;
|
||||||
|
Type: string;
|
||||||
|
// 'Local amount': number;
|
||||||
|
// 'Local currency': 'EUR';
|
||||||
|
Debit: string;
|
||||||
|
Credit: string;
|
||||||
|
Currency: string;
|
||||||
|
VAT: string;
|
||||||
|
vatPercentage?: string;
|
||||||
|
State: string;
|
||||||
|
'Receipt?': string;
|
||||||
|
'Receipt name(s)': '';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISpendeskTransaction {
|
||||||
|
simpleTransaction?: plugins.tsclass.ITransaction;
|
||||||
|
original: ISpendeskOriginalTransaction;
|
||||||
|
transactionHash: string;
|
||||||
|
paymentDate: Date;
|
||||||
|
settlementDate: Date;
|
||||||
|
month: string;
|
||||||
|
payer: string;
|
||||||
|
team: string;
|
||||||
|
description: string;
|
||||||
|
supplier: string;
|
||||||
|
expenseAccount: string;
|
||||||
|
paymentMethod: string;
|
||||||
|
paymentType: TPaymentType;
|
||||||
|
// 'Local amount': number;
|
||||||
|
// 'Local currency': 'EUR';
|
||||||
|
amount: number;
|
||||||
|
currency: TAvailableCurrencies;
|
||||||
|
vatAmount: number;
|
||||||
|
vatPercentage?: number;
|
||||||
|
paymentState: TPaymentState;
|
||||||
|
receiptAvailable: boolean;
|
||||||
|
receiptNames: string[];
|
||||||
|
}
|
14
tsconfig.json
Normal file
14
tsconfig.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"useDefineForClassFields": false,
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "NodeNext",
|
||||||
|
"moduleResolution": "NodeNext",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"verbatimModuleSyntax": true
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"dist_*/**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user