18 Commits

Author SHA1 Message Date
Robert Jagtiani
641fdf6213 Titel PY- 2025-08-03 22:47:02 +02:00
Robert Jagtiani
ac502169a9 landingpage partner header menu und Titel fix 2025-08-03 22:34:40 +02:00
Moritz Utcke
f6d9b565d7 Merge pull request #558 from IBCornelsen/staging
staging nach main
2025-08-02 13:05:25 -05:00
Moritz Utcke
288072ce1a Merge branch 'main' into staging 2025-08-02 14:03:56 -04:00
Moritz Utcke
e9c7f91a1d Merge pull request #556 from IBCornelsen/dev
Dev nach staging
2025-08-02 12:57:57 -05:00
Moritz Utcke
f29aaa2170 Prevent Wrong PR Fix 2025-08-02 13:57:34 -04:00
Moritz Utcke
249caafddb Monatliche Abrechnung auskommentiert 2025-08-02 13:52:42 -04:00
Jens Cornelsen
38333a117b . 2025-08-02 19:39:07 +02:00
Jens Cornelsen
c5042066ff Textanpassung Hilfe Box 2025-08-02 19:23:33 +02:00
Moritz Utcke
f028ac2d4e Fügt eine Auswahlmöglichkeit für eine Datenbank hinzu 2025-08-01 08:37:49 -05:00
Moritz Utcke
6372ade5c1 Update trello board id 2025-07-31 18:11:25 -05:00
Moritz Utcke
8378909517 Update Makefile 2025-07-30 13:12:19 -05:00
Moritz Utcke
67a44f8bdb Disable Auto Merge 2025-07-30 12:52:27 -05:00
Moritz Utcke
10b1aec389 Abrechnungsübersicht 2025-07-30 12:26:28 -05:00
Moritz Utcke
f9dc9ebd48 Behebt folgende Fehler aus Trello
Kaufabschluss bei Neukunden: Reg Box soll sofort erscheinen (ohne Umweg über Login Box)

Login bzw Reg Box verschwindet plöltzlich. Das passiert wahrscheinlich wenn man aus versehen neben die Box klickt. Das kann den Kunden verwirren
2025-07-30 09:51:57 -05:00
Jens Cornelsen
8bfa14352c Merge pull request #554 from IBCornelsen/staging
Fernwärme Hamburg hinzugefügt
2025-07-09 21:09:17 +02:00
Jens Cornelsen
ec7fccac35 Merge remote-tracking branch 'origin/staging' into staging 2025-07-08 17:50:45 +02:00
Jens Cornelsen
397a2ced4e Fernwärme Hamburg hinzugefügt 2025-07-08 17:16:27 +02:00
21 changed files with 557 additions and 934 deletions

View File

@@ -8,8 +8,6 @@ on:
jobs: jobs:
merge: merge:
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs:
reason: ${{ steps.check.outputs.reason }}
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -30,15 +28,9 @@ jobs:
id: check id: check
run: | run: |
git fetch origin git fetch origin
COUNT=$(git rev-list --count origin/staging..origin/main) if [ $(git rev-list --count origin/staging..origin/main) -gt 0 ]; then
if [ "$COUNT" -gt 0 ]; then
echo "reason=ok" >> $GITHUB_OUTPUT
echo "❌ Staging is behind main and requires manual merging." echo "❌ Staging is behind main and requires manual merging."
exit 1 exit 1
elif [ "$COUNT" -eq 0 ]; then
echo "reason=identical" >> $GITHUB_OUTPUT
echo "✅ Staging and main are identical. Nothing to do."
exit 42
fi fi
- name: Create PR from staging to main - name: Create PR from staging to main
@@ -61,7 +53,7 @@ jobs:
notify_failure: notify_failure:
needs: merge needs: merge
if: failure() && needs.merge.outputs.reason != 'identical' if: failure()
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Send Discord notification on failure - name: Send Discord notification on failure
@@ -70,3 +62,15 @@ jobs:
-X POST \ -X POST \
-d "{\"content\": \"🚨 Auto-Merge fehlgeschlagen! Bitte manuell prüfen: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\"}" \ -d "{\"content\": \"🚨 Auto-Merge fehlgeschlagen! Bitte manuell prüfen: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\"}" \
${{ secrets.DISCORD_WEBHOOK_URL }} ${{ 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 }}

View File

@@ -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

View File

@@ -13,18 +13,15 @@ jobs:
steps: steps:
- name: Prevent dev merges - name: Prevent dev merges
run: | run: |
echo "${{ github.head_ref }}"; if [[ "${{ github.head_ref }}" == "dev" && "${{ github.base_ref }}" == "main" ]]; then
echo "${{ github.base_ref }}"; echo "ERROR: Merging 'dev' into 'main' is forbidden!"
if [[ "${{ github.head_ref }}" == "dev" ]]; then
echo "ERROR: Merging 'dev' into '${{ github.base_ref }}' is forbidden!"
exit 1 exit 1
fi fi
- name: Allow only staging into main - name: Allow only staging into main
if: github.base_ref == 'main' if: github.base_ref == 'main'
run: | run: |
echo "${{ github.head_ref }}";
echo "${{ github.base_ref }}";
if [[ "${{ github.head_ref }}" != "staging" ]]; then if [[ "${{ github.head_ref }}" != "staging" ]]; then
echo "ERROR: Only 'staging' branch is allowed to merge into 'main'. Current: '${{ github.head_ref }}'" echo "ERROR: Only 'staging' branch is allowed to merge into 'main'. Current: '${{ github.head_ref }}'"
exit 1 exit 1

View File

@@ -61,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

View File

@@ -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=="],

View File

@@ -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",

View File

@@ -5,26 +5,42 @@ BUCKET_NAME="ibc-db-backup"
ENDPOINT_URL="https://s3.eu-central-3.ionoscloud.com" ENDPOINT_URL="https://s3.eu-central-3.ionoscloud.com"
LOCAL_DOWNLOAD_DIR="./" # Where to save the file LOCAL_DOWNLOAD_DIR="./" # Where to save the file
# === 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
CUSTOM_FILE="$1"
echo "🔍 Using custom file: $CUSTOM_FILE"
# Check if the file exists
if [ ! -f "$CUSTOM_FILE" ]; then
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"
# === Get latest file from IONOS S3 bucket ===
LATEST_FILE=$(aws s3api list-objects-v2 \
--bucket "$BUCKET_NAME" \ --bucket "$BUCKET_NAME" \
--prefix "data-dump" \ --prefix "data-dump" \
--endpoint-url "$ENDPOINT_URL" \ --endpoint-url "$ENDPOINT_URL" \
--query 'Contents | sort_by(@, &LastModified) | [-1].Key' \ --query 'Contents | sort_by(@, &LastModified) | [-1].Key' \
--output text) --output text)
# === Check if file was found === # === Check if file was found ===
if [ "$LATEST_FILE" == "None" ] || [ -z "$LATEST_FILE" ]; then if [ "$LATEST_FILE" == "None" ] || [ -z "$LATEST_FILE" ]; then
echo "❌ No matching .sql.br file found." echo "❌ No matching .sql.br file found."
exit 1 exit 1
fi fi
echo "🔍 Latest file found: $LATEST_FILE"
FILENAME=$(basename "$LATEST_FILE")
SQL_FILE="${FILENAME%.br}" # Remove .br suffix
FILENAME=$(basename "$LATEST_FILE") echo "📥 Downloading $LATEST_FILE"
SQL_FILE="${FILENAME%.br}" # Remove .br suffix aws s3 cp "s3://$BUCKET_NAME/$LATEST_FILE" "$LOCAL_DOWNLOAD_DIR" \
echo "📥 Downloading $LATEST_FILE"
aws s3 cp "s3://$BUCKET_NAME/$LATEST_FILE" "$LOCAL_DOWNLOAD_DIR" \
--endpoint-url "$ENDPOINT_URL" --endpoint-url "$ENDPOINT_URL"
fi
# === Decompress with Brotli === # === Decompress with Brotli ===
echo "🗜️ Decompressing $FILENAME -> $SQL_FILE" echo "🗜️ Decompressing $FILENAME -> $SQL_FILE"

View File

@@ -5,7 +5,6 @@ export const createCaller = createCallerFactory({
"klimafaktoren": await import("../src/pages/api/klimafaktoren.ts"), "klimafaktoren": await import("../src/pages/api/klimafaktoren.ts"),
"postleitzahlen": await import("../src/pages/api/postleitzahlen.ts"), "postleitzahlen": await import("../src/pages/api/postleitzahlen.ts"),
"unterlage": await import("../src/pages/api/unterlage.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/ausstellen": await import("../src/pages/api/admin/ausstellen.ts"),
"admin/bedarfsausweis-ausstellen": await import("../src/pages/api/admin/bedarfsausweis-ausstellen.ts"), "admin/bedarfsausweis-ausstellen": await import("../src/pages/api/admin/bedarfsausweis-ausstellen.ts"),
"admin/bestellbestaetigung": await import("../src/pages/api/admin/bestellbestaetigung.ts"), "admin/bestellbestaetigung": await import("../src/pages/api/admin/bestellbestaetigung.ts"),
@@ -13,6 +12,7 @@ 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"), "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"),
@@ -26,19 +26,20 @@ export const createCaller = createCallerFactory({
"geg-nachweis-gewerbe": await import("../src/pages/api/geg-nachweis-gewerbe/index.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"),
"objekt": await import("../src/pages/api/objekt/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"),
"objekt": await import("../src/pages/api/objekt/index.ts"),
"ticket": await import("../src/pages/api/ticket/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"), "user/self": await import("../src/pages/api/user/self.ts"),
"verbrauchsausweis-gewerbe/[id]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[id].ts"), "verbrauchsausweis-gewerbe/[id]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[id].ts"),
"verbrauchsausweis-gewerbe": await import("../src/pages/api/verbrauchsausweis-gewerbe/index.ts"), "verbrauchsausweis-gewerbe": await import("../src/pages/api/verbrauchsausweis-gewerbe/index.ts"),
"verbrauchsausweis-wohnen/[id]": await import("../src/pages/api/verbrauchsausweis-wohnen/[id].ts"), "verbrauchsausweis-wohnen/[id]": await import("../src/pages/api/verbrauchsausweis-wohnen/[id].ts"),
"verbrauchsausweis-wohnen": await import("../src/pages/api/verbrauchsausweis-wohnen/index.ts"), "verbrauchsausweis-wohnen": await import("../src/pages/api/verbrauchsausweis-wohnen/index.ts"),
"webhooks/mollie": await import("../src/pages/api/webhooks/mollie.ts"), "webhooks/mollie": await import("../src/pages/api/webhooks/mollie.ts"),
"objekt/[id]": await import("../src/pages/api/objekt/[id]/index.ts"),
"aufnahme/[id]/bilder": await import("../src/pages/api/aufnahme/[id]/bilder.ts"), "aufnahme/[id]/bilder": await import("../src/pages/api/aufnahme/[id]/bilder.ts"),
"aufnahme/[id]": await import("../src/pages/api/aufnahme/[id]/index.ts"), "aufnahme/[id]": await import("../src/pages/api/aufnahme/[id]/index.ts"),
"aufnahme/[id]/unterlagen": await import("../src/pages/api/aufnahme/[id]/unterlagen.ts"), "aufnahme/[id]/unterlagen": await import("../src/pages/api/aufnahme/[id]/unterlagen.ts"),
"objekt/[id]": await import("../src/pages/api/objekt/[id]/index.ts"),
}) })

View 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>

View File

@@ -1,109 +0,0 @@
<script lang="ts">
import { BedarfsausweisWohnen, Enums, Rechnung, VerbrauchsausweisGewerbe, VerbrauchsausweisWohnen } from "#lib/server/prisma.js";
import moment from "moment";
import { format } from "sharp";
export let bestellungen: (Rechnung & {
verbrauchsausweis_wohnen: VerbrauchsausweisWohnen | null,
verbrauchsausweis_gewerbe: VerbrauchsausweisGewerbe | null,
bedarfsausweis_wohnen: BedarfsausweisWohnen | null,
})[];
export let provisionen: Record<Enums.Ausweisart, number>;
export let partnerCodeErstesMal: Date;
const bestellungenNachMonat: Record<string, (typeof bestellungen)> = {};
for (const bestellung of bestellungen) {
const monat = moment(bestellung.created_at).format("Y-m");
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)
</script>
{#each periods as dt}
{@const jahrMonat = dt.format("Y-m")}
{#if jahrMonat in bestellungenNachMonat && bestellungenNachMonat[jahrMonat].length > 0}
<!-- Echo dropdown foreach month. -->
{@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}
<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 id='QTT' style='margin-top: 0 !important; display:none;'>
<thead>
<tr>
<td style='text-align:center;'>ID</td>
<td style='text-align:center;'>DATUM</td>
<td style='width:11em;text-align:center;'>GEBÄUDEADRESSE </td>
<td style='width:11em;text-align:center;'>PLZ </td>
<td style='width:11em;text-align:center;'>ORT </td>
<td style='text-align:center;'>AUSWEIS</td>
<td style='width:5em;text-align:center;'>BETRAG NETTO</td>
</tr>
</thead>
<tbody>
{#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]}
<tr>
<td style='width:1em;text-align:center;'>{bestellung.id}</td>
<td style='width:9em;text-align:center;font-weight:bold;'>{moment(bestellung.created_at).format("Y/m/d")}</td>
<td style='width:8em;text-align:left;'>{bestellung["objekt_strasse"]}</td>
<td style='width:5em;text-align:center;'>{bestellung["objekt_plz"]}</td>
<td style='width:6em;text-align:left;'>{bestellung["objekt_ort"]}</td>
<td style='width:3em;text-align:center;'>{bestellung['ausweisart']}</td>
<td style='width:8em;text-align:right;'>{provisionBestellung}</td>
</tr>
{/each}
</table>
{/if}
{/each}
<!-- foreach ($period as $dt) {
$year_month = $dt->format("Y-m");
$month_name = $months[$dt->format("m")];
if ((new DateTime(date("m/d/Y", strtotime($EEtimestamp))))->format("d") - (new DateTime(date("m/d/Y", strtotime($SStimestamp))))->format("d") == 1) {
$Pall = $dt->format("d/m/Y") . ' bis ' . (new DateTime($today))->format("d/m/Y");
} -->
<!-- } -->

View File

@@ -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&nbsp;telefonischer <b>Selbsteingabe online</b><br>inkl. ausführlicher&nbsp;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&nbsp;Verbrauchsabrechnungen&nbsp;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">

View File

@@ -70,7 +70,7 @@
</div> </div>
</div> </div>
{/if} {/if}
<a href="/dashboard/abrechnung" class="button ">Conversions</a> <!-- <a href="/dashboard/abrechnung" class="button ">Monatliche Abrechnung</a> -->
</div> </div>
<hr class="border-gray-600" /> <hr class="border-gray-600" />

View File

@@ -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>

View File

@@ -39,63 +39,38 @@ const isNET = pathname.includes("immonet");
</div> </div>
<div> <div>
<ul class="navlist"> <!-- Navigation als Liste (nur ab sm sichtbar) -->
<li> <ul class="navlist hidden xl:flex">
<a <li><a href={`/${partner}/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/`}><button class={tab === 0 ? "glow" : ""}>Verbrauchsausweis</button></a></li>
href={`/${partner}/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/`} <li><a href={`/${partner}/energieausweis-erstellen/verbrauchsausweis-gewerbe/`}><button class={tab === 1 ? "glow" : ""}>Verbrauchsausweis Gewerbe</button></a></li>
><button class={tab === 0 ? "glow" : ""} <li><a href={`/${partner}/energieausweis-erstellen/bedarfsausweis-wohngebaeude/`}><button class={tab === 2 ? "glow" : ""}>Bedarfsausweis</button></a></li>
>Verbrauchsausweis</button <li><a href={`/${partner}/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/`}><button class={tab === 3 ? "glow" : ""}>Bedarfsausweis Gewerbe</button></a></li>
></a> <li><a href={`/${partner}/angebot-anfragen/geg-nachweis-wohnen-anfragen/`}><button class={tab === 4 ? "glow" : ""}>GEG Nachweis Wohngebäude</button></a></li>
</li> <li><a href={`/${partner}/angebot-anfragen/geg-nachweis-gewerbe-anfragen/`}><button class={tab === 5 ? "glow" : ""}>GEG Nachweis Gewerbe</button></a></li>
<li> <li><a href={`/${partner}/welcher-ausweis/${partner}`}><button class={tab === 6 ? "glow" : ""}>Welcher Ausweis</button></a></li>
<a </ul>
href={`/${partner}/energieausweis-erstellen/verbrauchsausweis-gewerbe/`}
><button class={tab === 1 ? "glow" : ""} <!-- Navigation als Dropdown (nur bis sm sichtbar) -->
>Verbrauchsausweis Gewerbe</button <select
></a> class="xl:hidden border rounded p-2 w-[calc(100%-2rem)]"
</li> onchange="if (this.value) window.location.href=this.value"
<li> >
<a <option value="">Auswahl treffen…</option>
href={`/${partner}/energieausweis-erstellen/bedarfsausweis-wohngebaeude/`} <option value={`/${partner}/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/`} selected={tab === 0}>Verbrauchsausweis</option>
><button class={tab === 2 ? "glow" : ""} <option value={`/${partner}/energieausweis-erstellen/verbrauchsausweis-gewerbe/`} selected={tab === 1}>Verbrauchsausweis Gewerbe</option>
>Bedarfsausweis</button <option value={`/${partner}/energieausweis-erstellen/bedarfsausweis-wohngebaeude/`} selected={tab === 2}>Bedarfsausweis</option>
></a> <option value={`/${partner}/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/`} selected={tab === 3}>Bedarfsausweis Gewerbe</option>
</li> <option value={`/${partner}/angebot-anfragen/geg-nachweis-wohnen-anfragen/`} selected={tab === 4}>GEG Nachweis Wohngebäude</option>
<li> <option value={`/${partner}/angebot-anfragen/geg-nachweis-gewerbe-anfragen/`} selected={tab === 5}>GEG Nachweis Gewerbe</option>
<a <option value={`/${partner}/welcher-ausweis/${partner}`} selected={tab === 6}>Welcher Ausweis</option>
href={`/${partner}/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/`} </select>
><button class={tab === 3 ? "glow" : ""}
>Bedarfsausweis Gewerbe</button
></a>
</li>
<li>
<a
href={`/${partner}/angebot-anfragen/geg-nachweis-wohnen-anfragen/`}
><button class={tab === 4 ? "glow" : ""}
>GEG Nachweis Wohngebäude</button
></a>
</li>
<li>
<a
href={`/${partner}/angebot-anfragen/geg-nachweis-gewerbe-anfragen/`}
><button class={tab === 5 ? "glow" : ""}
>GEG Nachweis Gewerbe</button
></a>
</li>
<li>
<a href={`/${partner}/welcher-ausweis/${partner}`}
><button class={tab === 6 ? "glow" : ""}
>Welcher Ausweis</button
></a>
</li>
</ul>
</div> </div>
</div> </div>
</header> </header>
<div <div
id="titel" id="titel"
class="block w-full 2xl:h-[270px] lg:h-[148px] bg-cover px-24 py-20" class="block w-full lg:h-[270px] bg-cover !px-8 md:px-32 !py-8 md:py-16"
style={`background-image: url('/images/partner/${partner}/hero-energieausweis.jpg'); style={`background-image: url('/images/partner/${partner}/hero-energieausweis.jpg');
background-repeat:no-repeat; background-position:right;`} background-repeat:no-repeat; background-position:right;`}
> >
@@ -186,7 +161,7 @@ background-repeat:no-repeat; background-position:right;`}
font-family: "immo Sans"; font-family: "immo Sans";
font-weight:400; font-weight:400;
div{@apply w-fit bg-white/75 py-6 px-16 rounded-lg ring-2 ring-black/15 text-[1.45rem];box-shadow:8px 8px 16px rgba(0,0,0,0.5);} div{@apply w-fit bg-white/75 py-6 px-4 md:px-16 rounded-lg ring-2 ring-black/15 text-[1.45rem];box-shadow:8px 8px 16px rgba(0,0,0,0.5);}
} }
.header-button { .header-button {

View File

@@ -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"
>;
} }

View File

@@ -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 = {

View File

@@ -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>

View File

@@ -1156,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>
@@ -1215,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>

View File

@@ -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.

View File

@@ -1,27 +1,28 @@
--- ---
import AbrechungTable from "#components/Abrechnung/AbrechungTable.svelte"; 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 { Enums, prisma } from "#lib/server/prisma";
import { getCurrentUser } from "#lib/server/user"; import { getCurrentUser } from "#lib/server/user";
import moment from "moment"; import moment from "moment";
const start = moment(Astro.url.searchParams.get("start"));
const end = moment(Astro.url.searchParams.get("end"));
const start = moment(Astro.url.searchParams.get("start")) let startdatum = start.isValid() ? start.toDate() : moment().startOf("month").toDate();
const end = moment(Astro.url.searchParams.get("end")) let enddatum = end.isValid() ? end.toDate() : moment().endOf("month").toDate();
let startdatum = start.toDate(); const benutzer = await getCurrentUser(Astro);
let enddatum = end.toDate();
const benutzer = await getCurrentUser(Astro)
if (!benutzer) { if (!benutzer) {
return Astro.redirect("/404") return Astro.redirect("/404");
} }
const provisionen={ const provisionen = {
[Enums.Ausweisart.VerbrauchsausweisWohnen]: 10, [Enums.Ausweisart.VerbrauchsausweisWohnen]: 10,
[Enums.Ausweisart.BedarfsausweisWohnen]: 10, [Enums.Ausweisart.BedarfsausweisWohnen]: 10,
[Enums.Ausweisart.VerbrauchsausweisGewerbe]: 10, [Enums.Ausweisart.VerbrauchsausweisGewerbe]: 10,
} };
// $kommission = db()->one("SELECT abr_va, abr_ba, abr_vanw FROM users WHERE resellercode = :resellercode", ["resellercode" => $resellercode]); // $kommission = db()->one("SELECT abr_va, abr_ba, abr_vanw FROM users WHERE resellercode = :resellercode", ["resellercode" => $resellercode]);
// Select every entry from database where user was involved. // Select every entry from database where user was involved.
@@ -30,305 +31,206 @@ if (start.isValid() && end.isValid()) {
bestellungen = await prisma.rechnung.findMany({ bestellungen = await prisma.rechnung.findMany({
where: { where: {
partner_code: "immowelt", partner_code: "immowelt",
OR: [{ OR: [
{
verbrauchsausweis_gewerbe: { verbrauchsausweis_gewerbe: {
ausgestellt: true ausgestellt: true,
} },
}, },
{ {
bedarfsausweis_wohnen: { bedarfsausweis_wohnen: {
ausgestellt: true ausgestellt: true,
} },
}, },
{ {
verbrauchsausweis_wohnen: { verbrauchsausweis_wohnen: {
ausgestellt: true ausgestellt: true,
}
}],
AND: [{
created_at: {
gte: startdatum
}, },
}, {
created_at: {
lte: enddatum
}, },
}] ],
AND: [
{
created_at: {
gte: startdatum,
},
},
{
created_at: {
lte: enddatum,
},
},
],
}, },
orderBy: { orderBy: {
created_at: "desc" created_at: "desc",
}, },
include: { include: {
bedarfsausweis_wohnen: true, bedarfsausweis_wohnen: {
verbrauchsausweis_gewerbe: true, include: {
verbrauchsausweis_wohnen: true aufnahme: {
} include: {
objekt: true,
},
},
},
},
verbrauchsausweis_gewerbe: {
include: {
aufnahme: {
include: {
objekt: true,
},
},
},
},
verbrauchsausweis_wohnen: {
include: {
aufnahme: {
include: {
objekt: true,
},
},
},
},
},
}); });
} else { } else {
bestellungen = await prisma.rechnung.findMany({ bestellungen = await prisma.rechnung.findMany({
where: { where: {
partner_code: "immowelt", partner_code: "immowelt",
OR: [{ OR: [
{
verbrauchsausweis_gewerbe: { verbrauchsausweis_gewerbe: {
ausgestellt: true ausgestellt: true,
} },
}, },
{ {
bedarfsausweis_wohnen: { bedarfsausweis_wohnen: {
ausgestellt: true ausgestellt: true,
} },
}, },
{ {
verbrauchsausweis_wohnen: { verbrauchsausweis_wohnen: {
ausgestellt: true ausgestellt: true,
} },
}] },
],
}, },
orderBy: { orderBy: {
created_at: "desc" created_at: "desc",
}, },
include: { include: {
bedarfsausweis_wohnen: true, bedarfsausweis_wohnen: {
verbrauchsausweis_gewerbe: true, include: {
verbrauchsausweis_wohnen: true 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? // Wann wurde der partner_code zum ersten mal benutzt?
const partnerCodeErstesMal = (await prisma.rechnung.findFirst({ const partnerCodeErstesMal = (
await prisma.rechnung.findFirst({
select: { select: {
created_at: true created_at: true,
}, },
where: { where: {
partner_code: "immowelt", partner_code: "immowelt",
OR: [{ OR: [
{
verbrauchsausweis_gewerbe: { verbrauchsausweis_gewerbe: {
ausgestellt: true ausgestellt: true,
} },
}, },
{ {
bedarfsausweis_wohnen: { bedarfsausweis_wohnen: {
ausgestellt: true ausgestellt: true,
} },
}, },
{ {
verbrauchsausweis_wohnen: { verbrauchsausweis_wohnen: {
ausgestellt: true ausgestellt: true,
} },
}], },
],
created_at: { created_at: {
gte: moment().set("year", 2020).set("dayOfYear", 1).toDate() gte: moment().set("year", 2020).set("dayOfYear", 1).toDate(),
} },
}, },
orderBy: { orderBy: {
created_at: "asc" created_at: "asc",
} },
}))?.created_at })
)?.created_at;
let provision = 0; let provision = 0;
const ausweisarten: string[] = []; const ausweisarten: string[] = [];
for (const bestellung of bestellungen) { for (const bestellung of bestellungen) {
if (bestellung.verbrauchsausweis_wohnen) { if (bestellung.verbrauchsausweis_wohnen) {
ausweisarten.push(Enums.Ausweisart.VerbrauchsausweisWohnen) ausweisarten.push(Enums.Ausweisart.VerbrauchsausweisWohnen);
provision += provisionen[Enums.Ausweisart.VerbrauchsausweisWohnen] provision += provisionen[Enums.Ausweisart.VerbrauchsausweisWohnen];
} }
if (bestellung.bedarfsausweis_wohnen) { if (bestellung.bedarfsausweis_wohnen) {
ausweisarten.push(Enums.Ausweisart.BedarfsausweisWohnen) ausweisarten.push(Enums.Ausweisart.BedarfsausweisWohnen);
provision += provisionen[Enums.Ausweisart.BedarfsausweisWohnen] provision += provisionen[Enums.Ausweisart.BedarfsausweisWohnen];
} }
if (bestellung.verbrauchsausweis_gewerbe) { if (bestellung.verbrauchsausweis_gewerbe) {
ausweisarten.push(Enums.Ausweisart.VerbrauchsausweisGewerbe) ausweisarten.push(Enums.Ausweisart.VerbrauchsausweisGewerbe);
provision += provisionen[Enums.Ausweisart.VerbrauchsausweisGewerbe] provision += provisionen[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
/>
<!doctype html> <div class="fixed bottom-0 left-0 right-0 bg-white p-4 shadow">
<html lang="de"> <div class="flex justify-between items-center">
<head>
<meta charset="utf-8">
<title>Reporting | online-energieausweis.org</title>
<meta charset="utf-8">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script type="text/javascript" src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css" />
<link rel="stylesheet" href="./main.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
</head>
<style>
body {
font-family: arial;
}
#inputwrap {
position: fixed;
top: 0;
left: 10%;
width: 70%;
padding-top: 10px;
padding-bottom: 10px;
background: #fff;
}
#cal {
margin-right: 10px !important;
}
#demo {
width: 76%;
display: inline-block;
}
table tr,
td {
border: 0.1em solid #000;
padding: 0;
margin: 0;
}
#QTT {
border-collapse: collapse;
width: 70%;
margin-top: 8em;
margin-left: 10%;
table-layout: auto;
}
#QTT thead td {
background: #ff7d26;
font-weight: bold;
}
#QTT tr:nth-child(even) {
background-color: #f2f2f2;
}
#QTT td {
padding: 0.4em 0.4em 0.4em 0.4em;
text-align: right;
}
#logo1 {
display: inline-block;
margin-right: 1em;
margin-top: -3px;
}
#logo2 {
width: 18%;
margin-bottom: 0.5em;
float: right;
padding-top: -1px;
margin-right: -5px;
}
</style>
<div id='inputwrap' class='form-group' >
<div style='display:flex; justify-content: space-between; align-items:center;'>
<img id='logo1' src='https://widget.ib-cornelsen.de/OEA_WIDGETS/img/IBC-logo.png' alt='IBCornelsen' />
<h5 style='margin-top: 10px;'><b>Erziehlte Conversions von {benutzer.email}</b></h5>
</div>
<input type='text' id='demo' class='form-control' name='demo' value='' placeholder='Bitte Zeitraum auswählen' />
</div>
<AbrechungTable bestellungen={bestellungen} {provisionen} {partnerCodeErstesMal}></AbrechungTable>
<div id="total" class="footer">
<div class="inner">
<div> <div>
<p id="betrag_gesamt">Abrechnungsbetrag gesamt: <b>{provision} €</b></p> <p id="betrag_gesamt">
Abrechnungsbetrag gesamt: <b>{provision} €</b>
</p>
</div> </div>
<a target='_blank' rel='noreferrer noopener' 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> <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>
</div> </div>
</BlankLayout>
<script type="text/javascript">
$('#demo').daterangepicker({
"showDropdowns": true,
"minYear": 2019,
ranges: {
'Heute': [moment(), moment()],
'Gestern': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
'letzte 7 Tage': [moment().subtract(6, 'days'), moment()],
'letzte 30 Tage': [moment().subtract(29, 'days'), moment()],
'dieser Monat': [moment().startOf('month'), moment().endOf('month')],
'letzter Monat': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
},
"locale": {
"format": "DD/MM/YYYY",
"separator": " - ",
"applyLabel": "Übernehmen",
"cancelLabel": "Abrechen",
"fromLabel": "Von",
"toLabel": "Bis",
"customRangeLabel": "Benutzerdefiniert",
"weekLabel": "W",
"daysOfWeek": [
"So",
"Mo",
"Di",
"Mi",
"Do",
"Fr",
"Sa"
],
"monthNames": [
"Januar",
"Februar",
"März",
"April",
"Mai",
"Juni",
"Juli",
"August",
"September",
"Oktober",
"November",
"Dezember"
],
"firstDay": 1
},
"autoUpdateInput": false,
"alwaysShowCalendars": true,
"startDate": "<?php echo $day_start_display; ?>",
"endDate": "<?php echo $day_end_display; ?>",
"minDate": "01/10/2019"
}, function(start, end, label) {
var Pstart = start.format('MM/DD/YYYY');
var Pend = end.format('MM/DD/YYYY');
$("#start").val(Pstart);
$("#end").val(Pend);
$('#FO').submit();
});
// $("#demo").val(`Conversions im Zeitraum: <?php echo $Pall; ?>`);
</script>
<body>
<form id='FO' method='GET' action='index.php'>
<input type="hidden" id="start" name="start" value='' />
<input type="hidden" id="end" name="end" value='' />
</form>
<script>
</script>
</body>
</html>

View File

@@ -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>