diff --git a/.github/workflows/auto-merge-staging-into-main.yml b/.github/workflows/auto-merge-staging-into-main.yml index f233b3ad..848cde2e 100644 --- a/.github/workflows/auto-merge-staging-into-main.yml +++ b/.github/workflows/auto-merge-staging-into-main.yml @@ -8,6 +8,8 @@ on: jobs: merge: runs-on: ubuntu-latest + outputs: + reason: ${{ steps.check.outputs.reason }} steps: - name: Checkout repository uses: actions/checkout@v4 @@ -28,9 +30,15 @@ jobs: id: check run: | git fetch origin - if [ $(git rev-list --count origin/staging..origin/main) -gt 0 ]; then + COUNT=$(git rev-list --count origin/staging..origin/main) + if [ "$COUNT" -gt 0 ]; then + echo "reason=ok" >> $GITHUB_OUTPUT echo "❌ Staging is behind main and requires manual merging." exit 1 + elif [ "$COUNT" -eq 0 ]; then + echo "reason=identical" >> $GITHUB_OUTPUT + echo "✅ Staging and main are identical. Nothing to do." + exit 42 fi - name: Create PR from staging to main @@ -53,7 +61,7 @@ jobs: notify_failure: needs: merge - if: failure() + if: failure() && needs.merge.outputs.reason != 'identical' runs-on: ubuntu-latest steps: - name: Send Discord notification on failure @@ -61,16 +69,4 @@ jobs: 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 }} \ No newline at end of file diff --git a/.github/workflows/prevent-wrong-pr.yml b/.github/workflows/prevent-wrong-pr.yml new file mode 100644 index 00000000..d25826c0 --- /dev/null +++ b/.github/workflows/prevent-wrong-pr.yml @@ -0,0 +1,31 @@ +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: | + echo "${{ github.head_ref }}"; + echo "${{ github.base_ref }}"; + if [[ "${{ github.head_ref }}" == "dev" ]]; then + echo "ERROR: Merging 'dev' into '${{ github.base_ref }}' is forbidden!" + exit 1 + fi + + - name: Allow only staging into main + if: github.base_ref == 'main' + run: | + echo "${{ github.head_ref }}"; + echo "${{ github.base_ref }}"; + if [[ "${{ github.head_ref }}" != "staging" ]]; then + echo "ERROR: Only 'staging' branch is allowed to merge into 'main'. Current: '${{ github.head_ref }}'" + exit 1 + fi diff --git a/Makefile b/Makefile index 80f67115..b59f8b73 100644 --- a/Makefile +++ b/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 online-energieausweis: - bun run dev --host + NODE_ENV="development" bun run dev --host dev: database online-energieausweis @@ -30,6 +30,7 @@ run-database: stop-database docker volume create $(DB_VOLUME) docker build -t $(DB_CONTAINER_NAME) . docker run -d --name $(DB_CONTAINER_NAME) \ + --restart=always \ -e POSTGRES_USER=$(DB_USER) \ -e POSTGRES_PASSWORD=$(DB_PASSWORD) \ -p $(DB_PORT):5432 \ @@ -71,4 +72,4 @@ prod: install-dependencies prisma-studio backup-database-cronjob update-dwd-klim backup-database-cronjob: - pm2 delete daily-db-backup - pm2 start bash --name "daily-db-backup" --cron "0 0 * * *" -- backup-database.bash \ No newline at end of file + pm2 start bash --name "daily-db-backup" --no-autorestart --cron "0 0 * * *" -- backup-database.bash \ No newline at end of file diff --git a/backup-database.bash b/backup-database.bash index fc8a5f08..fee2a70d 100644 --- a/backup-database.bash +++ b/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 +<<<<<<< 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 +>>>>>>> dev echo "Uploaded $FILE_NAME_COMPLETE" diff --git a/docker-compose.yml b/docker-compose.yml index a0485abf..a96bb452 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,6 +2,7 @@ version: '3' services: database: build: ./ + restart: always env_file: - .env ports: diff --git a/prisma/schema/BedarfsausweisWohnen.prisma b/prisma/schema/BedarfsausweisWohnen.prisma index 656d4717..e3074294 100644 --- a/prisma/schema/BedarfsausweisWohnen.prisma +++ b/prisma/schema/BedarfsausweisWohnen.prisma @@ -41,19 +41,19 @@ model BedarfsausweisWohnen { volumen Float? dicht Boolean? fenster_flaeche_1 Float? - fenster_art_1 String? + fenster_art_1 Float? fenster_flaeche_2 Float? - fenster_art_2 String? + fenster_art_2 Float? dachfenster_flaeche Float? - dachfenster_art String? + dachfenster_art Float? haustuer_flaeche Float? - haustuer_art String? + haustuer_art Float? dach_bauart String? @db.VarChar decke_bauart String? @db.VarChar - dach_daemmung String? - decke_daemmung String? - aussenwand_daemmung String? - boden_daemmung String? + dach_daemmung Float? + decke_daemmung Float? + aussenwand_daemmung Float? + boden_daemmung Float? aussenwand_bauart String? @db.VarChar boden_bauart String? @db.VarChar warmwasser_verteilung String? @db.VarChar diff --git a/recover-db-dev.bash b/recover-db-dev.bash index e7b58155..a26cf714 100644 --- a/recover-db-dev.bash +++ b/recover-db-dev.bash @@ -2,7 +2,7 @@ # === Configuration === 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 # === Get latest file from IONOS S3 bucket === diff --git a/src/astro-typesafe-api-caller.ts b/src/astro-typesafe-api-caller.ts index 262124be..93464cda 100644 --- a/src/astro-typesafe-api-caller.ts +++ b/src/astro-typesafe-api-caller.ts @@ -5,6 +5,7 @@ export const createCaller = createCallerFactory({ "klimafaktoren": await import("../src/pages/api/klimafaktoren.ts"), "postleitzahlen": await import("../src/pages/api/postleitzahlen.ts"), "unterlage": await import("../src/pages/api/unterlage.ts"), + "aufnahme": await import("../src/pages/api/aufnahme/index.ts"), "admin/ausstellen": await import("../src/pages/api/admin/ausstellen.ts"), "admin/bedarfsausweis-ausstellen": await import("../src/pages/api/admin/bedarfsausweis-ausstellen.ts"), "admin/bestellbestaetigung": await import("../src/pages/api/admin/bestellbestaetigung.ts"), @@ -12,7 +13,6 @@ export const createCaller = createCallerFactory({ "admin/nicht-ausstellen": await import("../src/pages/api/admin/nicht-ausstellen.ts"), "admin/registriernummer": await import("../src/pages/api/admin/registriernummer.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/passwort-vergessen": await import("../src/pages/api/auth/passwort-vergessen.ts"), @@ -31,7 +31,6 @@ export const createCaller = createCallerFactory({ "rechnung/anfordern": await import("../src/pages/api/rechnung/anfordern.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/self": await import("../src/pages/api/user/self.ts"), "verbrauchsausweis-gewerbe/[id]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[id].ts"), "verbrauchsausweis-gewerbe": await import("../src/pages/api/verbrauchsausweis-gewerbe/index.ts"), diff --git a/src/client/lib/lesen.ts b/src/client/lib/lesen.ts new file mode 100644 index 00000000..c7ded8a2 --- /dev/null +++ b/src/client/lib/lesen.ts @@ -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 { + const benutzer = await api.user.GET.fetch({ id: benutzerId } + , { + headers: { + Authorization: `Bearer ${Cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)}` + } + }); + + return benutzer[0]; +} \ No newline at end of file diff --git a/src/client/lib/speichern.ts b/src/client/lib/speichern.ts index 31708641..89f6c2f0 100644 --- a/src/client/lib/speichern.ts +++ b/src/client/lib/speichern.ts @@ -1,5 +1,5 @@ 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 Cookies from "js-cookie"; @@ -161,4 +161,32 @@ export async function objektSpeichern(objekt: Objekt & { id?: string }): Promise return id; } +} + +export async function benutzerSpeichern(benutzer: Partial): Promise { + 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; } \ No newline at end of file diff --git a/src/components/Abrechnung/AbrechungTable.svelte b/src/components/Abrechnung/AbrechungTable.svelte new file mode 100644 index 00000000..03aa4efb --- /dev/null +++ b/src/components/Abrechnung/AbrechungTable.svelte @@ -0,0 +1,109 @@ + + + {#each periods as dt} + {@const jahrMonat = dt.format("Y-m")} + {#if jahrMonat in bestellungenNachMonat && bestellungenNachMonat[jahrMonat].length > 0} + + {@const provisionMonat = bestellungenNachMonat[jahrMonat].reduce((acc, bestellung) => { + if (bestellung.verbrauchsausweis_wohnen) { + return acc + provisionen[Enums.Ausweisart.VerbrauchsausweisWohnen]; + } + if (bestellung.bedarfsausweis_wohnen) { + return acc + provisionen[Enums.Ausweisart.BedarfsausweisWohnen]; + } + if (bestellung.verbrauchsausweis_gewerbe) { + return acc + provisionen[Enums.Ausweisart.VerbrauchsausweisGewerbe]; + } + + return acc; + }) * 1.19} + + + + + + + + + + + + + + + + {#each bestellungenNachMonat[jahrMonat] as bestellung} + {@const provisionBestellung = bestellung.verbrauchsausweis_wohnen ? provisionen[Enums.Ausweisart.VerbrauchsausweisWohnen] : bestellung.verbrauchsausweis_gewerbe ? provisionen[Enums.Ausweisart.VerbrauchsausweisGewerbe] : provisionen[Enums.Ausweisart.BedarfsausweisWohnen]} + + + + + + + + + + {/each} + + {/if} + {/each} + + + + \ No newline at end of file diff --git a/src/components/Dashboard/DashboardAusweis.svelte b/src/components/Dashboard/DashboardAusweis.svelte index 96ea5121..4134be86 100644 --- a/src/components/Dashboard/DashboardAusweis.svelte +++ b/src/components/Dashboard/DashboardAusweis.svelte @@ -257,6 +257,12 @@ let bedarfsausweisFileInput: HTMLInputElement; let bedarfsausweisAdditionalInput: HTMLInputElement; + + let dropdownOpen = false; + + function toggleDropdown() { + dropdownOpen = !dropdownOpen; + }
@@ -273,30 +279,41 @@ {/if}
+ {#if dropdownOpen}
+
+ +
+
+ - +
--> + {#if ausweis.bestellt && rechnung} +
+ +
+ {/if} -
+ {/if} + +
{#if ausweis.ausgestellt} Ausgestellt @@ -341,9 +358,6 @@
- {progress}%
{#await calculations then calculations}
diff --git a/src/components/Dashboard/DashboardSidebar.svelte b/src/components/Dashboard/DashboardSidebar.svelte index 5a0e4767..a3706fe8 100644 --- a/src/components/Dashboard/DashboardSidebar.svelte +++ b/src/components/Dashboard/DashboardSidebar.svelte @@ -70,6 +70,7 @@
{/if} + Conversions
diff --git a/src/lib/pdf/pdfVerbrauchsausweisGewerbe.ts b/src/lib/pdf/pdfVerbrauchsausweisGewerbe.ts index 2a420188..be32284f 100644 --- a/src/lib/pdf/pdfVerbrauchsausweisGewerbe.ts +++ b/src/lib/pdf/pdfVerbrauchsausweisGewerbe.ts @@ -431,7 +431,7 @@ export async function pdfVerbrauchsausweisGewerbe(ausweis: VerbrauchsausweisGewe }) page.drawImage(pfeilNachOben, { - x: vergleichsWertStromTranslationX, + x: vergleichsWertStromTranslationX, y: height - 437, width: pfeilWidth, height: 30 diff --git a/src/lib/server/user.ts b/src/lib/server/user.ts index 1b6070f3..f9be1df6 100644 --- a/src/lib/server/user.ts +++ b/src/lib/server/user.ts @@ -1,9 +1,27 @@ import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js"; import { checkAuthorizationHeader, checkAuthorizationHeaderNoThrow } from "#lib/middleware/authorization.js"; import { AstroGlobal } from "astro"; +import { Enums } from "#lib/client/prisma.js"; +import { prisma } from "#lib/server/prisma.js"; export function getCurrentUser(Astro: AstroGlobal) { const accessToken = Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value; 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; } \ No newline at end of file diff --git a/src/modules/KundendatenModule.svelte b/src/modules/KundendatenModule.svelte index 2e79158b..40444d5c 100644 --- a/src/modules/KundendatenModule.svelte +++ b/src/modules/KundendatenModule.svelte @@ -32,8 +32,12 @@ import { getMaximumDevitationInPercent } from "#client/lib/helpers.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 { benutzerSpeichern } from "#client/lib/speichern.js"; + import { benutzerLesen } from "#client/lib/lesen.js"; + import { exclude } from "#lib/exclude.js"; + export let user: Partial; + export let impersonatedUser: Partial | null = null; export let ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbe | BedarfsausweisWohnen; export let aufnahme: AufnahmeClient; export let objekt: ObjektClient; @@ -42,9 +46,8 @@ export let rechnung: RechnungClient | null = null; export let ausweisart: Enums.Ausweisart; export let aktiveBezahlmethode: Bezahlmethoden = Enums.Bezahlmethoden.paypal; - 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; @@ -59,9 +62,22 @@ ort = rechnung?.ort || localStorage.getItem("kundendaten.ort") || user.ort || ""; zusatzzeile = rechnung?.zusatzzeile || localStorage.getItem("kundendaten.zusatzzeile") || "" 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, versand_zusatzzeile: string | undefined, @@ -69,16 +85,13 @@ versand_strasse: string | undefined, versand_plz: string | undefined, versand_ort: string | undefined; - $: { - if (!abweichende_versand_adresse) { - versand_email = email - versand_zusatzzeile = zusatzzeile - versand_empfaenger = empfaenger - versand_strasse = strasse - versand_plz = plz - versand_ort = ort - } - } + + versand_email = "";//Todo Datenbankfeld fehlt noch + versand_zusatzzeile = rechnung?.versand_zusatzzeile ?? zusatzzeile; + versand_empfaenger = rechnung?.versand_empfaenger ?? empfaenger; + versand_strasse = rechnung?.versand_strasse ?? strasse; + versand_plz = rechnung?.versand_plz ?? plz; + versand_ort = rechnung?.versand_ort ?? ort; $: { // Wir speichern jede Änderung an den Kundendaten im localStorage ab. @@ -199,6 +212,12 @@ } 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( { email: email, @@ -206,10 +225,11 @@ strasse: strasse, plz: plz, ort: ort, - versand_empfaenger: versand_empfaenger, - versand_strasse: versand_strasse, - versand_plz: versand_plz, - versand_ort: versand_ort, + 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, telefon: telefon, nachweis_id: result.nachweis_id }, @@ -233,7 +253,7 @@ } } - async function speichern() { + async function speichern(authuser = null) { loginAction = speichern; if (!await validateAccessTokenClient()) { loginOverlayHidden = false; @@ -249,6 +269,62 @@ } else { result = await ausweisSpeichern(ausweis, objekt, aufnahme, bilder, unterlagen, ausweisart) } + + if (authuser) { + user = await benutzerLesen(authuser.id); + } + + let resultUser: Awaited> | Awaited> | 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) { addNotification({ dismissable: true, @@ -269,7 +345,7 @@ } } - async function bestellen() { + async function bestellen(authuser = null) { if (!form.checkValidity()) { addNotification({ dismissable: true, @@ -312,6 +388,22 @@ } } + if (authuser) { + user = await benutzerLesen(authuser.id); + } + + let resultUser: Awaited> | Awaited> | null = null; + const { passwort, ...baseUser } = impersonatedUser ?? user; + + const benutzerObjekt = { + ...baseUser, + name, + vorname, + telefon + }; + + resultUser = await benutzerSpeichern(benutzerObjekt); + if (rechnung && rechnung.status === "paid") { window.location.href = "/dashboard" return; @@ -320,6 +412,12 @@ try { 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) { const result = await api.rechnung._id.PATCH.fetch({ bezahlmethode: aktiveBezahlmethode, @@ -328,12 +426,13 @@ strasse: strasse, plz: plz, ort: ort, - versand_empfaenger: versand_empfaenger, - versand_strasse: versand_strasse, - versand_plz: versand_plz, - versand_ort: versand_ort, 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: { id: rechnung.id @@ -358,13 +457,16 @@ strasse: strasse, plz: plz, ort: ort, - versand_empfaenger: versand_empfaenger, - versand_strasse: versand_strasse, - versand_plz: versand_plz, - versand_ort: versand_ort, + 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, telefon: telefon, ausweis_id: ausweis.id, - partner_code + partner_code, + abweichende_versand_adresse: abweichende_versand_adresse }, { headers: { @@ -404,6 +506,7 @@ let form: HTMLFormElement; +{#if !nurRechnungsadresseUpdate}
{/if}
- +{/if}
@@ -702,7 +805,6 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8 @@ -739,7 +841,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
- + - {#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)}

Bitte untenstehende Punkte bestätigen. Bitte gehen Sie gegebenenfalls zurück zum Formular und überprüfen bzw. korrigieren Ihre Eingaben.

@@ -1072,31 +1174,33 @@ sm:grid-cols-[min-content_min-content_min-content] sm:justify-self-end sm:mt-8" - + - {#if rechnung && rechnung.status === "paid"} - - - {:else} - {#if gegAnfrage} + {#if !nurRechnungsadresseUpdate} + {#if rechnung && rechnung.status === "paid"} + bestellen()}>Absenden {:else} - + {#if gegAnfrage} + + {:else} + + {/if} {/if} {/if} diff --git a/src/pages/api/admin/ausstellen.ts b/src/pages/api/admin/ausstellen.ts index c30f00fc..29084cef 100644 --- a/src/pages/api/admin/ausstellen.ts +++ b/src/pages/api/admin/ausstellen.ts @@ -17,7 +17,6 @@ import { APIError, defineApiRoute } from "astro-typesafe-api/server"; import { z } from "astro:content"; import { transport } from "#lib/mail.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 { PutObjectCommand } from "@aws-sdk/client-s3"; import { s3Client } from "#lib/s3.js"; @@ -34,7 +33,6 @@ import { getVerbrauchsausweisWohnenKomplett, } from "#lib/server/db.js"; import { PDFDocument } from "pdf-lib"; -import * as fs from 'fs'; export const GET = defineApiRoute({ input: z.object({ diff --git a/src/pages/api/admin/bedarfsausweis-ausstellen.ts b/src/pages/api/admin/bedarfsausweis-ausstellen.ts index 08b9261a..a67e8b02 100644 --- a/src/pages/api/admin/bedarfsausweis-ausstellen.ts +++ b/src/pages/api/admin/bedarfsausweis-ausstellen.ts @@ -197,7 +197,7 @@ export const POST = defineApiRoute({ let filename: string; if (type === "Ausweis") { - filename = `ID_${ausweis.id}_Ausweis.pdf` + filename = `ID_${ausweis.id}_Energieausweis.pdf` } else { filename = `ID_${ausweis.id}_${name}`; } @@ -212,7 +212,7 @@ export const POST = defineApiRoute({ const command = new PutObjectCommand({ Bucket: "ibc-pdfs", - Key: name, + Key: filename, Body: buffer, ACL: "private", }); diff --git a/src/pages/api/auth/refresh-token.ts b/src/pages/api/auth/refresh-token.ts index 3ed57135..2d5b9491 100644 --- a/src/pages/api/auth/refresh-token.ts +++ b/src/pages/api/auth/refresh-token.ts @@ -62,6 +62,7 @@ export const GET = defineApiRoute({ exp: refreshTokenExpiry.valueOf(), }); + console.log("Creating refresh token for user ID:", user.id); const { id } = await prisma.refreshTokens.create({ data: { token: refreshToken, diff --git a/src/pages/api/rechnung/[id].ts b/src/pages/api/rechnung/[id].ts index e19131b3..5f70c5e6 100644 --- a/src/pages/api/rechnung/[id].ts +++ b/src/pages/api/rechnung/[id].ts @@ -16,12 +16,14 @@ export const PATCH = defineApiRoute({ strasse: true, telefon: true, empfaenger: true, + zusatzzeile: true, versand_empfaenger: true, versand_ort: true, versand_plz: true, versand_strasse: true, versand_zusatzzeile: true, - abweichende_versand_adresse: true + abweichende_versand_adresse: true, + email: true }), output: z.object({ checkout_url: z.string().optional(), @@ -31,22 +33,39 @@ export const PATCH = defineApiRoute({ headers: authorizationHeaders, async fetch(input, context, user) { // Wir holen uns die Rechnung - const rechnung = await prisma.rechnung.findUnique({ - where: { - id: context.params.id, - benutzer: { - id: user.id + let rechnung; + if (user.rolle !== Enums.BenutzerRolle.ADMIN) { + rechnung = await prisma.rechnung.findUnique({ + where: { + 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: { - bedarfsausweis_gewerbe: true, - bedarfsausweis_wohnen: true, - geg_nachweis_gewerbe: true, - geg_nachweis_wohnen: true, - verbrauchsausweis_gewerbe: true, - verbrauchsausweis_wohnen: true - } - }) + }) + } else { + rechnung = await prisma.rechnung.findUnique({ + where: { + id: context.params.id + }, + include: { + bedarfsausweis_gewerbe: true, + bedarfsausweis_wohnen: true, + geg_nachweis_gewerbe: true, + geg_nachweis_wohnen: true, + verbrauchsausweis_gewerbe: true, + verbrauchsausweis_wohnen: true + } + }) + } if (!rechnung) { throw new APIError({ @@ -66,12 +85,14 @@ export const PATCH = defineApiRoute({ strasse: input.strasse, telefon: input.telefon, empfaenger: input.empfaenger, + zusatzzeile: input.zusatzzeile, versand_empfaenger: input.versand_empfaenger, versand_ort: input.versand_ort, versand_plz: input.versand_plz, versand_strasse: input.versand_strasse, versand_zusatzzeile: input.versand_zusatzzeile, abweichende_versand_adresse: input.abweichende_versand_adresse, + email: input.email } }) diff --git a/src/pages/api/user/index.ts b/src/pages/api/user/index.ts index 4c769cc5..ba9f3cbc 100644 --- a/src/pages/api/user/index.ts +++ b/src/pages/api/user/index.ts @@ -5,18 +5,17 @@ import { adminMiddleware, authorizationMiddleware } from "#lib/middleware/author import { hashPassword } from "#lib/password.js"; import { createLexOfficeCustomer } from "#lib/server/lexoffice.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 { BenutzerSchema } from "src/generated/zod/benutzer.js"; import { z } from "zod"; +import { Enums } from "#lib/client/prisma.js"; export const POST = defineApiRoute({ input: BenutzerSchema.omit({ - id: true, lex_office_id: true, rolle: true, - created_at: true, - updated_at: true + created_at: true }), middleware: authorizationMiddleware, async fetch(input, context, user) { @@ -24,24 +23,36 @@ export const POST = defineApiRoute({ // 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({ where: { - id: user.id + id: updateData.id }, - data: { - 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, - } - }) + data: updateData + }); + + }, }) @@ -53,9 +64,14 @@ export const GET = defineApiRoute({ email: z.string() })), output: z.array(BenutzerSchema), - middleware: adminMiddleware, + middleware: authorizationMiddleware, async fetch(input, context, admin) { 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({ where: { id: input.id @@ -68,6 +84,11 @@ export const GET = defineApiRoute({ return [user]; } else { + //Only admin can read many users + if (admin.rolle != Enums.BenutzerRolle.ADMIN ) { + return; + } + const users = await prisma.benutzer.findMany({ where: { email: { diff --git a/src/pages/dashboard/abrechnung/index.astro b/src/pages/dashboard/abrechnung/index.astro new file mode 100644 index 00000000..f0fe5e8a --- /dev/null +++ b/src/pages/dashboard/abrechnung/index.astro @@ -0,0 +1,334 @@ +--- +import AbrechungTable from "#components/Abrechnung/AbrechungTable.svelte"; +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.toDate(); +let enddatum = end.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: true, + verbrauchsausweis_gewerbe: true, + verbrauchsausweis_wohnen: 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: true, + verbrauchsausweis_gewerbe: true, + verbrauchsausweis_wohnen: 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] + } +} + +--- + + + + + + + + Reporting | online-energieausweis.org + + + + + + + + + + + + + + + +
+
+IBCornelsen +
Erziehlte Conversions von {benutzer.email}
+
+ +
+ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/pages/dashboard/rechnung/aendern.astro b/src/pages/dashboard/rechnung/aendern.astro new file mode 100644 index 00000000..cfc37b59 --- /dev/null +++ b/src/pages/dashboard/rechnung/aendern.astro @@ -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 | null = null; + +if (user){ + if (user.id !== ausweis.benutzer_id && ausweis.benutzer_id !== undefined){ + impersonatedUser = await getOtherUser(Astro, ausweis.benutzer_id) || {} + } +} +--- + + + \ No newline at end of file diff --git a/src/pages/energieausweis-erstellen/bezahlung.astro b/src/pages/energieausweis-erstellen/bezahlung.astro index ef1a437c..48fda87c 100644 --- a/src/pages/energieausweis-erstellen/bezahlung.astro +++ b/src/pages/energieausweis-erstellen/bezahlung.astro @@ -3,10 +3,11 @@ import { getAusweisartFromId } from "#components/Ausweis/types"; import AusweisLayoutPruefung from "#layouts/AusweisLayoutPruefung.astro"; import { getPrismaAusweisAdapter } from "#lib/server/ausweis"; 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 { PaymentStatus } from "@mollie/api-client"; import { AusweisTyp } from "src/generated/enums"; +import { BenutzerClient } from "#components/Ausweis/types.js"; const uid = Astro.url.searchParams.get("uid") @@ -45,8 +46,16 @@ if (!ausweis) { if (ausweis.rechnung.status === PaymentStatus.paid) { return Astro.redirect("/dashboard") } + +let impersonatedUser: Partial | null = null; + +if (user){ + if (user.id !== ausweis.benutzer_id && ausweis.benutzer_id !== undefined){ + impersonatedUser = await getOtherUser(Astro, ausweis.benutzer_id) || {} + } +} --- - + diff --git a/src/pages/heap-snapshot.astro b/src/pages/heap-snapshot.astro new file mode 100644 index 00000000..1c1f49bf --- /dev/null +++ b/src/pages/heap-snapshot.astro @@ -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); +}); +--- \ No newline at end of file diff --git a/src/pages/kundendaten.astro b/src/pages/kundendaten.astro index cab2da8d..7b5a31b6 100644 --- a/src/pages/kundendaten.astro +++ b/src/pages/kundendaten.astro @@ -3,9 +3,10 @@ import KundendatenModule from "#modules/KundendatenModule.svelte"; import AusweisLayout from "#layouts/AusweisLayoutPruefung.astro"; 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 { 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. @@ -70,9 +71,16 @@ if (!params.has("ausweis") || !params.has("aufnahme") || !params.has("objekt") | } } +let impersonatedUser: Partial | null = null; + +if (user){ + if (user.id !== ausweis.benutzer_id && ausweis.benutzer_id !== undefined){ + impersonatedUser = await getOtherUser(Astro, ausweis.benutzer_id) || {} + } +} --- - + diff --git a/src/pages/pdf/ansichtsausweis.ts b/src/pages/pdf/ansichtsausweis.ts index 5b4028f2..84e1623b 100644 --- a/src/pages/pdf/ansichtsausweis.ts +++ b/src/pages/pdf/ansichtsausweis.ts @@ -45,14 +45,23 @@ export const GET: APIRoute = async (Astro) => { user = await getCurrentUser(Astro) let pdf: Uint8Array | 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 - // Dieser Ausweis wurde mit der alten Version erstellt, das PDF sollte bereits existieren. - pdf = await getS3File("ibc-pdfs", `ID_${id[1]}_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); + + if (ausweis.ausgestellt) { + if (/[A-Z]{2}[0-9]{8}/.test(ausweis.id)) { + const id = ausweis.id.match(/[A-Z]{2}([0-9]{8})/) as RegExpMatchArray + // Dieser Ausweis wurde mit der alten Version erstellt, das PDF sollte bereits existieren. + pdf = await getS3File("ibc-pdfs", `ID_${id[1]}_Energieausweis.pdf`) + } else { + 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, { diff --git a/wipe-database.bash b/wipe-database.bash index b25a5c46..13d4c8a3 100644 --- a/wipe-database.bash +++ b/wipe-database.bash @@ -9,6 +9,22 @@ DB_NAME="main" TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S") 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.' 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 fi -echo "📦 Backup wird erstellt..." -docker exec -t "$CONTAINER_NAME" pg_dumpall -c -U "$DB_USER" | brotli > "$FILE_NAME" -echo "✅ Backup abgeschlossen: $FILE_NAME" +if [[ "$SKIP_BACKUP" == false ]]; then + echo "📦 Backup wird erstellt..." + 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..." @@ -34,6 +52,7 @@ DECLARE r RECORD; sql TEXT := ''; BEGIN + -- Truncate all tables FOR r IN SELECT tablename FROM pg_tables @@ -42,6 +61,15 @@ BEGIN sql := sql || FORMAT('TRUNCATE TABLE public.%I CASCADE;', r.tablename); END LOOP; + -- Drop all sequences + FOR r IN + SELECT sequence_name + FROM information_schema.sequences + WHERE sequence_schema = 'public' + LOOP + sql := sql || FORMAT('DROP SEQUENCE IF EXISTS public.%I CASCADE;', r.sequence_name); + END LOOP; + EXECUTE sql; END $$;