76
.github/workflows/auto-merge-staging-into-main.yml
vendored
Normal file
76
.github/workflows/auto-merge-staging-into-main.yml
vendored
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
name: Auto Merge Staging into Main
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 2 * * *' # 2:00 UTC = 4:00 Europäische Zeit
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
merge:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set Git user
|
||||||
|
run: |
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
|
||||||
|
- name: Fetch all branches
|
||||||
|
run: |
|
||||||
|
git fetch origin main
|
||||||
|
git fetch origin staging
|
||||||
|
|
||||||
|
- name: Check if main has commits not in staging
|
||||||
|
id: check
|
||||||
|
run: |
|
||||||
|
git fetch origin
|
||||||
|
if [ $(git rev-list --count origin/staging..origin/main) -gt 0 ]; then
|
||||||
|
echo "❌ Staging is behind main and requires manual merging."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Create PR from staging to main
|
||||||
|
id: create_pr
|
||||||
|
run: |
|
||||||
|
PR_URL=$(gh pr create --base main --head staging --title "Auto-merge staging into main" --body "This PR was created automatically by GitHub Actions. It merges the latest \`staging\` into \`main\`.")
|
||||||
|
echo "PR_URL=$PR_URL" >> $GITHUB_OUTPUT
|
||||||
|
PR_NUMBER=$(echo $PR_URL | awk -F'/' '{print $NF}')
|
||||||
|
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Enable auto-merge on PR
|
||||||
|
if: steps.create_pr.outputs.PR_NUMBER != ''
|
||||||
|
run: |
|
||||||
|
gh pr merge ${{ steps.create_pr.outputs.PR_NUMBER }} --merge --auto
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
|
||||||
|
notify_failure:
|
||||||
|
needs: merge
|
||||||
|
if: failure()
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Send Discord notification on failure
|
||||||
|
run: |
|
||||||
|
curl -H "Content-Type: application/json" \
|
||||||
|
-X POST \
|
||||||
|
-d "{\"content\": \"🚨 Auto-Merge fehlgeschlagen! Bitte manuell prüfen: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\"}" \
|
||||||
|
${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||||
|
|
||||||
|
notify_success:
|
||||||
|
needs: merge
|
||||||
|
if: success()
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Send Discord notification on success
|
||||||
|
run: |
|
||||||
|
curl -H "Content-Type: application/json" \
|
||||||
|
-X POST \
|
||||||
|
-d "{\"content\": \"✅ Auto-Merge ausgeführt! Ergebnis jetzt auf [GitHub](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) und [online-energieausweis.org](https://online-energieausweis.org) einsehen.\"}" \
|
||||||
|
${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||||
2
.github/workflows/dev-pipeline.yml
vendored
2
.github/workflows/dev-pipeline.yml
vendored
@@ -28,4 +28,4 @@ jobs:
|
|||||||
git clean -f -d
|
git clean -f -d
|
||||||
git pull origin dev
|
git pull origin dev
|
||||||
git status
|
git status
|
||||||
make prod
|
make prod-no-backup
|
||||||
28
.github/workflows/prevent-wrong-pr.yml
vendored
Normal file
28
.github/workflows/prevent-wrong-pr.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
name: PR Rules Enforcement
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- staging
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check-pr:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Validate Pull Request Sources
|
||||||
|
steps:
|
||||||
|
- name: Prevent dev merges
|
||||||
|
run: |
|
||||||
|
if [[ "${{ github.head_ref }}" == "dev" && "${{ github.base_ref }}" == "main" ]]; then
|
||||||
|
echo "ERROR: Merging 'dev' into 'main' is forbidden!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
- name: Allow only staging into main
|
||||||
|
if: github.base_ref == 'main'
|
||||||
|
run: |
|
||||||
|
if [[ "${{ github.head_ref }}" != "staging" ]]; then
|
||||||
|
echo "ERROR: Only 'staging' branch is allowed to merge into 'main'. Current: '${{ github.head_ref }}'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
9
Makefile
9
Makefile
@@ -10,7 +10,7 @@ PERSISTENT_DIR := $(HOME)/persistent/$(APP_NAME)
|
|||||||
BACKUP_FILENAME := $(HOME)/backups/$(shell date +"%Y-%m-%d_%H-%M-%S").sql.gz
|
BACKUP_FILENAME := $(HOME)/backups/$(shell date +"%Y-%m-%d_%H-%M-%S").sql.gz
|
||||||
|
|
||||||
online-energieausweis:
|
online-energieausweis:
|
||||||
bun run dev --host
|
NODE_ENV="development" bun run dev --host
|
||||||
|
|
||||||
dev: database online-energieausweis
|
dev: database online-energieausweis
|
||||||
|
|
||||||
@@ -30,6 +30,7 @@ run-database: stop-database
|
|||||||
docker volume create $(DB_VOLUME)
|
docker volume create $(DB_VOLUME)
|
||||||
docker build -t $(DB_CONTAINER_NAME) .
|
docker build -t $(DB_CONTAINER_NAME) .
|
||||||
docker run -d --name $(DB_CONTAINER_NAME) \
|
docker run -d --name $(DB_CONTAINER_NAME) \
|
||||||
|
--restart=always \
|
||||||
-e POSTGRES_USER=$(DB_USER) \
|
-e POSTGRES_USER=$(DB_USER) \
|
||||||
-e POSTGRES_PASSWORD=$(DB_PASSWORD) \
|
-e POSTGRES_PASSWORD=$(DB_PASSWORD) \
|
||||||
-p $(DB_PORT):5432 \
|
-p $(DB_PORT):5432 \
|
||||||
@@ -60,7 +61,9 @@ all:
|
|||||||
update-dwd-klimafaktoren-cron:
|
update-dwd-klimafaktoren-cron:
|
||||||
pm2 start bun --name "update-dwd-klimafaktoren-cron" --cron "0 12 28 * *" -- src/cronjobs/update-dwd-klimafaktoren.ts
|
pm2 start bun --name "update-dwd-klimafaktoren-cron" --cron "0 12 28 * *" -- src/cronjobs/update-dwd-klimafaktoren.ts
|
||||||
|
|
||||||
prod: install-dependencies prisma-studio backup-database-cronjob update-dwd-klimafaktoren-cron
|
prod: prod-no-backup backup-database-cronjob
|
||||||
|
|
||||||
|
prod-no-backup: install-dependencies prisma-studio update-dwd-klimafaktoren-cron
|
||||||
bun run build
|
bun run build
|
||||||
mkdir -p ~/logs
|
mkdir -p ~/logs
|
||||||
mkdir -p ~/persistent/online-energieausweis
|
mkdir -p ~/persistent/online-energieausweis
|
||||||
@@ -71,4 +74,4 @@ prod: install-dependencies prisma-studio backup-database-cronjob update-dwd-klim
|
|||||||
|
|
||||||
backup-database-cronjob:
|
backup-database-cronjob:
|
||||||
- pm2 delete daily-db-backup
|
- pm2 delete daily-db-backup
|
||||||
pm2 start bash --name "daily-db-backup" --cron "0 0 * * *" -- backup-database.bash
|
pm2 start bash --name "daily-db-backup" --no-autorestart --cron "0 0 * * *" -- backup-database.bash
|
||||||
@@ -19,7 +19,11 @@ echo "Uploaded $FILE_NAME"
|
|||||||
|
|
||||||
docker exec -t online-energieausweis-database-1 pg_dumpall -c -U main | brotli --best > $FILE_NAME_COMPLETE
|
docker exec -t online-energieausweis-database-1 pg_dumpall -c -U main | brotli --best > $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"
|
||||||
|
|
||||||
|
|||||||
3
bun.lock
3
bun.lock
@@ -15,6 +15,7 @@
|
|||||||
"@pdfme/common": "^5.2.16",
|
"@pdfme/common": "^5.2.16",
|
||||||
"@pdfme/generator": "^5.2.16",
|
"@pdfme/generator": "^5.2.16",
|
||||||
"@pdfme/ui": "^5.2.16",
|
"@pdfme/ui": "^5.2.16",
|
||||||
|
"@svelte-plugins/datepicker": "^1.0.11",
|
||||||
"@trpc/client": "^10.45.2",
|
"@trpc/client": "^10.45.2",
|
||||||
"@trpc/server": "^10.45.2",
|
"@trpc/server": "^10.45.2",
|
||||||
"astro": "^4.16.17",
|
"astro": "^4.16.17",
|
||||||
@@ -711,6 +712,8 @@
|
|||||||
|
|
||||||
"@smithy/util-waiter": ["@smithy/util-waiter@4.0.2", "", { "dependencies": { "@smithy/abort-controller": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-piUTHyp2Axx3p/kc2CIJkYSv0BAaheBQmbACZgQSSfWUumWNW+R1lL+H9PDBxKJkvOeEX+hKYEFiwO8xagL8AQ=="],
|
"@smithy/util-waiter": ["@smithy/util-waiter@4.0.2", "", { "dependencies": { "@smithy/abort-controller": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-piUTHyp2Axx3p/kc2CIJkYSv0BAaheBQmbACZgQSSfWUumWNW+R1lL+H9PDBxKJkvOeEX+hKYEFiwO8xagL8AQ=="],
|
||||||
|
|
||||||
|
"@svelte-plugins/datepicker": ["@svelte-plugins/datepicker@1.0.11", "", {}, "sha512-Tqc07QLyRkCpc3Glg6oRLTUApLtCrOh52d6vJ7L32QI17HrwvcDDjaH3LF3X1SBm3CWdMrnqfJp3xjUZmB4wzw=="],
|
||||||
|
|
||||||
"@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@2.5.3", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^1.0.4", "debug": "^4.3.4", "deepmerge": "^4.3.1", "kleur": "^4.1.5", "magic-string": "^0.30.3", "svelte-hmr": "^0.15.3", "vitefu": "^0.2.4" }, "peerDependencies": { "svelte": "^3.54.0 || ^4.0.0 || ^5.0.0-next.0", "vite": "^4.0.0" } }, "sha512-erhNtXxE5/6xGZz/M9eXsmI7Pxa6MS7jyTy06zN3Ck++ldrppOnOlJwHHTsMC7DHDQdgUp4NAc4cDNQ9eGdB/w=="],
|
"@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@2.5.3", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^1.0.4", "debug": "^4.3.4", "deepmerge": "^4.3.1", "kleur": "^4.1.5", "magic-string": "^0.30.3", "svelte-hmr": "^0.15.3", "vitefu": "^0.2.4" }, "peerDependencies": { "svelte": "^3.54.0 || ^4.0.0 || ^5.0.0-next.0", "vite": "^4.0.0" } }, "sha512-erhNtXxE5/6xGZz/M9eXsmI7Pxa6MS7jyTy06zN3Ck++ldrppOnOlJwHHTsMC7DHDQdgUp4NAc4cDNQ9eGdB/w=="],
|
||||||
|
|
||||||
"@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@1.0.4", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^2.2.0", "svelte": "^3.54.0 || ^4.0.0", "vite": "^4.0.0" } }, "sha512-zjiuZ3yydBtwpF3bj0kQNV0YXe+iKE545QGZVTaylW3eAzFr+pJ/cwK8lZEaRp4JtaJXhD5DyWAV4AxLh6DgaQ=="],
|
"@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@1.0.4", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^2.2.0", "svelte": "^3.54.0 || ^4.0.0", "vite": "^4.0.0" } }, "sha512-zjiuZ3yydBtwpF3bj0kQNV0YXe+iKE545QGZVTaylW3eAzFr+pJ/cwK8lZEaRp4JtaJXhD5DyWAV4AxLh6DgaQ=="],
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ version: '3'
|
|||||||
services:
|
services:
|
||||||
database:
|
database:
|
||||||
build: ./
|
build: ./
|
||||||
|
restart: always
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
"@pdfme/common": "^5.2.16",
|
"@pdfme/common": "^5.2.16",
|
||||||
"@pdfme/generator": "^5.2.16",
|
"@pdfme/generator": "^5.2.16",
|
||||||
"@pdfme/ui": "^5.2.16",
|
"@pdfme/ui": "^5.2.16",
|
||||||
|
"@svelte-plugins/datepicker": "^1.0.11",
|
||||||
"@trpc/client": "^10.45.2",
|
"@trpc/client": "^10.45.2",
|
||||||
"@trpc/server": "^10.45.2",
|
"@trpc/server": "^10.45.2",
|
||||||
"astro": "^4.16.17",
|
"astro": "^4.16.17",
|
||||||
|
|||||||
@@ -41,19 +41,19 @@ model BedarfsausweisWohnen {
|
|||||||
volumen Float?
|
volumen Float?
|
||||||
dicht Boolean?
|
dicht Boolean?
|
||||||
fenster_flaeche_1 Float?
|
fenster_flaeche_1 Float?
|
||||||
fenster_art_1 String?
|
fenster_art_1 Float?
|
||||||
fenster_flaeche_2 Float?
|
fenster_flaeche_2 Float?
|
||||||
fenster_art_2 String?
|
fenster_art_2 Float?
|
||||||
dachfenster_flaeche Float?
|
dachfenster_flaeche Float?
|
||||||
dachfenster_art String?
|
dachfenster_art Float?
|
||||||
haustuer_flaeche Float?
|
haustuer_flaeche Float?
|
||||||
haustuer_art String?
|
haustuer_art Float?
|
||||||
dach_bauart String? @db.VarChar
|
dach_bauart String? @db.VarChar
|
||||||
decke_bauart String? @db.VarChar
|
decke_bauart String? @db.VarChar
|
||||||
dach_daemmung String?
|
dach_daemmung Float?
|
||||||
decke_daemmung String?
|
decke_daemmung Float?
|
||||||
aussenwand_daemmung String?
|
aussenwand_daemmung Float?
|
||||||
boden_daemmung String?
|
boden_daemmung Float?
|
||||||
aussenwand_bauart String? @db.VarChar
|
aussenwand_bauart String? @db.VarChar
|
||||||
boden_bauart String? @db.VarChar
|
boden_bauart String? @db.VarChar
|
||||||
warmwasser_verteilung String? @db.VarChar
|
warmwasser_verteilung String? @db.VarChar
|
||||||
|
|||||||
@@ -2,30 +2,46 @@
|
|||||||
|
|
||||||
# === Configuration ===
|
# === Configuration ===
|
||||||
BUCKET_NAME="ibc-db-backup"
|
BUCKET_NAME="ibc-db-backup"
|
||||||
ENDPOINT_URL="https://s3-eu-central-1.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
|
||||||
|
|
||||||
# === Get latest file from IONOS S3 bucket ===
|
# === Check if a custom file is given as a command line argument ===
|
||||||
LATEST_FILE=$(aws s3api list-objects-v2 \
|
if [ $# -eq 1 ]; then
|
||||||
--bucket "$BUCKET_NAME" \
|
CUSTOM_FILE="$1"
|
||||||
--prefix "data-dump" \
|
echo "🔍 Using custom file: $CUSTOM_FILE"
|
||||||
--endpoint-url "$ENDPOINT_URL" \
|
# Check if the file exists
|
||||||
--query 'Contents | sort_by(@, &LastModified) | [-1].Key' \
|
if [ ! -f "$CUSTOM_FILE" ]; then
|
||||||
--output text)
|
echo "❌ Custom file does not exist: $CUSTOM_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
LATEST_FILE="$CUSTOM_FILE"
|
||||||
|
FILENAME=$(basename "$LATEST_FILE")
|
||||||
|
SQL_FILE="${FILENAME%.br}" # Remove .br suffix
|
||||||
|
else
|
||||||
|
echo "🔍 No custom file provided, searching for latest .sql.br file in S3"
|
||||||
|
|
||||||
# === Check if file was found ===
|
# === Get latest file from IONOS S3 bucket ===
|
||||||
if [ "$LATEST_FILE" == "None" ] || [ -z "$LATEST_FILE" ]; then
|
LATEST_FILE=$(aws s3api list-objects-v2 \
|
||||||
echo "❌ No matching .sql.br file found."
|
--bucket "$BUCKET_NAME" \
|
||||||
exit 1
|
--prefix "data-dump" \
|
||||||
|
--endpoint-url "$ENDPOINT_URL" \
|
||||||
|
--query 'Contents | sort_by(@, &LastModified) | [-1].Key' \
|
||||||
|
--output text)
|
||||||
|
|
||||||
|
# === Check if file was found ===
|
||||||
|
if [ "$LATEST_FILE" == "None" ] || [ -z "$LATEST_FILE" ]; then
|
||||||
|
echo "❌ No matching .sql.br file found."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "🔍 Latest file found: $LATEST_FILE"
|
||||||
|
FILENAME=$(basename "$LATEST_FILE")
|
||||||
|
SQL_FILE="${FILENAME%.br}" # Remove .br suffix
|
||||||
|
|
||||||
|
echo "📥 Downloading $LATEST_FILE"
|
||||||
|
aws s3 cp "s3://$BUCKET_NAME/$LATEST_FILE" "$LOCAL_DOWNLOAD_DIR" \
|
||||||
|
--endpoint-url "$ENDPOINT_URL"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
FILENAME=$(basename "$LATEST_FILE")
|
|
||||||
SQL_FILE="${FILENAME%.br}" # Remove .br suffix
|
|
||||||
|
|
||||||
echo "📥 Downloading $LATEST_FILE"
|
|
||||||
aws s3 cp "s3://$BUCKET_NAME/$LATEST_FILE" "$LOCAL_DOWNLOAD_DIR" \
|
|
||||||
--endpoint-url "$ENDPOINT_URL"
|
|
||||||
|
|
||||||
# === Decompress with Brotli ===
|
# === Decompress with Brotli ===
|
||||||
echo "🗜️ Decompressing $FILENAME -> $SQL_FILE"
|
echo "🗜️ Decompressing $FILENAME -> $SQL_FILE"
|
||||||
brotli -d "$FILENAME"
|
brotli -d "$FILENAME"
|
||||||
|
|||||||
@@ -12,25 +12,25 @@ export const createCaller = createCallerFactory({
|
|||||||
"admin/nicht-ausstellen": await import("../src/pages/api/admin/nicht-ausstellen.ts"),
|
"admin/nicht-ausstellen": await import("../src/pages/api/admin/nicht-ausstellen.ts"),
|
||||||
"admin/registriernummer": await import("../src/pages/api/admin/registriernummer.ts"),
|
"admin/registriernummer": await import("../src/pages/api/admin/registriernummer.ts"),
|
||||||
"admin/stornieren": await import("../src/pages/api/admin/stornieren.ts"),
|
"admin/stornieren": await import("../src/pages/api/admin/stornieren.ts"),
|
||||||
"aufnahme": await import("../src/pages/api/aufnahme/index.ts"),
|
|
||||||
"ausweise": await import("../src/pages/api/ausweise/index.ts"),
|
|
||||||
"auth/access-token": await import("../src/pages/api/auth/access-token.ts"),
|
"auth/access-token": await import("../src/pages/api/auth/access-token.ts"),
|
||||||
"auth/passwort-vergessen": await import("../src/pages/api/auth/passwort-vergessen.ts"),
|
"auth/passwort-vergessen": await import("../src/pages/api/auth/passwort-vergessen.ts"),
|
||||||
"auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"),
|
"auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"),
|
||||||
|
"ausweise": await import("../src/pages/api/ausweise/index.ts"),
|
||||||
"bedarfsausweis-gewerbe/[id]": await import("../src/pages/api/bedarfsausweis-gewerbe/[id].ts"),
|
"bedarfsausweis-gewerbe/[id]": await import("../src/pages/api/bedarfsausweis-gewerbe/[id].ts"),
|
||||||
"bedarfsausweis-gewerbe": await import("../src/pages/api/bedarfsausweis-gewerbe/index.ts"),
|
"bedarfsausweis-gewerbe": await import("../src/pages/api/bedarfsausweis-gewerbe/index.ts"),
|
||||||
|
"aufnahme": await import("../src/pages/api/aufnahme/index.ts"),
|
||||||
"bedarfsausweis-wohnen/[id]": await import("../src/pages/api/bedarfsausweis-wohnen/[id].ts"),
|
"bedarfsausweis-wohnen/[id]": await import("../src/pages/api/bedarfsausweis-wohnen/[id].ts"),
|
||||||
"bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"),
|
"bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"),
|
||||||
"bilder/[id]": await import("../src/pages/api/bilder/[id].ts"),
|
"bilder/[id]": await import("../src/pages/api/bilder/[id].ts"),
|
||||||
"geg-nachweis-gewerbe/[id]": await import("../src/pages/api/geg-nachweis-gewerbe/[id].ts"),
|
|
||||||
"geg-nachweis-gewerbe": await import("../src/pages/api/geg-nachweis-gewerbe/index.ts"),
|
|
||||||
"geg-nachweis-wohnen/[id]": await import("../src/pages/api/geg-nachweis-wohnen/[id].ts"),
|
"geg-nachweis-wohnen/[id]": await import("../src/pages/api/geg-nachweis-wohnen/[id].ts"),
|
||||||
"geg-nachweis-wohnen": await import("../src/pages/api/geg-nachweis-wohnen/index.ts"),
|
"geg-nachweis-wohnen": await import("../src/pages/api/geg-nachweis-wohnen/index.ts"),
|
||||||
|
"geg-nachweis-gewerbe/[id]": await import("../src/pages/api/geg-nachweis-gewerbe/[id].ts"),
|
||||||
|
"geg-nachweis-gewerbe": await import("../src/pages/api/geg-nachweis-gewerbe/index.ts"),
|
||||||
"objekt": await import("../src/pages/api/objekt/index.ts"),
|
"objekt": await import("../src/pages/api/objekt/index.ts"),
|
||||||
|
"ticket": await import("../src/pages/api/ticket/index.ts"),
|
||||||
"rechnung/[id]": await import("../src/pages/api/rechnung/[id].ts"),
|
"rechnung/[id]": await import("../src/pages/api/rechnung/[id].ts"),
|
||||||
"rechnung/anfordern": await import("../src/pages/api/rechnung/anfordern.ts"),
|
"rechnung/anfordern": await import("../src/pages/api/rechnung/anfordern.ts"),
|
||||||
"rechnung": await import("../src/pages/api/rechnung/index.ts"),
|
"rechnung": await import("../src/pages/api/rechnung/index.ts"),
|
||||||
"ticket": await import("../src/pages/api/ticket/index.ts"),
|
|
||||||
"user": await import("../src/pages/api/user/index.ts"),
|
"user": await import("../src/pages/api/user/index.ts"),
|
||||||
"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"),
|
||||||
|
|||||||
15
src/client/lib/lesen.ts
Normal file
15
src/client/lib/lesen.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
||||||
|
import { Benutzer } from "#lib/client/prisma.js";
|
||||||
|
import { api } from "astro-typesafe-api/client";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
|
||||||
|
export async function benutzerLesen(benutzerId: string): Promise<Benutzer> {
|
||||||
|
const benutzer = await api.user.GET.fetch({ id: benutzerId }
|
||||||
|
, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${Cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return benutzer[0];
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
||||||
import { Aufnahme, Objekt } from "#lib/client/prisma.js";
|
import { Aufnahme, Benutzer, Objekt } from "#lib/client/prisma.js";
|
||||||
import { api } from "astro-typesafe-api/client";
|
import { api } from "astro-typesafe-api/client";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
|
|
||||||
@@ -162,3 +162,31 @@ export async function objektSpeichern(objekt: Objekt & { id?: string }): Promise
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function benutzerSpeichern(benutzer: Partial<Benutzer>): Promise<string> {
|
||||||
|
const completeBenutzer: Benutzer = {
|
||||||
|
id: benutzer.id,
|
||||||
|
name: benutzer.name ?? null,
|
||||||
|
email: benutzer.email,
|
||||||
|
passwort: "",
|
||||||
|
adresse: benutzer.adresse ?? null,
|
||||||
|
anrede: benutzer.anrede ?? null,
|
||||||
|
firma: benutzer.firma ?? null,
|
||||||
|
vorname: benutzer.vorname ?? null,
|
||||||
|
ort: benutzer.ort ?? null,
|
||||||
|
plz: benutzer.plz ?? null,
|
||||||
|
profilbild: benutzer.profilbild ?? null,
|
||||||
|
telefon: benutzer.telefon ?? null,
|
||||||
|
updated_at: new Date(),
|
||||||
|
verified: benutzer.verified ?? false,
|
||||||
|
};
|
||||||
|
|
||||||
|
await api.user.POST.fetch(completeBenutzer
|
||||||
|
, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${Cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return benutzer.id;
|
||||||
|
}
|
||||||
121
src/components/Abrechnung/AbrechnungTable.svelte
Normal file
121
src/components/Abrechnung/AbrechnungTable.svelte
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Aufnahme, BedarfsausweisWohnen, Enums, Objekt, Rechnung, VerbrauchsausweisGewerbe, VerbrauchsausweisWohnen } from "#lib/server/prisma.js";
|
||||||
|
import moment from "moment";
|
||||||
|
import { DatePicker } from "@svelte-plugins/datepicker"
|
||||||
|
export let bestellungen: (Rechnung & {
|
||||||
|
ausweis: (VerbrauchsausweisWohnen | BedarfsausweisWohnen | VerbrauchsausweisGewerbe) & { aufnahme: Aufnahme & { objekt: Objekt }}
|
||||||
|
})[];
|
||||||
|
export let provisionen: Record<Enums.Ausweisart, number>;
|
||||||
|
export let partnerCodeErstesMal: Date;
|
||||||
|
export let email: string;
|
||||||
|
|
||||||
|
const bestellungenNachMonat: Record<string, (typeof bestellungen)> = {};
|
||||||
|
for (const bestellung of bestellungen) {
|
||||||
|
const monat = moment(bestellung.created_at).format("Y-MM");
|
||||||
|
if (monat in bestellungenNachMonat) {
|
||||||
|
bestellungenNachMonat[monat].push(bestellung)
|
||||||
|
} else {
|
||||||
|
bestellungenNachMonat[monat] = [bestellung]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wir brauchen alle Monate zwischen dem ersten Mal, dass der partner_code benutzt wurde bis zum heutigen Zeitpunkt.
|
||||||
|
const months: Record<string, string> = {
|
||||||
|
"01": "Januar", "02": "Februar", "03": "März", "04": "April",
|
||||||
|
"05": "Mai", "06": "Juni", "07": "Juli", "08": "August",
|
||||||
|
"09": "September", "10": "Oktober", "11": "November", "12": "Dezember"
|
||||||
|
};
|
||||||
|
|
||||||
|
function getMonthlyPeriods(minTime?: Date): moment.Moment[] {
|
||||||
|
const min = minTime ? moment(minTime) : moment();
|
||||||
|
const start = min.clone().startOf('month');
|
||||||
|
|
||||||
|
const end = moment().add(1, 'month').startOf('month');
|
||||||
|
|
||||||
|
const monthsArray: moment.Moment[] = [];
|
||||||
|
const current = start.clone();
|
||||||
|
|
||||||
|
while (current.isBefore(end)) {
|
||||||
|
monthsArray.push(current.clone());
|
||||||
|
current.add(1, 'month');
|
||||||
|
}
|
||||||
|
|
||||||
|
return monthsArray.reverse(); // Most recent month first
|
||||||
|
}
|
||||||
|
|
||||||
|
const periods = getMonthlyPeriods(partnerCodeErstesMal)
|
||||||
|
|
||||||
|
|
||||||
|
let isOpen = false;
|
||||||
|
export let startDate = moment(partnerCodeErstesMal).startOf('month').toDate();
|
||||||
|
export let endDate = moment().endOf('month').toDate();
|
||||||
|
$: formattedStartDate = moment(startDate).format("DD.MM.YYYY");
|
||||||
|
$: formattedEndDate = moment(endDate).format("DD.MM.YYYY");
|
||||||
|
function toggleDatePicker() {
|
||||||
|
isOpen = !isOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onChange = ({ startDate, endDate }: { startDate: number, endDate: number }) => {
|
||||||
|
window.location.href = `/dashboard/abrechnung?start=${moment(startDate).format("YYYY-MM-DD")}&end=${moment(endDate).format("YYYY-MM-DD")}`;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="fixed top-0 left-0 right-0 bg-white p-4 shadow z-10">
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<DatePicker bind:isOpen bind:startDate bind:endDate isRange={true} onDateChange={onChange} isMultipane={true}>
|
||||||
|
<input type="text" class="w-min" readonly value={`${formattedStartDate} - ${formattedEndDate}`} on:click={toggleDatePicker} />
|
||||||
|
</DatePicker>
|
||||||
|
<p>Abrechnungsübersicht für <strong>{email}</strong></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<main class="my-24 flex justify-center max-w-6xl mx-auto px-4">
|
||||||
|
{#if !bestellungen || bestellungen.length === 0}
|
||||||
|
<p class="text-center text-gray-500">Keine Bestellungen gefunden.</p>
|
||||||
|
{/if}
|
||||||
|
{#each periods as dt}
|
||||||
|
{@const jahrMonat = dt.format("Y-MM")}
|
||||||
|
{#if jahrMonat in bestellungenNachMonat && bestellungenNachMonat[jahrMonat].length > 0}
|
||||||
|
<!-- Echo dropdown foreach month. -->
|
||||||
|
{@const provisionMonat = bestellungenNachMonat[jahrMonat].reduce((acc, bestellung) => {
|
||||||
|
return acc + provisionen[bestellung.ausweis.ausweisart] || 0;
|
||||||
|
}, 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'>
|
||||||
|
<p>$month_name $year_name - Klicke, um Tabelle anzuzeigen</p>
|
||||||
|
<a target='_blank' rel='noreferrer noopener' href='/user/abrechnung/pdf.php?month={dt.format("m")}&year={dt.format("Y")}'>PDF Ansehen</a>
|
||||||
|
</div> -->
|
||||||
|
<table class="w-full mb-4 border-collapse border border-gray-300">
|
||||||
|
<thead>
|
||||||
|
<tr class="bg-primary text-white">
|
||||||
|
<td class="text-center font-bold">ID</td>
|
||||||
|
<td class="text-center font-bold">DATUM</td>
|
||||||
|
<td class="text-center font-bold">GEBÄUDEADRESSE </td>
|
||||||
|
<td class="text-center font-bold">PLZ </td>
|
||||||
|
<td class="text-center font-bold">ORT </td>
|
||||||
|
<td class="text-center font-bold">AUSWEIS</td>
|
||||||
|
<td class="text-center font-bold w-48">BETRAG NETTO</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<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}
|
||||||
|
{@const provisionBestellung = provisionen[bestellung.ausweis.ausweisart] || 0}
|
||||||
|
<tr>
|
||||||
|
<td class="text-center px-4 w-24" style="font-family: monospace;">{bestellung.id}</td>
|
||||||
|
<td class="text-center font-bold w-32">{moment(bestellung.created_at).format("DD.MM.YYYY")}</td>
|
||||||
|
<td class="text-left w-64">{bestellung.ausweis.aufnahme.objekt.adresse}</td>
|
||||||
|
<td class="text-center w-16">{bestellung.ausweis.aufnahme.objekt.plz}</td>
|
||||||
|
<td class="text-left w-64">{bestellung.ausweis.aufnahme.objekt.ort}</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>
|
||||||
|
{/each}
|
||||||
|
</table>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</main>
|
||||||
@@ -214,8 +214,8 @@ grid-cols-1 gap-x-2 gap-y-4
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="text-center xs:text-left justify-self-stretch">
|
<div class="text-center xs:text-left justify-self-stretch">
|
||||||
<b>Verbrauchsausweis online</b><br>inkl. ausführlicher telefonischer
|
<b>Selbsteingabe online</b><br>inkl. ausführlicher telefonischer
|
||||||
Beratung
|
Beratung!
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-center xs:text-right">
|
<div class="text-center xs:text-right">
|
||||||
@@ -234,7 +234,7 @@ grid-cols-1 gap-x-2 gap-y-4
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="text-center xs:text-left justify-self-stretch">
|
<div class="text-center xs:text-left justify-self-stretch">
|
||||||
<b>Verbrauchsausweis offline</b><br>Sie schicken uns 3 Verbrauchsabrechnungen zu)
|
<b>Wir übernehmen die Eingabe</b><br>Sie übermitteln die nötigen Unterlagen per Upload oder E-Mail.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-center xs:text-right">
|
<div class="text-center xs:text-right">
|
||||||
|
|||||||
@@ -257,6 +257,12 @@
|
|||||||
|
|
||||||
let bedarfsausweisFileInput: HTMLInputElement;
|
let bedarfsausweisFileInput: HTMLInputElement;
|
||||||
let bedarfsausweisAdditionalInput: HTMLInputElement;
|
let bedarfsausweisAdditionalInput: HTMLInputElement;
|
||||||
|
|
||||||
|
let dropdownOpen = false;
|
||||||
|
|
||||||
|
function toggleDropdown() {
|
||||||
|
dropdownOpen = !dropdownOpen;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="relative bg-base-200 border border-base-300 rounded-lg p-4 mx-2">
|
<div class="relative bg-base-200 border border-base-300 rounded-lg p-4 mx-2">
|
||||||
@@ -273,30 +279,41 @@
|
|||||||
{/if}
|
{/if}
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div
|
<div
|
||||||
class="flex justify-end mb-2 dropdown dropdown-bottom absolute top-4 right-4"
|
class="mb-2 dropdown dropdown-bottom absolute top-4 right-4 bg-base-100"
|
||||||
>
|
>
|
||||||
<button class="rounded-full p-2.5 hover:bg-base-100">
|
<button class="rounded-full p-2.5 hover:bg-base-100" on:click={toggleDropdown}>
|
||||||
<DotsVertical size={15} />
|
<DotsVertical size={15} />
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
{#if dropdownOpen}
|
||||||
<ul
|
<ul
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-64 gap-2"
|
class="z-[1] menu p-2 shadow bg-base-100 rounded-box w-64 gap-2 border"
|
||||||
>
|
>
|
||||||
<li>
|
<!-- <div>
|
||||||
<button on:click={ausweisStornieren}
|
<button on:click={ausweisStornieren} class="flex items-center gap-2" disabled
|
||||||
><CrossCircled size={15} />Ausweis Stornieren</button
|
><CrossCircled size={15} />Stornieren</button
|
||||||
>
|
>
|
||||||
</li>
|
</div>
|
||||||
<li>
|
<div>
|
||||||
<button><Pencil2 size={15} /> Als Vorlage benutzen</button>
|
<button class="flex items-center gap-2" disabled
|
||||||
</li>
|
><Pencil2 size={15} /> Als Vorlage</button>
|
||||||
<li>
|
</div>
|
||||||
<button on:click={() => hilfeModal.showModal()}
|
<div>
|
||||||
|
<button on:click={() => hilfeModal.showModal()} class="flex items-center gap-2" disabled
|
||||||
><QuestionMarkCircled size={15} /> Hilfe Erhalten</button
|
><QuestionMarkCircled size={15} /> Hilfe Erhalten</button
|
||||||
>
|
>
|
||||||
</li>
|
</div> -->
|
||||||
|
{#if ausweis.bestellt && rechnung}
|
||||||
|
<div>
|
||||||
|
<a href="/dashboard/rechnung/aendern?rechnungid={rechnung.id}"><button> Adresse ändern</button
|
||||||
|
></a>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
{/if}
|
||||||
|
|
||||||
|
|
||||||
<div class="flex flex-row flex-wrap items-center gap-2">
|
<div class="flex flex-row flex-wrap items-center gap-2">
|
||||||
{#if ausweis.ausgestellt}
|
{#if ausweis.ausgestellt}
|
||||||
<span class="bg-green-600 px-2 py-0.5 text-sm font-semibold rounded-lg text-white">Ausgestellt</span>
|
<span class="bg-green-600 px-2 py-0.5 text-sm font-semibold rounded-lg text-white">Ausgestellt</span>
|
||||||
@@ -341,9 +358,6 @@
|
|||||||
<div class="w-full border rounded-lg my-2">
|
<div class="w-full border rounded-lg my-2">
|
||||||
<div class="bg-green-600 h-4 rounded-lg" class:bg-red-600={progress == 33} class:bg-primary={progress == 66} style="width: {progress}%;"></div>
|
<div class="bg-green-600 h-4 rounded-lg" class:bg-red-600={progress == 33} class:bg-primary={progress == 66} style="width: {progress}%;"></div>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-sm font-semibold text-base-content"
|
|
||||||
>{progress}%</span
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
{#await calculations then calculations}
|
{#await calculations then calculations}
|
||||||
<div class="flex flex-col mb-4">
|
<div class="flex flex-col mb-4">
|
||||||
|
|||||||
@@ -70,6 +70,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
<!-- <a href="/dashboard/abrechnung" class="button ">Monatliche Abrechnung</a> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr class="border-gray-600" />
|
<hr class="border-gray-600" />
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
export let hidden: boolean = true;
|
export let hidden: boolean = true;
|
||||||
export let closeable: boolean = true;
|
export let closeable: boolean = true;
|
||||||
import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock';
|
import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock';
|
||||||
|
import { Cross1 } from 'radix-svelte-icons';
|
||||||
|
|
||||||
$: if (globalThis.window) {
|
$: if (globalThis.window) {
|
||||||
if (hidden) {
|
if (hidden) {
|
||||||
@@ -12,13 +13,11 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="fixed top-0 left-0 w-[100vw] h-[100vh] flex items-center justify-center bg-[rgba(0,0,0,0.8)] z-50" class:hidden={hidden} on:click|self={() => {
|
<div class="fixed top-0 left-0 w-[100vw] h-[100vh] flex items-center justify-center bg-[rgba(0,0,0,0.8)] z-50" class:hidden={hidden}>
|
||||||
hidden = closeable ? true : hidden;
|
|
||||||
}}>
|
|
||||||
{#if closeable}
|
{#if closeable}
|
||||||
<button class="absolute top-4 left-4 text-white" on:click={() => {
|
<button class="absolute top-4 right-4 text-white bg-gray-50 bg-opacity-25 px-4 py-2 rounded-lg" type="button" on:click={() => {
|
||||||
hidden = true;
|
hidden = true;
|
||||||
}}>Schließen</button>
|
}}><Cross1 size={20}></Cross1></button>
|
||||||
{/if}
|
{/if}
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
@@ -177,7 +177,10 @@ $: standardXL =
|
|||||||
|
|
||||||
<WidgetCardTemplate
|
<WidgetCardTemplate
|
||||||
name="Verbrauchsausweis Wohngebäude"
|
name="Verbrauchsausweis Wohngebäude"
|
||||||
price={PRICES.VerbrauchsausweisWohnen[Enums.AusweisTyp.Standard] + (standardXL ? 10 : 0)}
|
price = {PRICES.VerbrauchsausweisWohnen[standardXL ? Enums.AusweisTyp.standardXL : Enums.AusweisTyp.Standard]}
|
||||||
|
price1 = {PRICES.VerbrauchsausweisWohnen[standardXL ? Enums.AusweisTyp.BeratungXL : Enums.AusweisTyp.Beratung]}
|
||||||
|
price2 = {PRICES.VerbrauchsausweisWohnen[standardXL ? Enums.AusweisTyp.OfflineXL : Enums.AusweisTyp.Offline]}
|
||||||
|
|
||||||
src={'https://online-energieausweis.org/images/partner/'+partner+'/wohngebaeude.svg'}
|
src={'https://online-energieausweis.org/images/partner/'+partner+'/wohngebaeude.svg'}
|
||||||
alt="Wohnhaus Verbrauchsausweis"
|
alt="Wohnhaus Verbrauchsausweis"
|
||||||
variant="einfach"
|
variant="einfach"
|
||||||
@@ -190,9 +193,12 @@ $: standardXL =
|
|||||||
["Ungenau durch individuelles Heizverhalten.", false],
|
["Ungenau durch individuelles Heizverhalten.", false],
|
||||||
["Wird nicht immer bei den Banken akzeptiert.", false]
|
["Wird nicht immer bei den Banken akzeptiert.", false]
|
||||||
]}
|
]}
|
||||||
href_buy={"https://online-energieausweis.org/"+partner+"/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/"}{standardXL ? '?ausweistyp=standardXL' : ''}
|
|
||||||
href_overview={"https://online-energieausweis.org/"+partner+"/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/produkt-uebersicht/"}{standardXL ? '?ausweistyp=standardXL' : ''}
|
href_buy1={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/${standardXL ? '?ausweistyp=standardXL' : ''}`}
|
||||||
></WidgetCardTemplate>
|
href_buy2={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/${standardXL ? '?ausweistyp=BeratungXL' : '?ausweistyp=Beratung'}`}
|
||||||
|
href_buy3={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/${standardXL ? '?ausweistyp=OfflineXL' : '?ausweistyp=Offline'}`}
|
||||||
|
|
||||||
|
></WidgetCardTemplate>
|
||||||
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@@ -200,7 +206,9 @@ $: standardXL =
|
|||||||
|
|
||||||
<WidgetCardTemplate
|
<WidgetCardTemplate
|
||||||
name="Bedarfsausweis Wohngebäude"
|
name="Bedarfsausweis Wohngebäude"
|
||||||
price={PRICES.BedarfsausweisWohnen[Enums.AusweisTyp.Standard] + (standardXL ? 25 : 0)}
|
price = {PRICES.BedarfsausweisWohnen[standardXL ? Enums.AusweisTyp.standardXL : Enums.AusweisTyp.Standard]}
|
||||||
|
price1 = {PRICES.BedarfsausweisWohnen[standardXL ? Enums.AusweisTyp.BeratungXL : Enums.AusweisTyp.Beratung]}
|
||||||
|
price2 = {PRICES.BedarfsausweisWohnen[standardXL ? Enums.AusweisTyp.OfflineXL : Enums.AusweisTyp.Offline]}
|
||||||
src={'https://online-energieausweis.org/images/partner/'+partner+'/wohngebaeude.svg'}
|
src={'https://online-energieausweis.org/images/partner/'+partner+'/wohngebaeude.svg'}
|
||||||
alt="Wohnhaus Bedarfsausweis"
|
alt="Wohnhaus Bedarfsausweis"
|
||||||
variant="fundiert"
|
variant="fundiert"
|
||||||
@@ -213,8 +221,11 @@ $: standardXL =
|
|||||||
["Kann als Grundlage für den ISFP dienen.", true],
|
["Kann als Grundlage für den ISFP dienen.", true],
|
||||||
["Objektivere Berechnungsmethode nach DIN 18599.", true],
|
["Objektivere Berechnungsmethode nach DIN 18599.", true],
|
||||||
]}
|
]}
|
||||||
href_buy={"https://online-energieausweis.org/"+partner+"/energieausweis-erstellen/bedarfsausweis-wohngebaeude/"}{standardXL ? '?ausweistyp=standardXL' : ''}
|
|
||||||
href_overview={"https://online-energieausweis.org/"+partner+"/energieausweis-erstellen/bedarfsausweis-wohngebaeude/produkt-uebersicht"}{standardXL ? '?ausweistyp=standardXL' : ''}
|
href_buy1={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/bedarfsausweis-wohngebaeude/${standardXL ? '?ausweistyp=standardXL' : ''}`}
|
||||||
|
href_buy2={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/bedarfsausweis-wohngebaeude/${standardXL ? '?ausweistyp=BeratungXL' : '?ausweistyp=Beratung'}`}
|
||||||
|
href_buy3={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/bedarfsausweis-wohngebaeude/${standardXL ? '?ausweistyp=OfflineXL' : '?ausweistyp=Offline'}`}
|
||||||
|
|
||||||
></WidgetCardTemplate>
|
></WidgetCardTemplate>
|
||||||
|
|
||||||
{/if}
|
{/if}
|
||||||
@@ -223,7 +234,9 @@ $: standardXL =
|
|||||||
|
|
||||||
<WidgetCardTemplate
|
<WidgetCardTemplate
|
||||||
name="Verbrauchsausweis Gewerbegebäude"
|
name="Verbrauchsausweis Gewerbegebäude"
|
||||||
price={PRICES.VerbrauchsausweisGewerbe[Enums.AusweisTyp.Standard] + (standardXL ? 15 : 0)}
|
price = {PRICES.VerbrauchsausweisGewerbe[standardXL ? Enums.AusweisTyp.standardXL : Enums.AusweisTyp.Standard]}
|
||||||
|
price1 = {PRICES.VerbrauchsausweisGewerbe[standardXL ? Enums.AusweisTyp.BeratungXL : Enums.AusweisTyp.Beratung]}
|
||||||
|
price2 = {PRICES.VerbrauchsausweisGewerbe[standardXL ? Enums.AusweisTyp.OfflineXL : Enums.AusweisTyp.Offline]}
|
||||||
src={'https://online-energieausweis.org/images/partner/'+partner+'/gewerbegebaeude.svg'}
|
src={'https://online-energieausweis.org/images/partner/'+partner+'/gewerbegebaeude.svg'}
|
||||||
alt="Gewerbe Verbrauchsausweis"
|
alt="Gewerbe Verbrauchsausweis"
|
||||||
variant="einfach"
|
variant="einfach"
|
||||||
@@ -237,8 +250,10 @@ $: standardXL =
|
|||||||
["Wird nicht immer bei den Banken akzeptiert.", false],
|
["Wird nicht immer bei den Banken akzeptiert.", false],
|
||||||
["Ungenau durch individuelles Heizverhalten", false],
|
["Ungenau durch individuelles Heizverhalten", false],
|
||||||
]}
|
]}
|
||||||
href_buy={"https://online-energieausweis.org/"+partner+"/energieausweis-erstellen/verbrauchsausweis-gewerbe/"}{standardXL ? '?ausweistyp=standardXL' : ''}
|
|
||||||
href_overview={"https://online-energieausweis.org/"+partner+"/energieausweis-erstellen/verbrauchsausweis-gewerbe/produkt-uebersicht/"}{standardXL ? '?ausweistyp=standardXL' : ''}
|
href_buy1={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-gewerbe/${standardXL ? '?ausweistyp=standardXL' : ''}`}
|
||||||
|
href_buy2={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-gewerbe/${standardXL ? '?ausweistyp=BeratungXL' : '?ausweistyp=Beratung'}`}
|
||||||
|
href_buy3={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-gewerbe/${standardXL ? '?ausweistyp=OfflineXL' : '?ausweistyp=Offline'}`}
|
||||||
></WidgetCardTemplate>
|
></WidgetCardTemplate>
|
||||||
|
|
||||||
{/if}
|
{/if}
|
||||||
@@ -247,7 +262,9 @@ $: standardXL =
|
|||||||
|
|
||||||
<WidgetCardTemplate
|
<WidgetCardTemplate
|
||||||
name="Bedarfsausweis Gewerbegebäude"
|
name="Bedarfsausweis Gewerbegebäude"
|
||||||
price={PRICES.BedarfsausweisGewerbe[Enums.AusweisTyp.Standard]}
|
price = {PRICES.BedarfsausweisGewerbe[standardXL ? Enums.AusweisTyp.standardXL : Enums.AusweisTyp.Standard]}
|
||||||
|
price1 = {PRICES.BedarfsausweisGewerbe[standardXL ? Enums.AusweisTyp.BeratungXL : Enums.AusweisTyp.Beratung]}
|
||||||
|
price2 = {PRICES.BedarfsausweisGewerbe[standardXL ? Enums.AusweisTyp.OfflineXL : Enums.AusweisTyp.Offline]}
|
||||||
src={'https://online-energieausweis.org/images/partner/'+partner+'/gewerbegebaeude.svg'}
|
src={'https://online-energieausweis.org/images/partner/'+partner+'/gewerbegebaeude.svg'}
|
||||||
alt="Gewerbe Bedarfsausweis"
|
alt="Gewerbe Bedarfsausweis"
|
||||||
variant="fundiert"
|
variant="fundiert"
|
||||||
@@ -261,8 +278,10 @@ $: standardXL =
|
|||||||
["Objektiveres, besser vergleichbares Ergebnis.", true],
|
["Objektiveres, besser vergleichbares Ergebnis.", true],
|
||||||
["Zulässig bei Leerstand oder fehlenden Verbräuchen", true],
|
["Zulässig bei Leerstand oder fehlenden Verbräuchen", true],
|
||||||
]}
|
]}
|
||||||
href_buy={"https://online-energieausweis.org/"+partner+"/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/"}
|
|
||||||
href_overview={"https://online-energieausweis.org/"+partner+"/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/produkt-uebersicht/"}
|
href_buy1={`https://online-energieausweis.org/${partner}/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/${standardXL ? '?ausweistyp=standardXL' : ''}`}
|
||||||
|
href_buy2={`https://online-energieausweis.org/${partner}/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/${standardXL ? '?ausweistyp=BeratungXL' : '?ausweistyp=Beratung'}`}
|
||||||
|
|
||||||
></WidgetCardTemplate>
|
></WidgetCardTemplate>
|
||||||
|
|
||||||
{/if}
|
{/if}
|
||||||
@@ -271,7 +290,9 @@ $: standardXL =
|
|||||||
|
|
||||||
<WidgetCardTemplate
|
<WidgetCardTemplate
|
||||||
name="GEG-Nachweis Wohngebäude"
|
name="GEG-Nachweis Wohngebäude"
|
||||||
price={PRICES.GEGNachweisWohnen[Enums.AusweisTyp.Standard]}
|
price = {PRICES.GEGNachweisWohnen[standardXL ? Enums.AusweisTyp.standardXL : Enums.AusweisTyp.Standard]}
|
||||||
|
price1 = {PRICES.GEGNachweisWohnen[standardXL ? Enums.AusweisTyp.BeratungXL : Enums.AusweisTyp.Beratung]}
|
||||||
|
price2 = {PRICES.GEGNachweisWohnen[standardXL ? Enums.AusweisTyp.OfflineXL : Enums.AusweisTyp.Offline]}
|
||||||
src={'https://online-energieausweis.org/images/partner/'+partner+'/wohngebaeude.svg'}
|
src={'https://online-energieausweis.org/images/partner/'+partner+'/wohngebaeude.svg'}
|
||||||
alt="GEG-Nachweis-Wohnen"
|
alt="GEG-Nachweis-Wohnen"
|
||||||
variant="Bauvorlage"
|
variant="Bauvorlage"
|
||||||
@@ -285,8 +306,10 @@ $: standardXL =
|
|||||||
["Berechnung und Bilanzierung nach aktueller DIN 18599.", true],
|
["Berechnung und Bilanzierung nach aktueller DIN 18599.", true],
|
||||||
["Zonierung und Erstellung eines 3D Gebäudemodells.", true],
|
["Zonierung und Erstellung eines 3D Gebäudemodells.", true],
|
||||||
]}
|
]}
|
||||||
href_buy={"https://online-energieausweis.org/"+partner+"/angebot-anfragen/geg-nachweis-wohnen-anfragen/"}
|
|
||||||
href_overview={"https://online-energieausweis.org/"+partner+"/angebot-anfragen/geg-nachweis-wohnen-anfragen/produkt-uebersicht/"}
|
href_buy1={`https://online-energieausweis.org/${partner}/angebot-anfragen/geg-nachweis-wohnen-anfragen/${standardXL ? '?ausweistyp=standardXL' : ''}`}
|
||||||
|
href_buy2={`https://online-energieausweis.org/${partner}/angebot-anfragen/geg-nachweis-wohnen-anfragen/${standardXL ? '?ausweistyp=BeratungXL' : '?ausweistyp=Beratung'}`}
|
||||||
|
|
||||||
|
|
||||||
></WidgetCardTemplate>
|
></WidgetCardTemplate>
|
||||||
|
|
||||||
@@ -296,7 +319,9 @@ $: standardXL =
|
|||||||
|
|
||||||
<WidgetCardTemplate
|
<WidgetCardTemplate
|
||||||
name="GEG-Nachweis Gewerbegebäude"
|
name="GEG-Nachweis Gewerbegebäude"
|
||||||
price={PRICES.GEGNachweisGewerbe[Enums.AusweisTyp.Standard]}
|
price = {PRICES.GEGNachweisGewerbe[standardXL ? Enums.AusweisTyp.standardXL : Enums.AusweisTyp.Standard]}
|
||||||
|
price1 = {PRICES.GEGNachweisGewerbe[standardXL ? Enums.AusweisTyp.BeratungXL : Enums.AusweisTyp.Beratung]}
|
||||||
|
price2 = {PRICES.GEGNachweisGewerbe[standardXL ? Enums.AusweisTyp.OfflineXL : Enums.AusweisTyp.Offline]}
|
||||||
src={'https://online-energieausweis.org/images/partner/'+partner+'/gewerbegebaeude.svg'}
|
src={'https://online-energieausweis.org/images/partner/'+partner+'/gewerbegebaeude.svg'}
|
||||||
alt="GEG-Nachweis-Gewerbe"
|
alt="GEG-Nachweis-Gewerbe"
|
||||||
variant="Bauvorlage"
|
variant="Bauvorlage"
|
||||||
@@ -310,8 +335,10 @@ $: standardXL =
|
|||||||
["Berechnung und Bilanzierung nach aktueller DIN 18599.", true],
|
["Berechnung und Bilanzierung nach aktueller DIN 18599.", true],
|
||||||
["Mehrzonenmodell inkl. Erstellung eines 3D Gebäudemodells.", true],
|
["Mehrzonenmodell inkl. Erstellung eines 3D Gebäudemodells.", true],
|
||||||
]}
|
]}
|
||||||
href_buy={"https://online-energieausweis.org/"+partner+"/angebot-anfragen/geg-nachweis-gewerbe-anfragen/"}
|
|
||||||
href_overview={"https://online-energieausweis.org/"+partner+"/angebot-anfragen/geg-nachweis-gewerbe-anfragen/produkt-uebersicht/"}
|
href_buy1={`https://online-energieausweis.org/${partner}/angebot-anfragen/geg-nachweis-gewerbe-anfragen/${standardXL ? '?ausweistyp=standardXL' : ''}`}
|
||||||
|
href_buy2={`https://online-energieausweis.org/${partner}/angebot-anfragen/geg-nachweis-gewerbe-anfragen/${standardXL ? '?ausweistyp=BeratungXL' : '?ausweistyp=Beratung'}`}
|
||||||
|
|
||||||
></WidgetCardTemplate>
|
></WidgetCardTemplate>
|
||||||
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -1,115 +1,148 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { fade } from "svelte/transition";
|
import { fade } from "svelte/transition";
|
||||||
export let price: number;
|
export let price: number;
|
||||||
|
|
||||||
|
export let price1: number;
|
||||||
|
export let price2: number;
|
||||||
|
|
||||||
export let name: string;
|
export let name: string;
|
||||||
export let variant: string;
|
export let variant: string;
|
||||||
export let services: [string, boolean][];
|
export let services: [string, boolean][];
|
||||||
export let href_buy: string;
|
export let href_buy1: string;
|
||||||
export let href_overview: string;
|
export let href_buy2: string;
|
||||||
|
export let href_buy3: string = "";
|
||||||
|
|
||||||
export let src: string;
|
export let src: string;
|
||||||
export let alt: string;
|
export let alt: string;
|
||||||
export let empfehlung: string;
|
export let empfehlung: string;
|
||||||
export let cta: string;
|
export let cta: string;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div class="produktbox" transition:fade={{ duration: 0 }}>
|
||||||
class="produktbox"
|
{#if empfehlung === "ja"}
|
||||||
transition:fade={{ duration: 0 }}
|
<div class="empfehlung" aria-label="Empfohlenes Produkt">
|
||||||
>
|
Empfehlung
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<h2 class="titel sm:mb-2">{name}</h2>
|
||||||
|
|
||||||
{#if empfehlung === "ja"}
|
<div class="sumCent">
|
||||||
<div class="empfehlung" aria-label="Empfohlenes Produkt">Empfehlung</div>
|
<div class="variante">{variant}</div>
|
||||||
{/if}
|
<img class="image" {src} {alt} />
|
||||||
<h2 class="titel sm:mb-2">{name}</h2>
|
<div class="">
|
||||||
|
<p class="price">
|
||||||
|
ab {price} €
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="sumCent">
|
|
||||||
<div class="variante">{variant}</div>
|
|
||||||
<img
|
|
||||||
class="image"
|
|
||||||
{src}
|
|
||||||
{alt}
|
|
||||||
/>
|
|
||||||
<div class="">
|
|
||||||
<p class="price">
|
|
||||||
ab {price} €
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="sumCent buttoncols">
|
|
||||||
<a
|
|
||||||
href={href_buy}
|
|
||||||
class="buttoncol"
|
|
||||||
aria-label="Jetzt {name} kaufen"
|
|
||||||
target="_blank"
|
|
||||||
>{cta}
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a
|
|
||||||
href={href_overview}
|
|
||||||
class="buttoncol"
|
|
||||||
aria-label="{name} Produkt-Übersicht"
|
|
||||||
target="_blank"
|
|
||||||
>Produkt-Übersicht</a
|
|
||||||
>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="sumRows forServices">
|
|
||||||
|
|
||||||
{#each services as [service, check]}
|
|
||||||
<div class="services">
|
|
||||||
<span>{@html service}</span>
|
|
||||||
<span class={check ? "check" : "check-no"}>{check ? "✔" : "✘"}</span>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<hr class="col-span-2 w-full md:w-[50%] md:m-auto bg-[#ffcc00] h-[2px]" />
|
||||||
|
|
||||||
|
<div class="sumRows forServices">
|
||||||
|
{#each services as [service, check]}
|
||||||
|
<div class="services">
|
||||||
|
<span>{@html service}</span>
|
||||||
|
<span class={check ? "check" : "check-no"}
|
||||||
|
>{check ? "✔" : "✘"}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr class="col-span-2 w-full md:w-[50%] md:m-auto bg-[#ffcc00] h-[2px]" />
|
||||||
|
|
||||||
|
<div class="sumCent buttoncols"
|
||||||
|
class:md:grid-cols-3={href_buy3}
|
||||||
|
class:md:grid-cols-2={!href_buy3}>
|
||||||
|
<a
|
||||||
|
href={href_buy1}
|
||||||
|
class="buttoncol"
|
||||||
|
aria-label="Jetzt {name} kaufen"
|
||||||
|
target="_blank"
|
||||||
|
>mach selbst (<span class="inside-price">{price}</span> €)
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href={href_buy2}
|
||||||
|
class="buttoncol"
|
||||||
|
aria-label="{name} Produkt-Übersicht"
|
||||||
|
target="_blank"
|
||||||
|
>wir helfen (<span class="inside-price">{price1}</span> €)
|
||||||
|
</a>
|
||||||
|
|
||||||
|
{#if href_buy3}
|
||||||
|
<a
|
||||||
|
href={href_buy3}
|
||||||
|
class="buttoncol"
|
||||||
|
aria-label="{name} Produkt-Übersicht"
|
||||||
|
target="_blank"
|
||||||
|
>wir machen (<span class="inside-price">{price2}</span> €)
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<style lang="postcss">
|
<style lang="postcss">
|
||||||
|
.produktbox {
|
||||||
.produktbox{@apply grid grid-cols-subgrid col-span-2 grid-rows-subgrid row-span-3 md:row-span-12 bg-black/5 rounded-lg
|
@apply grid grid-cols-subgrid col-span-2 grid-rows-subgrid row-span-3 md:row-span-12 bg-black/5 rounded-lg
|
||||||
px-2 py-2 mt-5;
|
px-2 py-2 mt-5;
|
||||||
box-shadow:2px 2px 8px rgba(0,0,0,0.25);
|
box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.25);
|
||||||
|
|
||||||
.sumCent{@apply justify-self-center col-span-2}
|
.sumCent {
|
||||||
.sumRows{@apply hidden sm:grid grid-rows-subgrid row-span-5 items-center}
|
@apply justify-self-center col-span-2;
|
||||||
.forServices{@apply grid-rows-subgrid row-span-5 items-center col-span-2 justify-center px-6}
|
}
|
||||||
|
.sumRows {
|
||||||
|
@apply hidden sm:grid grid-rows-subgrid row-span-5 items-center;
|
||||||
|
}
|
||||||
|
.forServices {
|
||||||
|
@apply grid-rows-subgrid row-span-5 items-center col-span-2 justify-center px-6;
|
||||||
|
}
|
||||||
|
|
||||||
.image{@apply w-[75%] mx-auto
|
.image {
|
||||||
md:w-[75%] md:pl-0}
|
@apply w-[75%] mx-auto
|
||||||
|
md:w-[75%] md:pl-0;
|
||||||
|
}
|
||||||
|
|
||||||
.buttoncols{@apply grid grid-cols-1 gap-x-4 w-full mb-4
|
.buttoncols {
|
||||||
md:grid-cols-2 md:w-[auto]}
|
@apply grid grid-cols-1 gap-x-4 w-full my-4
|
||||||
|
md:grid-cols-3 md:w-[auto];
|
||||||
|
}
|
||||||
|
|
||||||
.buttoncol{@apply mt-2 md:mt-0 text-center text-black bg-[#ffcc00] rounded-md px-3 py-1 no-underline
|
.buttoncol {
|
||||||
hover:bg-[#222222] hover:text-white}
|
@apply mt-2 md:mt-0 text-center text-black bg-[#ffcc00] rounded-md px-3 py-1 no-underline
|
||||||
|
hover:bg-[#222222] hover:text-white;
|
||||||
|
}
|
||||||
|
.inside-price {
|
||||||
|
@apply font-bold;
|
||||||
|
}
|
||||||
|
|
||||||
.price{@apply tracking-tighter text-[2rem] text-[#222222] pl-12 m-0 -mt-7 text-nowrap text-left;
|
.price {
|
||||||
font-family: "Antique Olive Compact bold";}
|
@apply tracking-tighter text-[2rem] text-[#222222] pl-12 m-0 -mt-7 text-nowrap text-left;
|
||||||
|
font-family: "Antique Olive Compact bold";
|
||||||
|
}
|
||||||
|
|
||||||
.titel {@apply col-span-2 text-center [font-size:_clamp(20px,2.5vw,28px)]}
|
.titel {
|
||||||
.empfehlung{@apply -mt-4 absolute justify-self-end rounded-md bg-red-700 text-white w-fit h-fit px-2 py-1 rotate-1 text-[0.65rem] ring-4 ring-white mr-6}
|
@apply col-span-2 text-center [font-size:_clamp(20px,2.5vw,28px)];
|
||||||
.variante {
|
}
|
||||||
@apply w-fit italic col-span-2 -mt-2 -mb-4 text-[1rem] text-[#222222] justify-self-start ring-2 ring-[#ffcc00] rounded-md pl-[4px] pr-[6px] py-[0px];
|
.empfehlung {
|
||||||
|
@apply -mt-4 absolute justify-self-end rounded-md bg-red-700 text-white w-fit h-fit px-2 py-1 rotate-1 text-[0.65rem] ring-4 ring-white mr-6;
|
||||||
|
}
|
||||||
|
.variante {
|
||||||
|
@apply w-fit italic col-span-2 -mt-2 -mb-4 text-[1rem] text-[#222222] justify-self-start ring-2 ring-[#ffcc00] rounded-md pl-[4px] pr-[6px] py-[0px];
|
||||||
|
}
|
||||||
|
|
||||||
|
.services {
|
||||||
|
@apply hidden text-start py-1 md:grid grid-rows-subgrid row-span-1 items-center md:grid-cols-[1fr_50px];
|
||||||
|
}
|
||||||
|
.services:not(:last-child) {
|
||||||
|
@apply border-b-[1px] border-gray-200;
|
||||||
|
}
|
||||||
|
.check {
|
||||||
|
@apply justify-self-end self-center font-bold text-green-700;
|
||||||
|
}
|
||||||
|
.check-no {
|
||||||
|
@apply justify-self-end self-center font-bold text-red-700;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.services {
|
|
||||||
@apply hidden text-start py-1 md:grid grid-rows-subgrid row-span-1 items-center md:grid-cols-[1fr_50px]
|
|
||||||
}
|
|
||||||
.services:not(:last-child) {
|
|
||||||
@apply border-b-[1px] border-gray-200;
|
|
||||||
}
|
|
||||||
.check {
|
|
||||||
@apply justify-self-end self-center font-bold text-green-700;
|
|
||||||
}
|
|
||||||
.check-no {
|
|
||||||
@apply justify-self-end self-center font-bold text-red-700;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,11 +1,27 @@
|
|||||||
import { AufnahmeClient, BedarfsausweisWohnenClient, BenutzerClient, BildClient, getAusweisartFromId, ObjektClient, RechnungClient, VerbrauchsausweisGewerbeClient, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types.js";
|
import {
|
||||||
|
AufnahmeClient,
|
||||||
|
BedarfsausweisWohnenClient,
|
||||||
|
BenutzerClient,
|
||||||
|
BildClient,
|
||||||
|
getAusweisartFromId,
|
||||||
|
ObjektClient,
|
||||||
|
RechnungClient,
|
||||||
|
VerbrauchsausweisGewerbeClient,
|
||||||
|
VerbrauchsausweisWohnenClient,
|
||||||
|
} from "#components/Ausweis/types.js";
|
||||||
import { pdfDatenblattVerbrauchsausweisGewerbe } from "#lib/pdf/pdfDatenblattVerbrauchsausweisGewerbe.js";
|
import { pdfDatenblattVerbrauchsausweisGewerbe } from "#lib/pdf/pdfDatenblattVerbrauchsausweisGewerbe.js";
|
||||||
import { pdfDatenblattVerbrauchsausweisWohnen } from "#lib/pdf/pdfDatenblattVerbrauchsausweisWohnen.js";
|
import { pdfDatenblattVerbrauchsausweisWohnen } from "#lib/pdf/pdfDatenblattVerbrauchsausweisWohnen.js";
|
||||||
import { pdfVerbrauchsausweisGewerbe } from "#lib/pdf/pdfVerbrauchsausweisGewerbe.js";
|
import { pdfVerbrauchsausweisGewerbe } from "#lib/pdf/pdfVerbrauchsausweisGewerbe.js";
|
||||||
import { pdfVerbrauchsausweisWohnen } from "#lib/pdf/pdfVerbrauchsausweisWohnen.js";
|
import { pdfVerbrauchsausweisWohnen } from "#lib/pdf/pdfVerbrauchsausweisWohnen.js";
|
||||||
import { pdfAushangVerbrauchsausweisGewerbe } from "#lib/pdf/pdfAushangVerbrauchsausweisGewerbe.js";
|
import { pdfAushangVerbrauchsausweisGewerbe } from "#lib/pdf/pdfAushangVerbrauchsausweisGewerbe.js";
|
||||||
import { Enums, prisma, Rechnung } from "#lib/server/prisma.js";
|
import {
|
||||||
|
BedarfsausweisWohnen,
|
||||||
|
Enums,
|
||||||
|
prisma,
|
||||||
|
Rechnung,
|
||||||
|
VerbrauchsausweisGewerbe,
|
||||||
|
VerbrauchsausweisWohnen,
|
||||||
|
} from "#lib/server/prisma.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gibt den richtigen Prisma Adapter für die Ausweisart basierend auf der UID zurück, oder null bei einer falschen UID.
|
* Gibt den richtigen Prisma Adapter für die Ausweisart basierend auf der UID zurück, oder null bei einer falschen UID.
|
||||||
@@ -15,17 +31,17 @@ export function getPrismaAusweisAdapter(id: string) {
|
|||||||
const ausweisart = getAusweisartFromId(id);
|
const ausweisart = getAusweisartFromId(id);
|
||||||
|
|
||||||
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
|
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
|
||||||
return prisma.verbrauchsausweisWohnen
|
return prisma.verbrauchsausweisWohnen;
|
||||||
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
||||||
return prisma.verbrauchsausweisGewerbe
|
return prisma.verbrauchsausweisGewerbe;
|
||||||
} else if (ausweisart === Enums.Ausweisart.BedarfsausweisWohnen) {
|
} else if (ausweisart === Enums.Ausweisart.BedarfsausweisWohnen) {
|
||||||
return prisma.bedarfsausweisWohnen
|
return prisma.bedarfsausweisWohnen;
|
||||||
} else if (ausweisart === Enums.Ausweisart.GEGNachweisWohnen) {
|
} else if (ausweisart === Enums.Ausweisart.GEGNachweisWohnen) {
|
||||||
return prisma.gEGNachweisWohnen
|
return prisma.gEGNachweisWohnen;
|
||||||
} else if (ausweisart === Enums.Ausweisart.GEGNachweisGewerbe) {
|
} else if (ausweisart === Enums.Ausweisart.GEGNachweisGewerbe) {
|
||||||
return prisma.gEGNachweisGewerbe
|
return prisma.gEGNachweisGewerbe;
|
||||||
} else if (ausweisart === Enums.Ausweisart.BedarfsausweisGewerbe) {
|
} else if (ausweisart === Enums.Ausweisart.BedarfsausweisGewerbe) {
|
||||||
return prisma.bedarfsausweisGewerbe
|
return prisma.bedarfsausweisGewerbe;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,50 +49,161 @@ export function getPrismaAusweisAdapter(id: string) {
|
|||||||
* Gibt den richtigen Ansichtsausweis basierend auf der Ausweisart zurück.
|
* Gibt den richtigen Ansichtsausweis basierend auf der Ausweisart zurück.
|
||||||
* @param ausweis
|
* @param ausweis
|
||||||
*/
|
*/
|
||||||
export async function getAnsichtsausweis(ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbeClient | BedarfsausweisWohnenClient, aufnahme: AufnahmeClient, objekt: ObjektClient, bilder: BildClient[], user: BenutzerClient, vorschau: boolean = true, ausweisart = getAusweisartFromId(ausweis.id)) {
|
export async function getAnsichtsausweis(
|
||||||
|
ausweis:
|
||||||
|
| VerbrauchsausweisWohnenClient
|
||||||
|
| VerbrauchsausweisGewerbeClient
|
||||||
|
| BedarfsausweisWohnenClient,
|
||||||
|
aufnahme: AufnahmeClient,
|
||||||
|
objekt: ObjektClient,
|
||||||
|
bilder: BildClient[],
|
||||||
|
user: BenutzerClient,
|
||||||
|
vorschau: boolean = true,
|
||||||
|
ausweisart = getAusweisartFromId(ausweis.id)
|
||||||
|
) {
|
||||||
if (!ausweisart) {
|
if (!ausweisart) {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
|
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
|
||||||
return await pdfVerbrauchsausweisWohnen(ausweis as VerbrauchsausweisWohnenClient, aufnahme, objekt, bilder, user, vorschau)
|
return await pdfVerbrauchsausweisWohnen(
|
||||||
|
ausweis as VerbrauchsausweisWohnenClient,
|
||||||
|
aufnahme,
|
||||||
|
objekt,
|
||||||
|
bilder,
|
||||||
|
user,
|
||||||
|
vorschau
|
||||||
|
);
|
||||||
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
||||||
return await pdfVerbrauchsausweisGewerbe(ausweis as VerbrauchsausweisGewerbeClient, aufnahme, objekt, bilder, user, vorschau)
|
return await pdfVerbrauchsausweisGewerbe(
|
||||||
|
ausweis as VerbrauchsausweisGewerbeClient,
|
||||||
|
aufnahme,
|
||||||
|
objekt,
|
||||||
|
bilder,
|
||||||
|
user,
|
||||||
|
vorschau
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gibt das richtige Datenblatt basierend auf der Ausweisart zurück.
|
* Gibt das richtige Datenblatt basierend auf der Ausweisart zurück.
|
||||||
* @param ausweis
|
* @param ausweis
|
||||||
*/
|
*/
|
||||||
export async function getDatenblatt(ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbeClient | BedarfsausweisWohnenClient, aufnahme: AufnahmeClient, objekt: ObjektClient, bilder: BildClient[], user: BenutzerClient, rechnung: Rechnung, ausweisart = getAusweisartFromId(ausweis.id)) {
|
export async function getDatenblatt(
|
||||||
|
ausweis:
|
||||||
|
| VerbrauchsausweisWohnenClient
|
||||||
|
| VerbrauchsausweisGewerbeClient
|
||||||
|
| BedarfsausweisWohnenClient,
|
||||||
|
aufnahme: AufnahmeClient,
|
||||||
|
objekt: ObjektClient,
|
||||||
|
bilder: BildClient[],
|
||||||
|
user: BenutzerClient,
|
||||||
|
rechnung: Rechnung,
|
||||||
|
ausweisart = getAusweisartFromId(ausweis.id)
|
||||||
|
) {
|
||||||
if (!ausweisart) {
|
if (!ausweisart) {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
|
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
|
||||||
return await pdfDatenblattVerbrauchsausweisWohnen(ausweis as VerbrauchsausweisWohnenClient, aufnahme, objekt, rechnung, bilder)
|
return await pdfDatenblattVerbrauchsausweisWohnen(
|
||||||
|
ausweis as VerbrauchsausweisWohnenClient,
|
||||||
|
aufnahme,
|
||||||
|
objekt,
|
||||||
|
rechnung,
|
||||||
|
bilder
|
||||||
|
);
|
||||||
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
||||||
return await pdfDatenblattVerbrauchsausweisGewerbe(ausweis as VerbrauchsausweisGewerbeClient, aufnahme, objekt, rechnung, bilder)
|
return await pdfDatenblattVerbrauchsausweisGewerbe(
|
||||||
|
ausweis as VerbrauchsausweisGewerbeClient,
|
||||||
|
aufnahme,
|
||||||
|
objekt,
|
||||||
|
rechnung,
|
||||||
|
bilder
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gibt den richtigen Aushang basierend auf der Ausweisart zurück.
|
* Gibt den richtigen Aushang basierend auf der Ausweisart zurück.
|
||||||
* @param ausweis
|
* @param ausweis
|
||||||
*/
|
*/
|
||||||
export async function getAushang(ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbeClient | BedarfsausweisWohnenClient, aufnahme: AufnahmeClient, objekt: ObjektClient, bilder: BildClient[], user: BenutzerClient, vorschau: boolean = true, rechnung: Rechnung, ausweisart = getAusweisartFromId(ausweis.id)) {
|
export async function getAushang(
|
||||||
|
ausweis:
|
||||||
|
| VerbrauchsausweisWohnenClient
|
||||||
|
| VerbrauchsausweisGewerbeClient
|
||||||
|
| BedarfsausweisWohnenClient,
|
||||||
|
aufnahme: AufnahmeClient,
|
||||||
|
objekt: ObjektClient,
|
||||||
|
bilder: BildClient[],
|
||||||
|
user: BenutzerClient,
|
||||||
|
vorschau: boolean = true,
|
||||||
|
rechnung: Rechnung,
|
||||||
|
ausweisart = getAusweisartFromId(ausweis.id)
|
||||||
|
) {
|
||||||
if (!ausweisart || !rechnung.services.includes(Enums.Service.Aushang)) {
|
if (!ausweisart || !rechnung.services.includes(Enums.Service.Aushang)) {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
||||||
return await pdfAushangVerbrauchsausweisGewerbe(ausweis as VerbrauchsausweisGewerbeClient, aufnahme, objekt, bilder, user, vorschau)
|
return await pdfAushangVerbrauchsausweisGewerbe(
|
||||||
|
ausweis as VerbrauchsausweisGewerbeClient,
|
||||||
|
aufnahme,
|
||||||
|
objekt,
|
||||||
|
bilder,
|
||||||
|
user,
|
||||||
|
vorschau
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extrahiert die Ausweisfelder aus einem Objekt, das mehrere Ausweisarten enthält, und fasst sie in einem gemeinsamen Feld `ausweis` zusammen.
|
||||||
|
* @param row Ein Objekt, das die Ausweisfelder enthält.
|
||||||
|
* @returns Ein neues Objekt, das die Ausweisfelder extrahiert und in einem gemeinsamen Feld `ausweis` zusammenfasst.
|
||||||
|
*/
|
||||||
|
export function extrahiereAusweisAusFeldMitMehrerenAusweisen<T>(
|
||||||
|
row: T & {
|
||||||
|
bedarfsausweis_wohnen?: BedarfsausweisWohnen;
|
||||||
|
verbrauchsausweis_wohnen?: VerbrauchsausweisWohnen;
|
||||||
|
verbrauchsausweis_gewerbe?: VerbrauchsausweisGewerbe;
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
const {
|
||||||
|
bedarfsausweis_wohnen,
|
||||||
|
verbrauchsausweis_wohnen,
|
||||||
|
verbrauchsausweis_gewerbe,
|
||||||
|
...rest
|
||||||
|
} = row;
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
ausweis: {
|
||||||
|
...(bedarfsausweis_wohnen ??
|
||||||
|
verbrauchsausweis_wohnen ??
|
||||||
|
verbrauchsausweis_gewerbe),
|
||||||
|
ausweisart: bedarfsausweis_wohnen
|
||||||
|
? Enums.Ausweisart.BedarfsausweisWohnen
|
||||||
|
: verbrauchsausweis_wohnen
|
||||||
|
? Enums.Ausweisart.VerbrauchsausweisWohnen
|
||||||
|
: Enums.Ausweisart.VerbrauchsausweisGewerbe,
|
||||||
|
},
|
||||||
|
} as {
|
||||||
|
ausweis: (
|
||||||
|
| BedarfsausweisWohnen
|
||||||
|
| VerbrauchsausweisWohnen
|
||||||
|
| VerbrauchsausweisGewerbe
|
||||||
|
) & { ausweisart: Enums.Ausweisart };
|
||||||
|
} & Omit<
|
||||||
|
T,
|
||||||
|
| "bedarfsausweis_wohnen"
|
||||||
|
| "verbrauchsausweis_wohnen"
|
||||||
|
| "verbrauchsausweis_gewerbe"
|
||||||
|
>;
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,27 @@
|
|||||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
||||||
import { checkAuthorizationHeader, checkAuthorizationHeaderNoThrow } from "#lib/middleware/authorization.js";
|
import { checkAuthorizationHeader, checkAuthorizationHeaderNoThrow } from "#lib/middleware/authorization.js";
|
||||||
import { AstroGlobal } from "astro";
|
import { AstroGlobal } from "astro";
|
||||||
|
import { Enums } from "#lib/client/prisma.js";
|
||||||
|
import { prisma } from "#lib/server/prisma.js";
|
||||||
|
|
||||||
export function getCurrentUser(Astro: AstroGlobal) {
|
export function getCurrentUser(Astro: AstroGlobal) {
|
||||||
const accessToken = Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value;
|
const accessToken = Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value;
|
||||||
|
|
||||||
return checkAuthorizationHeaderNoThrow(`Bearer ${accessToken}`)
|
return checkAuthorizationHeaderNoThrow(`Bearer ${accessToken}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getOtherUser(Astro: AstroGlobal, userId : string) {
|
||||||
|
const accessToken = Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value;
|
||||||
|
|
||||||
|
let currentUser = await checkAuthorizationHeaderNoThrow(`Bearer ${accessToken}`)
|
||||||
|
|
||||||
|
if (currentUser?.rolle == Enums.BenutzerRolle.ADMIN) {
|
||||||
|
const user = await prisma.benutzer.findUnique({
|
||||||
|
where: {
|
||||||
|
id: userId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
@@ -6,11 +6,10 @@
|
|||||||
export let onLogin: (response: Awaited<ReturnType<typeof loginClient>>) => any;
|
export let onLogin: (response: Awaited<ReturnType<typeof loginClient>>) => any;
|
||||||
export let email: string = "";
|
export let email: string = "";
|
||||||
export let password: string = "";
|
export let password: string = "";
|
||||||
|
export let route: "login" | "signup" = "login"
|
||||||
|
|
||||||
let route: "login" | "signup" = "login"
|
const navigate = (target: string) => {
|
||||||
|
route = target as typeof route;
|
||||||
const navigate = (target: typeof route) => {
|
|
||||||
route = target
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const loginData = {
|
const loginData = {
|
||||||
|
|||||||
@@ -1,384 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import ZipSearch from "../components/PlzSuche.svelte";
|
|
||||||
import Label from "../components/Label.svelte";
|
|
||||||
import type {
|
|
||||||
Bezahlmethoden,
|
|
||||||
} from "#lib/client/prisma";
|
|
||||||
import { Enums } from "#lib/client/prisma";
|
|
||||||
import PaymentOption from "#components/PaymentOption.svelte";
|
|
||||||
import CheckoutItem from "#components/CheckoutItem.svelte";
|
|
||||||
import { BenutzerClient, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types.js";
|
|
||||||
import { PRICES } from "#lib/constants.js";
|
|
||||||
import { RechnungClient } from "#components/Ausweis/types.js";
|
|
||||||
import { api } from "astro-typesafe-api/client";
|
|
||||||
|
|
||||||
export let user: BenutzerClient;
|
|
||||||
export let ausweis:
|
|
||||||
| VerbrauchsausweisWohnenClient;
|
|
||||||
// TODO: überarbeiten und zu inferProcedureOutput machen
|
|
||||||
let rechnung: Partial<RechnungClient> = {
|
|
||||||
email: user.email,
|
|
||||||
empfaenger: user.vorname + " " + user.name,
|
|
||||||
strasse: user.adresse,
|
|
||||||
plz: user.plz,
|
|
||||||
ort: user.ort,
|
|
||||||
versand_empfaenger: user.vorname + " " + user.name,
|
|
||||||
versand_strasse: user.adresse,
|
|
||||||
versand_plz: user.plz,
|
|
||||||
versand_ort: user.ort,
|
|
||||||
telefon: user.telefon,
|
|
||||||
};
|
|
||||||
|
|
||||||
let services = [
|
|
||||||
{
|
|
||||||
name: "Qualitätsdruck per Post (zusätzlich zur PDF Version) für 9€ inkl. MwSt.",
|
|
||||||
id: Enums.Service.Qualitaetsdruck,
|
|
||||||
price: 9,
|
|
||||||
selected: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Aushang (für öffentliche Gebäude gesetzlich vorgeschrieben) für 10€ inkl. MwSt.",
|
|
||||||
id: Enums.Service.Aushang,
|
|
||||||
price: 10,
|
|
||||||
selected: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Same Day Service (Bestellung Werktags vor 12:00 Uhr - Ausstellung bis 18:00 Uhr am gleichen Tag) für 29€ inkl. MwSt.",
|
|
||||||
id: Enums.Service.SameDay,
|
|
||||||
price: 29,
|
|
||||||
selected: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Telefonische Energieeffizienzberatung für 75€ inkl. MwSt.",
|
|
||||||
id: Enums.Service.Telefonberatung,
|
|
||||||
price: 75,
|
|
||||||
selected: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export let aktiveBezahlmethode: Bezahlmethoden =
|
|
||||||
Enums.Bezahlmethoden.paypal;
|
|
||||||
|
|
||||||
async function createPayment(e: SubmitEvent) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
const response = await api.rechnung.PUT.fetch({
|
|
||||||
...rechnung,
|
|
||||||
ausweisart: Enums.Ausweisart.VerbrauchsausweisWohnen,
|
|
||||||
ausweis_uid: ausweis.uid,
|
|
||||||
bezahlmethode: aktiveBezahlmethode,
|
|
||||||
services: services
|
|
||||||
.filter((service) => service.selected)
|
|
||||||
.map((service) => service.id),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (aktiveBezahlmethode === Enums.Bezahlmethoden.rechnung) {
|
|
||||||
window.location.href = `/payment/success?r=${response.uid}&a=${ausweis.uid}`
|
|
||||||
} else {
|
|
||||||
window.location.href = response.checkout_url as string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const priceTotal = services.reduce((acc, service) => {
|
|
||||||
if (service.selected) {
|
|
||||||
return acc + service.price;
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
}, 0) + PRICES[Enums.Ausweisart.VerbrauchsausweisWohnen][0];
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<form class="grid grid-cols-[2fr_1fr] gap-4 h-full" on:submit={createPayment}>
|
|
||||||
<div>
|
|
||||||
<h3 class="font-semibold">Ansprechpartner</h3>
|
|
||||||
<div class="rounded-lg border p-4 border-base-300 bg-base-100">
|
|
||||||
<div class="grid grid-cols-3 gap-4">
|
|
||||||
<!-- Anrede -->
|
|
||||||
<div>
|
|
||||||
<Label>Anrede *</Label>
|
|
||||||
<div>
|
|
||||||
<select name="anrede" bind:value={user.anrede}>
|
|
||||||
<option>bitte auswählen</option>
|
|
||||||
<option value="Herr">Herr</option>
|
|
||||||
<option value="Frau">Frau</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Vorname -->
|
|
||||||
<div>
|
|
||||||
<Label>Vorname *</Label>
|
|
||||||
<input
|
|
||||||
name="vorname"
|
|
||||||
type="text"
|
|
||||||
bind:value={user.vorname}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nachname -->
|
|
||||||
<div>
|
|
||||||
<Label>Nachname *</Label>
|
|
||||||
<input
|
|
||||||
name="name"
|
|
||||||
type="text"
|
|
||||||
bind:value={user.name}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="grid grid-cols-2 gap-4">
|
|
||||||
<!-- Telefon -->
|
|
||||||
<div>
|
|
||||||
<Label>Telefon</Label>
|
|
||||||
<input
|
|
||||||
name="telefon"
|
|
||||||
bind:value={user.telefon}
|
|
||||||
type="text"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Email -->
|
|
||||||
<div>
|
|
||||||
<Label>E-Mail *</Label>
|
|
||||||
<input
|
|
||||||
name="email"
|
|
||||||
type="email"
|
|
||||||
bind:value={user.email}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h3 class="mt-8 font-semibold">Rechnungsadresse</h3>
|
|
||||||
<div class="rounded-lg border p-4 border-base-300 bg-base-100">
|
|
||||||
<div class="grid grid-cols-2 gap-4">
|
|
||||||
<div>
|
|
||||||
<Label>Empfänger *</Label>
|
|
||||||
<input
|
|
||||||
name="rechnung_empfaenger"
|
|
||||||
type="text"
|
|
||||||
bind:value={rechnung.empfaenger}
|
|
||||||
required
|
|
||||||
data-rule-maxlength="100"
|
|
||||||
data-msg-maxlength="max. 100 Zeichen"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Zusatzzeile -->
|
|
||||||
<div>
|
|
||||||
<Label>Zusatzzeile</Label>
|
|
||||||
<input
|
|
||||||
name="rechnung_zusatzzeile"
|
|
||||||
bind:value={rechnung.zusatzzeile}
|
|
||||||
type="text"
|
|
||||||
data-rule-maxlength="80"
|
|
||||||
data-msg-maxlength="max. 80 Zeichen"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="grid grid-cols-3 gap-4">
|
|
||||||
<!-- Strasse -->
|
|
||||||
<div>
|
|
||||||
<Label>Straße, Hausnummer *</Label>
|
|
||||||
<input
|
|
||||||
name="rechnung_strasse"
|
|
||||||
bind:value={rechnung.strasse}
|
|
||||||
type="text"
|
|
||||||
required
|
|
||||||
data-rule-maxlength="40"
|
|
||||||
data-msg-maxlength="max. 40 Zeichen"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- PLZ -->
|
|
||||||
<ZipSearch
|
|
||||||
name="rechnung_plz"
|
|
||||||
bind:zip={rechnung.plz}
|
|
||||||
bind:city={rechnung.ort}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- Ort -->
|
|
||||||
<div>
|
|
||||||
<Label>Ort *</Label>
|
|
||||||
<input
|
|
||||||
name="rechnung_ort"
|
|
||||||
readonly
|
|
||||||
type="text"
|
|
||||||
required
|
|
||||||
value={rechnung.ort}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="grid grid-cols-2 gap-4">
|
|
||||||
<!-- Telefon -->
|
|
||||||
<div>
|
|
||||||
<Label>Telefon</Label>
|
|
||||||
<input
|
|
||||||
name="rechnung_telefon"
|
|
||||||
bind:value={rechnung.telefon}
|
|
||||||
type="text"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Email -->
|
|
||||||
<div>
|
|
||||||
<Label>E-Mail</Label>
|
|
||||||
<input
|
|
||||||
name="rechnung_email"
|
|
||||||
bind:value={rechnung.email}
|
|
||||||
type="email"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h3 class="mt-8 font-semibold">Versandadresse</h3>
|
|
||||||
<div class="rounded-lg border p-4 border-base-300 bg-base-100">
|
|
||||||
<div class="flex flex-row gap-2 items-center">
|
|
||||||
<input
|
|
||||||
class="w-[15px] h-[15px]"
|
|
||||||
type="checkbox"
|
|
||||||
name="abweichende_versand_adresse"
|
|
||||||
bind:checked={rechnung.abweichende_versand_adresse}
|
|
||||||
/>
|
|
||||||
<Label>Abweichende Versandadresse</Label>
|
|
||||||
</div>
|
|
||||||
<div class="grid grid-cols-2 gap-4">
|
|
||||||
<!-- Empfänger -->
|
|
||||||
<div>
|
|
||||||
<Label>Empfänger *</Label>
|
|
||||||
<input
|
|
||||||
name="versand_empfaenger"
|
|
||||||
type="text"
|
|
||||||
readonly={!rechnung.abweichende_versand_adresse}
|
|
||||||
bind:value={rechnung.versand_empfaenger}
|
|
||||||
required
|
|
||||||
data-rule-maxlength="100"
|
|
||||||
data-msg-maxlength="max. 100 Zeichen"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Zusatzzeile -->
|
|
||||||
<div>
|
|
||||||
<Label>Zusatzzeile</Label>
|
|
||||||
<input
|
|
||||||
name="versand_zusatzzeile"
|
|
||||||
type="text"
|
|
||||||
readonly={!rechnung.abweichende_versand_adresse}
|
|
||||||
bind:value={rechnung.versand_zusatzzeile}
|
|
||||||
data-rule-maxlength="80"
|
|
||||||
data-msg-maxlength="max. 80 Zeichen"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="grid grid-cols-3 gap-4">
|
|
||||||
<!-- Strasse -->
|
|
||||||
<div>
|
|
||||||
<Label>Straße, Hausnummer *</Label>
|
|
||||||
<input
|
|
||||||
name="versand_strasse"
|
|
||||||
type="text"
|
|
||||||
readonly={!rechnung.abweichende_versand_adresse}
|
|
||||||
bind:value={rechnung.versand_strasse}
|
|
||||||
required
|
|
||||||
data-rule-maxlength="40"
|
|
||||||
data-msg-maxlength="max. 40 Zeichen"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- PLZ -->
|
|
||||||
<ZipSearch
|
|
||||||
name="versand_plz"
|
|
||||||
readonly={!rechnung.abweichende_versand_adresse}
|
|
||||||
bind:zip={rechnung.versand_plz}
|
|
||||||
bind:city={rechnung.versand_ort}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- Ort -->
|
|
||||||
<div>
|
|
||||||
<Label>Ort *</Label>
|
|
||||||
<input
|
|
||||||
name="versand_ort"
|
|
||||||
type="text"
|
|
||||||
readonly
|
|
||||||
required
|
|
||||||
bind:value={rechnung.versand_ort}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h3 class="mt-8 font-semibold">Bezahlmethode</h3>
|
|
||||||
<div
|
|
||||||
class="rounded-lg border p-4 border-base-300 bg-base-100 flex flex-row gap-4 justify-between"
|
|
||||||
>
|
|
||||||
<PaymentOption
|
|
||||||
bezahlmethode={Enums.Bezahlmethoden.paypal}
|
|
||||||
bind:aktiveBezahlmethode
|
|
||||||
name={"PayPal"}
|
|
||||||
icon={"/images/paypal.png"}
|
|
||||||
></PaymentOption>
|
|
||||||
<PaymentOption
|
|
||||||
bezahlmethode={Enums.Bezahlmethoden.sofort}
|
|
||||||
bind:aktiveBezahlmethode
|
|
||||||
name={"Sofort"}
|
|
||||||
icon={"/images/sofort.png"}
|
|
||||||
></PaymentOption>
|
|
||||||
<PaymentOption
|
|
||||||
bezahlmethode={Enums.Bezahlmethoden.giropay}
|
|
||||||
bind:aktiveBezahlmethode
|
|
||||||
name={"Giropay"}
|
|
||||||
icon={"/images/giropay.png"}
|
|
||||||
></PaymentOption>
|
|
||||||
<PaymentOption
|
|
||||||
bezahlmethode={Enums.Bezahlmethoden.creditcard}
|
|
||||||
bind:aktiveBezahlmethode
|
|
||||||
name={"Kreditkarte"}
|
|
||||||
icon={"/images/mastercard.png"}
|
|
||||||
></PaymentOption>
|
|
||||||
<PaymentOption
|
|
||||||
bezahlmethode={Enums.Bezahlmethoden.rechnung}
|
|
||||||
bind:aktiveBezahlmethode
|
|
||||||
name={"Rechnung"}
|
|
||||||
icon={"/images/rechnung.png"}
|
|
||||||
></PaymentOption>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h3 class="font-semibold">Zusammenfassung</h3>
|
|
||||||
<div class="rounded-lg border p-4 border-base-300 bg-base-100">
|
|
||||||
<CheckoutItem
|
|
||||||
image={"https://www.gih.de/wp-content/uploads/2015/11/EnergieausweisW-E.jpg"}
|
|
||||||
name={"Energieausweis"}
|
|
||||||
description={"Verbrauchsausweis Wohnen"}
|
|
||||||
price={45}
|
|
||||||
quantity={1}
|
|
||||||
removable={false}
|
|
||||||
maxQuantity={1}
|
|
||||||
/>
|
|
||||||
<div class="mt-auto">
|
|
||||||
<hr />
|
|
||||||
<div class="flex flex-row items-center justify-between">
|
|
||||||
<span class="opacity-75 text-sm">Netto</span>
|
|
||||||
<span class="font-semibold text-sm">{Math.round(priceTotal * 0.81 * 100) / 100}€</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-row items-center justify-between">
|
|
||||||
<span class="opacity-75 text-sm">19% MwSt</span>
|
|
||||||
<span class="font-semibold text-sm">{Math.round(priceTotal * 0.19 * 100) / 100}}€</span>
|
|
||||||
</div>
|
|
||||||
<hr />
|
|
||||||
<div class="flex flex-row items-center justify-between">
|
|
||||||
<span class="opacity-75 text-sm">Gesamt</span>
|
|
||||||
<span class="font-semibold text-sm">{Math.round(priceTotal)}€</span>
|
|
||||||
</div>
|
|
||||||
<p class="mt-8">Mit dem Klick auf "Bestellung Bestätigen" akzeptieren sie unsere <a href="/agb">AGB</a> und <a href="/impressum">Datenschutzbestimmungen</a>. Sie werden zu ihrem ausgewählten Bezahlprovider weitergeleitet, nach Bezahlung werden sie automatisch zu unserem Portal zurückgeleitet.</p>
|
|
||||||
<button class="btn btn-secondary w-full mt-4"
|
|
||||||
>Bestellung Bestätigen</button
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
@@ -32,8 +32,12 @@
|
|||||||
import { getMaximumDevitationInPercent } from "#client/lib/helpers.js";
|
import { getMaximumDevitationInPercent } from "#client/lib/helpers.js";
|
||||||
import { endEnergieVerbrauchVerbrauchsausweis_2016_Client } from "#lib/Berechnungen/VerbrauchsausweisWohnen/VerbrauchsausweisWohnen_2016_Client.js";
|
import { endEnergieVerbrauchVerbrauchsausweis_2016_Client } from "#lib/Berechnungen/VerbrauchsausweisWohnen/VerbrauchsausweisWohnen_2016_Client.js";
|
||||||
import { endEnergieVerbrauchVerbrauchsausweisGewerbe_2016_Client } from "#lib/Berechnungen/VerbrauchsausweisGewerbe/VerbrauchsausweisGewerbe_2016_Client.js";
|
import { endEnergieVerbrauchVerbrauchsausweisGewerbe_2016_Client } from "#lib/Berechnungen/VerbrauchsausweisGewerbe/VerbrauchsausweisGewerbe_2016_Client.js";
|
||||||
|
import { benutzerSpeichern } from "#client/lib/speichern.js";
|
||||||
|
import { benutzerLesen } from "#client/lib/lesen.js";
|
||||||
|
import { exclude } from "#lib/exclude.js";
|
||||||
|
|
||||||
export let user: Partial<BenutzerClient>;
|
export let user: Partial<BenutzerClient>;
|
||||||
|
export let impersonatedUser: Partial<BenutzerClient> | null = null;
|
||||||
export let ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbe | BedarfsausweisWohnen;
|
export let ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbe | BedarfsausweisWohnen;
|
||||||
export let aufnahme: AufnahmeClient;
|
export let aufnahme: AufnahmeClient;
|
||||||
export let objekt: ObjektClient;
|
export let objekt: ObjektClient;
|
||||||
@@ -42,9 +46,8 @@
|
|||||||
export let rechnung: RechnungClient | null = null;
|
export let rechnung: RechnungClient | null = null;
|
||||||
export let ausweisart: Enums.Ausweisart;
|
export let ausweisart: Enums.Ausweisart;
|
||||||
export let aktiveBezahlmethode: Bezahlmethoden = Enums.Bezahlmethoden.paypal;
|
export let aktiveBezahlmethode: Bezahlmethoden = Enums.Bezahlmethoden.paypal;
|
||||||
|
|
||||||
export let partner_code: string;
|
export let partner_code: string;
|
||||||
|
export let nurRechnungsadresseUpdate: Boolean | null = false;
|
||||||
|
|
||||||
let email: string, vorname: string, name: string, empfaenger: string, strasse: string, plz: string, ort: string, zusatzzeile: string, telefon: string;
|
let email: string, vorname: string, name: string, empfaenger: string, strasse: string, plz: string, ort: string, zusatzzeile: string, telefon: string;
|
||||||
|
|
||||||
@@ -59,9 +62,22 @@
|
|||||||
ort = rechnung?.ort || localStorage.getItem("kundendaten.ort") || user.ort || "";
|
ort = rechnung?.ort || localStorage.getItem("kundendaten.ort") || user.ort || "";
|
||||||
zusatzzeile = rechnung?.zusatzzeile || localStorage.getItem("kundendaten.zusatzzeile") || ""
|
zusatzzeile = rechnung?.zusatzzeile || localStorage.getItem("kundendaten.zusatzzeile") || ""
|
||||||
telefon = rechnung?.telefon || localStorage.getItem("kundendaten.telefon") || user.telefon || "";
|
telefon = rechnung?.telefon || localStorage.getItem("kundendaten.telefon") || user.telefon || "";
|
||||||
|
} else if (impersonatedUser) {
|
||||||
|
vorname = impersonatedUser.vorname || "";
|
||||||
|
name = impersonatedUser.name || "";
|
||||||
|
telefon = impersonatedUser.telefon || "";
|
||||||
|
email = impersonatedUser.email || "";
|
||||||
|
if (rechnung){
|
||||||
|
empfaenger = rechnung?.empfaenger || "";
|
||||||
|
strasse = rechnung?.strasse || "";
|
||||||
|
plz = rechnung?.plz || "";
|
||||||
|
ort = rechnung?.ort || "";
|
||||||
|
zusatzzeile = rechnung?.zusatzzeile || "";
|
||||||
|
email = rechnung?.email || "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let abweichende_versand_adresse = JSON.parse(localStorage.getItem("kundendaten.abweichende_versand_adresse") || "false")
|
let abweichende_versand_adresse = rechnung?.abweichende_versand_adresse ?? JSON.parse(localStorage.getItem("kundendaten.abweichende_versand_adresse") || "false")
|
||||||
|
|
||||||
let versand_email: string | undefined,
|
let versand_email: string | undefined,
|
||||||
versand_zusatzzeile: string | undefined,
|
versand_zusatzzeile: string | undefined,
|
||||||
@@ -69,16 +85,13 @@
|
|||||||
versand_strasse: string | undefined,
|
versand_strasse: string | undefined,
|
||||||
versand_plz: string | undefined,
|
versand_plz: string | undefined,
|
||||||
versand_ort: string | undefined;
|
versand_ort: string | undefined;
|
||||||
$: {
|
|
||||||
if (!abweichende_versand_adresse) {
|
versand_email = "";//Todo Datenbankfeld fehlt noch
|
||||||
versand_email = email
|
versand_zusatzzeile = rechnung?.versand_zusatzzeile ?? zusatzzeile;
|
||||||
versand_zusatzzeile = zusatzzeile
|
versand_empfaenger = rechnung?.versand_empfaenger ?? empfaenger;
|
||||||
versand_empfaenger = empfaenger
|
versand_strasse = rechnung?.versand_strasse ?? strasse;
|
||||||
versand_strasse = strasse
|
versand_plz = rechnung?.versand_plz ?? plz;
|
||||||
versand_plz = plz
|
versand_ort = rechnung?.versand_ort ?? ort;
|
||||||
versand_ort = ort
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
// Wir speichern jede Änderung an den Kundendaten im localStorage ab.
|
// Wir speichern jede Änderung an den Kundendaten im localStorage ab.
|
||||||
@@ -199,6 +212,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const merged_versand_empfaenger = versand_empfaenger || empfaenger;
|
||||||
|
const merged_versand_strasse = versand_strasse || strasse;
|
||||||
|
const merged_versand_plz = versand_plz || plz;
|
||||||
|
const merged_versand_ort = versand_ort || ort;
|
||||||
|
const merged_versand_zusatzzeile = versand_zusatzzeile || zusatzzeile;
|
||||||
|
|
||||||
const { id } = await api.rechnung.anfordern.PUT.fetch(
|
const { id } = await api.rechnung.anfordern.PUT.fetch(
|
||||||
{
|
{
|
||||||
email: email,
|
email: email,
|
||||||
@@ -206,10 +225,11 @@
|
|||||||
strasse: strasse,
|
strasse: strasse,
|
||||||
plz: plz,
|
plz: plz,
|
||||||
ort: ort,
|
ort: ort,
|
||||||
versand_empfaenger: versand_empfaenger,
|
versand_empfaenger: merged_versand_empfaenger,
|
||||||
versand_strasse: versand_strasse,
|
versand_strasse: merged_versand_strasse,
|
||||||
versand_plz: versand_plz,
|
versand_plz: merged_versand_plz,
|
||||||
versand_ort: versand_ort,
|
versand_ort: merged_versand_ort,
|
||||||
|
versand_zusatzzeile: merged_versand_zusatzzeile,
|
||||||
telefon: telefon,
|
telefon: telefon,
|
||||||
nachweis_id: result.nachweis_id
|
nachweis_id: result.nachweis_id
|
||||||
},
|
},
|
||||||
@@ -233,7 +253,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function speichern() {
|
async function speichern(authuser = null) {
|
||||||
loginAction = speichern;
|
loginAction = speichern;
|
||||||
if (!await validateAccessTokenClient()) {
|
if (!await validateAccessTokenClient()) {
|
||||||
loginOverlayHidden = false;
|
loginOverlayHidden = false;
|
||||||
@@ -249,6 +269,62 @@
|
|||||||
} else {
|
} else {
|
||||||
result = await ausweisSpeichern(ausweis, objekt, aufnahme, bilder, unterlagen, ausweisart)
|
result = await ausweisSpeichern(ausweis, objekt, aufnahme, bilder, unterlagen, ausweisart)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (authuser) {
|
||||||
|
user = await benutzerLesen(authuser.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let resultUser: Awaited<ReturnType<typeof benutzerSpeichern>> | Awaited<ReturnType<typeof benutzerSpeichern>> | null = null;
|
||||||
|
const { passwort, ...baseUser } = impersonatedUser ?? user;
|
||||||
|
|
||||||
|
const benutzerObjekt = {
|
||||||
|
...baseUser,
|
||||||
|
name,
|
||||||
|
vorname,
|
||||||
|
telefon
|
||||||
|
};
|
||||||
|
|
||||||
|
resultUser = await benutzerSpeichern(benutzerObjekt);
|
||||||
|
|
||||||
|
|
||||||
|
let id: string, checkout_url: string | undefined;
|
||||||
|
|
||||||
|
if (rechnung) {
|
||||||
|
const merged_versand_empfaenger = versand_empfaenger || empfaenger;
|
||||||
|
const merged_versand_strasse = versand_strasse || strasse;
|
||||||
|
const merged_versand_plz = versand_plz || plz;
|
||||||
|
const merged_versand_ort = versand_ort || ort;
|
||||||
|
const merged_versand_zusatzzeile = versand_zusatzzeile || zusatzzeile;
|
||||||
|
|
||||||
|
const result = await api.rechnung._id.PATCH.fetch({
|
||||||
|
bezahlmethode: aktiveBezahlmethode,
|
||||||
|
abweichende_versand_adresse: abweichende_versand_adresse,
|
||||||
|
empfaenger,
|
||||||
|
strasse,
|
||||||
|
plz,
|
||||||
|
ort,
|
||||||
|
telefon,
|
||||||
|
email,
|
||||||
|
zusatzzeile,
|
||||||
|
versand_empfaenger: merged_versand_empfaenger,
|
||||||
|
versand_strasse: merged_versand_strasse,
|
||||||
|
versand_plz: merged_versand_plz,
|
||||||
|
versand_ort: merged_versand_ort,
|
||||||
|
versand_zusatzzeile: merged_versand_zusatzzeile
|
||||||
|
}, {
|
||||||
|
params: {
|
||||||
|
id: rechnung.id
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${Cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
id = result.id;
|
||||||
|
checkout_url = result.checkout_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
addNotification({
|
addNotification({
|
||||||
dismissable: true,
|
dismissable: true,
|
||||||
@@ -269,7 +345,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function bestellen() {
|
async function bestellen(authuser = null) {
|
||||||
if (!form.checkValidity()) {
|
if (!form.checkValidity()) {
|
||||||
addNotification({
|
addNotification({
|
||||||
dismissable: true,
|
dismissable: true,
|
||||||
@@ -312,6 +388,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (authuser) {
|
||||||
|
user = await benutzerLesen(authuser.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let resultUser: Awaited<ReturnType<typeof benutzerSpeichern>> | Awaited<ReturnType<typeof benutzerSpeichern>> | null = null;
|
||||||
|
const { passwort, ...baseUser } = impersonatedUser ?? user;
|
||||||
|
|
||||||
|
const benutzerObjekt = {
|
||||||
|
...baseUser,
|
||||||
|
name,
|
||||||
|
vorname,
|
||||||
|
telefon
|
||||||
|
};
|
||||||
|
|
||||||
|
resultUser = await benutzerSpeichern(benutzerObjekt);
|
||||||
|
|
||||||
if (rechnung && rechnung.status === "paid") {
|
if (rechnung && rechnung.status === "paid") {
|
||||||
window.location.href = "/dashboard"
|
window.location.href = "/dashboard"
|
||||||
return;
|
return;
|
||||||
@@ -320,6 +412,12 @@
|
|||||||
try {
|
try {
|
||||||
let id: string, checkout_url: string | undefined;
|
let id: string, checkout_url: string | undefined;
|
||||||
|
|
||||||
|
const merged_versand_empfaenger = versand_empfaenger || empfaenger;
|
||||||
|
const merged_versand_strasse = versand_strasse || strasse;
|
||||||
|
const merged_versand_plz = versand_plz || plz;
|
||||||
|
const merged_versand_ort = versand_ort || ort;
|
||||||
|
const merged_versand_zusatzzeile = versand_zusatzzeile || zusatzzeile;
|
||||||
|
|
||||||
if (rechnung) {
|
if (rechnung) {
|
||||||
const result = await api.rechnung._id.PATCH.fetch({
|
const result = await api.rechnung._id.PATCH.fetch({
|
||||||
bezahlmethode: aktiveBezahlmethode,
|
bezahlmethode: aktiveBezahlmethode,
|
||||||
@@ -328,12 +426,13 @@
|
|||||||
strasse: strasse,
|
strasse: strasse,
|
||||||
plz: plz,
|
plz: plz,
|
||||||
ort: ort,
|
ort: ort,
|
||||||
versand_empfaenger: versand_empfaenger,
|
|
||||||
versand_strasse: versand_strasse,
|
|
||||||
versand_plz: versand_plz,
|
|
||||||
versand_ort: versand_ort,
|
|
||||||
telefon: telefon,
|
telefon: telefon,
|
||||||
versand_zusatzzeile: versand_zusatzzeile
|
zusatzzeile: zusatzzeile,
|
||||||
|
versand_empfaenger: merged_versand_empfaenger,
|
||||||
|
versand_strasse: merged_versand_strasse,
|
||||||
|
versand_plz: merged_versand_plz,
|
||||||
|
versand_ort: merged_versand_ort,
|
||||||
|
versand_zusatzzeile: merged_versand_zusatzzeile
|
||||||
}, {
|
}, {
|
||||||
params: {
|
params: {
|
||||||
id: rechnung.id
|
id: rechnung.id
|
||||||
@@ -358,13 +457,16 @@
|
|||||||
strasse: strasse,
|
strasse: strasse,
|
||||||
plz: plz,
|
plz: plz,
|
||||||
ort: ort,
|
ort: ort,
|
||||||
versand_empfaenger: versand_empfaenger,
|
zusatzzeile: zusatzzeile,
|
||||||
versand_strasse: versand_strasse,
|
versand_empfaenger: merged_versand_empfaenger,
|
||||||
versand_plz: versand_plz,
|
versand_strasse: merged_versand_strasse,
|
||||||
versand_ort: versand_ort,
|
versand_plz: merged_versand_plz,
|
||||||
|
versand_ort: merged_versand_ort,
|
||||||
|
versand_zusatzzeile: merged_versand_zusatzzeile,
|
||||||
telefon: telefon,
|
telefon: telefon,
|
||||||
ausweis_id: ausweis.id,
|
ausweis_id: ausweis.id,
|
||||||
partner_code
|
partner_code,
|
||||||
|
abweichende_versand_adresse: abweichende_versand_adresse
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
@@ -404,6 +506,7 @@
|
|||||||
let form: HTMLFormElement;
|
let form: HTMLFormElement;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#if !nurRechnungsadresseUpdate}
|
||||||
<div
|
<div
|
||||||
id="skala"
|
id="skala"
|
||||||
class="bg-white grid grid-cols-1 gap-x-8 gap-y-4 px-0 sm:p-4
|
class="bg-white grid grid-cols-1 gap-x-8 gap-y-4 px-0 sm:p-4
|
||||||
@@ -434,7 +537,7 @@
|
|||||||
<Progressbar active={1} {ausweisart} ausweistyp={ausweis.ausweistyp} anliegen={"Energieausweis erstellen"} />
|
<Progressbar active={1} {ausweisart} ausweistyp={ausweis.ausweistyp} anliegen={"Energieausweis erstellen"} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<form id="formInput-2" bind:this={form}>
|
<form id="formInput-2" bind:this={form}>
|
||||||
<div id="formular-box" class="formular-boxen ring-0">
|
<div id="formular-box" class="formular-boxen ring-0">
|
||||||
@@ -702,7 +805,6 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
|||||||
<input
|
<input
|
||||||
name="versand_ort"
|
name="versand_ort"
|
||||||
type="text"
|
type="text"
|
||||||
readonly
|
|
||||||
required
|
required
|
||||||
bind:value={versand_ort}
|
bind:value={versand_ort}
|
||||||
/>
|
/>
|
||||||
@@ -739,7 +841,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- E-mail -->
|
<!-- E-mail -->
|
||||||
|
<!-- Versand Email wird derzeit nicht verwendet
|
||||||
<div class="input-standard order-12 md:order-12 xl:order-12">
|
<div class="input-standard order-12 md:order-12 xl:order-12">
|
||||||
<InputLabel title="E-mail *"></InputLabel>
|
<InputLabel title="E-mail *"></InputLabel>
|
||||||
|
|
||||||
@@ -756,7 +858,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
|||||||
</HelpLabel>
|
</HelpLabel>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
-->
|
||||||
<!-- Telefon
|
<!-- Telefon
|
||||||
|
|
||||||
<div class="input-standard order-[13] md:order-[13] xl:order-[13]">
|
<div class="input-standard order-[13] md:order-[13] xl:order-[13]">
|
||||||
@@ -780,7 +882,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
|||||||
</Bereich
|
</Bereich
|
||||||
>
|
>
|
||||||
|
|
||||||
{#if !gegAnfrage}
|
{#if !gegAnfrage && !nurRechnungsadresseUpdate}
|
||||||
<Bereich bereich="3" title="Bezahlmethode">
|
<Bereich bereich="3" title="Bezahlmethode">
|
||||||
<div
|
<div
|
||||||
id="bezahlung"
|
id="bezahlung"
|
||||||
@@ -891,7 +993,7 @@ grid-cols-3 sm:grid-cols-5 justify-around justify-items-center items-center"
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<!-- Falls wir es mit einem Ausweis zu tun haben und der Nutzer keine Hilfe bestellt hat dann zeigen wir eine Box mit sachen an die vielleicht unklar sind. -->
|
<!-- Falls wir es mit einem Ausweis zu tun haben und der Nutzer keine Hilfe bestellt hat dann zeigen wir eine Box mit sachen an die vielleicht unklar sind. -->
|
||||||
{#if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen || ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe || ausweisart === Enums.Ausweisart.BedarfsausweisWohnen) && (ausweis.ausweistyp === Enums.AusweisTyp.Standard || ausweis.ausweistyp === Enums.AusweisTyp.standardXL)}
|
{#if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen || ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe || ausweisart === Enums.Ausweisart.BedarfsausweisWohnen) && (ausweis.ausweistyp === Enums.AusweisTyp.Standard || ausweis.ausweistyp === Enums.AusweisTyp.standardXL) && (!nurRechnungsadresseUpdate)}
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-1 gap-x-6 my-6">
|
<div class="grid grid-cols-1 sm:grid-cols-1 gap-x-6 my-6">
|
||||||
<div class="pruefpunkte bereich-box bg-white">
|
<div class="pruefpunkte bereich-box bg-white">
|
||||||
<h3>Bitte untenstehende Punkte bestätigen. Bitte gehen Sie gegebenenfalls zurück zum Formular und überprüfen bzw. korrigieren Ihre Eingaben.</h3>
|
<h3>Bitte untenstehende Punkte bestätigen. Bitte gehen Sie gegebenenfalls zurück zum Formular und überprüfen bzw. korrigieren Ihre Eingaben.</h3>
|
||||||
@@ -1054,7 +1156,7 @@ grid-cols-3 sm:grid-cols-5 justify-around justify-items-center items-center"
|
|||||||
{/if}
|
{/if}
|
||||||
<!-- Für alle -->
|
<!-- Für alle -->
|
||||||
<div class="pruefpunkt">
|
<div class="pruefpunkt">
|
||||||
<input type="checkbox"/>
|
<input type="checkbox" required/>
|
||||||
<div class="text-left">
|
<div class="text-left">
|
||||||
Ich habe die AGB und DSGVO im <a href="/impressum#agb" target="_blank" rel="noopener noreferrer">Impressum</a> gelesen und akzeptiert.
|
Ich habe die AGB und DSGVO im <a href="/impressum#agb" target="_blank" rel="noopener noreferrer">Impressum</a> gelesen und akzeptiert.
|
||||||
</div>
|
</div>
|
||||||
@@ -1072,31 +1174,33 @@ sm:grid-cols-[min-content_min-content_min-content] sm:justify-self-end sm:mt-8"
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<button class="order-2 button" type="button" on:click={speichern}>Speichern</button>
|
<button class="order-2 button" type="button" on:click={() => speichern()}>Speichern</button>
|
||||||
|
|
||||||
{#if rechnung && rechnung.status === "paid"}
|
{#if !nurRechnungsadresseUpdate}
|
||||||
<!-- Von einer GEG Anfrage sollte man sowieso nicht noch mal auf die Kundendaten Seite gelangen, also brauchen wir das hier nicht. -->
|
{#if rechnung && rechnung.status === "paid"}
|
||||||
<button
|
<!-- Von einer GEG Anfrage sollte man sowieso nicht noch mal auf die Kundendaten Seite gelangen, also brauchen wir das hier nicht. -->
|
||||||
class="order-1 sm:order-2 button cursor-pointer"
|
|
||||||
data-cy="bestellen"
|
|
||||||
type="button"
|
|
||||||
on:click={bestellen}>Absenden</button
|
|
||||||
>
|
|
||||||
{:else}
|
|
||||||
{#if gegAnfrage}
|
|
||||||
<button
|
<button
|
||||||
class="order-1 sm:order-2 button cursor-pointer"
|
class="order-1 sm:order-2 button cursor-pointer"
|
||||||
type="button"
|
|
||||||
data-cy="bestellen"
|
data-cy="bestellen"
|
||||||
on:click={anfordern}>Angebot anfordern</button
|
type="button"
|
||||||
|
on:click={() => bestellen()}>Absenden</button
|
||||||
>
|
>
|
||||||
{:else}
|
{:else}
|
||||||
<button
|
{#if gegAnfrage}
|
||||||
class="order-1 sm:order-2 button cursor-pointer"
|
<button
|
||||||
data-cy="bestellen"
|
class="order-1 sm:order-2 button cursor-pointer"
|
||||||
type="button"
|
type="button"
|
||||||
on:click={bestellen}>Kostenpflichtig bestellen</button
|
data-cy="bestellen"
|
||||||
>
|
on:click={anfordern}>Angebot anfordern</button
|
||||||
|
>
|
||||||
|
{:else}
|
||||||
|
<button
|
||||||
|
class="order-1 sm:order-2 button cursor-pointer"
|
||||||
|
data-cy="bestellen"
|
||||||
|
type="button"
|
||||||
|
on:click={() => bestellen()}>Kostenpflichtig bestellen</button
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@@ -1111,7 +1215,7 @@ sm:grid-cols-[min-content_min-content_min-content] sm:justify-self-end sm:mt-8"
|
|||||||
|
|
||||||
<Overlay bind:hidden={loginOverlayHidden}>
|
<Overlay bind:hidden={loginOverlayHidden}>
|
||||||
<div class="bg-white w-full max-w-screen-sm py-8">
|
<div class="bg-white w-full max-w-screen-sm py-8">
|
||||||
<EmbeddedAuthFlowModule onLogin={loginAction} email={email}></EmbeddedAuthFlowModule>
|
<EmbeddedAuthFlowModule onLogin={loginAction} email={email} route="signup"></EmbeddedAuthFlowModule>
|
||||||
</div>
|
</div>
|
||||||
</Overlay>
|
</Overlay>
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,10 @@
|
|||||||
|
|
||||||
export let redirect: string | null = null;
|
export let redirect: string | null = null;
|
||||||
|
|
||||||
|
function handleInput(event) {
|
||||||
|
email = event.target.value.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
async function login(e: SubmitEvent) {
|
async function login(e: SubmitEvent) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (passwort.length < 8) {
|
if (passwort.length < 8) {
|
||||||
@@ -83,6 +87,7 @@
|
|||||||
name="email"
|
name="email"
|
||||||
class="input input-bordered text-base text-base-content font-medium"
|
class="input input-bordered text-base text-base-content font-medium"
|
||||||
bind:value={email}
|
bind:value={email}
|
||||||
|
on:input={handleInput}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
---
|
---
|
||||||
import AusweisLayout from "#layouts/AusweisLayoutDatenPartner.astro";
|
import AusweisLayout from "#layouts/AusweisLayoutDatenPartner.astro";
|
||||||
import VerbrauchsausweisWohnenModule from "#modules/VerbrauchsausweisWohnen/VerbrauchsausweisWohnenModule.svelte";
|
|
||||||
import { AufnahmeClient, BildClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
|
||||||
import { Aufnahme, BedarfsausweisGewerbe, Bild, Enums, Objekt, Unterlage, VerbrauchsausweisWohnen } from "#lib/server/prisma";
|
import { Aufnahme, BedarfsausweisGewerbe, Bild, Enums, Objekt, Unterlage, VerbrauchsausweisWohnen } from "#lib/server/prisma";
|
||||||
import { getAufnahme, getBedarfsausweisGewerbe, getBilder, getObjekt, getUnterlagen, getVerbrauchsausweisWohnen } from "#lib/server/db";
|
import { getAufnahme, getBedarfsausweisGewerbe, getBilder, getObjekt, getUnterlagen, getVerbrauchsausweisWohnen } from "#lib/server/db";
|
||||||
import { getCurrentUser } from "#lib/server/user";
|
import { getCurrentUser } from "#lib/server/user";
|
||||||
@@ -9,7 +7,7 @@ import BedarfsausweisGewerbeModule from "#modules/angebot-anfragen/Bedarfsauswei
|
|||||||
|
|
||||||
const id = Astro.url.searchParams.get("id");
|
const id = Astro.url.searchParams.get("id");
|
||||||
const aufnahme_id = Astro.url.searchParams.get("aufnahme")
|
const aufnahme_id = Astro.url.searchParams.get("aufnahme")
|
||||||
let nachweistyp = Astro.url.searchParams.get("nachweistyp") as Enums.AusweisTyp || Enums.AusweisTyp.Standard;
|
let nachweistyp = Astro.url.searchParams.get("ausweistyp") as Enums.AusweisTyp || Enums.AusweisTyp.Standard;
|
||||||
|
|
||||||
let nachweis: BedarfsausweisGewerbe = {} as BedarfsausweisGewerbe;
|
let nachweis: BedarfsausweisGewerbe = {} as BedarfsausweisGewerbe;
|
||||||
let aufnahme: Aufnahme = {} as Aufnahme;
|
let aufnahme: Aufnahme = {} as Aufnahme;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import GEGNachweisGewerbeModule from "#modules/angebot-anfragen/GEGNachweisGewer
|
|||||||
|
|
||||||
const id = Astro.url.searchParams.get("id");
|
const id = Astro.url.searchParams.get("id");
|
||||||
const aufnahme_id = Astro.url.searchParams.get("aufnahme")
|
const aufnahme_id = Astro.url.searchParams.get("aufnahme")
|
||||||
let nachweistyp = Astro.url.searchParams.get("nachweistyp") as Enums.AusweisTyp || Enums.AusweisTyp.Standard;
|
let nachweistyp = Astro.url.searchParams.get("ausweistyp") as Enums.AusweisTyp || Enums.AusweisTyp.Standard;
|
||||||
|
|
||||||
let nachweis: GEGNachweisGewerbe = {} as GEGNachweisGewerbe;
|
let nachweis: GEGNachweisGewerbe = {} as GEGNachweisGewerbe;
|
||||||
let aufnahme: Aufnahme = {} as Aufnahme;
|
let aufnahme: Aufnahme = {} as Aufnahme;
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
|||||||
import { z } from "astro:content";
|
import { z } from "astro:content";
|
||||||
import { transport } from "#lib/mail.js";
|
import { transport } from "#lib/mail.js";
|
||||||
import {Attachment} from "nodemailer/lib/mailer/index.js";
|
import {Attachment} from "nodemailer/lib/mailer/index.js";
|
||||||
import { BASE_URI } from "#lib/constants.js";
|
|
||||||
import { getAnsichtsausweis, getDatenblatt, getAushang } from "#lib/server/ausweis.js";
|
import { getAnsichtsausweis, getDatenblatt, getAushang } from "#lib/server/ausweis.js";
|
||||||
import { PutObjectCommand } from "@aws-sdk/client-s3";
|
import { PutObjectCommand } from "@aws-sdk/client-s3";
|
||||||
import { s3Client } from "#lib/s3.js";
|
import { s3Client } from "#lib/s3.js";
|
||||||
@@ -34,7 +33,6 @@ import {
|
|||||||
getVerbrauchsausweisWohnenKomplett,
|
getVerbrauchsausweisWohnenKomplett,
|
||||||
} from "#lib/server/db.js";
|
} from "#lib/server/db.js";
|
||||||
import { PDFDocument } from "pdf-lib";
|
import { PDFDocument } from "pdf-lib";
|
||||||
import * as fs from 'fs';
|
|
||||||
|
|
||||||
export const GET = defineApiRoute({
|
export const GET = defineApiRoute({
|
||||||
input: z.object({
|
input: z.object({
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ export const POST = defineApiRoute({
|
|||||||
let filename: string;
|
let filename: string;
|
||||||
|
|
||||||
if (type === "Ausweis") {
|
if (type === "Ausweis") {
|
||||||
filename = `ID_${ausweis.id}_Ausweis.pdf`
|
filename = `ID_${ausweis.id}_Energieausweis.pdf`
|
||||||
} else {
|
} else {
|
||||||
filename = `ID_${ausweis.id}_${name}`;
|
filename = `ID_${ausweis.id}_${name}`;
|
||||||
}
|
}
|
||||||
@@ -212,7 +212,7 @@ export const POST = defineApiRoute({
|
|||||||
|
|
||||||
const command = new PutObjectCommand({
|
const command = new PutObjectCommand({
|
||||||
Bucket: "ibc-pdfs",
|
Bucket: "ibc-pdfs",
|
||||||
Key: name,
|
Key: filename,
|
||||||
Body: buffer,
|
Body: buffer,
|
||||||
ACL: "private",
|
ACL: "private",
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ export const GET = defineApiRoute({
|
|||||||
exp: refreshTokenExpiry.valueOf(),
|
exp: refreshTokenExpiry.valueOf(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log("Creating refresh token for user ID:", user.id);
|
||||||
const { id } = await prisma.refreshTokens.create({
|
const { id } = await prisma.refreshTokens.create({
|
||||||
data: {
|
data: {
|
||||||
token: refreshToken,
|
token: refreshToken,
|
||||||
|
|||||||
@@ -16,12 +16,14 @@ export const PATCH = defineApiRoute({
|
|||||||
strasse: true,
|
strasse: true,
|
||||||
telefon: true,
|
telefon: true,
|
||||||
empfaenger: true,
|
empfaenger: true,
|
||||||
|
zusatzzeile: true,
|
||||||
versand_empfaenger: true,
|
versand_empfaenger: true,
|
||||||
versand_ort: true,
|
versand_ort: true,
|
||||||
versand_plz: true,
|
versand_plz: true,
|
||||||
versand_strasse: true,
|
versand_strasse: true,
|
||||||
versand_zusatzzeile: true,
|
versand_zusatzzeile: true,
|
||||||
abweichende_versand_adresse: true
|
abweichende_versand_adresse: true,
|
||||||
|
email: true
|
||||||
}),
|
}),
|
||||||
output: z.object({
|
output: z.object({
|
||||||
checkout_url: z.string().optional(),
|
checkout_url: z.string().optional(),
|
||||||
@@ -31,22 +33,39 @@ export const PATCH = defineApiRoute({
|
|||||||
headers: authorizationHeaders,
|
headers: authorizationHeaders,
|
||||||
async fetch(input, context, user) {
|
async fetch(input, context, user) {
|
||||||
// Wir holen uns die Rechnung
|
// Wir holen uns die Rechnung
|
||||||
const rechnung = await prisma.rechnung.findUnique({
|
let rechnung;
|
||||||
where: {
|
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
||||||
id: context.params.id,
|
rechnung = await prisma.rechnung.findUnique({
|
||||||
benutzer: {
|
where: {
|
||||||
id: user.id
|
id: context.params.id,
|
||||||
|
benutzer: {
|
||||||
|
id: user.id
|
||||||
|
}
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
bedarfsausweis_gewerbe: true,
|
||||||
|
bedarfsausweis_wohnen: true,
|
||||||
|
geg_nachweis_gewerbe: true,
|
||||||
|
geg_nachweis_wohnen: true,
|
||||||
|
verbrauchsausweis_gewerbe: true,
|
||||||
|
verbrauchsausweis_wohnen: true
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
include: {
|
} else {
|
||||||
bedarfsausweis_gewerbe: true,
|
rechnung = await prisma.rechnung.findUnique({
|
||||||
bedarfsausweis_wohnen: true,
|
where: {
|
||||||
geg_nachweis_gewerbe: true,
|
id: context.params.id
|
||||||
geg_nachweis_wohnen: true,
|
},
|
||||||
verbrauchsausweis_gewerbe: true,
|
include: {
|
||||||
verbrauchsausweis_wohnen: true
|
bedarfsausweis_gewerbe: true,
|
||||||
}
|
bedarfsausweis_wohnen: true,
|
||||||
})
|
geg_nachweis_gewerbe: true,
|
||||||
|
geg_nachweis_wohnen: true,
|
||||||
|
verbrauchsausweis_gewerbe: true,
|
||||||
|
verbrauchsausweis_wohnen: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (!rechnung) {
|
if (!rechnung) {
|
||||||
throw new APIError({
|
throw new APIError({
|
||||||
@@ -66,12 +85,14 @@ export const PATCH = defineApiRoute({
|
|||||||
strasse: input.strasse,
|
strasse: input.strasse,
|
||||||
telefon: input.telefon,
|
telefon: input.telefon,
|
||||||
empfaenger: input.empfaenger,
|
empfaenger: input.empfaenger,
|
||||||
|
zusatzzeile: input.zusatzzeile,
|
||||||
versand_empfaenger: input.versand_empfaenger,
|
versand_empfaenger: input.versand_empfaenger,
|
||||||
versand_ort: input.versand_ort,
|
versand_ort: input.versand_ort,
|
||||||
versand_plz: input.versand_plz,
|
versand_plz: input.versand_plz,
|
||||||
versand_strasse: input.versand_strasse,
|
versand_strasse: input.versand_strasse,
|
||||||
versand_zusatzzeile: input.versand_zusatzzeile,
|
versand_zusatzzeile: input.versand_zusatzzeile,
|
||||||
abweichende_versand_adresse: input.abweichende_versand_adresse,
|
abweichende_versand_adresse: input.abweichende_versand_adresse,
|
||||||
|
email: input.email
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export const PUT = defineApiRoute({
|
|||||||
labels[category as keyof typeof labels]) ||
|
labels[category as keyof typeof labels]) ||
|
||||||
"650e909fdc09629a4d6d495d")
|
"650e909fdc09629a4d6d495d")
|
||||||
url.searchParams.append("key", "e057eb39018368ea96e456c753ac41b4")
|
url.searchParams.append("key", "e057eb39018368ea96e456c753ac41b4")
|
||||||
url.searchParams.append("idList", "67d75ca7403fd22c49bc7447")
|
url.searchParams.append("idList", "650303186e721b4bef0c3980")
|
||||||
url.searchParams.append("token", "ATTA8b65b3587ab627167038cc32a3460650973eb181cde01dabb208ca1e90ed5467AC06A4F2")
|
url.searchParams.append("token", "ATTA8b65b3587ab627167038cc32a3460650973eb181cde01dabb208ca1e90ed5467AC06A4F2")
|
||||||
|
|
||||||
// Wir laden das Ticket zu Trello hoch.
|
// Wir laden das Ticket zu Trello hoch.
|
||||||
|
|||||||
@@ -5,18 +5,17 @@ import { adminMiddleware, authorizationMiddleware } from "#lib/middleware/author
|
|||||||
import { hashPassword } from "#lib/password.js";
|
import { hashPassword } from "#lib/password.js";
|
||||||
import { createLexOfficeCustomer } from "#lib/server/lexoffice.js";
|
import { createLexOfficeCustomer } from "#lib/server/lexoffice.js";
|
||||||
import { sendRegisterMail } from "#lib/server/mail/registrierung.js";
|
import { sendRegisterMail } from "#lib/server/mail/registrierung.js";
|
||||||
import { prisma } from "#lib/server/prisma.js";
|
import { Benutzer, prisma } from "#lib/server/prisma.js";
|
||||||
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||||
import { BenutzerSchema } from "src/generated/zod/benutzer.js";
|
import { BenutzerSchema } from "src/generated/zod/benutzer.js";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
import { Enums } from "#lib/client/prisma.js";
|
||||||
|
|
||||||
export const POST = defineApiRoute({
|
export const POST = defineApiRoute({
|
||||||
input: BenutzerSchema.omit({
|
input: BenutzerSchema.omit({
|
||||||
id: true,
|
|
||||||
lex_office_id: true,
|
lex_office_id: true,
|
||||||
rolle: true,
|
rolle: true,
|
||||||
created_at: true,
|
created_at: true
|
||||||
updated_at: true
|
|
||||||
}),
|
}),
|
||||||
middleware: authorizationMiddleware,
|
middleware: authorizationMiddleware,
|
||||||
async fetch(input, context, user) {
|
async fetch(input, context, user) {
|
||||||
@@ -24,24 +23,36 @@ export const POST = defineApiRoute({
|
|||||||
// TODO: Email wurde geändert, neue Bestätigunsmail schicken.
|
// TODO: Email wurde geändert, neue Bestätigunsmail schicken.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateData: any = {};
|
||||||
|
updateData.id = user.id;
|
||||||
|
if (input.adresse) updateData.adresse = input.adresse;
|
||||||
|
if (input.anrede) updateData.anrede = input.anrede;
|
||||||
|
if (input.email) updateData.email = input.email;
|
||||||
|
if (input.firma) updateData.firma = input.firma;
|
||||||
|
if (input.name) updateData.name = input.name;
|
||||||
|
if (input.vorname) updateData.vorname = input.vorname;
|
||||||
|
if (input.ort) updateData.ort = input.ort;
|
||||||
|
if (input.passwort.length != 0) updateData.passwort = hashPassword(input.passwort);
|
||||||
|
if (input.plz) updateData.plz = input.plz;
|
||||||
|
if (input.profilbild) updateData.profilbild = input.profilbild;
|
||||||
|
if (input.telefon) updateData.telefon = input.telefon;
|
||||||
|
if (input.verified) updateData.telefon = input.verified;
|
||||||
|
|
||||||
|
//Only Admin can update other users
|
||||||
|
if (user.rolle == Enums.BenutzerRolle.ADMIN && input.id != user.id) {
|
||||||
|
updateData.id = input.id;
|
||||||
|
} else if(user.rolle != Enums.BenutzerRolle.ADMIN && input.id != user.id){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await prisma.benutzer.update({
|
await prisma.benutzer.update({
|
||||||
where: {
|
where: {
|
||||||
id: user.id
|
id: updateData.id
|
||||||
},
|
},
|
||||||
data: {
|
data: updateData
|
||||||
adresse: input.adresse,
|
});
|
||||||
anrede: input.anrede,
|
|
||||||
email: input.email,
|
|
||||||
firma: input.firma,
|
|
||||||
name: input.name,
|
|
||||||
vorname: input.vorname,
|
|
||||||
ort: input.ort,
|
|
||||||
passwort: hashPassword(input.passwort),
|
|
||||||
plz: input.plz,
|
|
||||||
profilbild: input.profilbild,
|
|
||||||
telefon: input.telefon,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -53,9 +64,14 @@ export const GET = defineApiRoute({
|
|||||||
email: z.string()
|
email: z.string()
|
||||||
})),
|
})),
|
||||||
output: z.array(BenutzerSchema),
|
output: z.array(BenutzerSchema),
|
||||||
middleware: adminMiddleware,
|
middleware: authorizationMiddleware,
|
||||||
async fetch(input, context, admin) {
|
async fetch(input, context, admin) {
|
||||||
if ("id" in input) {
|
if ("id" in input) {
|
||||||
|
//Only Admin can read other users
|
||||||
|
if (admin.rolle != Enums.BenutzerRolle.ADMIN && input.id != admin.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const user = await prisma.benutzer.findUnique({
|
const user = await prisma.benutzer.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: input.id
|
id: input.id
|
||||||
@@ -68,6 +84,11 @@ export const GET = defineApiRoute({
|
|||||||
|
|
||||||
return [user];
|
return [user];
|
||||||
} else {
|
} else {
|
||||||
|
//Only admin can read many users
|
||||||
|
if (admin.rolle != Enums.BenutzerRolle.ADMIN ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const users = await prisma.benutzer.findMany({
|
const users = await prisma.benutzer.findMany({
|
||||||
where: {
|
where: {
|
||||||
email: {
|
email: {
|
||||||
|
|||||||
236
src/pages/dashboard/abrechnung/index.astro
Normal file
236
src/pages/dashboard/abrechnung/index.astro
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
---
|
||||||
|
import AbrechnungTable from "#components/Abrechnung/AbrechnungTable.svelte";
|
||||||
|
import BlankLayout from "#layouts/BlankLayout.astro";
|
||||||
|
import { extrahiereAusweisAusFeldMitMehrerenAusweisen } from "#lib/server/ausweis";
|
||||||
|
import { Enums, prisma } from "#lib/server/prisma";
|
||||||
|
import { getCurrentUser } from "#lib/server/user";
|
||||||
|
import moment from "moment";
|
||||||
|
|
||||||
|
const start = moment(Astro.url.searchParams.get("start"));
|
||||||
|
const end = moment(Astro.url.searchParams.get("end"));
|
||||||
|
|
||||||
|
let startdatum = start.isValid() ? start.toDate() : moment().startOf("month").toDate();
|
||||||
|
let enddatum = end.isValid() ? end.toDate() : moment().endOf("month").toDate();
|
||||||
|
|
||||||
|
const benutzer = await getCurrentUser(Astro);
|
||||||
|
|
||||||
|
if (!benutzer) {
|
||||||
|
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]);
|
||||||
|
// Select every entry from database where user was involved.
|
||||||
|
let bestellungen;
|
||||||
|
if (start.isValid() && end.isValid()) {
|
||||||
|
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: startdatum,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
created_at: {
|
||||||
|
lte: enddatum,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
bestellungen = await prisma.rechnung.findMany({
|
||||||
|
where: {
|
||||||
|
partner_code: "immowelt",
|
||||||
|
OR: [
|
||||||
|
{
|
||||||
|
verbrauchsausweis_gewerbe: {
|
||||||
|
ausgestellt: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bedarfsausweis_wohnen: {
|
||||||
|
ausgestellt: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
verbrauchsausweis_wohnen: {
|
||||||
|
ausgestellt: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wann wurde der partner_code zum ersten mal benutzt?
|
||||||
|
const partnerCodeErstesMal = (
|
||||||
|
await prisma.rechnung.findFirst({
|
||||||
|
select: {
|
||||||
|
created_at: true,
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
partner_code: "immowelt",
|
||||||
|
OR: [
|
||||||
|
{
|
||||||
|
verbrauchsausweis_gewerbe: {
|
||||||
|
ausgestellt: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bedarfsausweis_wohnen: {
|
||||||
|
ausgestellt: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
verbrauchsausweis_wohnen: {
|
||||||
|
ausgestellt: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
created_at: {
|
||||||
|
gte: moment().set("year", 2020).set("dayOfYear", 1).toDate(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
created_at: "asc",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)?.created_at;
|
||||||
|
|
||||||
|
let provision = 0;
|
||||||
|
const ausweisarten: string[] = [];
|
||||||
|
for (const bestellung of bestellungen) {
|
||||||
|
if (bestellung.verbrauchsausweis_wohnen) {
|
||||||
|
ausweisarten.push(Enums.Ausweisart.VerbrauchsausweisWohnen);
|
||||||
|
provision += provisionen[Enums.Ausweisart.VerbrauchsausweisWohnen];
|
||||||
|
}
|
||||||
|
if (bestellung.bedarfsausweis_wohnen) {
|
||||||
|
ausweisarten.push(Enums.Ausweisart.BedarfsausweisWohnen);
|
||||||
|
provision += provisionen[Enums.Ausweisart.BedarfsausweisWohnen];
|
||||||
|
}
|
||||||
|
if (bestellung.verbrauchsausweis_gewerbe) {
|
||||||
|
ausweisarten.push(Enums.Ausweisart.VerbrauchsausweisGewerbe);
|
||||||
|
provision += provisionen[Enums.Ausweisart.VerbrauchsausweisGewerbe];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
<BlankLayout title="Monatliche Abrechnung">
|
||||||
|
<AbrechnungTable
|
||||||
|
bestellungen={bestellungen.map((bestellung) =>
|
||||||
|
extrahiereAusweisAusFeldMitMehrerenAusweisen(bestellung)
|
||||||
|
)}
|
||||||
|
{provisionen}
|
||||||
|
{partnerCodeErstesMal}
|
||||||
|
startDate={startdatum}
|
||||||
|
endDate={enddatum}
|
||||||
|
email={benutzer.email}
|
||||||
|
client:load
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="fixed bottom-0 left-0 right-0 bg-white p-4 shadow">
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<div>
|
||||||
|
<p id="betrag_gesamt">
|
||||||
|
Abrechnungsbetrag gesamt: <b>{provision} €</b>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
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")}`
|
||||||
|
>PDF für letzten Monat generieren.</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</BlankLayout>
|
||||||
108
src/pages/dashboard/rechnung/aendern.astro
Normal file
108
src/pages/dashboard/rechnung/aendern.astro
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
---
|
||||||
|
import { encodeToken } from "#lib/auth/token";
|
||||||
|
import { TokenType } from "#lib/auth/types";
|
||||||
|
import { API_ACCESS_TOKEN_COOKIE_NAME, API_REFRESH_TOKEN_COOKIE_NAME } from "#lib/constants";
|
||||||
|
import { Enums, prisma } from "#lib/server/prisma";
|
||||||
|
import moment from "moment";
|
||||||
|
import { createCaller } from "src/astro-typesafe-api-caller";
|
||||||
|
import KundendatenModule from "#modules/KundendatenModule.svelte";
|
||||||
|
import AusweisLayout from "#layouts/AusweisLayoutPruefung.astro";
|
||||||
|
import { getCurrentUser, getOtherUser } from "#lib/server/user";
|
||||||
|
import { getAusweisartFromId } from "#components/Ausweis/types";
|
||||||
|
import { getAufnahme, getBedarfsausweisWohnen, getBilder, getObjekt, getRechnung, getUnterlagen, getVerbrauchsausweisGewerbe, getVerbrauchsausweisWohnen } from "#lib/server/db";
|
||||||
|
import { BenutzerClient } from "#components/Ausweis/types.js";
|
||||||
|
|
||||||
|
function getExistingAusweis(rechnung) {
|
||||||
|
if (rechnung.verbrauchsausweis_wohnen) {
|
||||||
|
return rechnung.verbrauchsausweis_wohnen;
|
||||||
|
}
|
||||||
|
if (rechnung.verbrauchsausweis_gewerbe) {
|
||||||
|
return rechnung.verbrauchsausweis_gewerbe;
|
||||||
|
}
|
||||||
|
if (rechnung.bedarfsausweis_wohnen) {
|
||||||
|
return rechnung.bedarfsausweis_wohnen ;
|
||||||
|
}
|
||||||
|
if (rechnung.bedarfsausweis_gewerbe) {
|
||||||
|
return rechnung.bedarfsausweis_gewerbe;
|
||||||
|
}
|
||||||
|
if (rechnung.geg_nachweis_gewerbe) {
|
||||||
|
return rechnung.geg_nachweis_gewerbe;
|
||||||
|
}
|
||||||
|
if (rechnung.geg_nachweis_wohnen) {
|
||||||
|
return rechnung.geg_nachweis_wohnen;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await getCurrentUser(Astro);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return Astro.redirect("/auth/login")
|
||||||
|
}
|
||||||
|
|
||||||
|
const rechnungid = Astro.url.searchParams.get("rechnungid")
|
||||||
|
|
||||||
|
if (!rechnungid) {
|
||||||
|
return Astro.redirect("/404")
|
||||||
|
}
|
||||||
|
|
||||||
|
let rechnung;
|
||||||
|
|
||||||
|
//Only Admin can read foreign invoices
|
||||||
|
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
||||||
|
rechnung = await prisma.rechnung.findUnique({
|
||||||
|
where: {
|
||||||
|
id: rechnungid,
|
||||||
|
benutzer_id: user.id
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
verbrauchsausweis_wohnen: true,
|
||||||
|
verbrauchsausweis_gewerbe: true,
|
||||||
|
bedarfsausweis_wohnen: true,
|
||||||
|
bedarfsausweis_gewerbe: true,
|
||||||
|
geg_nachweis_gewerbe: true,
|
||||||
|
geg_nachweis_wohnen: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
rechnung = await prisma.rechnung.findUnique({
|
||||||
|
where: {
|
||||||
|
id: rechnungid,
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
verbrauchsausweis_wohnen: true,
|
||||||
|
verbrauchsausweis_gewerbe: true,
|
||||||
|
bedarfsausweis_wohnen: true,
|
||||||
|
bedarfsausweis_gewerbe: true,
|
||||||
|
geg_nachweis_gewerbe: true,
|
||||||
|
geg_nachweis_wohnen: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rechnung) {
|
||||||
|
return Astro.redirect("/404")
|
||||||
|
}
|
||||||
|
|
||||||
|
const ausweis = getExistingAusweis(rechnung);
|
||||||
|
const ausweisart = getAusweisartFromId(ausweis.id)
|
||||||
|
|
||||||
|
let aufnahme, objekt, bilder, unterlagen, partner_code;
|
||||||
|
|
||||||
|
aufnahme = await getAufnahme(ausweis.aufnahme_id)
|
||||||
|
objekt = await getObjekt(aufnahme?.objekt_id)
|
||||||
|
bilder = await getBilder(ausweis.aufnahme_id)
|
||||||
|
unterlagen = await getUnterlagen(ausweis.aufnahme_id)
|
||||||
|
|
||||||
|
|
||||||
|
let impersonatedUser: Partial<BenutzerClient> | null = null;
|
||||||
|
|
||||||
|
if (user){
|
||||||
|
if (user.id !== ausweis.benutzer_id && ausweis.benutzer_id !== undefined){
|
||||||
|
impersonatedUser = await getOtherUser(Astro, ausweis.benutzer_id) || {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
---
|
||||||
|
<AusweisLayout title="Kundendaten Aufnehmen - IBCornelsen">
|
||||||
|
<KundendatenModule {user} {impersonatedUser} {ausweis} {objekt} {aufnahme} {bilder} {rechnung} {ausweisart} {unterlagen} {partner_code} aktiveBezahlmethode={Enums.Bezahlmethoden.paypal} nurRechnungsadresseUpdate={true} client:only ></KundendatenModule>
|
||||||
|
</AusweisLayout>
|
||||||
@@ -3,10 +3,11 @@ import { getAusweisartFromId } from "#components/Ausweis/types";
|
|||||||
import AusweisLayoutPruefung from "#layouts/AusweisLayoutPruefung.astro";
|
import AusweisLayoutPruefung from "#layouts/AusweisLayoutPruefung.astro";
|
||||||
import { getPrismaAusweisAdapter } from "#lib/server/ausweis";
|
import { getPrismaAusweisAdapter } from "#lib/server/ausweis";
|
||||||
import { Enums } from "#lib/server/prisma";
|
import { Enums } from "#lib/server/prisma";
|
||||||
import { getCurrentUser } from "#lib/server/user";
|
import { getCurrentUser, getOtherUser } from "#lib/server/user";
|
||||||
import KundendatenModule from "#modules/KundendatenModule.svelte";
|
import KundendatenModule from "#modules/KundendatenModule.svelte";
|
||||||
import { PaymentStatus } from "@mollie/api-client";
|
import { PaymentStatus } from "@mollie/api-client";
|
||||||
import { AusweisTyp } from "src/generated/enums";
|
import { AusweisTyp } from "src/generated/enums";
|
||||||
|
import { BenutzerClient } from "#components/Ausweis/types.js";
|
||||||
|
|
||||||
const uid = Astro.url.searchParams.get("uid")
|
const uid = Astro.url.searchParams.get("uid")
|
||||||
|
|
||||||
@@ -45,8 +46,16 @@ if (!ausweis) {
|
|||||||
if (ausweis.rechnung.status === PaymentStatus.paid) {
|
if (ausweis.rechnung.status === PaymentStatus.paid) {
|
||||||
return Astro.redirect("/dashboard")
|
return Astro.redirect("/dashboard")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let impersonatedUser: Partial<BenutzerClient> | null = null;
|
||||||
|
|
||||||
|
if (user){
|
||||||
|
if (user.id !== ausweis.benutzer_id && ausweis.benutzer_id !== undefined){
|
||||||
|
impersonatedUser = await getOtherUser(Astro, ausweis.benutzer_id) || {}
|
||||||
|
}
|
||||||
|
}
|
||||||
---
|
---
|
||||||
|
|
||||||
<AusweisLayoutPruefung title="Energieausweis Bezahlung">
|
<AusweisLayoutPruefung title="Energieausweis Bezahlung">
|
||||||
<KundendatenModule {user} {ausweis} objekt={ausweis.aufnahme.objekt} rechnung={ausweis.rechnung} aufnahme={ausweis.aufnahme} bilder={ausweis.aufnahme.bilder} {ausweisart} ausweistyp={AusweisTyp.Standard} aktiveBezahlmethode={Enums.Bezahlmethoden.paypal} client:only></KundendatenModule>
|
<KundendatenModule {user} {impersonatedUser} {ausweis} objekt={ausweis.aufnahme.objekt} rechnung={ausweis.rechnung} aufnahme={ausweis.aufnahme} bilder={ausweis.aufnahme.bilder} {ausweisart} ausweistyp={AusweisTyp.Standard} aktiveBezahlmethode={Enums.Bezahlmethoden.paypal} client:only></KundendatenModule>
|
||||||
</AusweisLayoutPruefung>
|
</AusweisLayoutPruefung>
|
||||||
|
|||||||
19
src/pages/heap-snapshot.astro
Normal file
19
src/pages/heap-snapshot.astro
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
import { getHeapSnapshot } from "v8";
|
||||||
|
import * as fs from "fs";
|
||||||
|
|
||||||
|
// Create a named heap snapshot
|
||||||
|
const snapshotStream = getHeapSnapshot();
|
||||||
|
const fileName = `heap-${Date.now()}.heapsnapshot`;
|
||||||
|
const fileStream = fs.createWriteStream(fileName);
|
||||||
|
|
||||||
|
snapshotStream.pipe(fileStream);
|
||||||
|
|
||||||
|
fileStream.on("finish", () => {
|
||||||
|
console.log(`Heap snapshot saved to ${fileName}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
fileStream.on("error", (err) => {
|
||||||
|
console.error("Error writing heap snapshot:", err);
|
||||||
|
});
|
||||||
|
---
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
---
|
|
||||||
|
|
||||||
import KaufabschlussModule from "#modules/KaufabschlussModule.svelte";
|
|
||||||
import AusweisLayout from "#layouts/AusweisLayoutPruefung.astro";
|
|
||||||
import { Enums } from "#lib/client/prisma";
|
|
||||||
import { createCaller } from "src/astro-typesafe-api-caller";
|
|
||||||
|
|
||||||
// Man sollte nur auf diese Seite kommen, wenn ein Ausweis bereits vorliegt und in der Datenbank abgespeichert wurde.
|
|
||||||
const uid = Astro.url.searchParams.get("uid");
|
|
||||||
|
|
||||||
if (!uid) {
|
|
||||||
return Astro.redirect("/404");
|
|
||||||
}
|
|
||||||
|
|
||||||
const caller = createCaller(Astro);
|
|
||||||
|
|
||||||
const ausweis = await caller.v1.verbrauchsausweisWohnen.get({
|
|
||||||
uid
|
|
||||||
})
|
|
||||||
|
|
||||||
const user = await caller.v1.benutzer.self();
|
|
||||||
|
|
||||||
if (!ausweis || !user) {
|
|
||||||
return Astro.redirect("/404");
|
|
||||||
}
|
|
||||||
---
|
|
||||||
|
|
||||||
<AusweisLayout title="Kundendaten Aufnehmen - IBCornelsen">
|
|
||||||
<KaufabschlussModule user={user} ausweis={ausweis} aktiveBezahlmethode={Enums.Bezahlmethoden.paypal} client:load></KaufabschlussModule>
|
|
||||||
</AusweisLayout>
|
|
||||||
|
|
||||||
@@ -3,9 +3,10 @@
|
|||||||
import KundendatenModule from "#modules/KundendatenModule.svelte";
|
import KundendatenModule from "#modules/KundendatenModule.svelte";
|
||||||
import AusweisLayout from "#layouts/AusweisLayoutPruefung.astro";
|
import AusweisLayout from "#layouts/AusweisLayoutPruefung.astro";
|
||||||
import { Enums } from "#lib/client/prisma";
|
import { Enums } from "#lib/client/prisma";
|
||||||
import { getCurrentUser } from "#lib/server/user";
|
import { getCurrentUser, getOtherUser } from "#lib/server/user";
|
||||||
import { getAusweisartFromId } from "#components/Ausweis/types";
|
import { getAusweisartFromId } from "#components/Ausweis/types";
|
||||||
import { getAufnahme, getBedarfsausweisWohnen, getBilder, getObjekt, getRechnung, getUnterlagen, getVerbrauchsausweisGewerbe, getVerbrauchsausweisWohnen } from "#lib/server/db";
|
import { getAufnahme, getBedarfsausweisWohnen, getBilder, getObjekt, getRechnung, getUnterlagen, getVerbrauchsausweisGewerbe, getVerbrauchsausweisWohnen } from "#lib/server/db";
|
||||||
|
import { BenutzerClient } from "#components/Ausweis/types.js";
|
||||||
|
|
||||||
// Man sollte nur auf diese Seite kommen, wenn ein Ausweis bereits vorliegt und in der Datenbank abgespeichert wurde.
|
// Man sollte nur auf diese Seite kommen, wenn ein Ausweis bereits vorliegt und in der Datenbank abgespeichert wurde.
|
||||||
|
|
||||||
@@ -70,9 +71,16 @@ if (!params.has("ausweis") || !params.has("aufnahme") || !params.has("objekt") |
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let impersonatedUser: Partial<BenutzerClient> | null = null;
|
||||||
|
|
||||||
|
if (user){
|
||||||
|
if (user.id !== ausweis.benutzer_id && ausweis.benutzer_id !== undefined){
|
||||||
|
impersonatedUser = await getOtherUser(Astro, ausweis.benutzer_id) || {}
|
||||||
|
}
|
||||||
|
}
|
||||||
---
|
---
|
||||||
|
|
||||||
<AusweisLayout title="Kundendaten Aufnehmen - IBCornelsen">
|
<AusweisLayout title="Kundendaten Aufnehmen - IBCornelsen">
|
||||||
<KundendatenModule {user} {ausweis} {objekt} {aufnahme} {bilder} {rechnung} {ausweisart} {unterlagen} {partner_code} aktiveBezahlmethode={Enums.Bezahlmethoden.paypal} client:only ></KundendatenModule>
|
<KundendatenModule {user} {impersonatedUser} {ausweis} {objekt} {aufnahme} {bilder} {rechnung} {ausweisart} {unterlagen} {partner_code} aktiveBezahlmethode={Enums.Bezahlmethoden.paypal} client:only ></KundendatenModule>
|
||||||
</AusweisLayout>
|
</AusweisLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -45,14 +45,23 @@ export const GET: APIRoute = async (Astro) => {
|
|||||||
user = await getCurrentUser(Astro)
|
user = await getCurrentUser(Astro)
|
||||||
|
|
||||||
let pdf: Uint8Array<ArrayBufferLike> | null = null;
|
let pdf: Uint8Array<ArrayBufferLike> | null = null;
|
||||||
if (/[A-Z]{2}[0-9]{8}/.test(ausweis.id)) {
|
|
||||||
const id = ausweis.id.match(/[A-Z]{2}([0-9]{8})/) as RegExpMatchArray
|
if (ausweis.ausgestellt) {
|
||||||
// Dieser Ausweis wurde mit der alten Version erstellt, das PDF sollte bereits existieren.
|
if (/[A-Z]{2}[0-9]{8}/.test(ausweis.id)) {
|
||||||
pdf = await getS3File("ibc-pdfs", `ID_${id[1]}_Energieausweis.pdf`)
|
const id = ausweis.id.match(/[A-Z]{2}([0-9]{8})/) as RegExpMatchArray
|
||||||
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
|
// Dieser Ausweis wurde mit der alten Version erstellt, das PDF sollte bereits existieren.
|
||||||
pdf = await pdfVerbrauchsausweisWohnen(ausweis as VerbrauchsausweisWohnenClient, aufnahme, objekt, bilder, user, !ausweis.ausgestellt);
|
pdf = await getS3File("ibc-pdfs", `ID_${id[1]}_Energieausweis.pdf`)
|
||||||
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
} else {
|
||||||
pdf = await pdfVerbrauchsausweisGewerbe(ausweis as VerbrauchsausweisGewerbeClient, aufnahme, objekt, bilder, user, !ausweis.ausgestellt);
|
pdf = await getS3File("ibc-pdfs", `ID_${ausweis.id}_Energieausweis.pdf`)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
|
||||||
|
pdf = await pdfVerbrauchsausweisWohnen(ausweis as VerbrauchsausweisWohnenClient, aufnahme, objekt, bilder, user, !ausweis.ausgestellt);
|
||||||
|
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
||||||
|
pdf = await pdfVerbrauchsausweisGewerbe(ausweis as VerbrauchsausweisGewerbeClient, aufnahme, objekt, bilder, user, !ausweis.ausgestellt);
|
||||||
|
} else if (ausweisart === Enums.Ausweisart.BedarfsausweisWohnen) {
|
||||||
|
//todo
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Response(pdf, {
|
return new Response(pdf, {
|
||||||
|
|||||||
@@ -9,6 +9,22 @@ DB_NAME="main"
|
|||||||
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
|
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
|
||||||
FILE_NAME="backup-$TIMESTAMP.sql.br"
|
FILE_NAME="backup-$TIMESTAMP.sql.br"
|
||||||
|
|
||||||
|
# Wir holen uns den parameter --skip-backup, um zu entscheiden, ob wir ein Backup machen wollen
|
||||||
|
SKIP_BACKUP=false
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
--skip-backup)
|
||||||
|
SKIP_BACKUP=true
|
||||||
|
shift # Remove the argument from the list
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unbekannter Parameter: $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
REQUIRED_CONFIRMATION='Ja, ich möchte alle Daten unwiderruflich löschen.'
|
REQUIRED_CONFIRMATION='Ja, ich möchte alle Daten unwiderruflich löschen.'
|
||||||
|
|
||||||
echo "⚠️ WARNUNG: Diese Aktion wird alle Tabellen und Einträge in der Datenbank vollständig löschen!"
|
echo "⚠️ WARNUNG: Diese Aktion wird alle Tabellen und Einträge in der Datenbank vollständig löschen!"
|
||||||
@@ -21,9 +37,11 @@ if [[ "$USER_CONFIRMATION" != "$REQUIRED_CONFIRMATION" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "📦 Backup wird erstellt..."
|
if [[ "$SKIP_BACKUP" == false ]]; then
|
||||||
docker exec -t "$CONTAINER_NAME" pg_dumpall -c -U "$DB_USER" | brotli > "$FILE_NAME"
|
echo "📦 Backup wird erstellt..."
|
||||||
echo "✅ Backup abgeschlossen: $FILE_NAME"
|
docker exec -t "$CONTAINER_NAME" pg_dumpall -c -U "$DB_USER" | brotli > "$FILE_NAME"
|
||||||
|
echo "✅ Backup abgeschlossen: $FILE_NAME"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "🧨 Alle Daten aus allen Tabellen werden gelöscht..."
|
echo "🧨 Alle Daten aus allen Tabellen werden gelöscht..."
|
||||||
|
|
||||||
@@ -34,6 +52,7 @@ DECLARE
|
|||||||
r RECORD;
|
r RECORD;
|
||||||
sql TEXT := '';
|
sql TEXT := '';
|
||||||
BEGIN
|
BEGIN
|
||||||
|
-- Truncate all tables
|
||||||
FOR r IN
|
FOR r IN
|
||||||
SELECT tablename
|
SELECT tablename
|
||||||
FROM pg_tables
|
FROM pg_tables
|
||||||
@@ -42,6 +61,15 @@ BEGIN
|
|||||||
sql := sql || FORMAT('TRUNCATE TABLE public.%I CASCADE;', r.tablename);
|
sql := sql || FORMAT('TRUNCATE TABLE public.%I CASCADE;', r.tablename);
|
||||||
END LOOP;
|
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;
|
EXECUTE sql;
|
||||||
END
|
END
|
||||||
$$;
|
$$;
|
||||||
|
|||||||
Reference in New Issue
Block a user