@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
FILE_NAME=data-dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql.br
|
FILE_NAME=data-dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql.br
|
||||||
FILE_NAME_COMPLETE=full-dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql.br
|
FILE_NAME_COMPLETE=full-dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql.br
|
||||||
|
DATABASE_NAME=database
|
||||||
|
|
||||||
# Das wird benötigt für AWS Ionos Kompatibilität.
|
# Das wird benötigt für AWS Ionos Kompatibilität.
|
||||||
export AWS_REQUEST_CHECKSUM_CALCULATION=when_required
|
export AWS_REQUEST_CHECKSUM_CALCULATION=when_required
|
||||||
@@ -11,19 +12,15 @@ export AWS_RESPONSE_CHECKSUM_VALIDATION=when_required
|
|||||||
# IMPORTANT: Dieser Befehl benötigt das `ionos` Profil, sonst wird er nicht funktionieren.
|
# IMPORTANT: Dieser Befehl benötigt das `ionos` Profil, sonst wird er nicht funktionieren.
|
||||||
# Das Profil kann mit `aws configure --profile ionos` erstellt werden.
|
# Das Profil kann mit `aws configure --profile ionos` erstellt werden.
|
||||||
# Den Key dafür findet man auf https://dcd.ionos.com/latest/?lang=en#/key-management
|
# Den Key dafür findet man auf https://dcd.ionos.com/latest/?lang=en#/key-management
|
||||||
docker exec -t online-energieausweis-database-1 pg_dump --data-only -U main main | brotli --best > $FILE_NAME
|
docker exec -t $DATABASE_NAME pg_dump --data-only -U main main | brotli --quality=3 > $FILE_NAME
|
||||||
|
|
||||||
aws s3 cp $FILE_NAME s3://ibc-db-backup/ --profile ionos --endpoint-url https://s3.eu-central-3.ionoscloud.com --storage-class STANDARD
|
aws s3 cp $FILE_NAME s3://ibc-db-backup/ --profile ionos --endpoint-url https://s3.eu-central-3.ionoscloud.com --storage-class STANDARD
|
||||||
|
|
||||||
echo "Uploaded $FILE_NAME"
|
echo "Uploaded $FILE_NAME"
|
||||||
|
|
||||||
docker exec -t online-energieausweis-database-1 pg_dumpall -c -U main | brotli --best > $FILE_NAME_COMPLETE
|
docker exec -t $DATABASE_NAME pg_dumpall -c -U main | brotli --quality=3 > $FILE_NAME_COMPLETE
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
aws s3 cp $FILE_NAME_COMPLETE s3://ibc-db-backup/ --profile ionos --endpoint-url https://s3-eu-central-3.ionoscloud.com --storage-class STANDARD
|
|
||||||
=======
|
|
||||||
aws s3 cp $FILE_NAME_COMPLETE s3://ibc-db-backup/ --profile ionos --endpoint-url https://s3.eu-central-3.ionoscloud.com --storage-class STANDARD
|
aws s3 cp $FILE_NAME_COMPLETE s3://ibc-db-backup/ --profile ionos --endpoint-url https://s3.eu-central-3.ionoscloud.com --storage-class STANDARD
|
||||||
>>>>>>> dev
|
|
||||||
|
|
||||||
echo "Uploaded $FILE_NAME_COMPLETE"
|
echo "Uploaded $FILE_NAME_COMPLETE"
|
||||||
|
|
||||||
|
|||||||
33
bun.lock
33
bun.lock
@@ -27,6 +27,7 @@
|
|||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"flag-icons": "^6.15.0",
|
"flag-icons": "^6.15.0",
|
||||||
"fontkit": "^2.0.4",
|
"fontkit": "^2.0.4",
|
||||||
|
"handlebars": "^4.7.8",
|
||||||
"highlight.run": "^9.14.0",
|
"highlight.run": "^9.14.0",
|
||||||
"is-base64": "^1.1.0",
|
"is-base64": "^1.1.0",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
@@ -39,7 +40,7 @@
|
|||||||
"nodemailer": "^6.10.0",
|
"nodemailer": "^6.10.0",
|
||||||
"pdf-lib": "^1.17.1",
|
"pdf-lib": "^1.17.1",
|
||||||
"postcss-nested": "^7.0.2",
|
"postcss-nested": "^7.0.2",
|
||||||
"puppeteer": "^24.7.2",
|
"puppeteer": "^24.15.0",
|
||||||
"radix-svelte-icons": "^1.0.0",
|
"radix-svelte-icons": "^1.0.0",
|
||||||
"sass": "^1.83.4",
|
"sass": "^1.83.4",
|
||||||
"sharp": "^0.33.5",
|
"sharp": "^0.33.5",
|
||||||
@@ -524,7 +525,7 @@
|
|||||||
|
|
||||||
"@proload/core": ["@proload/core@0.3.3", "", { "dependencies": { "deepmerge": "^4.2.2", "escalade": "^3.1.1" } }, "sha512-7dAFWsIK84C90AMl24+N/ProHKm4iw0akcnoKjRvbfHifJZBLhaDsDus1QJmhG12lXj4e/uB/8mB/0aduCW+NQ=="],
|
"@proload/core": ["@proload/core@0.3.3", "", { "dependencies": { "deepmerge": "^4.2.2", "escalade": "^3.1.1" } }, "sha512-7dAFWsIK84C90AMl24+N/ProHKm4iw0akcnoKjRvbfHifJZBLhaDsDus1QJmhG12lXj4e/uB/8mB/0aduCW+NQ=="],
|
||||||
|
|
||||||
"@puppeteer/browsers": ["@puppeteer/browsers@2.10.2", "", { "dependencies": { "debug": "^4.4.0", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.5.0", "semver": "^7.7.1", "tar-fs": "^3.0.8", "yargs": "^17.7.2" }, "bin": { "browsers": "lib/cjs/main-cli.js" } }, "sha512-i4Ez+s9oRWQbNjtI/3+jxr7OH508mjAKvza0ekPJem0ZtmsYHP3B5dq62+IaBHKaGCOuqJxXzvFLUhJvQ6jtsQ=="],
|
"@puppeteer/browsers": ["@puppeteer/browsers@2.10.6", "", { "dependencies": { "debug": "^4.4.1", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.5.0", "semver": "^7.7.2", "tar-fs": "^3.1.0", "yargs": "^17.7.2" }, "bin": { "browsers": "lib/cjs/main-cli.js" } }, "sha512-pHUn6ZRt39bP3698HFQlu2ZHCkS/lPcpv7fVQcGBSzNNygw171UXAKrCUhy+TEMw4lEttOKDgNpb04hwUAJeiQ=="],
|
||||||
|
|
||||||
"@rc-component/async-validator": ["@rc-component/async-validator@5.0.4", "", { "dependencies": { "@babel/runtime": "^7.24.4" } }, "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg=="],
|
"@rc-component/async-validator": ["@rc-component/async-validator@5.0.4", "", { "dependencies": { "@babel/runtime": "^7.24.4" } }, "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg=="],
|
||||||
|
|
||||||
@@ -1060,7 +1061,7 @@
|
|||||||
|
|
||||||
"chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="],
|
"chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="],
|
||||||
|
|
||||||
"chromium-bidi": ["chromium-bidi@4.1.1", "", { "dependencies": { "mitt": "^3.0.1", "zod": "^3.24.1" }, "peerDependencies": { "devtools-protocol": "*" } }, "sha512-biR7t4vF3YluE6RlMSk9IWk+b9U+WWyzHp+N2pL9vRTk+UXHYRTVp7jTK58ZNzMLBgoLMHY4QyJMbeuw3eKxqg=="],
|
"chromium-bidi": ["chromium-bidi@7.2.0", "", { "dependencies": { "mitt": "^3.0.1", "zod": "^3.24.1" }, "peerDependencies": { "devtools-protocol": "*" } }, "sha512-gREyhyBstermK+0RbcJLbFhcQctg92AGgDe/h/taMJEOLRdtSswBAO9KmvltFSQWgM2LrwWu5SIuEUbdm3JsyQ=="],
|
||||||
|
|
||||||
"ci-info": ["ci-info@4.1.0", "", {}, "sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A=="],
|
"ci-info": ["ci-info@4.1.0", "", {}, "sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A=="],
|
||||||
|
|
||||||
@@ -1244,7 +1245,7 @@
|
|||||||
|
|
||||||
"devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
|
"devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
|
||||||
|
|
||||||
"devtools-protocol": ["devtools-protocol@0.0.1425554", "", {}, "sha512-uRfxR6Nlzdzt0ihVIkV+sLztKgs7rgquY/Mhcv1YNCWDh5IZgl5mnn2aeEnW5stYTE0wwiF4RYVz8eMEpV1SEw=="],
|
"devtools-protocol": ["devtools-protocol@0.0.1464554", "", {}, "sha512-CAoP3lYfwAGQTaAXYvA6JZR0fjGUb7qec1qf4mToyoH2TZgUFeIqYcjh6f9jNuhHfuZiEdH+PONHYrLhRQX6aw=="],
|
||||||
|
|
||||||
"dezalgo": ["dezalgo@1.0.4", "", { "dependencies": { "asap": "^2.0.0", "wrappy": "1" } }, "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig=="],
|
"dezalgo": ["dezalgo@1.0.4", "", { "dependencies": { "asap": "^2.0.0", "wrappy": "1" } }, "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig=="],
|
||||||
|
|
||||||
@@ -1518,6 +1519,8 @@
|
|||||||
|
|
||||||
"h3": ["h3@1.14.0", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.2", "defu": "^6.1.4", "destr": "^2.0.3", "iron-webcrypto": "^1.2.1", "ohash": "^1.1.4", "radix3": "^1.1.2", "ufo": "^1.5.4", "uncrypto": "^0.1.3", "unenv": "^1.10.0" } }, "sha512-ao22eiONdgelqcnknw0iD645qW0s9NnrJHr5OBz4WOMdBdycfSas1EQf1wXRsm+PcB2Yoj43pjBPwqIpJQTeWg=="],
|
"h3": ["h3@1.14.0", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.2", "defu": "^6.1.4", "destr": "^2.0.3", "iron-webcrypto": "^1.2.1", "ohash": "^1.1.4", "radix3": "^1.1.2", "ufo": "^1.5.4", "uncrypto": "^0.1.3", "unenv": "^1.10.0" } }, "sha512-ao22eiONdgelqcnknw0iD645qW0s9NnrJHr5OBz4WOMdBdycfSas1EQf1wXRsm+PcB2Yoj43pjBPwqIpJQTeWg=="],
|
||||||
|
|
||||||
|
"handlebars": ["handlebars@4.7.8", "", { "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "optionalDependencies": { "uglify-js": "^3.1.4" }, "bin": { "handlebars": "bin/handlebars" } }, "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ=="],
|
||||||
|
|
||||||
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
||||||
|
|
||||||
"has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
|
"has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
|
||||||
@@ -1980,6 +1983,8 @@
|
|||||||
|
|
||||||
"negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="],
|
"negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="],
|
||||||
|
|
||||||
|
"neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="],
|
||||||
|
|
||||||
"neotraverse": ["neotraverse@0.6.18", "", {}, "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA=="],
|
"neotraverse": ["neotraverse@0.6.18", "", {}, "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA=="],
|
||||||
|
|
||||||
"netmask": ["netmask@2.0.2", "", {}, "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg=="],
|
"netmask": ["netmask@2.0.2", "", {}, "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg=="],
|
||||||
@@ -2190,9 +2195,9 @@
|
|||||||
|
|
||||||
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
||||||
|
|
||||||
"puppeteer": ["puppeteer@24.7.2", "", { "dependencies": { "@puppeteer/browsers": "2.10.2", "chromium-bidi": "4.1.1", "cosmiconfig": "^9.0.0", "devtools-protocol": "0.0.1425554", "puppeteer-core": "24.7.2", "typed-query-selector": "^2.12.0" }, "bin": { "puppeteer": "lib/cjs/puppeteer/node/cli.js" } }, "sha512-ifYqoY6wGs0yZeFuFPn8BE9FhuveXkarF+eO18I2e/axdoCh4Qh1AE+qXdJBhdaeoPt6eRNTY4Dih29Jbq8wow=="],
|
"puppeteer": ["puppeteer@24.15.0", "", { "dependencies": { "@puppeteer/browsers": "2.10.6", "chromium-bidi": "7.2.0", "cosmiconfig": "^9.0.0", "devtools-protocol": "0.0.1464554", "puppeteer-core": "24.15.0", "typed-query-selector": "^2.12.0" }, "bin": { "puppeteer": "lib/cjs/puppeteer/node/cli.js" } }, "sha512-HPSOTw+DFsU/5s2TUUWEum9WjFbyjmvFDuGHtj2X4YUz2AzOzvKMkT3+A3FR+E+ZefiX/h3kyLyXzWJWx/eMLQ=="],
|
||||||
|
|
||||||
"puppeteer-core": ["puppeteer-core@24.7.2", "", { "dependencies": { "@puppeteer/browsers": "2.10.2", "chromium-bidi": "4.1.1", "debug": "^4.4.0", "devtools-protocol": "0.0.1425554", "typed-query-selector": "^2.12.0", "ws": "^8.18.1" } }, "sha512-P9pZyTmJqKODFCnkZgemCpoFA4LbAa8+NumHVQKyP5X9IgdNS1ZnAnIh1sMAwhF8/xEUGf7jt+qmNLlKieFw1Q=="],
|
"puppeteer-core": ["puppeteer-core@24.15.0", "", { "dependencies": { "@puppeteer/browsers": "2.10.6", "chromium-bidi": "7.2.0", "debug": "^4.4.1", "devtools-protocol": "0.0.1464554", "typed-query-selector": "^2.12.0", "ws": "^8.18.3" } }, "sha512-2iy0iBeWbNyhgiCGd/wvGrDSo73emNFjSxYOcyAqYiagkYt5q4cPfVXaVDKBsukgc2fIIfLAalBZlaxldxdDYg=="],
|
||||||
|
|
||||||
"qs": ["qs@6.13.0", "", { "dependencies": { "side-channel": "^1.0.6" } }, "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg=="],
|
"qs": ["qs@6.13.0", "", { "dependencies": { "side-channel": "^1.0.6" } }, "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg=="],
|
||||||
|
|
||||||
@@ -2566,7 +2571,7 @@
|
|||||||
|
|
||||||
"tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="],
|
"tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="],
|
||||||
|
|
||||||
"tar-fs": ["tar-fs@3.0.8", "", { "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" }, "optionalDependencies": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0" } }, "sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg=="],
|
"tar-fs": ["tar-fs@3.1.0", "", { "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" }, "optionalDependencies": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0" } }, "sha512-5Mty5y/sOF1YWj1J6GiBodjlDc05CUR8PKXrsnFAiSG0xA+GHeWLovaZPYUDXkH/1iKRf2+M5+OrRgzC7O9b7w=="],
|
||||||
|
|
||||||
"tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="],
|
"tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="],
|
||||||
|
|
||||||
@@ -2666,6 +2671,8 @@
|
|||||||
|
|
||||||
"ufo": ["ufo@1.5.4", "", {}, "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ=="],
|
"ufo": ["ufo@1.5.4", "", {}, "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ=="],
|
||||||
|
|
||||||
|
"uglify-js": ["uglify-js@3.19.3", "", { "bin": { "uglifyjs": "bin/uglifyjs" } }, "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ=="],
|
||||||
|
|
||||||
"uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="],
|
"uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="],
|
||||||
|
|
||||||
"undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="],
|
"undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="],
|
||||||
@@ -2764,13 +2771,15 @@
|
|||||||
|
|
||||||
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
|
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
|
||||||
|
|
||||||
|
"wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="],
|
||||||
|
|
||||||
"wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
"wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||||
|
|
||||||
"wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
"wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||||
|
|
||||||
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||||
|
|
||||||
"ws": ["ws@8.18.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w=="],
|
"ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
|
||||||
|
|
||||||
"xml-crypto": ["xml-crypto@6.0.0", "", { "dependencies": { "@xmldom/is-dom-node": "^1.0.1", "@xmldom/xmldom": "^0.8.10", "xpath": "^0.0.33" } }, "sha512-L3RgnkaDrHaYcCnoENv4Idzt1ZRj5U1z1BDH98QdDTQfssScx8adgxhd9qwyYo+E3fXbQZjEQH7aiXHLVgxGvw=="],
|
"xml-crypto": ["xml-crypto@6.0.0", "", { "dependencies": { "@xmldom/is-dom-node": "^1.0.1", "@xmldom/xmldom": "^0.8.10", "xpath": "^0.0.33" } }, "sha512-L3RgnkaDrHaYcCnoENv4Idzt1ZRj5U1z1BDH98QdDTQfssScx8adgxhd9qwyYo+E3fXbQZjEQH7aiXHLVgxGvw=="],
|
||||||
|
|
||||||
@@ -2870,7 +2879,9 @@
|
|||||||
|
|
||||||
"@prisma/schema-files-loader/fs-extra": ["fs-extra@11.1.1", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ=="],
|
"@prisma/schema-files-loader/fs-extra": ["fs-extra@11.1.1", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ=="],
|
||||||
|
|
||||||
"@puppeteer/browsers/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
"@puppeteer/browsers/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
|
||||||
|
|
||||||
|
"@puppeteer/browsers/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
||||||
|
|
||||||
"@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
"@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||||
|
|
||||||
@@ -2968,6 +2979,8 @@
|
|||||||
|
|
||||||
"gray-matter/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
|
"gray-matter/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
|
||||||
|
|
||||||
|
"handlebars/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||||
|
|
||||||
"hasha/type-fest": ["type-fest@0.8.1", "", {}, "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="],
|
"hasha/type-fest": ["type-fest@0.8.1", "", {}, "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="],
|
||||||
|
|
||||||
"ignore-walk/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="],
|
"ignore-walk/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="],
|
||||||
@@ -3066,6 +3079,8 @@
|
|||||||
|
|
||||||
"proxy-agent/proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
|
"proxy-agent/proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
|
||||||
|
|
||||||
|
"puppeteer-core/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
|
||||||
|
|
||||||
"rc-align/rc-util": ["rc-util@4.21.1", "", { "dependencies": { "add-dom-event-listener": "^1.1.0", "prop-types": "^15.5.10", "react-is": "^16.12.0", "react-lifecycles-compat": "^3.0.4", "shallowequal": "^1.1.0" } }, "sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg=="],
|
"rc-align/rc-util": ["rc-util@4.21.1", "", { "dependencies": { "add-dom-event-listener": "^1.1.0", "prop-types": "^15.5.10", "react-is": "^16.12.0", "react-lifecycles-compat": "^3.0.4", "shallowequal": "^1.1.0" } }, "sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg=="],
|
||||||
|
|
||||||
"rc-animate/rc-util": ["rc-util@4.21.1", "", { "dependencies": { "add-dom-event-listener": "^1.1.0", "prop-types": "^15.5.10", "react-is": "^16.12.0", "react-lifecycles-compat": "^3.0.4", "shallowequal": "^1.1.0" } }, "sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg=="],
|
"rc-animate/rc-util": ["rc-util@4.21.1", "", { "dependencies": { "add-dom-event-listener": "^1.1.0", "prop-types": "^15.5.10", "react-is": "^16.12.0", "react-lifecycles-compat": "^3.0.4", "shallowequal": "^1.1.0" } }, "sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg=="],
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
database:
|
database:
|
||||||
|
container_name: database
|
||||||
|
image: postgres:17.5
|
||||||
|
|
||||||
build: ./
|
build: ./
|
||||||
restart: always
|
restart: always
|
||||||
env_file:
|
env_file:
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"flag-icons": "^6.15.0",
|
"flag-icons": "^6.15.0",
|
||||||
"fontkit": "^2.0.4",
|
"fontkit": "^2.0.4",
|
||||||
|
"handlebars": "^4.7.8",
|
||||||
"highlight.run": "^9.14.0",
|
"highlight.run": "^9.14.0",
|
||||||
"is-base64": "^1.1.0",
|
"is-base64": "^1.1.0",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
@@ -53,7 +54,7 @@
|
|||||||
"nodemailer": "^6.10.0",
|
"nodemailer": "^6.10.0",
|
||||||
"pdf-lib": "^1.17.1",
|
"pdf-lib": "^1.17.1",
|
||||||
"postcss-nested": "^7.0.2",
|
"postcss-nested": "^7.0.2",
|
||||||
"puppeteer": "^24.7.2",
|
"puppeteer": "^24.15.0",
|
||||||
"radix-svelte-icons": "^1.0.0",
|
"radix-svelte-icons": "^1.0.0",
|
||||||
"sass": "^1.83.4",
|
"sass": "^1.83.4",
|
||||||
"sharp": "^0.33.5",
|
"sharp": "^0.33.5",
|
||||||
|
|||||||
49
prisma/migrations/20250804180940_provisionen/migration.sql
Normal file
49
prisma/migrations/20250804180940_provisionen/migration.sql
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- The `fenster_art_1` column on the `BedarfsausweisWohnen` table would be dropped and recreated. This will lead to data loss if there is data in the column.
|
||||||
|
- The `fenster_art_2` column on the `BedarfsausweisWohnen` table would be dropped and recreated. This will lead to data loss if there is data in the column.
|
||||||
|
- The `dachfenster_art` column on the `BedarfsausweisWohnen` table would be dropped and recreated. This will lead to data loss if there is data in the column.
|
||||||
|
- The `haustuer_art` column on the `BedarfsausweisWohnen` table would be dropped and recreated. This will lead to data loss if there is data in the column.
|
||||||
|
- The `dach_daemmung` column on the `BedarfsausweisWohnen` table would be dropped and recreated. This will lead to data loss if there is data in the column.
|
||||||
|
- The `decke_daemmung` column on the `BedarfsausweisWohnen` table would be dropped and recreated. This will lead to data loss if there is data in the column.
|
||||||
|
- The `aussenwand_daemmung` column on the `BedarfsausweisWohnen` table would be dropped and recreated. This will lead to data loss if there is data in the column.
|
||||||
|
- The `boden_daemmung` column on the `BedarfsausweisWohnen` table would be dropped and recreated. This will lead to data loss if there is data in the column.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- AlterEnum
|
||||||
|
ALTER TYPE "BenutzerRolle" ADD VALUE 'RESELLER';
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "BedarfsausweisWohnen" DROP COLUMN "fenster_art_1",
|
||||||
|
ADD COLUMN "fenster_art_1" DOUBLE PRECISION,
|
||||||
|
DROP COLUMN "fenster_art_2",
|
||||||
|
ADD COLUMN "fenster_art_2" DOUBLE PRECISION,
|
||||||
|
DROP COLUMN "dachfenster_art",
|
||||||
|
ADD COLUMN "dachfenster_art" DOUBLE PRECISION,
|
||||||
|
DROP COLUMN "haustuer_art",
|
||||||
|
ADD COLUMN "haustuer_art" DOUBLE PRECISION,
|
||||||
|
DROP COLUMN "dach_daemmung",
|
||||||
|
ADD COLUMN "dach_daemmung" DOUBLE PRECISION,
|
||||||
|
DROP COLUMN "decke_daemmung",
|
||||||
|
ADD COLUMN "decke_daemmung" DOUBLE PRECISION,
|
||||||
|
DROP COLUMN "aussenwand_daemmung",
|
||||||
|
ADD COLUMN "aussenwand_daemmung" DOUBLE PRECISION,
|
||||||
|
DROP COLUMN "boden_daemmung",
|
||||||
|
ADD COLUMN "boden_daemmung" DOUBLE PRECISION;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Provisionen" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"ausweisart" TEXT NOT NULL,
|
||||||
|
"provision_prozent" DOUBLE PRECISION NOT NULL,
|
||||||
|
"provision_betrag" DOUBLE PRECISION NOT NULL,
|
||||||
|
"benutzer_id" VARCHAR(11),
|
||||||
|
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updated_at" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "Provisionen_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "Provisionen" ADD CONSTRAINT "Provisionen_benutzer_id_fkey" FOREIGN KEY ("benutzer_id") REFERENCES "benutzer"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- The primary key for the `Provisionen` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||||
|
- The `id` column on the `Provisionen` table would be dropped and recreated. This will lead to data loss if there is data in the column.
|
||||||
|
- Changed the type of `ausweisart` on the `Provisionen` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Provisionen" DROP CONSTRAINT "Provisionen_pkey",
|
||||||
|
DROP COLUMN "id",
|
||||||
|
ADD COLUMN "id" SERIAL NOT NULL,
|
||||||
|
DROP COLUMN "ausweisart",
|
||||||
|
ADD COLUMN "ausweisart" "Ausweisart" NOT NULL,
|
||||||
|
ADD CONSTRAINT "Provisionen_pkey" PRIMARY KEY ("id");
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
enum BenutzerRolle {
|
enum BenutzerRolle {
|
||||||
USER
|
USER
|
||||||
ADMIN
|
ADMIN
|
||||||
|
RESELLER
|
||||||
}
|
}
|
||||||
|
|
||||||
model Benutzer {
|
model Benutzer {
|
||||||
@@ -50,6 +51,7 @@ model Benutzer {
|
|||||||
events Event[]
|
events Event[]
|
||||||
|
|
||||||
@@map("benutzer")
|
@@map("benutzer")
|
||||||
|
Provisionen Provisionen[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
10
prisma/schema/Provisionen.prisma
Normal file
10
prisma/schema/Provisionen.prisma
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
model Provisionen {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
ausweisart Ausweisart
|
||||||
|
provision_prozent Float
|
||||||
|
provision_betrag Float
|
||||||
|
benutzer_id String? @db.VarChar(11)
|
||||||
|
benutzer Benutzer? @relation(fields: [benutzer_id], references: [id])
|
||||||
|
created_at DateTime @default(now())
|
||||||
|
updated_at DateTime @updatedAt
|
||||||
|
}
|
||||||
@@ -4,19 +4,35 @@
|
|||||||
BUCKET_NAME="ibc-db-backup"
|
BUCKET_NAME="ibc-db-backup"
|
||||||
ENDPOINT_URL="https://s3.eu-central-3.ionoscloud.com"
|
ENDPOINT_URL="https://s3.eu-central-3.ionoscloud.com"
|
||||||
LOCAL_DOWNLOAD_DIR="./" # Where to save the file
|
LOCAL_DOWNLOAD_DIR="./" # Where to save the file
|
||||||
|
DATABASE_NAME=database
|
||||||
|
|
||||||
# === Check if a custom file is given as a command line argument ===
|
# === Check if a custom file is given as a command line argument ===
|
||||||
if [ $# -eq 1 ]; then
|
if [ $# -eq 1 ]; then
|
||||||
CUSTOM_FILE="$1"
|
CUSTOM_FILE="$1"
|
||||||
echo "🔍 Using custom file: $CUSTOM_FILE"
|
echo "🔍 Using custom file: $CUSTOM_FILE"
|
||||||
# Check if the file exists
|
# Check if file exists locally
|
||||||
if [ ! -f "$CUSTOM_FILE" ]; then
|
if [ ! -f "$CUSTOM_FILE" ]; then
|
||||||
echo "❌ Custom file does not exist: $CUSTOM_FILE"
|
# Check if the file exists on the remote
|
||||||
|
if ! aws s3api head-object --bucket "$BUCKET_NAME" --key "$CUSTOM_FILE" --endpoint-url "$ENDPOINT_URL" > /dev/null 2>&1; then
|
||||||
|
echo "❌ Custom file does not exist in S3 bucket or locally."
|
||||||
exit 1
|
exit 1
|
||||||
|
else
|
||||||
|
echo "📥 Downloading $CUSTOM_FILE from S3"
|
||||||
|
aws s3 cp "s3://$BUCKET_NAME/$CUSTOM_FILE" "$LOCAL_DOWNLOAD_DIR" \
|
||||||
|
--endpoint-url "$ENDPOINT_URL"
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
LATEST_FILE="$CUSTOM_FILE"
|
LATEST_FILE="$CUSTOM_FILE"
|
||||||
FILENAME=$(basename "$LATEST_FILE")
|
FILENAME=$(basename "$LATEST_FILE")
|
||||||
|
if [[ "$FILENAME" == *.br ]]; then
|
||||||
|
echo "🗜️ Detected compressed file: $FILENAME"
|
||||||
|
# Remove the .br suffix for the SQL file
|
||||||
SQL_FILE="${FILENAME%.br}" # Remove .br suffix
|
SQL_FILE="${FILENAME%.br}" # Remove .br suffix
|
||||||
|
brotli -d "$FILENAME"
|
||||||
|
else
|
||||||
|
SQL_FILE=$FILENAME
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo "🔍 No custom file provided, searching for latest .sql.br file in S3"
|
echo "🔍 No custom file provided, searching for latest .sql.br file in S3"
|
||||||
|
|
||||||
@@ -36,22 +52,27 @@ else
|
|||||||
echo "🔍 Latest file found: $LATEST_FILE"
|
echo "🔍 Latest file found: $LATEST_FILE"
|
||||||
FILENAME=$(basename "$LATEST_FILE")
|
FILENAME=$(basename "$LATEST_FILE")
|
||||||
SQL_FILE="${FILENAME%.br}" # Remove .br suffix
|
SQL_FILE="${FILENAME%.br}" # Remove .br suffix
|
||||||
|
|
||||||
echo "📥 Downloading $LATEST_FILE"
|
echo "📥 Downloading $LATEST_FILE"
|
||||||
aws s3 cp "s3://$BUCKET_NAME/$LATEST_FILE" "$LOCAL_DOWNLOAD_DIR" \
|
aws s3 cp "s3://$BUCKET_NAME/$LATEST_FILE" "$LOCAL_DOWNLOAD_DIR" \
|
||||||
--endpoint-url "$ENDPOINT_URL"
|
--endpoint-url "$ENDPOINT_URL"
|
||||||
|
|
||||||
|
brotli -d "$FILENAME"
|
||||||
|
echo "🗜️ Decompressed to $SQL_FILE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# === Decompress with Brotli ===
|
|
||||||
echo "🗜️ Decompressing $FILENAME -> $SQL_FILE"
|
|
||||||
brotli -d "$FILENAME"
|
|
||||||
|
|
||||||
# === Import into Postgres inside Docker ===
|
# === Import into Postgres inside Docker ===
|
||||||
echo "🐘 Importing into PostgreSQL (online-energieausweis-database-1:main)"
|
echo "🐘 Importing into PostgreSQL ($DATABASE_NAME:main)"
|
||||||
docker exec -i "online-energieausweis-database-1" env PGPASSWORD="hHMP8cd^N3SnzGRR" \
|
docker exec -i "$DATABASE_NAME" env PGPASSWORD="hHMP8cd^N3SnzGRR" \
|
||||||
psql -U "main" -d "main" < "$SQL_FILE"
|
psql -v ON_ERROR_STOP=0 -U main -d main < "$SQL_FILE"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
echo "✅ Import complete."
|
echo "✅ Import complete."
|
||||||
|
|
||||||
# === Optional: Clean up
|
# === Optional: Clean up
|
||||||
|
# If custom file was provided, do not delete it
|
||||||
|
if [ -z "$CUSTOM_FILE" ]; then
|
||||||
|
echo "🧹 Cleaning up downloaded files..."
|
||||||
rm "$FILENAME" "$SQL_FILE"
|
rm "$FILENAME" "$SQL_FILE"
|
||||||
|
fi
|
||||||
@@ -35,6 +35,8 @@ export const createCaller = createCallerFactory({
|
|||||||
"user/self": await import("../src/pages/api/user/self.ts"),
|
"user/self": await import("../src/pages/api/user/self.ts"),
|
||||||
"verbrauchsausweis-gewerbe/[id]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[id].ts"),
|
"verbrauchsausweis-gewerbe/[id]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[id].ts"),
|
||||||
"verbrauchsausweis-gewerbe": await import("../src/pages/api/verbrauchsausweis-gewerbe/index.ts"),
|
"verbrauchsausweis-gewerbe": await import("../src/pages/api/verbrauchsausweis-gewerbe/index.ts"),
|
||||||
|
"user": await import("../src/pages/api/user/index.ts"),
|
||||||
|
"user/self": await import("../src/pages/api/user/self.ts"),
|
||||||
"verbrauchsausweis-wohnen/[id]": await import("../src/pages/api/verbrauchsausweis-wohnen/[id].ts"),
|
"verbrauchsausweis-wohnen/[id]": await import("../src/pages/api/verbrauchsausweis-wohnen/[id].ts"),
|
||||||
"verbrauchsausweis-wohnen": await import("../src/pages/api/verbrauchsausweis-wohnen/index.ts"),
|
"verbrauchsausweis-wohnen": await import("../src/pages/api/verbrauchsausweis-wohnen/index.ts"),
|
||||||
"webhooks/mollie": await import("../src/pages/api/webhooks/mollie.ts"),
|
"webhooks/mollie": await import("../src/pages/api/webhooks/mollie.ts"),
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Aufnahme, BedarfsausweisWohnen, Enums, Objekt, Rechnung, VerbrauchsausweisGewerbe, VerbrauchsausweisWohnen } from "#lib/server/prisma.js";
|
import { Aufnahme, BedarfsausweisWohnen, Enums, Objekt, Provisionen, Rechnung, VerbrauchsausweisGewerbe, VerbrauchsausweisWohnen } from "#lib/server/prisma.js";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { DatePicker } from "@svelte-plugins/datepicker"
|
import { DatePicker } from "@svelte-plugins/datepicker"
|
||||||
export let bestellungen: (Rechnung & {
|
export let bestellungen: (Rechnung & {
|
||||||
ausweis: (VerbrauchsausweisWohnen | BedarfsausweisWohnen | VerbrauchsausweisGewerbe) & { aufnahme: Aufnahme & { objekt: Objekt }}
|
ausweis: (VerbrauchsausweisWohnen | BedarfsausweisWohnen | VerbrauchsausweisGewerbe) & { aufnahme: Aufnahme & { objekt: Objekt }}
|
||||||
})[];
|
})[];
|
||||||
export let provisionen: Record<Enums.Ausweisart, number>;
|
export let provisionen: Provisionen[];
|
||||||
export let partnerCodeErstesMal: Date;
|
|
||||||
export let email: string;
|
export let email: string;
|
||||||
|
export let startdatum: Date;
|
||||||
|
export let enddatum: Date;
|
||||||
|
|
||||||
const bestellungenNachMonat: Record<string, (typeof bestellungen)> = {};
|
const bestellungenNachMonat: Record<string, (typeof bestellungen)> = {};
|
||||||
for (const bestellung of bestellungen) {
|
for (const bestellung of bestellungen) {
|
||||||
@@ -26,11 +27,9 @@
|
|||||||
"09": "September", "10": "Oktober", "11": "November", "12": "Dezember"
|
"09": "September", "10": "Oktober", "11": "November", "12": "Dezember"
|
||||||
};
|
};
|
||||||
|
|
||||||
function getMonthlyPeriods(minTime?: Date): moment.Moment[] {
|
function getMonthlyPeriods(from: Date, to: Date): moment.Moment[] {
|
||||||
const min = minTime ? moment(minTime) : moment();
|
const start = moment(from).startOf('month');
|
||||||
const start = min.clone().startOf('month');
|
const end = moment(to).endOf('month');
|
||||||
|
|
||||||
const end = moment().add(1, 'month').startOf('month');
|
|
||||||
|
|
||||||
const monthsArray: moment.Moment[] = [];
|
const monthsArray: moment.Moment[] = [];
|
||||||
const current = start.clone();
|
const current = start.clone();
|
||||||
@@ -43,14 +42,12 @@
|
|||||||
return monthsArray.reverse(); // Most recent month first
|
return monthsArray.reverse(); // Most recent month first
|
||||||
}
|
}
|
||||||
|
|
||||||
const periods = getMonthlyPeriods(partnerCodeErstesMal)
|
const periods = getMonthlyPeriods(startdatum, enddatum)
|
||||||
|
|
||||||
|
|
||||||
let isOpen = false;
|
let isOpen = false;
|
||||||
export let startDate = moment(partnerCodeErstesMal).startOf('month').toDate();
|
$: formatiertesStartDatum = moment(startdatum).format("DD.MM.YYYY");
|
||||||
export let endDate = moment().endOf('month').toDate();
|
$: formatiertesEndDatum = moment(enddatum).format("DD.MM.YYYY");
|
||||||
$: formattedStartDate = moment(startDate).format("DD.MM.YYYY");
|
|
||||||
$: formattedEndDate = moment(endDate).format("DD.MM.YYYY");
|
|
||||||
function toggleDatePicker() {
|
function toggleDatePicker() {
|
||||||
isOpen = !isOpen;
|
isOpen = !isOpen;
|
||||||
}
|
}
|
||||||
@@ -62,14 +59,14 @@
|
|||||||
|
|
||||||
<div class="fixed top-0 left-0 right-0 bg-white p-4 shadow z-10">
|
<div class="fixed top-0 left-0 right-0 bg-white p-4 shadow z-10">
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<DatePicker bind:isOpen bind:startDate bind:endDate isRange={true} onDateChange={onChange} isMultipane={true}>
|
<DatePicker bind:isOpen bind:startDate={startdatum} bind:endDate={enddatum} isRange={true} onDateChange={onChange} isMultipane={true}>
|
||||||
<input type="text" class="w-min" readonly value={`${formattedStartDate} - ${formattedEndDate}`} on:click={toggleDatePicker} />
|
<input type="text" class="w-min" readonly value={`${formatiertesStartDatum} - ${formatiertesEndDatum}`} on:click={toggleDatePicker} />
|
||||||
</DatePicker>
|
</DatePicker>
|
||||||
<p>Abrechnungsübersicht für <strong>{email}</strong></p>
|
<p>Abrechnungsübersicht für <strong>{email}</strong></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<main class="my-24 flex justify-center max-w-6xl mx-auto px-4">
|
<main class="my-24 flex flex-col justify-center max-w-6xl mx-auto px-4">
|
||||||
{#if !bestellungen || bestellungen.length === 0}
|
{#if !bestellungen || bestellungen.length === 0}
|
||||||
<p class="text-center text-gray-500">Keine Bestellungen gefunden.</p>
|
<p class="text-center text-gray-500">Keine Bestellungen gefunden.</p>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -78,44 +75,60 @@
|
|||||||
{#if jahrMonat in bestellungenNachMonat && bestellungenNachMonat[jahrMonat].length > 0}
|
{#if jahrMonat in bestellungenNachMonat && bestellungenNachMonat[jahrMonat].length > 0}
|
||||||
<!-- Echo dropdown foreach month. -->
|
<!-- Echo dropdown foreach month. -->
|
||||||
{@const provisionMonat = bestellungenNachMonat[jahrMonat].reduce((acc, bestellung) => {
|
{@const provisionMonat = bestellungenNachMonat[jahrMonat].reduce((acc, bestellung) => {
|
||||||
return acc + provisionen[bestellung.ausweis.ausweisart] || 0;
|
return acc + (provisionen.find((p) => p.ausweisart === bestellung.ausweis.ausweisart)?.provision_betrag || 0);
|
||||||
}, 0) * 1.19}
|
}, 0) * 1.19}
|
||||||
|
|
||||||
<!-- <div onclick="$(this).nextUntil('.dropdown_month').filter('table').toggle(); $('#betrag_gesamt').html('Abrechnungsbetrag $month_name: <b>$provision_month €</b>')" class='dropdown_month'>
|
<details class="group" open>
|
||||||
<p>$month_name $year_name - Klicke, um Tabelle anzuzeigen</p>
|
<summary class="flex justify-between items-center cursor-pointer p-4 bg-gray-100 hover:bg-gray-200">
|
||||||
<a target='_blank' rel='noreferrer noopener' href='/user/abrechnung/pdf.php?month={dt.format("m")}&year={dt.format("Y")}'>PDF Ansehen</a>
|
<span class="font-semibold">{moment(dt).format("MMMM YYYY")}</span>
|
||||||
</div> -->
|
<div class="flex flex-row gap-4 items-center">
|
||||||
|
<span class="text-gray-500">{provisionMonat.toFixed(2)} €</span>
|
||||||
|
<svg class="w-4 h-4 transition-transform duration-300 group-open:rotate-180" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<polyline points="6 9 12 15 18 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</summary>
|
||||||
|
<div class="p-4">
|
||||||
<table class="w-full mb-4 border-collapse border border-gray-300">
|
<table class="w-full mb-4 border-collapse border border-gray-300">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="bg-primary text-white">
|
<tr class="bg-primary text-white w-full">
|
||||||
<td class="text-center font-bold">ID</td>
|
<td class="text-center p-2 font-bold">ID</td>
|
||||||
<td class="text-center font-bold">DATUM</td>
|
<td class="text-center p-2 font-bold">Datum</td>
|
||||||
<td class="text-center font-bold">GEBÄUDEADRESSE </td>
|
<td class="text-center p-2 font-bold">Ausweis</td>
|
||||||
<td class="text-center font-bold">PLZ </td>
|
<td class="text-center p-2 font-bold">Provision in %</td>
|
||||||
<td class="text-center font-bold">ORT </td>
|
<td class="text-center p-2 font-bold">Betrag Netto</td>
|
||||||
<td class="text-center font-bold">AUSWEIS</td>
|
|
||||||
<td class="text-center font-bold w-48">BETRAG NETTO</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="text-sm">
|
<tbody class="text-sm">
|
||||||
<tr class="bg-secondary text-white">
|
|
||||||
<td class="text-center font-bold" colspan="6">{months[dt.format("MM")]} {dt.format("YYYY")}</td>
|
|
||||||
<td class="text-right font-bold w-48" style="font-family: monospace;">{provisionMonat.toFixed(2)} €</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
{#each bestellungenNachMonat[jahrMonat] as bestellung}
|
{#each bestellungenNachMonat[jahrMonat] as bestellung}
|
||||||
{@const provisionBestellung = provisionen[bestellung.ausweis.ausweisart] || 0}
|
{@const provisionBestellung = provisionen.find((p) => p.ausweisart === bestellung.ausweis.ausweisart)}
|
||||||
<tr>
|
<tr class="border-b border-gray-300 hover:bg-gray-100">
|
||||||
<td class="text-center px-4 w-24" style="font-family: monospace;">{bestellung.id}</td>
|
<td class="text-center py-2 px-4 w-24" style="font-family: monospace;">{bestellung.ausweis.id}</td>
|
||||||
<td class="text-center font-bold w-32">{moment(bestellung.created_at).format("DD.MM.YYYY")}</td>
|
<td class="text-center py-2 font-bold w-32">{moment(bestellung.created_at).format("DD.MM.YYYY HH:mm")}</td>
|
||||||
<td class="text-left w-64">{bestellung.ausweis.aufnahme.objekt.adresse}</td>
|
<td class="text-center py-2 w-32">{bestellung.ausweis.ausweisart}</td>
|
||||||
<td class="text-center w-16">{bestellung.ausweis.aufnahme.objekt.plz}</td>
|
<td class="text-center py-2 w-32">{provisionBestellung?.provision_prozent || 0} %</td>
|
||||||
<td class="text-left w-64">{bestellung.ausweis.aufnahme.objekt.ort}</td>
|
<td class="text-right py-2 w-24" style="font-family: monospace;">{provisionBestellung?.provision_betrag.toFixed(2)} €</td>
|
||||||
<td class="text-center w-32">{bestellung.ausweis.ausweisart}</td>
|
|
||||||
<td class="text-right w-48" style="font-family: monospace;">{provisionBestellung.toFixed(2)} €</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
{:else if !bestellungenNachMonat[jahrMonat] || bestellungenNachMonat[jahrMonat].length === 0}
|
||||||
|
<details class="group">
|
||||||
|
<summary class="flex justify-between items-center cursor-pointer p-4 bg-gray-100 hover:bg-gray-200">
|
||||||
|
<span class="font-semibold">{moment(dt).format("MMMM YYYY")}</span>
|
||||||
|
<div class="flex flex-row gap-4 items-center">
|
||||||
|
<span class="text-gray-500">Keine Bestellungen gefunden</span>
|
||||||
|
<svg class="w-4 h-4 transition-transform duration-300 group-open:rotate-180" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<polyline points="6 9 12 15 18 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</summary>
|
||||||
|
<div class="p-4 border-t border-gray-200">
|
||||||
|
<p class="text-gray-500">Für diesen Monat liegen uns keine Bestellungen über ihren Resellercode vor.</p>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</main>
|
</main>
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
CaretDown,
|
CaretDown,
|
||||||
MagnifyingGlass,
|
MagnifyingGlass,
|
||||||
} from "radix-svelte-icons";
|
} from "radix-svelte-icons";
|
||||||
import { Benutzer } from "#lib/server/prisma.js";
|
import { Benutzer, Enums } from "#lib/server/prisma.js";
|
||||||
|
|
||||||
export let lightTheme: boolean;
|
export let lightTheme: boolean;
|
||||||
export let benutzer: Benutzer;
|
export let benutzer: Benutzer;
|
||||||
@@ -70,7 +70,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<!-- <a href="/dashboard/abrechnung" class="button ">Monatliche Abrechnung</a> -->
|
{#if benutzer.rolle === Enums.BenutzerRolle.RESELLER}
|
||||||
|
<a href="/dashboard/abrechnung" class="button ">Monatliche Abrechnung</a>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr class="border-gray-600" />
|
<hr class="border-gray-600" />
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export type Lueftungskonzept = (typeof Lueftungskonzept)[keyof typeof Lueftungsk
|
|||||||
export const BenutzerRolle = {
|
export const BenutzerRolle = {
|
||||||
USER: "USER",
|
USER: "USER",
|
||||||
ADMIN: "ADMIN",
|
ADMIN: "ADMIN",
|
||||||
|
RESELLER: "RESELLER",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type BenutzerRolle = (typeof BenutzerRolle)[keyof typeof BenutzerRolle];
|
export type BenutzerRolle = (typeof BenutzerRolle)[keyof typeof BenutzerRolle];
|
||||||
|
|||||||
@@ -38,19 +38,19 @@ export const BedarfsausweisWohnenSchema = z.object({
|
|||||||
volumen: z.number().nullish(),
|
volumen: z.number().nullish(),
|
||||||
dicht: z.boolean().nullish(),
|
dicht: z.boolean().nullish(),
|
||||||
fenster_flaeche_1: z.number().nullish(),
|
fenster_flaeche_1: z.number().nullish(),
|
||||||
fenster_art_1: z.string().nullish(),
|
fenster_art_1: z.number().nullish(),
|
||||||
fenster_flaeche_2: z.number().nullish(),
|
fenster_flaeche_2: z.number().nullish(),
|
||||||
fenster_art_2: z.string().nullish(),
|
fenster_art_2: z.number().nullish(),
|
||||||
dachfenster_flaeche: z.number().nullish(),
|
dachfenster_flaeche: z.number().nullish(),
|
||||||
dachfenster_art: z.string().nullish(),
|
dachfenster_art: z.number().nullish(),
|
||||||
haustuer_flaeche: z.number().nullish(),
|
haustuer_flaeche: z.number().nullish(),
|
||||||
haustuer_art: z.string().nullish(),
|
haustuer_art: z.number().nullish(),
|
||||||
dach_bauart: z.string().nullish(),
|
dach_bauart: z.string().nullish(),
|
||||||
decke_bauart: z.string().nullish(),
|
decke_bauart: z.string().nullish(),
|
||||||
dach_daemmung: z.string().nullish(),
|
dach_daemmung: z.number().nullish(),
|
||||||
decke_daemmung: z.string().nullish(),
|
decke_daemmung: z.number().nullish(),
|
||||||
aussenwand_daemmung: z.string().nullish(),
|
aussenwand_daemmung: z.number().nullish(),
|
||||||
boden_daemmung: z.string().nullish(),
|
boden_daemmung: z.number().nullish(),
|
||||||
aussenwand_bauart: z.string().nullish(),
|
aussenwand_bauart: z.string().nullish(),
|
||||||
boden_bauart: z.string().nullish(),
|
boden_bauart: z.string().nullish(),
|
||||||
warmwasser_verteilung: z.string().nullish(),
|
warmwasser_verteilung: z.string().nullish(),
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export * from "./gegnachweiswohnen"
|
|||||||
export * from "./klimafaktoren"
|
export * from "./klimafaktoren"
|
||||||
export * from "./objekt"
|
export * from "./objekt"
|
||||||
export * from "./postleitzahlen"
|
export * from "./postleitzahlen"
|
||||||
|
export * from "./provisionen"
|
||||||
export * from "./rechnung"
|
export * from "./rechnung"
|
||||||
export * from "./refreshtokens"
|
export * from "./refreshtokens"
|
||||||
export * from "./tickets"
|
export * from "./tickets"
|
||||||
|
|||||||
12
src/generated/zod/provisionen.ts
Normal file
12
src/generated/zod/provisionen.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import * as z from "zod"
|
||||||
|
import { Ausweisart } from "@prisma/client"
|
||||||
|
|
||||||
|
export const ProvisionenSchema = z.object({
|
||||||
|
id: z.number().int(),
|
||||||
|
ausweisart: z.nativeEnum(Ausweisart),
|
||||||
|
provision_prozent: z.number(),
|
||||||
|
provision_betrag: z.number(),
|
||||||
|
benutzer_id: z.string().nullish(),
|
||||||
|
created_at: z.date(),
|
||||||
|
updated_at: z.date(),
|
||||||
|
})
|
||||||
@@ -64,7 +64,7 @@ export const GET = defineApiRoute({
|
|||||||
const { id } = ctx.params;
|
const { id } = ctx.params;
|
||||||
|
|
||||||
const aufnahme = await prisma.aufnahme.findUnique({
|
const aufnahme = await prisma.aufnahme.findUnique({
|
||||||
where: user.rolle === Enums.BenutzerRolle.USER ? {
|
where: user.rolle !== Enums.BenutzerRolle.ADMIN ? {
|
||||||
id,
|
id,
|
||||||
benutzer_id: user.id
|
benutzer_id: user.id
|
||||||
} : { id },
|
} : { id },
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export const GET = defineApiRoute({
|
|||||||
const { id } = context.params;
|
const { id } = context.params;
|
||||||
|
|
||||||
const aufnahme = await prisma.aufnahme.findUnique({
|
const aufnahme = await prisma.aufnahme.findUnique({
|
||||||
where: user.rolle === Enums.BenutzerRolle.USER ? {
|
where: user.rolle !== Enums.BenutzerRolle.ADMIN ? {
|
||||||
id,
|
id,
|
||||||
benutzer_id: user.id
|
benutzer_id: user.id
|
||||||
} : { id },
|
} : { id },
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export const PATCH = defineApiRoute({
|
|||||||
data: input
|
data: input
|
||||||
})
|
})
|
||||||
|
|
||||||
if (user.rolle === Enums.BenutzerRolle.USER) {
|
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
||||||
await sendAusweisGespeichertMail(user, ctx.params.id as string)
|
await sendAusweisGespeichertMail(user, ctx.params.id as string)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export const PUT = defineApiRoute({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (user.rolle === Enums.BenutzerRolle.USER) {
|
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
||||||
await sendAusweisGespeichertMail(user, id)
|
await sendAusweisGespeichertMail(user, id)
|
||||||
}
|
}
|
||||||
return nachweis.id
|
return nachweis.id
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export const PATCH = defineApiRoute({
|
|||||||
},
|
},
|
||||||
data: input
|
data: input
|
||||||
})
|
})
|
||||||
if (user.rolle === Enums.BenutzerRolle.USER) {
|
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
||||||
await sendAusweisGespeichertMail(user, ctx.params.id as string)
|
await sendAusweisGespeichertMail(user, ctx.params.id as string)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export const PUT = defineApiRoute({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (user.rolle === Enums.BenutzerRolle.USER) {
|
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
||||||
await sendAusweisGespeichertMail(user, id)
|
await sendAusweisGespeichertMail(user, id)
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export const PATCH = defineApiRoute({
|
|||||||
},
|
},
|
||||||
data: input
|
data: input
|
||||||
})
|
})
|
||||||
if (user.rolle === Enums.BenutzerRolle.USER) {
|
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
||||||
await sendAusweisGespeichertMail(user, ctx.params.id as string)
|
await sendAusweisGespeichertMail(user, ctx.params.id as string)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ export const PUT = defineApiRoute({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (user.rolle === Enums.BenutzerRolle.USER) {
|
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
||||||
await sendAusweisGespeichertMail(user, id)
|
await sendAusweisGespeichertMail(user, id)
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export const PATCH = defineApiRoute({
|
|||||||
},
|
},
|
||||||
data: input
|
data: input
|
||||||
})
|
})
|
||||||
if (user.rolle === Enums.BenutzerRolle.USER) {
|
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
||||||
await sendAusweisGespeichertMail(user, ctx.params.id as string)
|
await sendAusweisGespeichertMail(user, ctx.params.id as string)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ export const PUT = defineApiRoute({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (user.rolle === Enums.BenutzerRolle.USER) {
|
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
||||||
await sendAusweisGespeichertMail(user, id)
|
await sendAusweisGespeichertMail(user, id)
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export const GET = defineApiRoute({
|
|||||||
const { id } = ctx.params;
|
const { id } = ctx.params;
|
||||||
|
|
||||||
const objekt = await prisma.objekt.findUnique({
|
const objekt = await prisma.objekt.findUnique({
|
||||||
where: user.rolle === Enums.BenutzerRolle.USER ? {
|
where: user.rolle !== Enums.BenutzerRolle.ADMIN ? {
|
||||||
id,
|
id,
|
||||||
benutzer_id: user.id
|
benutzer_id: user.id
|
||||||
} : { id },
|
} : { id },
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export const PATCH = defineApiRoute({
|
|||||||
data: input
|
data: input
|
||||||
})
|
})
|
||||||
|
|
||||||
if (user.rolle === Enums.BenutzerRolle.USER) {
|
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
||||||
await sendAusweisGespeichertMail(user, ctx.params.id as string)
|
await sendAusweisGespeichertMail(user, ctx.params.id as string)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -173,7 +173,7 @@ export const GET = defineApiRoute({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ausweis = await prisma.verbrauchsausweisGewerbe.findUnique({
|
const ausweis = await prisma.verbrauchsausweisGewerbe.findUnique({
|
||||||
where: user.rolle === Enums.BenutzerRolle.USER ? {
|
where: user.rolle !== Enums.BenutzerRolle.ADMIN ? {
|
||||||
id,
|
id,
|
||||||
benutzer_id: user.id
|
benutzer_id: user.id
|
||||||
} : { id },
|
} : { id },
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export const PATCH = defineApiRoute({
|
|||||||
data: input
|
data: input
|
||||||
})
|
})
|
||||||
|
|
||||||
if (user.rolle === Enums.BenutzerRolle.USER) {
|
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
||||||
await sendAusweisGespeichertMail(user, ctx.params.id as string)
|
await sendAusweisGespeichertMail(user, ctx.params.id as string)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -174,7 +174,7 @@ export const GET = defineApiRoute({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
|
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
|
||||||
where: user.rolle === Enums.BenutzerRolle.USER ? {
|
where: user.rolle !== Enums.BenutzerRolle.ADMIN ? {
|
||||||
id,
|
id,
|
||||||
benutzer_id: user.id
|
benutzer_id: user.id
|
||||||
} : { id },
|
} : { id },
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export const PUT = defineApiRoute({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (user.rolle === Enums.BenutzerRolle.USER) {
|
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
||||||
await sendAusweisGespeichertMail(user, id);
|
await sendAusweisGespeichertMail(user, id);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -18,12 +18,6 @@ if (!benutzer) {
|
|||||||
return Astro.redirect("/404");
|
return Astro.redirect("/404");
|
||||||
}
|
}
|
||||||
|
|
||||||
const provisionen = {
|
|
||||||
[Enums.Ausweisart.VerbrauchsausweisWohnen]: 10,
|
|
||||||
[Enums.Ausweisart.BedarfsausweisWohnen]: 10,
|
|
||||||
[Enums.Ausweisart.VerbrauchsausweisGewerbe]: 10,
|
|
||||||
};
|
|
||||||
|
|
||||||
// $kommission = db()->one("SELECT abr_va, abr_ba, abr_vanw FROM users WHERE resellercode = :resellercode", ["resellercode" => $resellercode]);
|
// $kommission = db()->one("SELECT abr_va, abr_ba, abr_vanw FROM users WHERE resellercode = :resellercode", ["resellercode" => $resellercode]);
|
||||||
// Select every entry from database where user was involved.
|
// Select every entry from database where user was involved.
|
||||||
let bestellungen;
|
let bestellungen;
|
||||||
@@ -152,7 +146,8 @@ if (start.isValid() && end.isValid()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wann wurde der partner_code zum ersten mal benutzt?
|
// Wann wurde der partner_code zum ersten mal benutzt?
|
||||||
const partnerCodeErstesMal = (
|
if (!startdatum) {
|
||||||
|
startdatum = (
|
||||||
await prisma.rechnung.findFirst({
|
await prisma.rechnung.findFirst({
|
||||||
select: {
|
select: {
|
||||||
created_at: true,
|
created_at: true,
|
||||||
@@ -184,22 +179,30 @@ const partnerCodeErstesMal = (
|
|||||||
created_at: "asc",
|
created_at: "asc",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)?.created_at;
|
)?.created_at || moment().startOf("month").toDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const provisionen = await prisma.provisionen.findMany({
|
||||||
|
where: {
|
||||||
|
benutzer_id: benutzer.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
let provision = 0;
|
let provision = 0;
|
||||||
const ausweisarten: string[] = [];
|
const ausweisarten: string[] = [];
|
||||||
for (const bestellung of bestellungen) {
|
for (const bestellung of bestellungen) {
|
||||||
if (bestellung.verbrauchsausweis_wohnen) {
|
if (bestellung.verbrauchsausweis_wohnen) {
|
||||||
ausweisarten.push(Enums.Ausweisart.VerbrauchsausweisWohnen);
|
ausweisarten.push(Enums.Ausweisart.VerbrauchsausweisWohnen);
|
||||||
provision += provisionen[Enums.Ausweisart.VerbrauchsausweisWohnen];
|
provision += provisionen.find((p) => p.ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen)?.provision_betrag || 0;
|
||||||
}
|
}
|
||||||
if (bestellung.bedarfsausweis_wohnen) {
|
if (bestellung.bedarfsausweis_wohnen) {
|
||||||
ausweisarten.push(Enums.Ausweisart.BedarfsausweisWohnen);
|
ausweisarten.push(Enums.Ausweisart.BedarfsausweisWohnen);
|
||||||
provision += provisionen[Enums.Ausweisart.BedarfsausweisWohnen];
|
provision += provisionen.find((p) => p.ausweisart === Enums.Ausweisart.BedarfsausweisWohnen)?.provision_betrag || 0;
|
||||||
}
|
}
|
||||||
if (bestellung.verbrauchsausweis_gewerbe) {
|
if (bestellung.verbrauchsausweis_gewerbe) {
|
||||||
ausweisarten.push(Enums.Ausweisart.VerbrauchsausweisGewerbe);
|
ausweisarten.push(Enums.Ausweisart.VerbrauchsausweisGewerbe);
|
||||||
provision += provisionen[Enums.Ausweisart.VerbrauchsausweisGewerbe];
|
provision += provisionen.find((p) => p.ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe)?.provision_betrag || 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
@@ -210,9 +213,8 @@ for (const bestellung of bestellungen) {
|
|||||||
extrahiereAusweisAusFeldMitMehrerenAusweisen(bestellung)
|
extrahiereAusweisAusFeldMitMehrerenAusweisen(bestellung)
|
||||||
)}
|
)}
|
||||||
{provisionen}
|
{provisionen}
|
||||||
{partnerCodeErstesMal}
|
startdatum={startdatum}
|
||||||
startDate={startdatum}
|
enddatum={enddatum}
|
||||||
endDate={enddatum}
|
|
||||||
email={benutzer.email}
|
email={benutzer.email}
|
||||||
client:load
|
client:load
|
||||||
/>
|
/>
|
||||||
@@ -220,15 +222,15 @@ for (const bestellung of bestellungen) {
|
|||||||
<div class="fixed bottom-0 left-0 right-0 bg-white p-4 shadow">
|
<div class="fixed bottom-0 left-0 right-0 bg-white p-4 shadow">
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<div>
|
<div>
|
||||||
<p id="betrag_gesamt">
|
<p>
|
||||||
Abrechnungsbetrag gesamt: <b>{provision} €</b>
|
Abrechnungsbetrag gesamt: <b>{provision.toFixed(2)} €</b>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<a
|
<a
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer noopener"
|
rel="noreferrer noopener"
|
||||||
class="bg-secondary text-white px-4 py-2 rounded-lg hover:bg-secondary-focus"
|
class="bg-secondary text-white px-4 py-2 rounded-lg hover:bg-secondary-focus"
|
||||||
href=`/user/abrechnung/pdf.php?month=${moment().subtract(1, "month").get("month")}&year=${moment().subtract(1, "month").get("year")}`
|
href=`/dashboard/abrechnung/monatlich.pdf?d=${moment().subtract(1, "month").format("YYYY-MM")}`
|
||||||
>PDF für letzten Monat generieren.</a
|
>PDF für letzten Monat generieren.</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
136
src/pages/dashboard/abrechnung/monatlich.pdf.astro
Normal file
136
src/pages/dashboard/abrechnung/monatlich.pdf.astro
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
---
|
||||||
|
import abrechnungTemplateHTML from "../../../templates/pdf/abrechnung.handlebars?raw";
|
||||||
|
import puppeteer from "puppeteer";
|
||||||
|
import Handlebars from "handlebars";
|
||||||
|
import moment from "moment";
|
||||||
|
import { getCurrentUser } from "#lib/server/user";
|
||||||
|
import { prisma } from "#lib/server/prisma";
|
||||||
|
import { extrahiereAusweisAusFeldMitMehrerenAusweisen } from "#lib/server/ausweis";
|
||||||
|
|
||||||
|
const datum = moment(Astro.url.searchParams.get("d"));
|
||||||
|
const benutzer = await getCurrentUser(Astro);
|
||||||
|
|
||||||
|
if (!benutzer) {
|
||||||
|
return Astro.redirect("/404");
|
||||||
|
}
|
||||||
|
|
||||||
|
let bestellungen = await prisma.rechnung.findMany({
|
||||||
|
where: {
|
||||||
|
partner_code: "immowelt",
|
||||||
|
OR: [
|
||||||
|
{
|
||||||
|
verbrauchsausweis_gewerbe: {
|
||||||
|
ausgestellt: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bedarfsausweis_wohnen: {
|
||||||
|
ausgestellt: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
verbrauchsausweis_wohnen: {
|
||||||
|
ausgestellt: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
AND: [
|
||||||
|
{
|
||||||
|
created_at: {
|
||||||
|
gte: datum.startOf("month").toDate(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
created_at: {
|
||||||
|
lte: datum.endOf("month").toDate(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
created_at: "desc",
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
bedarfsausweis_wohnen: {
|
||||||
|
include: {
|
||||||
|
aufnahme: {
|
||||||
|
include: {
|
||||||
|
objekt: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
verbrauchsausweis_gewerbe: {
|
||||||
|
include: {
|
||||||
|
aufnahme: {
|
||||||
|
include: {
|
||||||
|
objekt: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
verbrauchsausweis_wohnen: {
|
||||||
|
include: {
|
||||||
|
aufnahme: {
|
||||||
|
include: {
|
||||||
|
objekt: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const provisionen = await prisma.provisionen.findMany({
|
||||||
|
where: {
|
||||||
|
benutzer_id: benutzer.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const ausweisBestellungen = bestellungen.map(bestellung => extrahiereAusweisAusFeldMitMehrerenAusweisen(bestellung));
|
||||||
|
|
||||||
|
console.log(ausweisBestellungen);
|
||||||
|
|
||||||
|
|
||||||
|
const browser = await puppeteer.launch({
|
||||||
|
headless: true,
|
||||||
|
args: ["--no-sandbox", "--disable-setuid-sandbox"],
|
||||||
|
});
|
||||||
|
const page = await browser.newPage();
|
||||||
|
|
||||||
|
// Wir splitten die Daten in Blöcke auf, der erste Block hat 11 Einträge, die folgenden Blöcke haben 15 Einträge.
|
||||||
|
|
||||||
|
const blocks = [];
|
||||||
|
const firstBlock = ausweisBestellungen.slice(0, 16);
|
||||||
|
const remainingBlocks = ausweisBestellungen.slice(16);
|
||||||
|
|
||||||
|
blocks.push(firstBlock);
|
||||||
|
for (let i = 0; i < remainingBlocks.length; i += 20) {
|
||||||
|
blocks.push(remainingBlocks.slice(i, i + 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
Handlebars.registerHelper("get-provision-prozent", function (ausweisart) {
|
||||||
|
const provisionEintrag = provisionen.find((p) => p.ausweisart === ausweisart);
|
||||||
|
return provisionEintrag ? provisionEintrag.provision_prozent : 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
Handlebars.registerHelper("get-provision-betrag", function (ausweisart) {
|
||||||
|
const provisionEintrag = provisionen.find((p) => p.ausweisart === ausweisart);
|
||||||
|
return provisionEintrag ? provisionEintrag.provision_betrag.toFixed(2) : "0.00";
|
||||||
|
});
|
||||||
|
|
||||||
|
const template = Handlebars.compile(abrechnungTemplateHTML);
|
||||||
|
const html = template({ monat: datum.format("MMMM YYYY"), bestellungen: blocks });
|
||||||
|
await page.goto(`data:text/html;charset=UTF-8,${encodeURIComponent(html)}`, {
|
||||||
|
waitUntil: "networkidle0",
|
||||||
|
});
|
||||||
|
const pdf = await page.pdf({ path: "abrechnung.pdf", format: "A4" });
|
||||||
|
await browser.close();
|
||||||
|
|
||||||
|
return new Response(pdf, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/pdf",
|
||||||
|
"Content-Disposition": "attachment; filename=abrechnung.pdf",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
---
|
||||||
@@ -28,7 +28,7 @@ if (!user) {
|
|||||||
|
|
||||||
|
|
||||||
const aufnahme = await prisma.aufnahme.findUnique({
|
const aufnahme = await prisma.aufnahme.findUnique({
|
||||||
where: user.rolle === Enums.BenutzerRolle.USER ? {
|
where: user.rolle !== Enums.BenutzerRolle.ADMIN ? {
|
||||||
benutzer: {
|
benutzer: {
|
||||||
id: user.id
|
id: user.id
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ if (!user) {
|
|||||||
|
|
||||||
const totalPageCount = await prisma.aufnahme.count({
|
const totalPageCount = await prisma.aufnahme.count({
|
||||||
where:
|
where:
|
||||||
user.rolle === Enums.BenutzerRolle.USER
|
user.rolle !== Enums.BenutzerRolle.ADMIN
|
||||||
? {
|
? {
|
||||||
benutzer: {
|
benutzer: {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
@@ -27,7 +27,7 @@ const totalPageCount = await prisma.aufnahme.count({
|
|||||||
let ausweis;
|
let ausweis;
|
||||||
// Wir fragen den neuesten Ausweis ab
|
// Wir fragen den neuesten Ausweis ab
|
||||||
// Falls der Nutzer ein Admin ist dann kommt der ganz neueste ansonsten der neueste des eingeloggten Benutzers.
|
// Falls der Nutzer ein Admin ist dann kommt der ganz neueste ansonsten der neueste des eingeloggten Benutzers.
|
||||||
if (user.rolle === Enums.BenutzerRolle.USER) {
|
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
||||||
const adapter = getPrismaAusweisAdapter(id);
|
const adapter = getPrismaAusweisAdapter(id);
|
||||||
ausweis = await adapter?.findUnique({
|
ausweis = await adapter?.findUnique({
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
import { Enums, prisma } from "#lib/server/prisma";
|
import { Enums, prisma } from "#lib/server/prisma";
|
||||||
import UserLayout from "#layouts/DashboardLayout.astro";
|
import UserLayout from "#layouts/DashboardLayout.astro";
|
||||||
import { getCurrentUser } from "#lib/server/user";
|
import { getCurrentUser } from "#lib/server/user";
|
||||||
import moment from "moment";
|
|
||||||
|
|
||||||
const page = Number(Astro.url.searchParams.get("p"));
|
const page = Number(Astro.url.searchParams.get("p"));
|
||||||
|
|
||||||
@@ -14,7 +13,7 @@ if (!user) {
|
|||||||
|
|
||||||
const totalPageCount = await prisma.aufnahme.count({
|
const totalPageCount = await prisma.aufnahme.count({
|
||||||
where:
|
where:
|
||||||
user.rolle === Enums.BenutzerRolle.USER
|
user.rolle !== Enums.BenutzerRolle.ADMIN || Enums.BenutzerRolle.RESELLER
|
||||||
? {
|
? {
|
||||||
benutzer: {
|
benutzer: {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
@@ -23,14 +22,16 @@ const totalPageCount = await prisma.aufnahme.count({
|
|||||||
: {},
|
: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (page < 1 || page > totalPageCount) {
|
if ((page < 1 || page > totalPageCount) && totalPageCount > 0) {
|
||||||
return Astro.redirect("/dashboard/objekte?p=1");
|
return Astro.redirect("/dashboard/objekte?p=1");
|
||||||
|
} else if (totalPageCount === 0) {
|
||||||
|
return Astro.redirect("/dashboard/objekte/leer");
|
||||||
}
|
}
|
||||||
|
|
||||||
let result: { id: string; updated_at: Date }[] = [];
|
let result: { id: string; updated_at: Date }[] = [];
|
||||||
// Wir fragen den neuesten Ausweis ab
|
// Wir fragen den neuesten Ausweis ab
|
||||||
// Falls der Nutzer ein Admin ist dann kommt der ganz neueste ansonsten der neueste des eingeloggten Benutzers.
|
// Falls der Nutzer ein Admin ist dann kommt der ganz neueste ansonsten der neueste des eingeloggten Benutzers.
|
||||||
if (user.rolle === Enums.BenutzerRolle.USER) {
|
if (user.rolle !== Enums.BenutzerRolle.ADMIN || user.rolle === Enums.BenutzerRolle.RESELLER) {
|
||||||
result =
|
result =
|
||||||
await prisma.$queryRaw`SELECT id, updated_at FROM "VerbrauchsausweisWohnen" WHERE benutzer_id = ${user.id} UNION ALL
|
await prisma.$queryRaw`SELECT id, updated_at FROM "VerbrauchsausweisWohnen" WHERE benutzer_id = ${user.id} UNION ALL
|
||||||
SELECT id, updated_at FROM "VerbrauchsausweisGewerbe" WHERE benutzer_id = ${user.id} UNION ALL
|
SELECT id, updated_at FROM "VerbrauchsausweisGewerbe" WHERE benutzer_id = ${user.id} UNION ALL
|
||||||
@@ -40,15 +41,6 @@ if (user.rolle === Enums.BenutzerRolle.USER) {
|
|||||||
SELECT id, updated_at FROM "GEGNachweisGewerbe" WHERE benutzer_id = ${user.id}
|
SELECT id, updated_at FROM "GEGNachweisGewerbe" WHERE benutzer_id = ${user.id}
|
||||||
ORDER BY updated_at DESC LIMIT 1 OFFSET ${page - 1}`;
|
ORDER BY updated_at DESC LIMIT 1 OFFSET ${page - 1}`;
|
||||||
} else {
|
} else {
|
||||||
const date = moment().subtract(2, "hours").toDate()
|
|
||||||
|
|
||||||
// SELECT id, updated_at FROM "VerbrauchsausweisWohnen" WHERE created_at >= ${date} AND bestellt = ${true} UNION ALL
|
|
||||||
// SELECT id, updated_at FROM "VerbrauchsausweisGewerbe" WHERE created_at >= ${date} AND bestellt = ${true} UNION ALL
|
|
||||||
// SELECT id, updated_at FROM "BedarfsausweisWohnen" WHERE created_at >= ${date} AND bestellt = ${true} UNION ALL
|
|
||||||
// SELECT id, updated_at FROM "BedarfsausweisGewerbe" WHERE created_at >= ${date} AND bestellt = ${true} UNION ALL
|
|
||||||
// SELECT id, updated_at FROM "GEGNachweisWohnen" WHERE created_at >= ${date} AND bestellt = ${true} UNION ALL
|
|
||||||
// SELECT id, updated_at FROM "GEGNachweisGewerbe" WHERE created_at >= ${date} AND bestellt = ${true}
|
|
||||||
|
|
||||||
result =
|
result =
|
||||||
await prisma.$queryRaw`SELECT id, updated_at FROM "VerbrauchsausweisWohnen" WHERE ausgestellt = ${false} AND bestellt = ${true} UNION ALL
|
await prisma.$queryRaw`SELECT id, updated_at FROM "VerbrauchsausweisWohnen" WHERE ausgestellt = ${false} AND bestellt = ${true} UNION ALL
|
||||||
SELECT id, updated_at FROM "VerbrauchsausweisGewerbe" WHERE ausgestellt = ${false} AND bestellt = ${true} UNION ALL
|
SELECT id, updated_at FROM "VerbrauchsausweisGewerbe" WHERE ausgestellt = ${false} AND bestellt = ${true} UNION ALL
|
||||||
|
|||||||
15
src/pages/dashboard/objekte/leer.astro
Normal file
15
src/pages/dashboard/objekte/leer.astro
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
import DashboardLayout from "#layouts/DashboardLayout.astro";
|
||||||
|
import { getCurrentUser } from "#lib/server/user";
|
||||||
|
|
||||||
|
const user = await getCurrentUser(Astro);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return Astro.redirect("/auth/login");
|
||||||
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<DashboardLayout title="Objekte" user={user} besteller={null}>
|
||||||
|
<p>Sie haben bisher keine Ausweise erstellt. Klicken sie <a href="/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/">hier</a>, um einen neuen Ausweis zu erstellen.</p>
|
||||||
|
</DashboardLayout>
|
||||||
84
src/templates/pdf/abrechnung.handlebars
Normal file
84
src/templates/pdf/abrechnung.handlebars
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Abrechnung</title>
|
||||||
|
<link href="https://unpkg.com/tailwindcss@2.0.1/dist/tailwind.min.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{{#each bestellungen}}
|
||||||
|
<header class="p-12 flex flex-row items-center justify-between" style="border-bottom: 12px #f37e3c solid;">
|
||||||
|
<img src="https://online-energieausweis.org/images/header/logo-big.png" alt="" class="h-24">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<p>fon 040 · 209339850</p>
|
||||||
|
<p>fax 040 · 209339859</p>
|
||||||
|
<p class="font-semibold">online-energieausweis.org</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<article class="py-8 px-16">
|
||||||
|
{{#if @first}}
|
||||||
|
<div class="flex flex-col gap-4">
|
||||||
|
<div class="flex flex-row">
|
||||||
|
<p class="text-sm">IB Cornelsen · Katendeich 5A · 21035 Hamburg</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<p>Immowelt GmbH</p>
|
||||||
|
<p>Nordostpark 3-5</p>
|
||||||
|
<p>90411 Nürnberg</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
<div class="flex flex-col gap-4 mt-12">
|
||||||
|
{{#if @first}}
|
||||||
|
<div class="flex flex-row justify-between items-center">
|
||||||
|
<p class="font-semibold">Erzielte Conversions {{ @root.monat }}</p>
|
||||||
|
<p>Erstellt am 16.11.23</p>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
<table class="table border-collapse border border-black">
|
||||||
|
<thead>
|
||||||
|
<tr class="h-16">
|
||||||
|
<th class="text-center text-sm border-black border" style="background-color: #f37e3c;">ID - Datum</th>
|
||||||
|
<th class="text-center text-sm border-black border" style="background-color: #f37e3c;">Produkt</th>
|
||||||
|
<th class="text-center text-sm border-black border" style="background-color: #f37e3c;">Produktpreis</th>
|
||||||
|
<th class="text-center text-sm border-black border" style="background-color: #f37e3c;">Provision in %</th>
|
||||||
|
<th class="text-center text-sm border-black border" style="background-color: #f37e3c;">Betrag Netto</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{#each this}}
|
||||||
|
<tr>
|
||||||
|
{{#with ausweis}}
|
||||||
|
<td class="border-black border p-1">
|
||||||
|
<p class="text-sm">{{ id }}</p>
|
||||||
|
<p class="text-sm">{{ createdAt }}</p>
|
||||||
|
</td>
|
||||||
|
<td class=" border-black border p-1 text-sm text-center">
|
||||||
|
{{ ausweisart }}
|
||||||
|
</td>
|
||||||
|
{{/with}}
|
||||||
|
<td class=" border-black border p-1 font-semibold text-sm text-center">
|
||||||
|
{{ betrag }} €
|
||||||
|
</td>
|
||||||
|
{{#with ausweis}}
|
||||||
|
<td class=" border-black border p-1 text-sm text-center">
|
||||||
|
{{get-provision-prozent ausweisart}} %
|
||||||
|
</td>
|
||||||
|
<td class=" border-black border p-1 text-sm text-center">
|
||||||
|
{{get-provision-betrag ausweisart}} €
|
||||||
|
</td>
|
||||||
|
{{/with}}
|
||||||
|
</tr>
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
<footer class="px-16 py-6 flex flex-row justify-between items-center fixed bottom-0 left-0 w-full" style="border-top: 12px #f37e3c solid;">
|
||||||
|
<p class="font-semibold">Copyright © 2018 · IB Cornelsen</p>
|
||||||
|
<p class="font-semibold">info@online-energieausweis.org</p>
|
||||||
|
</footer>
|
||||||
|
{{/each}}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Config
|
# Config
|
||||||
CONTAINER_NAME="online-energieausweis-database-1"
|
CONTAINER_NAME="database"
|
||||||
DB_USER="main"
|
DB_USER="main"
|
||||||
DB_NAME="main"
|
DB_NAME="main"
|
||||||
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
|
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
|
||||||
@@ -39,40 +39,16 @@ fi
|
|||||||
|
|
||||||
if [[ "$SKIP_BACKUP" == false ]]; then
|
if [[ "$SKIP_BACKUP" == false ]]; then
|
||||||
echo "📦 Backup wird erstellt..."
|
echo "📦 Backup wird erstellt..."
|
||||||
docker exec -t "$CONTAINER_NAME" pg_dumpall -c -U "$DB_USER" | brotli > "$FILE_NAME"
|
docker exec -t "$CONTAINER_NAME" pg_dumpall -c -U "$DB_USER" | brotli --quality=1 > "$FILE_NAME"
|
||||||
echo "✅ Backup abgeschlossen: $FILE_NAME"
|
echo "✅ Backup abgeschlossen: $FILE_NAME"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "🧨 Alle Daten aus allen Tabellen werden gelöscht..."
|
echo "🧨 Alle Daten aus allen Tabellen werden gelöscht..."
|
||||||
|
|
||||||
# Generate and run TRUNCATE statements for all tables in the public schema
|
# Generate and run TRUNCATE statements for all tables in the public schema
|
||||||
docker exec -i "$CONTAINER_NAME" psql -U "$DB_USER" "$DB_NAME" <<'EOSQL'
|
docker exec -i "$CONTAINER_NAME" psql -U "$DB_USER" "postgres" <<'EOSQL'
|
||||||
DO $$
|
DROP DATABASE IF EXISTS main;
|
||||||
DECLARE
|
CREATE DATABASE main WITH OWNER main ENCODING 'UTF8';
|
||||||
r RECORD;
|
|
||||||
sql TEXT := '';
|
|
||||||
BEGIN
|
|
||||||
-- Truncate all tables
|
|
||||||
FOR r IN
|
|
||||||
SELECT tablename
|
|
||||||
FROM pg_tables
|
|
||||||
WHERE schemaname = 'public'
|
|
||||||
LOOP
|
|
||||||
sql := sql || FORMAT('TRUNCATE TABLE public.%I CASCADE;', r.tablename);
|
|
||||||
END LOOP;
|
|
||||||
|
|
||||||
-- Drop all sequences
|
|
||||||
FOR r IN
|
|
||||||
SELECT sequence_name
|
|
||||||
FROM information_schema.sequences
|
|
||||||
WHERE sequence_schema = 'public'
|
|
||||||
LOOP
|
|
||||||
sql := sql || FORMAT('DROP SEQUENCE IF EXISTS public.%I CASCADE;', r.sequence_name);
|
|
||||||
END LOOP;
|
|
||||||
|
|
||||||
EXECUTE sql;
|
|
||||||
END
|
|
||||||
$$;
|
|
||||||
EOSQL
|
EOSQL
|
||||||
|
|
||||||
echo "✅ Alle Tabellen gelöscht und Schema zurückgesetzt."
|
echo "✅ Alle Tabellen gelöscht und Schema zurückgesetzt."
|
||||||
|
|||||||
Reference in New Issue
Block a user