From 648ecc5901914d775c0725ce098b537dc17f4827 Mon Sep 17 00:00:00 2001 From: Moritz Utcke Date: Tue, 5 Aug 2025 09:25:37 -0400 Subject: [PATCH 01/17] PDF Abrechnung --- .../auto-merge-staging-into-main.yml | 76 ------------------- .../20250805131533_partner_code/migration.sql | 2 + prisma/schema/Benutzer.prisma | 1 + .../Abrechnung/AbrechnungTable.svelte | 1 + src/generated/zod/benutzer.ts | 1 + src/pages/dashboard/abrechnung/index.astro | 16 ++-- .../dashboard/abrechnung/monatlich.pdf.astro | 2 +- src/pages/dashboard/admin/impersonate.astro | 2 +- src/pages/dashboard/objekte/index.astro | 8 +- 9 files changed, 17 insertions(+), 92 deletions(-) delete mode 100644 .github/workflows/auto-merge-staging-into-main.yml create mode 100644 prisma/migrations/20250805131533_partner_code/migration.sql diff --git a/.github/workflows/auto-merge-staging-into-main.yml b/.github/workflows/auto-merge-staging-into-main.yml deleted file mode 100644 index f233b3ad..00000000 --- a/.github/workflows/auto-merge-staging-into-main.yml +++ /dev/null @@ -1,76 +0,0 @@ -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 }} \ No newline at end of file diff --git a/prisma/migrations/20250805131533_partner_code/migration.sql b/prisma/migrations/20250805131533_partner_code/migration.sql new file mode 100644 index 00000000..e251e2a3 --- /dev/null +++ b/prisma/migrations/20250805131533_partner_code/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "benutzer" ADD COLUMN "partner_code" TEXT; diff --git a/prisma/schema/Benutzer.prisma b/prisma/schema/Benutzer.prisma index a4eb8ffe..836889fa 100644 --- a/prisma/schema/Benutzer.prisma +++ b/prisma/schema/Benutzer.prisma @@ -21,6 +21,7 @@ model Benutzer { rolle BenutzerRolle @default(USER) firma String? lex_office_id String? + partner_code String? verified Boolean @default(false) diff --git a/src/components/Abrechnung/AbrechnungTable.svelte b/src/components/Abrechnung/AbrechnungTable.svelte index c43f4495..810acace 100644 --- a/src/components/Abrechnung/AbrechnungTable.svelte +++ b/src/components/Abrechnung/AbrechnungTable.svelte @@ -82,6 +82,7 @@ {moment(dt).format("MMMM YYYY")}
+ PDF generieren {provisionMonat.toFixed(2)} € diff --git a/src/generated/zod/benutzer.ts b/src/generated/zod/benutzer.ts index 18291303..ec3fd360 100644 --- a/src/generated/zod/benutzer.ts +++ b/src/generated/zod/benutzer.ts @@ -17,6 +17,7 @@ export const BenutzerSchema = z.object({ rolle: z.nativeEnum(BenutzerRolle), firma: z.string().nullish(), lex_office_id: z.string().nullish(), + partner_code: z.string().nullish(), verified: z.boolean(), created_at: z.date(), updated_at: z.date(), diff --git a/src/pages/dashboard/abrechnung/index.astro b/src/pages/dashboard/abrechnung/index.astro index bcedfb34..4db48c6f 100644 --- a/src/pages/dashboard/abrechnung/index.astro +++ b/src/pages/dashboard/abrechnung/index.astro @@ -24,7 +24,7 @@ let bestellungen; if (start.isValid() && end.isValid()) { bestellungen = await prisma.rechnung.findMany({ where: { - partner_code: "immowelt", + partner_code: benutzer.partner_code, OR: [ { verbrauchsausweis_gewerbe: { @@ -91,7 +91,7 @@ if (start.isValid() && end.isValid()) { } else { bestellungen = await prisma.rechnung.findMany({ where: { - partner_code: "immowelt", + partner_code: benutzer.partner_code, OR: [ { verbrauchsausweis_gewerbe: { @@ -153,12 +153,12 @@ if (!startdatum) { created_at: true, }, where: { - partner_code: "immowelt", - OR: [ - { - verbrauchsausweis_gewerbe: { - ausgestellt: true, - }, + partner_code: benutzer.partner_code, + OR: [ + { + verbrauchsausweis_gewerbe: { + ausgestellt: true, + }, }, { bedarfsausweis_wohnen: { diff --git a/src/pages/dashboard/abrechnung/monatlich.pdf.astro b/src/pages/dashboard/abrechnung/monatlich.pdf.astro index 66bd9f6f..708975dd 100644 --- a/src/pages/dashboard/abrechnung/monatlich.pdf.astro +++ b/src/pages/dashboard/abrechnung/monatlich.pdf.astro @@ -16,7 +16,7 @@ if (!benutzer) { let bestellungen = await prisma.rechnung.findMany({ where: { - partner_code: "immowelt", + partner_code: benutzer.partner_code, OR: [ { verbrauchsausweis_gewerbe: { diff --git a/src/pages/dashboard/admin/impersonate.astro b/src/pages/dashboard/admin/impersonate.astro index 69e9043d..236e152d 100644 --- a/src/pages/dashboard/admin/impersonate.astro +++ b/src/pages/dashboard/admin/impersonate.astro @@ -61,5 +61,5 @@ Astro.cookies.set(API_ACCESS_TOKEN_COOKIE_NAME, accessToken, { expires: moment().add(30, "minutes").toDate() }) -return Astro.redirect("/dashboard") +return Astro.redirect("/dashboard"); --- \ No newline at end of file diff --git a/src/pages/dashboard/objekte/index.astro b/src/pages/dashboard/objekte/index.astro index 713f2576..ea05c072 100644 --- a/src/pages/dashboard/objekte/index.astro +++ b/src/pages/dashboard/objekte/index.astro @@ -31,7 +31,7 @@ if ((page < 1 || page > totalPageCount) && totalPageCount > 0) { let result: { id: string; updated_at: Date }[] = []; // Wir fragen den neuesten Ausweis ab // Falls der Nutzer ein Admin ist dann kommt der ganz neueste ansonsten der neueste des eingeloggten Benutzers. -if (user.rolle !== Enums.BenutzerRolle.ADMIN || user.rolle === Enums.BenutzerRolle.RESELLER) { +if (user.rolle !== Enums.BenutzerRolle.ADMIN) { result = await prisma.$queryRaw`SELECT id, updated_at FROM "VerbrauchsausweisWohnen" WHERE benutzer_id = ${user.id} UNION ALL SELECT id, updated_at FROM "VerbrauchsausweisGewerbe" WHERE benutzer_id = ${user.id} UNION ALL @@ -54,8 +54,4 @@ if (user.rolle !== Enums.BenutzerRolle.ADMIN || user.rolle === Enums.BenutzerRol if (result.length > 0) { return Astro.redirect(`/dashboard/objekte/${result[0].id}?p=${page}`) } ---- - - -

Keine Ausweise konnten gefunden werden.

- +--- \ No newline at end of file From 7b7a1f77a0a4188be1bd84d51a6189e290bc5ab8 Mon Sep 17 00:00:00 2001 From: Moritz Utcke Date: Tue, 5 Aug 2025 09:41:00 -0400 Subject: [PATCH 02/17] Zeitzonen --- bun.lock | 4 ++-- package.json | 2 +- src/astro-typesafe-api-caller.ts | 16 +++++++--------- src/components/Abrechnung/AbrechnungTable.svelte | 4 +++- src/pages/dashboard/abrechnung/index.astro | 4 +++- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/bun.lock b/bun.lock index 0af6ee99..bf5a8067 100644 --- a/bun.lock +++ b/bun.lock @@ -36,7 +36,7 @@ "jwt-decode": "^4.0.0", "mime": "^4.0.6", "moment": "^2.30.1", - "moment-timezone": "^0.5.46", + "moment-timezone": "^0.6.0", "nodemailer": "^6.10.0", "pdf-lib": "^1.17.1", "postcss-nested": "^7.0.2", @@ -1965,7 +1965,7 @@ "moment": ["moment@2.30.1", "", {}, "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how=="], - "moment-timezone": ["moment-timezone@0.5.47", "", { "dependencies": { "moment": "^2.29.4" } }, "sha512-UbNt/JAWS0m/NJOebR0QMRHBk0hu03r5dx9GK8Cs0AS3I81yDcOc9k+DytPItgVvBP7J6Mf6U2n3BPAacAV9oA=="], + "moment-timezone": ["moment-timezone@0.6.0", "", { "dependencies": { "moment": "^2.29.4" } }, "sha512-ldA5lRNm3iJCWZcBCab4pnNL3HSZYXVb/3TYr75/1WCTWYuTqYUb5f/S384pncYjJ88lbO8Z4uPDvmoluHJc8Q=="], "mrmime": ["mrmime@2.0.0", "", {}, "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw=="], diff --git a/package.json b/package.json index 12e5f6fd..5fd7c213 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "jwt-decode": "^4.0.0", "mime": "^4.0.6", "moment": "^2.30.1", - "moment-timezone": "^0.5.46", + "moment-timezone": "^0.6.0", "nodemailer": "^6.10.0", "pdf-lib": "^1.17.1", "postcss-nested": "^7.0.2", diff --git a/src/astro-typesafe-api-caller.ts b/src/astro-typesafe-api-caller.ts index 7b6d9fb1..cf57dd92 100644 --- a/src/astro-typesafe-api-caller.ts +++ b/src/astro-typesafe-api-caller.ts @@ -13,14 +13,14 @@ export const createCaller = createCallerFactory({ "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"), + "bedarfsausweis-wohnen/[id]": await import("../src/pages/api/bedarfsausweis-wohnen/[id].ts"), + "bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"), + "bedarfsausweis-gewerbe/[id]": await import("../src/pages/api/bedarfsausweis-gewerbe/[id].ts"), + "bedarfsausweis-gewerbe": await import("../src/pages/api/bedarfsausweis-gewerbe/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"), "auth/refresh-token": await import("../src/pages/api/auth/refresh-token.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-wohnen/[id]": await import("../src/pages/api/bedarfsausweis-wohnen/[id].ts"), - "bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"), + "ausweise": await import("../src/pages/api/ausweise/index.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"), @@ -29,14 +29,12 @@ export const createCaller = createCallerFactory({ "rechnung/[id]": await import("../src/pages/api/rechnung/[id].ts"), "rechnung/anfordern": await import("../src/pages/api/rechnung/anfordern.ts"), "rechnung": await import("../src/pages/api/rechnung/index.ts"), - "objekt": await import("../src/pages/api/objekt/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"), + "ticket": await import("../src/pages/api/ticket/index.ts"), + "objekt": await import("../src/pages/api/objekt/index.ts"), "verbrauchsausweis-gewerbe/[id]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[id].ts"), "verbrauchsausweis-gewerbe": await import("../src/pages/api/verbrauchsausweis-gewerbe/index.ts"), - "user": await import("../src/pages/api/user/index.ts"), - "user/self": await import("../src/pages/api/user/self.ts"), "verbrauchsausweis-wohnen/[id]": await import("../src/pages/api/verbrauchsausweis-wohnen/[id].ts"), "verbrauchsausweis-wohnen": await import("../src/pages/api/verbrauchsausweis-wohnen/index.ts"), "webhooks/mollie": await import("../src/pages/api/webhooks/mollie.ts"), diff --git a/src/components/Abrechnung/AbrechnungTable.svelte b/src/components/Abrechnung/AbrechnungTable.svelte index 810acace..87140394 100644 --- a/src/components/Abrechnung/AbrechnungTable.svelte +++ b/src/components/Abrechnung/AbrechnungTable.svelte @@ -1,6 +1,6 @@ diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index 5d79cd5e..e5630c35 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -150,7 +150,7 @@ height="0" width="0" style="display:none;visibility:hidden">