Compare commits
1 Commits
UMBE
...
registrier
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc0509cac2 |
@@ -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 }}
|
||||
2
.github/workflows/dev-pipeline.yml
vendored
2
.github/workflows/dev-pipeline.yml
vendored
@@ -28,4 +28,4 @@ jobs:
|
||||
git clean -f -d
|
||||
git pull origin dev
|
||||
git status
|
||||
make prod-no-backup
|
||||
make prod
|
||||
9
.github/workflows/prevent-wrong-pr.yml
vendored
9
.github/workflows/prevent-wrong-pr.yml
vendored
@@ -13,15 +13,18 @@ jobs:
|
||||
steps:
|
||||
- name: Prevent dev merges
|
||||
run: |
|
||||
if [[ "${{ github.head_ref }}" == "dev" && "${{ github.base_ref }}" == "main" ]]; then
|
||||
echo "ERROR: Merging 'dev' into 'main' is forbidden!"
|
||||
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
|
||||
|
||||
6
Makefile
6
Makefile
@@ -59,11 +59,9 @@ all:
|
||||
bun run dev 2>&1 | tee ~/logs/`date '+%d-%m-%Y_%H:%M:%S'`.log
|
||||
|
||||
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" --no-autorestart --cron "0 12 28 * *" -- src/cronjobs/update-dwd-klimafaktoren.ts
|
||||
|
||||
prod: prod-no-backup backup-database-cronjob
|
||||
|
||||
prod-no-backup: install-dependencies prisma-studio update-dwd-klimafaktoren-cron
|
||||
prod: install-dependencies prisma-studio backup-database-cronjob update-dwd-klimafaktoren-cron
|
||||
bun run build
|
||||
mkdir -p ~/logs
|
||||
mkdir -p ~/persistent/online-energieausweis
|
||||
|
||||
3
bun.lock
3
bun.lock
@@ -15,7 +15,6 @@
|
||||
"@pdfme/common": "^5.2.16",
|
||||
"@pdfme/generator": "^5.2.16",
|
||||
"@pdfme/ui": "^5.2.16",
|
||||
"@svelte-plugins/datepicker": "^1.0.11",
|
||||
"@trpc/client": "^10.45.2",
|
||||
"@trpc/server": "^10.45.2",
|
||||
"astro": "^4.16.17",
|
||||
@@ -712,8 +711,6 @@
|
||||
|
||||
"@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-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=="],
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
version: '3'
|
||||
name: database
|
||||
services:
|
||||
database:
|
||||
build: ./
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
"@pdfme/common": "^5.2.16",
|
||||
"@pdfme/generator": "^5.2.16",
|
||||
"@pdfme/ui": "^5.2.16",
|
||||
"@svelte-plugins/datepicker": "^1.0.11",
|
||||
"@trpc/client": "^10.45.2",
|
||||
"@trpc/server": "^10.45.2",
|
||||
"astro": "^4.16.17",
|
||||
|
||||
@@ -3,27 +3,17 @@
|
||||
# === Configuration ===
|
||||
BUCKET_NAME="ibc-db-backup"
|
||||
ENDPOINT_URL="https://s3.eu-central-3.ionoscloud.com"
|
||||
LOCAL_DOWNLOAD_DIR="./" # Where to save the file
|
||||
LOCAL_DOWNLOAD_DIR="./"
|
||||
|
||||
# === Check if a custom file is given as a command line argument ===
|
||||
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
|
||||
# === Use filename from argument if provided ===
|
||||
if [ -n "$1" ]; then
|
||||
LATEST_FILE="$1"
|
||||
else
|
||||
echo "🔍 No custom file provided, searching for latest .sql.br file in S3"
|
||||
|
||||
echo "📡 No filename provided, fetching latest..."
|
||||
# === Get latest file from IONOS S3 bucket ===
|
||||
LATEST_FILE=$(aws s3api list-objects-v2 \
|
||||
LATEST_FILE=$(aws --profile ionos s3api list-objects-v2 \
|
||||
--bucket "$BUCKET_NAME" \
|
||||
--prefix "data-dump" \
|
||||
--prefix "full-dump" \
|
||||
--endpoint-url "$ENDPOINT_URL" \
|
||||
--query 'Contents | sort_by(@, &LastModified) | [-1].Key' \
|
||||
--output text)
|
||||
@@ -33,22 +23,22 @@ else
|
||||
echo "❌ No matching .sql.br file found."
|
||||
exit 1
|
||||
fi
|
||||
echo "🔍 Latest file found: $LATEST_FILE"
|
||||
FILENAME=$(basename "$LATEST_FILE")
|
||||
SQL_FILE="${FILENAME%.br}" # Remove .br suffix
|
||||
|
||||
echo "📥 Downloading $LATEST_FILE"
|
||||
aws s3 cp "s3://$BUCKET_NAME/$LATEST_FILE" "$LOCAL_DOWNLOAD_DIR" \
|
||||
--endpoint-url "$ENDPOINT_URL"
|
||||
fi
|
||||
|
||||
FILENAME=$(basename "$LATEST_FILE")
|
||||
SQL_FILE="${FILENAME%.br}" # Remove .br suffix
|
||||
|
||||
echo "📥 Downloading $LATEST_FILE"
|
||||
aws --profile ionos s3 cp "s3://$BUCKET_NAME/$LATEST_FILE" "$LOCAL_DOWNLOAD_DIR" \
|
||||
--endpoint-url "$ENDPOINT_URL"
|
||||
|
||||
# === Decompress with Brotli ===
|
||||
echo "🗜️ Decompressing $FILENAME -> $SQL_FILE"
|
||||
brotli -d "$FILENAME"
|
||||
|
||||
# === Import into Postgres inside Docker ===
|
||||
echo "🐘 Importing into PostgreSQL (online-energieausweis-database-1:main)"
|
||||
docker exec -i "online-energieausweis-database-1" env PGPASSWORD="hHMP8cd^N3SnzGRR" \
|
||||
echo "🐘 Importing into PostgreSQL (database:main)"
|
||||
docker exec -i "database" env PGPASSWORD="hHMP8cd^N3SnzGRR" \
|
||||
psql -U "main" -d "main" < "$SQL_FILE"
|
||||
|
||||
echo "✅ Import complete."
|
||||
|
||||
@@ -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,13 +13,15 @@ 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"),
|
||||
"auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"),
|
||||
"auth/verification-code": await import("../src/pages/api/auth/verification-code.ts"),
|
||||
"aufnahme": await import("../src/pages/api/aufnahme/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"),
|
||||
"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"),
|
||||
"bilder/[id]": await import("../src/pages/api/bilder/[id].ts"),
|
||||
@@ -26,20 +29,19 @@ export const createCaller = createCallerFactory({
|
||||
"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": 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/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"),
|
||||
"verbrauchsausweis-gewerbe/[id]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[id].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": await import("../src/pages/api/verbrauchsausweis-wohnen/index.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]": await import("../src/pages/api/aufnahme/[id]/index.ts"),
|
||||
"aufnahme/[id]/unterlagen": await import("../src/pages/api/aufnahme/[id]/unterlagen.ts"),
|
||||
"objekt/[id]": await import("../src/pages/api/objekt/[id]/index.ts"),
|
||||
})
|
||||
@@ -1,121 +0,0 @@
|
||||
<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>
|
||||
108
src/components/Abrechnung/AbrechungTable.svelte
Normal file
108
src/components/Abrechnung/AbrechungTable.svelte
Normal file
@@ -0,0 +1,108 @@
|
||||
<script lang="ts">
|
||||
import { BedarfsausweisWohnen, Enums, Rechnung, VerbrauchsausweisGewerbe, VerbrauchsausweisWohnen } from "#lib/server/prisma.js";
|
||||
import moment from "moment";
|
||||
|
||||
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");
|
||||
} -->
|
||||
|
||||
|
||||
<!-- } -->
|
||||
@@ -214,8 +214,8 @@ grid-cols-1 gap-x-2 gap-y-4
|
||||
/>
|
||||
|
||||
<div class="text-center xs:text-left justify-self-stretch">
|
||||
<b>Selbsteingabe online</b><br>inkl. ausführlicher telefonischer
|
||||
Beratung!
|
||||
<b>Verbrauchsausweis online</b><br>inkl. ausführlicher telefonischer
|
||||
Beratung
|
||||
</div>
|
||||
|
||||
<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">
|
||||
<b>Wir übernehmen die Eingabe</b><br>Sie übermitteln die nötigen Unterlagen per Upload oder E-Mail.
|
||||
<b>Verbrauchsausweis offline</b><br>Sie schicken uns 3 Verbrauchsabrechnungen zu)
|
||||
</div>
|
||||
|
||||
<div class="text-center xs:text-right">
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<!-- <a href="/dashboard/abrechnung" class="button ">Monatliche Abrechnung</a> -->
|
||||
<a href="/dashboard/abrechnung" class="button ">Conversions</a>
|
||||
</div>
|
||||
|
||||
<hr class="border-gray-600" />
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
export let hidden: boolean = true;
|
||||
export let closeable: boolean = true;
|
||||
import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock';
|
||||
import { Cross1 } from 'radix-svelte-icons';
|
||||
|
||||
$: if (globalThis.window) {
|
||||
if (hidden) {
|
||||
@@ -13,11 +12,13 @@
|
||||
}
|
||||
</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}>
|
||||
<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={() => {
|
||||
hidden = closeable ? true : hidden;
|
||||
}}>
|
||||
{#if closeable}
|
||||
<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={() => {
|
||||
<button class="absolute top-4 left-4 text-white" on:click={() => {
|
||||
hidden = true;
|
||||
}}><Cross1 size={20}></Cross1></button>
|
||||
}}>Schließen</button>
|
||||
{/if}
|
||||
<slot></slot>
|
||||
</div>
|
||||
@@ -39,38 +39,63 @@ const isNET = pathname.includes("immonet");
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<!-- Navigation als Liste (nur ab sm sichtbar) -->
|
||||
<ul class="navlist hidden xl:flex">
|
||||
<li><a href={`/${partner}/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/`}><button class={tab === 0 ? "glow" : ""}>Verbrauchsausweis</button></a></li>
|
||||
<li><a href={`/${partner}/energieausweis-erstellen/verbrauchsausweis-gewerbe/`}><button class={tab === 1 ? "glow" : ""}>Verbrauchsausweis Gewerbe</button></a></li>
|
||||
<li><a href={`/${partner}/energieausweis-erstellen/bedarfsausweis-wohngebaeude/`}><button class={tab === 2 ? "glow" : ""}>Bedarfsausweis</button></a></li>
|
||||
<li><a href={`/${partner}/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/`}><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>
|
||||
|
||||
<!-- Navigation als Dropdown (nur bis sm sichtbar) -->
|
||||
<select
|
||||
class="xl:hidden border rounded p-2 w-[calc(100%-2rem)]"
|
||||
onchange="if (this.value) window.location.href=this.value"
|
||||
>
|
||||
<option value="">Auswahl treffen…</option>
|
||||
<option value={`/${partner}/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/`} selected={tab === 0}>Verbrauchsausweis</option>
|
||||
<option value={`/${partner}/energieausweis-erstellen/verbrauchsausweis-gewerbe/`} selected={tab === 1}>Verbrauchsausweis Gewerbe</option>
|
||||
<option value={`/${partner}/energieausweis-erstellen/bedarfsausweis-wohngebaeude/`} selected={tab === 2}>Bedarfsausweis</option>
|
||||
<option value={`/${partner}/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/`} selected={tab === 3}>Bedarfsausweis Gewerbe</option>
|
||||
<option value={`/${partner}/angebot-anfragen/geg-nachweis-wohnen-anfragen/`} selected={tab === 4}>GEG Nachweis Wohngebäude</option>
|
||||
<option value={`/${partner}/angebot-anfragen/geg-nachweis-gewerbe-anfragen/`} selected={tab === 5}>GEG Nachweis Gewerbe</option>
|
||||
<option value={`/${partner}/welcher-ausweis/${partner}`} selected={tab === 6}>Welcher Ausweis</option>
|
||||
</select>
|
||||
<ul class="navlist">
|
||||
<li>
|
||||
<a
|
||||
href={`/${partner}/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/`}
|
||||
><button class={tab === 0 ? "glow" : ""}
|
||||
>Verbrauchsausweis</button
|
||||
></a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href={`/${partner}/energieausweis-erstellen/verbrauchsausweis-gewerbe/`}
|
||||
><button class={tab === 1 ? "glow" : ""}
|
||||
>Verbrauchsausweis Gewerbe</button
|
||||
></a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href={`/${partner}/energieausweis-erstellen/bedarfsausweis-wohngebaeude/`}
|
||||
><button class={tab === 2 ? "glow" : ""}
|
||||
>Bedarfsausweis</button
|
||||
></a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href={`/${partner}/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/`}
|
||||
><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>
|
||||
</header>
|
||||
|
||||
<div
|
||||
id="titel"
|
||||
class="block w-full lg:h-[270px] bg-cover !px-8 md:px-32 !py-8 md:py-16"
|
||||
class="block w-full 2xl:h-[270px] lg:h-[148px] bg-cover px-24 py-20"
|
||||
style={`background-image: url('/images/partner/${partner}/hero-energieausweis.jpg');
|
||||
background-repeat:no-repeat; background-position:right;`}
|
||||
>
|
||||
@@ -161,7 +186,7 @@ background-repeat:no-repeat; background-position:right;`}
|
||||
font-family: "immo Sans";
|
||||
font-weight:400;
|
||||
|
||||
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);}
|
||||
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);}
|
||||
}
|
||||
|
||||
.header-button {
|
||||
|
||||
@@ -1,72 +1,68 @@
|
||||
<script lang="ts">
|
||||
import { fade } from "svelte/transition";
|
||||
import WidgetCardTemplate from "#components/widgets/immowelt/WidgetCardTemplate.svelte";
|
||||
import { PRICES } from "#lib/constants.js";
|
||||
import { Enums } from "#lib/client/prisma";
|
||||
import { Enums } from "#lib/client/prisma.js";
|
||||
|
||||
|
||||
let ausnahme: boolean = false;
|
||||
let oneBOX: boolean = false;
|
||||
let threeBOX: boolean = false;
|
||||
|
||||
let gebaeudetyp: string = "bitte auswählen";
|
||||
let anlass: string = "bitte auswählen";
|
||||
let einheiten: string = "bitte auswählen";
|
||||
let sanierungsstatus: string = "bitte auswählen";
|
||||
let baujahr: string = "bitte auswählen";
|
||||
let heizungsAlter: string = "bitte auswählen";
|
||||
let leerStand: string = "bitte auswählen";
|
||||
let threeBOX: boolean = false;
|
||||
|
||||
const partner:string = "immowelt";
|
||||
let gebaeudetyp: string = "bitte auswählen";
|
||||
let anlass: string = "bitte auswählen";
|
||||
let einheiten: string = "bitte auswählen";
|
||||
let sanierungsstatus: string = "bitte auswählen";
|
||||
let baujahr: string = "bitte auswählen";
|
||||
let heizungsAlter: string = "bitte auswählen";
|
||||
let leerStand: string = "bitte auswählen";
|
||||
|
||||
const twoBoxReason = ["Vermietung/Verkauf", "Aushangpflicht", "Sonstiges"];
|
||||
const gewerbeHouse = ["Gewerbegebäude", "Mischgebäude"];
|
||||
const partner: string = "immowelt";
|
||||
|
||||
$: ausnahme =
|
||||
leerStand === "mehr als 30" ||
|
||||
heizungsAlter === "< 3" ||
|
||||
(baujahr === "vor 1978" && einheiten === "bis 4 Wohneinheiten" && sanierungsstatus === "unsaniert");
|
||||
const twoBoxReason = ["Vermietung/Verkauf", "Aushangpflicht", "Sonstiges"];
|
||||
const gewerbeHouse = ["Gewerbegebäude", "Mischgebäude"];
|
||||
|
||||
$: isTwoBoxReason = twoBoxReason.includes(anlass);
|
||||
$: ausnahme =
|
||||
leerStand === "mehr als 30" ||
|
||||
heizungsAlter === "< 3" ||
|
||||
(baujahr === "vor 1978" &&
|
||||
einheiten === "bis 4 Wohneinheiten" &&
|
||||
sanierungsstatus === "unsaniert");
|
||||
|
||||
$: isGewerbe = gewerbeHouse.includes(gebaeudetyp);
|
||||
$: isTwoBoxReason = twoBoxReason.includes(anlass);
|
||||
|
||||
$: oneBOX =
|
||||
(ausnahme && !isGewerbe) ||
|
||||
(!isTwoBoxReason && gebaeudetyp !== "Mischgebäude") ||
|
||||
(gebaeudetyp === "Gewerbegebäude" && leerStand === "mehr als 30");
|
||||
$: isGewerbe = gewerbeHouse.includes(gebaeudetyp);
|
||||
|
||||
$: threeBOX =
|
||||
(ausnahme && gebaeudetyp === "Mischgebäude" && isTwoBoxReason && leerStand !== "mehr als 30");
|
||||
$: oneBOX =
|
||||
(ausnahme && !isGewerbe) ||
|
||||
(!isTwoBoxReason && gebaeudetyp !== "Mischgebäude") ||
|
||||
(gebaeudetyp === "Gewerbegebäude" && leerStand === "mehr als 30");
|
||||
|
||||
$: standardXL =
|
||||
(einheiten === "mehr als 4 Wohneinheiten")
|
||||
$: threeBOX =
|
||||
ausnahme &&
|
||||
gebaeudetyp === "Mischgebäude" &&
|
||||
isTwoBoxReason &&
|
||||
leerStand !== "mehr als 30";
|
||||
|
||||
$: standardXL = einheiten === "mehr als 4 Wohneinheiten";
|
||||
</script>
|
||||
|
||||
|
||||
<div id="IBC_app">
|
||||
|
||||
<input id="recode" type="hidden" value="widgetvorlage" />
|
||||
|
||||
<div id="OEA_input">
|
||||
|
||||
|
||||
<div id="firstrow" class="firstrow"
|
||||
class:sm:grid-cols-3={isTwoBoxReason}
|
||||
class:sm:grid-cols-2={!isTwoBoxReason}>
|
||||
|
||||
|
||||
|
||||
<div
|
||||
id="firstrow"
|
||||
class="firstrow"
|
||||
class:sm:grid-cols-3={isTwoBoxReason}
|
||||
class:sm:grid-cols-2={!isTwoBoxReason}
|
||||
>
|
||||
<div class="auswahl">
|
||||
<div class="titel">Anlass</div>
|
||||
<select
|
||||
id="anlass"
|
||||
class="selectfeld"
|
||||
bind:value={anlass}>
|
||||
>
|
||||
<select id="anlass" class="selectfeld" bind:value={anlass}>
|
||||
>
|
||||
<option selected disabled>bitte auswählen</option>
|
||||
<option value="Vermietung/Verkauf">Vermietung/Verkauf</option>
|
||||
<option value="Vermietung/Verkauf"
|
||||
>Vermietung/Verkauf</option
|
||||
>
|
||||
<option value="Modernisierung">Modernisierung</option>
|
||||
<option value="Neubau">Neubau</option>
|
||||
<option value="Erweiterung">Erweiterung</option>
|
||||
@@ -77,10 +73,8 @@ $: standardXL =
|
||||
|
||||
<div class="auswahl">
|
||||
<div class="titel">Gebäudetyp</div>
|
||||
<select
|
||||
class="selectfeld"
|
||||
bind:value={gebaeudetyp}>
|
||||
>
|
||||
<select class="selectfeld" bind:value={gebaeudetyp}>
|
||||
>
|
||||
<option selected disabled>bitte auswählen</option>
|
||||
<option value="Einfamilienhaus">Einfamilienhaus</option>
|
||||
<option value="Zweifamilienhaus">Zweifamilienhaus</option>
|
||||
@@ -91,97 +85,94 @@ $: standardXL =
|
||||
</div>
|
||||
|
||||
{#if isTwoBoxReason}
|
||||
<div class="auswahl">
|
||||
<div class="titel">Sanierungsstand</div>
|
||||
<select
|
||||
class="selectfeld"
|
||||
bind:value={sanierungsstatus}>
|
||||
|
||||
>
|
||||
<option selected disabled>bitte auswählen</option>
|
||||
<option value="saniert">saniert</option>
|
||||
<option value="unsaniert">unsaniert</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="auswahl">
|
||||
<div class="titel">Sanierungsstand</div>
|
||||
<select class="selectfeld" bind:value={sanierungsstatus}>
|
||||
>
|
||||
<option selected disabled>bitte auswählen</option>
|
||||
<option value="saniert">saniert</option>
|
||||
<option value="unsaniert">unsaniert</option>
|
||||
</select>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
|
||||
{#if isTwoBoxReason}
|
||||
<div id="secondrow" class="secondrow">
|
||||
<div class="auswahl">
|
||||
<div class="titel">Baujahr</div>
|
||||
<select
|
||||
id="baujahr"
|
||||
class="selectfeld"
|
||||
bind:value={baujahr}
|
||||
|
||||
>
|
||||
<option selected disabled>bitte auswählen</option>
|
||||
<option value="vor 1978">vor 1978</option>
|
||||
<option value="nach 1977">nach 1977</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="secondrow" class="secondrow">
|
||||
<div class="auswahl">
|
||||
<div class="titel">Baujahr</div>
|
||||
<select
|
||||
id="baujahr"
|
||||
class="selectfeld"
|
||||
bind:value={baujahr}
|
||||
>
|
||||
<option selected disabled>bitte auswählen</option>
|
||||
<option value="vor 1978">vor 1978</option>
|
||||
<option value="nach 1977">nach 1977</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="auswahl">
|
||||
<div class="titel">Heizungsalter</div>
|
||||
<select
|
||||
class="selectfeld"
|
||||
bind:value={heizungsAlter}
|
||||
>
|
||||
<select class="selectfeld" bind:value={heizungsAlter}>
|
||||
<option selected disabled>bitte auswählen</option>
|
||||
<option value="< 3">jünger als 3 Jahre</option>
|
||||
<option value=">= 3">3 Jahre oder älter</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="auswahl">
|
||||
<div class="titel">Wohneinheiten</div>
|
||||
<select
|
||||
class="selectfeld"
|
||||
bind:value={einheiten}
|
||||
>
|
||||
<option selected disabled>bitte auswählen</option>
|
||||
<option value="bis 4 Wohneinheiten"
|
||||
>bis 4 Wohneinheiten</option
|
||||
>
|
||||
<option value="mehr als 4 Wohneinheiten"
|
||||
>mehr als 4 Wohneinheiten</option
|
||||
>
|
||||
</select>
|
||||
</div>
|
||||
<div class="auswahl">
|
||||
<div class="titel">Wohneinheiten</div>
|
||||
<select class="selectfeld" bind:value={einheiten}>
|
||||
<option selected disabled>bitte auswählen</option>
|
||||
<option value="bis 4 Wohneinheiten"
|
||||
>bis 4 Wohneinheiten</option
|
||||
>
|
||||
<option value="mehr als 4 Wohneinheiten"
|
||||
>mehr als 4 Wohneinheiten</option
|
||||
>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="OEA_item4">
|
||||
<div class="titel">Leerstand</div>
|
||||
<select
|
||||
class="selectfeld ausnahmen"
|
||||
bind:value={leerStand}
|
||||
>
|
||||
<option selected disabled>bitte auswählen</option>
|
||||
<option value="bis 30">bis 30%</option>
|
||||
<option value="mehr als 30">mehr als 30%</option>
|
||||
</select>
|
||||
<div class="OEA_item4">
|
||||
<div class="titel">Leerstand</div>
|
||||
<select class="selectfeld ausnahmen" bind:value={leerStand}>
|
||||
<option selected disabled>bitte auswählen</option>
|
||||
<option value="bis 30">bis 30%</option>
|
||||
<option value="mehr als 30">mehr als 30%</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div id="thirdrow" class="thirdrow"
|
||||
class:grid-cols-1={oneBOX}
|
||||
class:md:grid-cols-6={threeBOX}
|
||||
class:md:grid-cols-4={!oneBOX && !threeBOX}
|
||||
>
|
||||
|
||||
|
||||
{#if isTwoBoxReason && (gebaeudetyp != "Gewerbegebäude") && (ausnahme === false)}
|
||||
|
||||
|
||||
<div
|
||||
id="thirdrow"
|
||||
class="thirdrow"
|
||||
class:grid-cols-1={oneBOX}
|
||||
class:md:grid-cols-6={threeBOX}
|
||||
class:md:grid-cols-4={!oneBOX && !threeBOX}
|
||||
>
|
||||
{#if isTwoBoxReason && gebaeudetyp != "Gewerbegebäude" && ausnahme === false}
|
||||
<WidgetCardTemplate
|
||||
name="Verbrauchsausweis Wohngebäude"
|
||||
price = {PRICES.VerbrauchsausweisWohnen[standardXL ? Enums.AusweisTyp.standardXL : Enums.AusweisTyp.Standard]}
|
||||
price1 = {PRICES.VerbrauchsausweisWohnen[standardXL ? Enums.AusweisTyp.BeratungXL : Enums.AusweisTyp.Beratung]}
|
||||
price2 = {PRICES.VerbrauchsausweisWohnen[standardXL ? Enums.AusweisTyp.OfflineXL : Enums.AusweisTyp.Offline]}
|
||||
|
||||
src={'https://online-energieausweis.org/images/partner/'+partner+'/wohngebaeude.svg'}
|
||||
price={PRICES.VerbrauchsausweisWohnen[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.standardXL
|
||||
: Enums.AusweisTyp.Standard
|
||||
]}
|
||||
price1={PRICES.VerbrauchsausweisWohnen[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.BeratungXL
|
||||
: Enums.AusweisTyp.Beratung
|
||||
]}
|
||||
price2={PRICES.VerbrauchsausweisWohnen[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.OfflineXL
|
||||
: Enums.AusweisTyp.Offline
|
||||
]}
|
||||
src={"https://online-energieausweis.org/images/partner/" +
|
||||
partner +
|
||||
"/wohngebaeude.svg"}
|
||||
alt="Wohnhaus Verbrauchsausweis"
|
||||
variant="einfach"
|
||||
empfehlung="nein"
|
||||
@@ -189,27 +180,40 @@ $: standardXL =
|
||||
services={[
|
||||
["3 Jahresverbräuche der Heizung benötigt.", true],
|
||||
["Zulässig bei Vermietung oder Verkauf.", true],
|
||||
["Unzulässig bei unsanierten Gebäuden vor 1978.", false],
|
||||
[
|
||||
"Unzulässig bei unsanierten Gebäuden vor 1978.",
|
||||
false,
|
||||
],
|
||||
["Ungenau durch individuelles Heizverhalten.", false],
|
||||
["Wird nicht immer bei den Banken akzeptiert.", false]
|
||||
["Wird nicht immer bei den Banken akzeptiert.", false],
|
||||
]}
|
||||
|
||||
href_buy1={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/${standardXL ? '?ausweistyp=standardXL' : ''}`}
|
||||
href_buy2={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/${standardXL ? '?ausweistyp=BeratungXL' : '?ausweistyp=Beratung'}`}
|
||||
href_buy3={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/${standardXL ? '?ausweistyp=OfflineXL' : '?ausweistyp=Offline'}`}
|
||||
|
||||
></WidgetCardTemplate>
|
||||
|
||||
href_buy1={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/${standardXL ? "?ausweistyp=standardXL" : ""}`}
|
||||
href_buy2={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/${standardXL ? "?ausweistyp=BeratungXL" : "?ausweistyp=Beratung"}`}
|
||||
href_buy3={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/${standardXL ? "?ausweistyp=OfflineXL" : "?ausweistyp=Offline"}`}
|
||||
></WidgetCardTemplate>
|
||||
{/if}
|
||||
|
||||
{#if isTwoBoxReason && (gebaeudetyp != "Gewerbegebäude")}
|
||||
|
||||
{#if isTwoBoxReason && gebaeudetyp != "Gewerbegebäude"}
|
||||
<WidgetCardTemplate
|
||||
name="Bedarfsausweis Wohngebäude"
|
||||
price = {PRICES.BedarfsausweisWohnen[standardXL ? Enums.AusweisTyp.standardXL : Enums.AusweisTyp.Standard]}
|
||||
price1 = {PRICES.BedarfsausweisWohnen[standardXL ? Enums.AusweisTyp.BeratungXL : Enums.AusweisTyp.Beratung]}
|
||||
price2 = {PRICES.BedarfsausweisWohnen[standardXL ? Enums.AusweisTyp.OfflineXL : Enums.AusweisTyp.Offline]}
|
||||
src={'https://online-energieausweis.org/images/partner/'+partner+'/wohngebaeude.svg'}
|
||||
price={PRICES.BedarfsausweisWohnen[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.standardXL
|
||||
: Enums.AusweisTyp.Standard
|
||||
]}
|
||||
price1={PRICES.BedarfsausweisWohnen[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.BeratungXL
|
||||
: Enums.AusweisTyp.Beratung
|
||||
]}
|
||||
price2={PRICES.BedarfsausweisWohnen[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.OfflineXL
|
||||
: Enums.AusweisTyp.Offline
|
||||
]}
|
||||
src={"https://online-energieausweis.org/images/partner/" +
|
||||
partner +
|
||||
"/wohngebaeude.svg"}
|
||||
alt="Wohnhaus Bedarfsausweis"
|
||||
variant="fundiert"
|
||||
empfehlung="ja"
|
||||
@@ -219,200 +223,283 @@ $: standardXL =
|
||||
["Für Vermietung, Verkauf und Finanzierung.", true],
|
||||
["Zulässig auch für unsanierte Objekte.", true],
|
||||
["Kann als Grundlage für den ISFP dienen.", true],
|
||||
["Objektivere Berechnungsmethode nach DIN 18599.", true],
|
||||
[
|
||||
"Objektivere Berechnungsmethode nach DIN 18599.",
|
||||
true,
|
||||
],
|
||||
]}
|
||||
|
||||
href_buy1={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/bedarfsausweis-wohngebaeude/${standardXL ? '?ausweistyp=standardXL' : ''}`}
|
||||
href_buy2={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/bedarfsausweis-wohngebaeude/${standardXL ? '?ausweistyp=BeratungXL' : '?ausweistyp=Beratung'}`}
|
||||
href_buy3={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/bedarfsausweis-wohngebaeude/${standardXL ? '?ausweistyp=OfflineXL' : '?ausweistyp=Offline'}`}
|
||||
|
||||
href_buy1={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/bedarfsausweis-wohngebaeude/${standardXL ? "?ausweistyp=standardXL" : ""}`}
|
||||
href_buy2={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/bedarfsausweis-wohngebaeude/${standardXL ? "?ausweistyp=BeratungXL" : "?ausweistyp=Beratung"}`}
|
||||
href_buy3={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/bedarfsausweis-wohngebaeude/${standardXL ? "?ausweistyp=OfflineXL" : "?ausweistyp=Offline"}`}
|
||||
></WidgetCardTemplate>
|
||||
|
||||
{/if}
|
||||
|
||||
{#if isTwoBoxReason && isGewerbe && (leerStand != "mehr als 30")}
|
||||
|
||||
{#if isTwoBoxReason && isGewerbe && leerStand != "mehr als 30"}
|
||||
<WidgetCardTemplate
|
||||
name="Verbrauchsausweis Gewerbegebäude"
|
||||
price = {PRICES.VerbrauchsausweisGewerbe[standardXL ? Enums.AusweisTyp.standardXL : Enums.AusweisTyp.Standard]}
|
||||
price1 = {PRICES.VerbrauchsausweisGewerbe[standardXL ? Enums.AusweisTyp.BeratungXL : Enums.AusweisTyp.Beratung]}
|
||||
price2 = {PRICES.VerbrauchsausweisGewerbe[standardXL ? Enums.AusweisTyp.OfflineXL : Enums.AusweisTyp.Offline]}
|
||||
src={'https://online-energieausweis.org/images/partner/'+partner+'/gewerbegebaeude.svg'}
|
||||
price={PRICES.VerbrauchsausweisGewerbe[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.standardXL
|
||||
: Enums.AusweisTyp.Standard
|
||||
]}
|
||||
price1={PRICES.VerbrauchsausweisGewerbe[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.BeratungXL
|
||||
: Enums.AusweisTyp.Beratung
|
||||
]}
|
||||
price2={PRICES.VerbrauchsausweisGewerbe[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.OfflineXL
|
||||
: Enums.AusweisTyp.Offline
|
||||
]}
|
||||
src={"https://online-energieausweis.org/images/partner/" +
|
||||
partner +
|
||||
"/gewerbegebaeude.svg"}
|
||||
alt="Gewerbe Verbrauchsausweis"
|
||||
variant="einfach"
|
||||
empfehlung="nein"
|
||||
cta="jetzt online erstellen"
|
||||
cta="jetzt online erstellen"
|
||||
services={[
|
||||
|
||||
["3 Jahresverbräuche von Heizung Gebäudestrom nötig.", true],
|
||||
[
|
||||
"3 Jahresverbräuche von Heizung Gebäudestrom nötig.",
|
||||
true,
|
||||
],
|
||||
["Zulässig bei Vermietung oder Verkauf.", true],
|
||||
["Für bauliche und energetische Maßnahmen ungeeignet.", false],
|
||||
[
|
||||
"Für bauliche und energetische Maßnahmen ungeeignet.",
|
||||
false,
|
||||
],
|
||||
["Wird nicht immer bei den Banken akzeptiert.", false],
|
||||
["Ungenau durch individuelles Heizverhalten", false],
|
||||
["Ungenau durch individuelles Heizverhalten", false],
|
||||
]}
|
||||
|
||||
href_buy1={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-gewerbe/${standardXL ? '?ausweistyp=standardXL' : ''}`}
|
||||
href_buy2={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-gewerbe/${standardXL ? '?ausweistyp=BeratungXL' : '?ausweistyp=Beratung'}`}
|
||||
href_buy3={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-gewerbe/${standardXL ? '?ausweistyp=OfflineXL' : '?ausweistyp=Offline'}`}
|
||||
href_buy1={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-gewerbe/${standardXL ? "?ausweistyp=standardXL" : ""}`}
|
||||
href_buy2={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-gewerbe/${standardXL ? "?ausweistyp=BeratungXL" : "?ausweistyp=Beratung"}`}
|
||||
href_buy3={`https://online-energieausweis.org/${partner}/energieausweis-erstellen/verbrauchsausweis-gewerbe/${standardXL ? "?ausweistyp=OfflineXL" : "?ausweistyp=Offline"}`}
|
||||
></WidgetCardTemplate>
|
||||
|
||||
{/if}
|
||||
|
||||
{#if isTwoBoxReason && isGewerbe}
|
||||
|
||||
<WidgetCardTemplate
|
||||
name="Bedarfsausweis Gewerbegebäude"
|
||||
price = {PRICES.BedarfsausweisGewerbe[standardXL ? Enums.AusweisTyp.standardXL : Enums.AusweisTyp.Standard]}
|
||||
price1 = {PRICES.BedarfsausweisGewerbe[standardXL ? Enums.AusweisTyp.BeratungXL : Enums.AusweisTyp.Beratung]}
|
||||
price2 = {PRICES.BedarfsausweisGewerbe[standardXL ? Enums.AusweisTyp.OfflineXL : Enums.AusweisTyp.Offline]}
|
||||
src={'https://online-energieausweis.org/images/partner/'+partner+'/gewerbegebaeude.svg'}
|
||||
price={PRICES.BedarfsausweisGewerbe[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.standardXL
|
||||
: Enums.AusweisTyp.Standard
|
||||
]}
|
||||
price1={PRICES.BedarfsausweisGewerbe[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.BeratungXL
|
||||
: Enums.AusweisTyp.Beratung
|
||||
]}
|
||||
price2={PRICES.BedarfsausweisGewerbe[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.OfflineXL
|
||||
: Enums.AusweisTyp.Offline
|
||||
]}
|
||||
src={"https://online-energieausweis.org/images/partner/" +
|
||||
partner +
|
||||
"/gewerbegebaeude.svg"}
|
||||
alt="Gewerbe Bedarfsausweis"
|
||||
variant="fundiert"
|
||||
empfehlung="ja"
|
||||
cta="Angebot anfragen"
|
||||
services={[
|
||||
|
||||
["Mehrzonenmodell nach DIN 18599.", true],
|
||||
["Zulässig bei Vermietung oder Verkauf.", true],
|
||||
["Grundlage für Sanierung-Varianten.", true],
|
||||
["Objektiveres, besser vergleichbares Ergebnis.", true],
|
||||
["Zulässig bei Leerstand oder fehlenden Verbräuchen", true],
|
||||
[
|
||||
"Zulässig bei Leerstand oder fehlenden Verbräuchen",
|
||||
true,
|
||||
],
|
||||
]}
|
||||
|
||||
href_buy1={`https://online-energieausweis.org/${partner}/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/${standardXL ? '?ausweistyp=standardXL' : ''}`}
|
||||
href_buy2={`https://online-energieausweis.org/${partner}/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/${standardXL ? '?ausweistyp=BeratungXL' : '?ausweistyp=Beratung'}`}
|
||||
|
||||
href_buy1={`https://online-energieausweis.org/${partner}/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/${standardXL ? "?ausweistyp=standardXL" : ""}`}
|
||||
href_buy2={`https://online-energieausweis.org/${partner}/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/${standardXL ? "?ausweistyp=BeratungXL" : "?ausweistyp=Beratung"}`}
|
||||
></WidgetCardTemplate>
|
||||
|
||||
{/if}
|
||||
|
||||
{#if (anlass != "bitte auswählen") && !isTwoBoxReason && (gebaeudetyp != "Gewerbegebäude")}
|
||||
|
||||
<WidgetCardTemplate
|
||||
name="GEG-Nachweis Wohngebäude"
|
||||
price = {PRICES.GEGNachweisWohnen[standardXL ? Enums.AusweisTyp.standardXL : Enums.AusweisTyp.Standard]}
|
||||
price1 = {PRICES.GEGNachweisWohnen[standardXL ? Enums.AusweisTyp.BeratungXL : Enums.AusweisTyp.Beratung]}
|
||||
price2 = {PRICES.GEGNachweisWohnen[standardXL ? Enums.AusweisTyp.OfflineXL : Enums.AusweisTyp.Offline]}
|
||||
src={'https://online-energieausweis.org/images/partner/'+partner+'/wohngebaeude.svg'}
|
||||
alt="GEG-Nachweis-Wohnen"
|
||||
variant="Bauvorlage"
|
||||
empfehlung="ja"
|
||||
cta="Angebot anfragen"
|
||||
services={[
|
||||
|
||||
["Nachweis fürs Bauamt bei Neubau oder Modernisierung.", true],
|
||||
["Beinhaltet die Effizienz der Bauteile und Anlagentechnik.", true],
|
||||
["Erstellung des Energieausweises nach Abschluss inklusive.", true],
|
||||
["Berechnung und Bilanzierung nach aktueller DIN 18599.", true],
|
||||
["Zonierung und Erstellung eines 3D Gebäudemodells.", true],
|
||||
]}
|
||||
|
||||
href_buy1={`https://online-energieausweis.org/${partner}/angebot-anfragen/geg-nachweis-wohnen-anfragen/${standardXL ? '?ausweistyp=standardXL' : ''}`}
|
||||
href_buy2={`https://online-energieausweis.org/${partner}/angebot-anfragen/geg-nachweis-wohnen-anfragen/${standardXL ? '?ausweistyp=BeratungXL' : '?ausweistyp=Beratung'}`}
|
||||
|
||||
|
||||
></WidgetCardTemplate>
|
||||
|
||||
{#if anlass != "bitte auswählen" && !isTwoBoxReason && gebaeudetyp != "Gewerbegebäude"}
|
||||
<WidgetCardTemplate
|
||||
name="GEG-Nachweis Wohngebäude"
|
||||
price={PRICES.GEGNachweisWohnen[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.standardXL
|
||||
: Enums.AusweisTyp.Standard
|
||||
]}
|
||||
price1={PRICES.GEGNachweisWohnen[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.BeratungXL
|
||||
: Enums.AusweisTyp.Beratung
|
||||
]}
|
||||
price2={PRICES.GEGNachweisWohnen[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.OfflineXL
|
||||
: Enums.AusweisTyp.Offline
|
||||
]}
|
||||
src={"https://online-energieausweis.org/images/partner/" +
|
||||
partner +
|
||||
"/wohngebaeude.svg"}
|
||||
alt="GEG-Nachweis-Wohnen"
|
||||
variant="Bauvorlage"
|
||||
empfehlung="ja"
|
||||
cta="Angebot anfragen"
|
||||
services={[
|
||||
[
|
||||
"Nachweis fürs Bauamt bei Neubau oder Modernisierung.",
|
||||
true,
|
||||
],
|
||||
[
|
||||
"Beinhaltet die Effizienz der Bauteile und Anlagentechnik.",
|
||||
true,
|
||||
],
|
||||
[
|
||||
"Erstellung des Energieausweises nach Abschluss inklusive.",
|
||||
true,
|
||||
],
|
||||
[
|
||||
"Berechnung und Bilanzierung nach aktueller DIN 18599.",
|
||||
true,
|
||||
],
|
||||
[
|
||||
"Zonierung und Erstellung eines 3D Gebäudemodells.",
|
||||
true,
|
||||
],
|
||||
]}
|
||||
href_buy1={`https://online-energieausweis.org/${partner}/angebot-anfragen/geg-nachweis-wohnen-anfragen/${standardXL ? "?ausweistyp=standardXL" : ""}`}
|
||||
href_buy2={`https://online-energieausweis.org/${partner}/angebot-anfragen/geg-nachweis-wohnen-anfragen/${standardXL ? "?ausweistyp=BeratungXL" : "?ausweistyp=Beratung"}`}
|
||||
></WidgetCardTemplate>
|
||||
{/if}
|
||||
|
||||
{#if (anlass != "bitte auswählen") && !isTwoBoxReason && isGewerbe}
|
||||
|
||||
<WidgetCardTemplate
|
||||
name="GEG-Nachweis Gewerbegebäude"
|
||||
price = {PRICES.GEGNachweisGewerbe[standardXL ? Enums.AusweisTyp.standardXL : Enums.AusweisTyp.Standard]}
|
||||
price1 = {PRICES.GEGNachweisGewerbe[standardXL ? Enums.AusweisTyp.BeratungXL : Enums.AusweisTyp.Beratung]}
|
||||
price2 = {PRICES.GEGNachweisGewerbe[standardXL ? Enums.AusweisTyp.OfflineXL : Enums.AusweisTyp.Offline]}
|
||||
src={'https://online-energieausweis.org/images/partner/'+partner+'/gewerbegebaeude.svg'}
|
||||
alt="GEG-Nachweis-Gewerbe"
|
||||
variant="Bauvorlage"
|
||||
empfehlung="ja"
|
||||
cta="Angebot anfragen"
|
||||
services={[
|
||||
|
||||
["Nachweis fürs Bauamt bei Neubau oder Modernisierung.", true],
|
||||
["Beinhaltet die Effizienz der Bauteile und Anlagentechnik.", true],
|
||||
["Erstellung des Energieausweises nach Abschluss inklusive.", true],
|
||||
["Berechnung und Bilanzierung nach aktueller DIN 18599.", true],
|
||||
["Mehrzonenmodell inkl. Erstellung eines 3D Gebäudemodells.", true],
|
||||
]}
|
||||
|
||||
href_buy1={`https://online-energieausweis.org/${partner}/angebot-anfragen/geg-nachweis-gewerbe-anfragen/${standardXL ? '?ausweistyp=standardXL' : ''}`}
|
||||
href_buy2={`https://online-energieausweis.org/${partner}/angebot-anfragen/geg-nachweis-gewerbe-anfragen/${standardXL ? '?ausweistyp=BeratungXL' : '?ausweistyp=Beratung'}`}
|
||||
|
||||
></WidgetCardTemplate>
|
||||
|
||||
{#if anlass != "bitte auswählen" && !isTwoBoxReason && isGewerbe}
|
||||
<WidgetCardTemplate
|
||||
name="GEG-Nachweis Gewerbegebäude"
|
||||
price={PRICES.GEGNachweisGewerbe[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.standardXL
|
||||
: Enums.AusweisTyp.Standard
|
||||
]}
|
||||
price1={PRICES.GEGNachweisGewerbe[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.BeratungXL
|
||||
: Enums.AusweisTyp.Beratung
|
||||
]}
|
||||
price2={PRICES.GEGNachweisGewerbe[
|
||||
standardXL
|
||||
? Enums.AusweisTyp.OfflineXL
|
||||
: Enums.AusweisTyp.Offline
|
||||
]}
|
||||
src={"https://online-energieausweis.org/images/partner/" +
|
||||
partner +
|
||||
"/gewerbegebaeude.svg"}
|
||||
alt="GEG-Nachweis-Gewerbe"
|
||||
variant="Bauvorlage"
|
||||
empfehlung="ja"
|
||||
cta="Angebot anfragen"
|
||||
services={[
|
||||
[
|
||||
"Nachweis fürs Bauamt bei Neubau oder Modernisierung.",
|
||||
true,
|
||||
],
|
||||
[
|
||||
"Beinhaltet die Effizienz der Bauteile und Anlagentechnik.",
|
||||
true,
|
||||
],
|
||||
[
|
||||
"Erstellung des Energieausweises nach Abschluss inklusive.",
|
||||
true,
|
||||
],
|
||||
[
|
||||
"Berechnung und Bilanzierung nach aktueller DIN 18599.",
|
||||
true,
|
||||
],
|
||||
[
|
||||
"Mehrzonenmodell inkl. Erstellung eines 3D Gebäudemodells.",
|
||||
true,
|
||||
],
|
||||
]}
|
||||
href_buy1={`https://online-energieausweis.org/${partner}/angebot-anfragen/geg-nachweis-gewerbe-anfragen/${standardXL ? "?ausweistyp=standardXL" : ""}`}
|
||||
href_buy2={`https://online-energieausweis.org/${partner}/angebot-anfragen/geg-nachweis-gewerbe-anfragen/${standardXL ? "?ausweistyp=BeratungXL" : "?ausweistyp=Beratung"}`}
|
||||
></WidgetCardTemplate>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<style lang="postcss">
|
||||
#IBC_app {
|
||||
@font-face {
|
||||
font-family: "immo Sans";
|
||||
src: url("/fonts/Immo-Sans/immoSans-Regular.eot");
|
||||
src:
|
||||
url("/fonts/Immo-Sans/immoSans-Regular.eot?#iefix")
|
||||
format("embedded-opentype"),
|
||||
url("/fonts/Immo-Sans/immoSans-Regular.woff2") format("woff2"),
|
||||
url("/fonts/Immo-Sans/immoSans-Regular.woff") format("woff");
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
#IBC_app {
|
||||
@font-face {
|
||||
font-family: "immo Sans Bold";
|
||||
src: url("/fonts/Immo-Sans/immoSans-Bold.eot");
|
||||
src:
|
||||
url("/fonts/Immo-Sans/immoSans-Bold.eot?#iefix")
|
||||
format("embedded-opentype"),
|
||||
url("../../Fonts/Immo-Sans/immoSans-Bold.woff2") format("woff2"),
|
||||
url("../../Fonts/Immo-Sans/immoSans-Bold.woff") format("woff");
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "immo Sans";
|
||||
src: url('/fonts/Immo-Sans/immoSans-Regular.eot');
|
||||
src: url('/fonts/Immo-Sans/immoSans-Regular.eot?#iefix') format('embedded-opentype'),
|
||||
url('/fonts/Immo-Sans/immoSans-Regular.woff2') format('woff2'),
|
||||
url('/fonts/Immo-Sans/immoSans-Regular.woff') format('woff');
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Antique Olive Compact bold";
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
src: url("/fonts/Antique Olive Std Compact.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "immo Sans Bold";
|
||||
src: url('/fonts/Immo-Sans/immoSans-Bold.eot');
|
||||
src: url('/fonts/Immo-Sans/immoSans-Bold.eot?#iefix') format('embedded-opentype'), url('../../Fonts/Immo-Sans/immoSans-Bold.woff2') format('woff2'), url('../../Fonts/Immo-Sans/immoSans-Bold.woff') format('woff');
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Antique Olive Compact bold';
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display:swap;
|
||||
src: url("/fonts/Antique Olive Std Compact.woff2") format('woff2');
|
||||
}
|
||||
|
||||
@apply min-w-[320px] max-w-[1920px] p-[4px]
|
||||
@apply min-w-[320px] max-w-[1920px] p-[4px]
|
||||
sm:p-[10px];
|
||||
|
||||
font-family: "immo Sans";
|
||||
select option{
|
||||
font-family: "immo Sans",sans-serif;}
|
||||
font-family: "immo Sans";
|
||||
select option {
|
||||
font-family: "immo Sans", sans-serif;
|
||||
}
|
||||
|
||||
.firstrow{@apply grid grid-cols-1 gap-x-4 gap-y-2
|
||||
.firstrow {
|
||||
@apply grid grid-cols-1 gap-x-4 gap-y-2
|
||||
sm:grid-cols-2 sm:gap-x-4 sm:gap-y-2;
|
||||
|
||||
.titel{@apply text-black font-bold bg-[#ffcc00] px-2 py-1 rounded-[0.25rem];}
|
||||
.titel {
|
||||
@apply text-black font-bold bg-[#ffcc00] px-2 py-1 rounded-[0.25rem];
|
||||
}
|
||||
|
||||
.selectfeld{@apply w-full px-2 py-1 min-h-[38px] ring-1 ring-black/15}
|
||||
.selectfeld {
|
||||
@apply w-full px-2 py-1 min-h-[38px] ring-1 ring-black/15;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.secondrow{@apply grid grid-cols-2 gap-x-4 gap-y-2 mt-4
|
||||
.secondrow {
|
||||
@apply grid grid-cols-2 gap-x-4 gap-y-2 mt-4
|
||||
sm:grid-cols-4 sm:gap-x-4 sm:gap-y-2;
|
||||
|
||||
.titel{@apply text-black font-bold bg-[#cccccc] px-2 py-1 rounded-[0.25rem];}
|
||||
|
||||
.selectfeld{@apply w-full px-2 py-1 min-h-[38px] ring-1 ring-black/15}
|
||||
.titel {
|
||||
@apply text-black font-bold bg-[#cccccc] px-2 py-1 rounded-[0.25rem];
|
||||
}
|
||||
|
||||
}
|
||||
.selectfeld {
|
||||
@apply w-full px-2 py-1 min-h-[38px] ring-1 ring-black/15;
|
||||
}
|
||||
}
|
||||
|
||||
#OEA_input{@apply grid}
|
||||
#OEA_input {
|
||||
@apply grid;
|
||||
}
|
||||
|
||||
.thirdrow{@apply grid grid-cols-1 gap-x-4 gap-y-2 col-start-1
|
||||
.thirdrow {
|
||||
@apply grid grid-cols-1 gap-x-4 gap-y-2 col-start-1
|
||||
md:grid-cols-4 md:gap-x-4 md:gap-y-2;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
ab {price} €
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<hr class="col-span-2 w-full md:w-[50%] md:m-auto bg-[#ffcc00] h-[2px]" />
|
||||
@@ -50,11 +49,13 @@
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<hr class="col-span-2 w-full md:w-[50%] md:m-auto bg-[#ffcc00] h-[2px]" />
|
||||
<hr class="col-span-2 w-full md:w-[50%] md:m-auto bg-[#ffcc00] h-[2px]" />
|
||||
|
||||
<div class="sumCent buttoncols"
|
||||
class:md:grid-cols-3={href_buy3}
|
||||
class:md:grid-cols-2={!href_buy3}>
|
||||
<div
|
||||
class="sumCent buttoncols"
|
||||
class:md:grid-cols-3={href_buy3}
|
||||
class:md:grid-cols-2={!href_buy3}
|
||||
>
|
||||
<a
|
||||
href={href_buy1}
|
||||
class="buttoncol"
|
||||
|
||||
@@ -38,13 +38,13 @@ export const BedarfsausweisWohnenSchema = z.object({
|
||||
volumen: z.number().nullish(),
|
||||
dicht: z.boolean().nullish(),
|
||||
fenster_flaeche_1: z.number().nullish(),
|
||||
fenster_art_1: z.string().nullish(),
|
||||
fenster_art_1: z.number().nullish(),
|
||||
fenster_flaeche_2: z.number().nullish(),
|
||||
fenster_art_2: z.string().nullish(),
|
||||
fenster_art_2: z.number().nullish(),
|
||||
dachfenster_flaeche: z.number().nullish(),
|
||||
dachfenster_art: z.string().nullish(),
|
||||
dachfenster_art: z.number().nullish(),
|
||||
haustuer_flaeche: z.number().nullish(),
|
||||
haustuer_art: z.string().nullish(),
|
||||
haustuer_art: z.number().nullish(),
|
||||
dach_bauart: z.string().nullish(),
|
||||
decke_bauart: z.string().nullish(),
|
||||
dach_daemmung: z.string().nullish(),
|
||||
|
||||
29
src/lib/auth/time-based-hash.ts
Normal file
29
src/lib/auth/time-based-hash.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
import { uptime } from "os"
|
||||
import crypto from "crypto";
|
||||
|
||||
/**
|
||||
* Generiert einen zeitbasierten Hash der sich alle 15 Minuten ändert und an die Uptime des servers gekoppelt ist.
|
||||
* @param email - Die E-Mail-Adresse des Benutzers, die als Teil des Hashes verwendet wird.
|
||||
* @param time - Die Zeit in Millisekunden, die seit dem Start des Servers vergangen ist (Standard ist die Uptime des Servers).
|
||||
* @param length - Die Länge des zurückgegebenen Hashes (Standard ist 6 Zeichen).
|
||||
* @returns Ein zeitbasierter Hash, der sich alle 15 Minuten ändert und auf der E-Mail-Adresse basiert.
|
||||
*/
|
||||
export function createTimeBasedHash(email: string, time: number = uptime(), length: number = 6): string {
|
||||
const now = Date.now();
|
||||
const elapsed = now - time;
|
||||
const window = Math.floor(elapsed / (15 * 60 * 1000)); // 15 minute windows
|
||||
|
||||
const data = `${email}:${window}`;
|
||||
|
||||
// Use a cryptographic hash (you can also use HMAC with a secret if you want)
|
||||
const hash = crypto.createHash('sha256').update(data).digest();
|
||||
|
||||
// Convert part of the hash to an integer
|
||||
const int = hash.readUInt32BE(0); // take first 4 bytes
|
||||
|
||||
// Modulo to get 6 digits
|
||||
const pin = (int % 1000000).toString().padStart(6, '0');
|
||||
|
||||
return pin;
|
||||
}
|
||||
@@ -1,27 +1,11 @@
|
||||
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 { pdfDatenblattVerbrauchsausweisWohnen } from "#lib/pdf/pdfDatenblattVerbrauchsausweisWohnen.js";
|
||||
import { pdfVerbrauchsausweisGewerbe } from "#lib/pdf/pdfVerbrauchsausweisGewerbe.js";
|
||||
import { pdfVerbrauchsausweisWohnen } from "#lib/pdf/pdfVerbrauchsausweisWohnen.js";
|
||||
import { pdfAushangVerbrauchsausweisGewerbe } from "#lib/pdf/pdfAushangVerbrauchsausweisGewerbe.js";
|
||||
import {
|
||||
BedarfsausweisWohnen,
|
||||
Enums,
|
||||
prisma,
|
||||
Rechnung,
|
||||
VerbrauchsausweisGewerbe,
|
||||
VerbrauchsausweisWohnen,
|
||||
} from "#lib/server/prisma.js";
|
||||
import { Enums, prisma, Rechnung } 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.
|
||||
@@ -31,179 +15,68 @@ export function getPrismaAusweisAdapter(id: string) {
|
||||
const ausweisart = getAusweisartFromId(id);
|
||||
|
||||
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
|
||||
return prisma.verbrauchsausweisWohnen;
|
||||
return prisma.verbrauchsausweisWohnen
|
||||
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
||||
return prisma.verbrauchsausweisGewerbe;
|
||||
return prisma.verbrauchsausweisGewerbe
|
||||
} else if (ausweisart === Enums.Ausweisart.BedarfsausweisWohnen) {
|
||||
return prisma.bedarfsausweisWohnen;
|
||||
return prisma.bedarfsausweisWohnen
|
||||
} else if (ausweisart === Enums.Ausweisart.GEGNachweisWohnen) {
|
||||
return prisma.gEGNachweisWohnen;
|
||||
return prisma.gEGNachweisWohnen
|
||||
} else if (ausweisart === Enums.Ausweisart.GEGNachweisGewerbe) {
|
||||
return prisma.gEGNachweisGewerbe;
|
||||
return prisma.gEGNachweisGewerbe
|
||||
} else if (ausweisart === Enums.Ausweisart.BedarfsausweisGewerbe) {
|
||||
return prisma.bedarfsausweisGewerbe;
|
||||
return prisma.bedarfsausweisGewerbe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
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) {
|
||||
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.
|
||||
* @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) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
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) {
|
||||
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.
|
||||
* @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)) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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"
|
||||
>;
|
||||
}
|
||||
return null
|
||||
}
|
||||
41
src/lib/server/mail/code.ts
Normal file
41
src/lib/server/mail/code.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { transport } from "#lib/mail.js";
|
||||
import {
|
||||
Benutzer,
|
||||
} from "#lib/client/prisma.js";
|
||||
import { createTimeBasedHash } from "#lib/auth/time-based-hash.js";
|
||||
|
||||
export async function sendVerificationCodeMail(
|
||||
user: Benutzer
|
||||
) {
|
||||
const code = createTimeBasedHash(user.email)
|
||||
|
||||
await transport.sendMail({
|
||||
from: `"IBCornelsen" <info@online-energieausweis.org>`,
|
||||
to: user.email,
|
||||
subject: `Ihre Registrierung bei IBCornelsen`,
|
||||
bcc: "info@online-energieausweis.org",
|
||||
html: `<p>Sehr geehrte*r ${user.vorname} ${user.name},</p>
|
||||
<p>Um Ihre Registrierung abzuschließen, geben Sie folgenden Bestätigungscode auf der Website ein, um Ihre E-Mail-Adresse zu bestätigen:<br><br>
|
||||
<b>${code}</b>
|
||||
</p>
|
||||
<p>
|
||||
Mit freundlichen Grüßen,
|
||||
<br>
|
||||
Dipl.-Ing. Jens Cornelsen
|
||||
<br>
|
||||
<br>
|
||||
<strong>IB Cornelsen</strong>
|
||||
<br>
|
||||
Katendeich 5A
|
||||
<br>
|
||||
21035 Hamburg
|
||||
<br>
|
||||
www.online-energieausweis.org
|
||||
<br>
|
||||
<br>
|
||||
fon 040 · 209339850
|
||||
<br>
|
||||
fax 040 · 209339859
|
||||
</p>`
|
||||
});
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
} from "#lib/client/prisma.js";
|
||||
import { encodeToken } from "#lib/auth/token.js";
|
||||
import { TokenType } from "#lib/auth/types.js";
|
||||
import { createTimeBasedHash } from "#lib/auth/time-based-hash.js";
|
||||
|
||||
export async function sendRegisterMail(
|
||||
user: Benutzer
|
||||
@@ -12,9 +13,11 @@ export async function sendRegisterMail(
|
||||
const verificationJwt = encodeToken({
|
||||
typ: TokenType.Verify,
|
||||
exp: Date.now() + (15 * 60 * 1000),
|
||||
uid: user.uid
|
||||
id: user.id
|
||||
})
|
||||
|
||||
const code = createTimeBasedHash(user.email)
|
||||
|
||||
await transport.sendMail({
|
||||
from: `"IBCornelsen" <info@online-energieausweis.org>`,
|
||||
to: user.email,
|
||||
@@ -22,10 +25,11 @@ export async function sendRegisterMail(
|
||||
bcc: "info@online-energieausweis.org",
|
||||
html: `<p>Sehr geehrte*r ${user.vorname} ${user.name},</p>
|
||||
<p>vielen Dank für Ihre Registrierung bei IBCornelsen. Ihr Benutzerkonto wurde erfolgreich erstellt.<br><br>
|
||||
|
||||
Um Ihre Registrierung abzuschließen, klicken Sie bitte auf den folgenden Link, um Ihre E-Mail-Adresse zu bestätigen:<br><br>
|
||||
|
||||
<a href="${BASE_URI}/auth/verify?t=${verificationJwt}">E-Mail-Adresse bestätigen</a><br></p>
|
||||
<a href="${BASE_URI}/auth/verify?t=${verificationJwt}">E-Mail-Adresse bestätigen</a><br><br>
|
||||
Oder geben Sie folgenden Bestätigungscode auf der Website ein:<br>
|
||||
<b>${code}</b>
|
||||
</p>
|
||||
<p>
|
||||
Mit freundlichen Grüßen,
|
||||
<br>
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
export let onLogin: (response: Awaited<ReturnType<typeof loginClient>>) => any;
|
||||
export let email: string = "";
|
||||
export let password: string = "";
|
||||
export let route: "login" | "signup" = "login"
|
||||
|
||||
const navigate = (target: string) => {
|
||||
route = target as typeof route;
|
||||
let route: "login" | "signup" = "login"
|
||||
|
||||
const navigate = (target: typeof route) => {
|
||||
route = target
|
||||
}
|
||||
|
||||
const loginData = {
|
||||
|
||||
384
src/modules/KaufabschlussModule.svelte
Normal file
384
src/modules/KaufabschlussModule.svelte
Normal file
@@ -0,0 +1,384 @@
|
||||
<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>
|
||||
@@ -1156,7 +1156,7 @@ grid-cols-3 sm:grid-cols-5 justify-around justify-items-center items-center"
|
||||
{/if}
|
||||
<!-- Für alle -->
|
||||
<div class="pruefpunkt">
|
||||
<input type="checkbox" required/>
|
||||
<input type="checkbox"/>
|
||||
<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.
|
||||
</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}>
|
||||
<div class="bg-white w-full max-w-screen-sm py-8">
|
||||
<EmbeddedAuthFlowModule onLogin={loginAction} email={email} route="signup"></EmbeddedAuthFlowModule>
|
||||
<EmbeddedAuthFlowModule onLogin={loginAction} email={email}></EmbeddedAuthFlowModule>
|
||||
</div>
|
||||
</Overlay>
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
}
|
||||
|
||||
try {
|
||||
const { uid } = await api.user.PUT.fetch({
|
||||
await api.user.PUT.fetch({
|
||||
email,
|
||||
passwort,
|
||||
vorname,
|
||||
@@ -42,7 +42,7 @@
|
||||
return
|
||||
}
|
||||
|
||||
window.location.href = "/auth/login";
|
||||
window.location.href = `/auth/code?email=${email}`;
|
||||
} catch (e) {
|
||||
errorHidden = false;
|
||||
}
|
||||
|
||||
89
src/modules/auth/CodeModule.svelte
Normal file
89
src/modules/auth/CodeModule.svelte
Normal file
@@ -0,0 +1,89 @@
|
||||
<script lang="ts">
|
||||
import { addNotification } from "#components/Notifications/shared.js";
|
||||
import { CrossCircled } from "radix-svelte-icons";
|
||||
import { fade } from "svelte/transition";
|
||||
import { api } from "astro-typesafe-api/client";
|
||||
import NotificationWrapper from "#components/Notifications/NotificationWrapper.svelte";
|
||||
|
||||
export let redirect: string | null = null;
|
||||
export let email: string;
|
||||
|
||||
function verify(e: SubmitEvent) {
|
||||
e.preventDefault();
|
||||
const code = numbers.join("");
|
||||
|
||||
if (code.length !== 6) {
|
||||
addNotification({
|
||||
message: "Bitte geben Sie einen gültigen Verifizierungscode ein.",
|
||||
dismissable: true,
|
||||
timeout: 3000,
|
||||
type: "error"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
api.auth["verification-code"].POST.fetch({ code, email }).then(() => {
|
||||
if (redirect) {
|
||||
window.location.href = redirect;
|
||||
} else {
|
||||
window.location.href = "/";
|
||||
}
|
||||
}).catch(() => {
|
||||
errorHidden = false;
|
||||
});
|
||||
}
|
||||
|
||||
// TODO
|
||||
function codeErneutAnfordern() {
|
||||
api.auth["verification-code"].GET.fetch(null, {
|
||||
headers: {
|
||||
"Authorization": "Bearer"
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let numbers = new Array(6).fill("");
|
||||
|
||||
let errorHidden = true;
|
||||
</script>
|
||||
|
||||
<div class="mx-auto w-1/3 bg-base-200 p-8 border border-base-300 rounded-lg">
|
||||
<h1 class="text-3xl mb-4">Verifizierung</h1>
|
||||
<p>Wir haben ihnen einen Verifizierungscode per Email geschickt, bitte geben sie diesen ein um ihre Registrierung fertigzustellen.</p>
|
||||
<form on:submit={verify}>
|
||||
<div class="flex flex-row gap-4 w-full justify-center my-12">
|
||||
{#each { length: 6 } as _, i}
|
||||
<input
|
||||
type="text"
|
||||
class="input input-bordered text-4xl text-base-content font-medium w-12 text-center"
|
||||
bind:value={numbers[i]}
|
||||
maxlength="1"
|
||||
on:input={function(e) {
|
||||
if (i !== 5) {
|
||||
e.target.nextSibling.focus()
|
||||
}
|
||||
}}
|
||||
required
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<button type="submit" class="button"
|
||||
>Abschicken</button
|
||||
>
|
||||
|
||||
|
||||
<!-- <button type="button" on:click={codeErneutAnfordern} class="button"
|
||||
>Code erneut anfordern</button
|
||||
> -->
|
||||
</div>
|
||||
{#if !errorHidden}
|
||||
<div class="flex flex-row gap-4 mt-8" in:fade out:fade={{delay: 400}}>
|
||||
<CrossCircled size={24} />
|
||||
<span class="font-semibold"> Da ist wohl etwas schiefgelaufen. Der eingegebene Verifizierungscode ist ungültig.</span>
|
||||
</div>
|
||||
{/if}
|
||||
</form>
|
||||
<NotificationWrapper></NotificationWrapper>
|
||||
</div>
|
||||
70
src/pages/api/auth/verification-code.ts
Normal file
70
src/pages/api/auth/verification-code.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { z } from "zod";
|
||||
import { prisma } from "#lib/server/prisma.js";
|
||||
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||
import { sendVerificationCodeMail } from "#lib/server/mail/code.js";
|
||||
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||
import { createTimeBasedHash } from "#lib/auth/time-based-hash.js";
|
||||
|
||||
|
||||
export const GET = defineApiRoute({
|
||||
meta: {
|
||||
description:
|
||||
"Fragt einen neuen Verifizierungscode per Mail an.",
|
||||
tags: ["Benutzer"],
|
||||
summary: "Verifizierungscode anfragen.",
|
||||
},
|
||||
middleware: authorizationMiddleware,
|
||||
output: z.void(),
|
||||
async fetch(input, ctx) {
|
||||
// Falls der Nutzer nicht existiert, wird eine Fehlermeldung zurückgegeben.
|
||||
const user = await prisma.benutzer.findUnique({
|
||||
where: {
|
||||
email: input.email.toLowerCase(),
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new APIError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Benutzer konnte nicht gefunden werden.",
|
||||
});
|
||||
}
|
||||
|
||||
await sendVerificationCodeMail(user);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
export const POST = defineApiRoute({
|
||||
meta: {
|
||||
description:
|
||||
"Versucht den Nutzer mithilfe des abgeschickten Codes zu verifizieren.",
|
||||
tags: ["Benutzer"],
|
||||
summary: "Verifizieren.",
|
||||
},
|
||||
input: z.object({
|
||||
code: z.string(),
|
||||
email: z.string().email().toLowerCase(),
|
||||
}),
|
||||
output: z.void(),
|
||||
async fetch({ code, email }, ctx) {
|
||||
const generatedCode = createTimeBasedHash(email);
|
||||
console.log(generatedCode, code);
|
||||
|
||||
if (code !== generatedCode) {
|
||||
throw new APIError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Der eingegebene Verifizierungscode ist ungültig.",
|
||||
});
|
||||
}
|
||||
|
||||
await prisma.benutzer.update({
|
||||
where: {
|
||||
email: email.toLowerCase(),
|
||||
},
|
||||
data: {
|
||||
verified: true,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -57,7 +57,7 @@ export const PUT = defineApiRoute({
|
||||
labels[category as keyof typeof labels]) ||
|
||||
"650e909fdc09629a4d6d495d")
|
||||
url.searchParams.append("key", "e057eb39018368ea96e456c753ac41b4")
|
||||
url.searchParams.append("idList", "650303186e721b4bef0c3980")
|
||||
url.searchParams.append("idList", "67d75ca7403fd22c49bc7447")
|
||||
url.searchParams.append("token", "ATTA8b65b3587ab627167038cc32a3460650973eb181cde01dabb208ca1e90ed5467AC06A4F2")
|
||||
|
||||
// Wir laden das Ticket zu Trello hoch.
|
||||
|
||||
24
src/pages/auth/code.astro
Normal file
24
src/pages/auth/code.astro
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
import CodeModule from "../../modules/auth/CodeModule.svelte";
|
||||
import MinimalLayout from "#layouts/MinimalLayout.astro";
|
||||
import { validateAccessTokenServer } from "#server/lib/validateAccessToken";
|
||||
|
||||
const valid = await validateAccessTokenServer(Astro)
|
||||
|
||||
if (valid) {
|
||||
return Astro.redirect("/dashboard")
|
||||
}
|
||||
|
||||
const redirect = Astro.url.searchParams.get("redirect");
|
||||
const email = Astro.url.searchParams.get("email");
|
||||
|
||||
if (!email) {
|
||||
return Astro.redirect("/");
|
||||
}
|
||||
|
||||
|
||||
---
|
||||
|
||||
<MinimalLayout title="Verifizierung - IBCornelsen">
|
||||
<CodeModule client:load {redirect} {email}></CodeModule>
|
||||
</MinimalLayout>
|
||||
@@ -1,28 +1,27 @@
|
||||
---
|
||||
import AbrechnungTable from "#components/Abrechnung/AbrechnungTable.svelte";
|
||||
import BlankLayout from "#layouts/BlankLayout.astro";
|
||||
import { extrahiereAusweisAusFeldMitMehrerenAusweisen } from "#lib/server/ausweis";
|
||||
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.isValid() ? start.toDate() : moment().startOf("month").toDate();
|
||||
let enddatum = end.isValid() ? end.toDate() : moment().endOf("month").toDate();
|
||||
const start = moment(Astro.url.searchParams.get("start"))
|
||||
const end = moment(Astro.url.searchParams.get("end"))
|
||||
|
||||
const benutzer = await getCurrentUser(Astro);
|
||||
let startdatum = start.toDate();
|
||||
let enddatum = end.toDate();
|
||||
|
||||
const benutzer = await getCurrentUser(Astro)
|
||||
|
||||
if (!benutzer) {
|
||||
return Astro.redirect("/404");
|
||||
return Astro.redirect("/404")
|
||||
}
|
||||
|
||||
const provisionen = {
|
||||
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.
|
||||
@@ -31,206 +30,305 @@ if (start.isValid() && end.isValid()) {
|
||||
bestellungen = await prisma.rechnung.findMany({
|
||||
where: {
|
||||
partner_code: "immowelt",
|
||||
OR: [
|
||||
{
|
||||
verbrauchsausweis_gewerbe: {
|
||||
ausgestellt: true,
|
||||
},
|
||||
OR: [{
|
||||
verbrauchsausweis_gewerbe: {
|
||||
ausgestellt: true
|
||||
}
|
||||
},
|
||||
{
|
||||
bedarfsausweis_wohnen: {
|
||||
ausgestellt: true
|
||||
}
|
||||
},
|
||||
{
|
||||
verbrauchsausweis_wohnen: {
|
||||
ausgestellt: true
|
||||
}
|
||||
}],
|
||||
AND: [{
|
||||
created_at: {
|
||||
gte: startdatum
|
||||
},
|
||||
{
|
||||
bedarfsausweis_wohnen: {
|
||||
ausgestellt: true,
|
||||
},
|
||||
}, {
|
||||
created_at: {
|
||||
lte: enddatum
|
||||
},
|
||||
{
|
||||
verbrauchsausweis_wohnen: {
|
||||
ausgestellt: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
AND: [
|
||||
{
|
||||
created_at: {
|
||||
gte: startdatum,
|
||||
},
|
||||
},
|
||||
{
|
||||
created_at: {
|
||||
lte: enddatum,
|
||||
},
|
||||
},
|
||||
],
|
||||
}]
|
||||
},
|
||||
orderBy: {
|
||||
created_at: "desc",
|
||||
created_at: "desc"
|
||||
},
|
||||
include: {
|
||||
bedarfsausweis_wohnen: {
|
||||
include: {
|
||||
aufnahme: {
|
||||
include: {
|
||||
objekt: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
verbrauchsausweis_gewerbe: {
|
||||
include: {
|
||||
aufnahme: {
|
||||
include: {
|
||||
objekt: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
verbrauchsausweis_wohnen: {
|
||||
include: {
|
||||
aufnahme: {
|
||||
include: {
|
||||
objekt: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
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,
|
||||
},
|
||||
},
|
||||
],
|
||||
OR: [{
|
||||
verbrauchsausweis_gewerbe: {
|
||||
ausgestellt: true
|
||||
}
|
||||
},
|
||||
{
|
||||
bedarfsausweis_wohnen: {
|
||||
ausgestellt: true
|
||||
}
|
||||
},
|
||||
{
|
||||
verbrauchsausweis_wohnen: {
|
||||
ausgestellt: true
|
||||
}
|
||||
}]
|
||||
},
|
||||
orderBy: {
|
||||
created_at: "desc",
|
||||
created_at: "desc"
|
||||
},
|
||||
include: {
|
||||
bedarfsausweis_wohnen: {
|
||||
include: {
|
||||
aufnahme: {
|
||||
include: {
|
||||
objekt: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
verbrauchsausweis_gewerbe: {
|
||||
include: {
|
||||
aufnahme: {
|
||||
include: {
|
||||
objekt: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
verbrauchsausweis_wohnen: {
|
||||
include: {
|
||||
aufnahme: {
|
||||
include: {
|
||||
objekt: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
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(),
|
||||
const partnerCodeErstesMal = (await prisma.rechnung.findFirst({
|
||||
select: {
|
||||
created_at: true
|
||||
},
|
||||
where: {
|
||||
partner_code: "immowelt",
|
||||
OR: [{
|
||||
verbrauchsausweis_gewerbe: {
|
||||
ausgestellt: true
|
||||
}
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
created_at: "asc",
|
||||
},
|
||||
})
|
||||
)?.created_at;
|
||||
{
|
||||
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];
|
||||
ausweisarten.push(Enums.Ausweisart.VerbrauchsausweisWohnen)
|
||||
provision += provisionen[Enums.Ausweisart.VerbrauchsausweisWohnen]
|
||||
}
|
||||
if (bestellung.bedarfsausweis_wohnen) {
|
||||
ausweisarten.push(Enums.Ausweisart.BedarfsausweisWohnen);
|
||||
provision += provisionen[Enums.Ausweisart.BedarfsausweisWohnen];
|
||||
ausweisarten.push(Enums.Ausweisart.BedarfsausweisWohnen)
|
||||
provision += provisionen[Enums.Ausweisart.BedarfsausweisWohnen]
|
||||
}
|
||||
if (bestellung.verbrauchsausweis_gewerbe) {
|
||||
ausweisarten.push(Enums.Ausweisart.VerbrauchsausweisGewerbe);
|
||||
provision += provisionen[Enums.Ausweisart.VerbrauchsausweisGewerbe];
|
||||
ausweisarten.push(Enums.Ausweisart.VerbrauchsausweisGewerbe)
|
||||
provision += provisionen[Enums.Ausweisart.VerbrauchsausweisGewerbe]
|
||||
}
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
<BlankLayout title="Monatliche Abrechnung">
|
||||
<AbrechnungTable
|
||||
bestellungen={bestellungen.map((bestellung) =>
|
||||
extrahiereAusweisAusFeldMitMehrerenAusweisen(bestellung)
|
||||
)}
|
||||
{provisionen}
|
||||
{partnerCodeErstesMal}
|
||||
startDate={startdatum}
|
||||
endDate={enddatum}
|
||||
email={benutzer.email}
|
||||
client:load
|
||||
/>
|
||||
|
||||
<div class="fixed bottom-0 left-0 right-0 bg-white p-4 shadow">
|
||||
<div class="flex justify-between items-center">
|
||||
<div>
|
||||
<p id="betrag_gesamt">
|
||||
Abrechnungsbetrag gesamt: <b>{provision} €</b>
|
||||
</p>
|
||||
</div>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
class="bg-secondary text-white px-4 py-2 rounded-lg hover:bg-secondary-focus"
|
||||
href=`/user/abrechnung/pdf.php?month=${moment().subtract(1, "month").get("month")}&year=${moment().subtract(1, "month").get("year")}`
|
||||
>PDF für letzten Monat generieren.</a
|
||||
>
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
|
||||
<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>
|
||||
<p id="betrag_gesamt">Abrechnungsbetrag gesamt: <b>{provision} €</b></p>
|
||||
</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>
|
||||
</div>
|
||||
</BlankLayout>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
31
src/pages/kaufabschluss.astro
Normal file
31
src/pages/kaufabschluss.astro
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
|
||||
import KaufabschlussModule from "#modules/KaufabschlussModule.svelte";
|
||||
import AusweisLayout from "#layouts/AusweisLayoutPruefung.astro";
|
||||
import { Enums } from "#lib/client/prisma";
|
||||
import { createCaller } from "src/astro-typesafe-api-caller";
|
||||
|
||||
// Man sollte nur auf diese Seite kommen, wenn ein Ausweis bereits vorliegt und in der Datenbank abgespeichert wurde.
|
||||
const uid = Astro.url.searchParams.get("uid");
|
||||
|
||||
if (!uid) {
|
||||
return Astro.redirect("/404");
|
||||
}
|
||||
|
||||
const caller = createCaller(Astro);
|
||||
|
||||
const ausweis = await caller.v1.verbrauchsausweisWohnen.get({
|
||||
uid
|
||||
})
|
||||
|
||||
const user = await caller.v1.benutzer.self();
|
||||
|
||||
if (!ausweis || !user) {
|
||||
return Astro.redirect("/404");
|
||||
}
|
||||
---
|
||||
|
||||
<AusweisLayout title="Kundendaten Aufnehmen - IBCornelsen">
|
||||
<KaufabschlussModule user={user} ausweis={ausweis} aktiveBezahlmethode={Enums.Bezahlmethoden.paypal} client:load></KaufabschlussModule>
|
||||
</AusweisLayout>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
set -e
|
||||
|
||||
# Config
|
||||
CONTAINER_NAME="online-energieausweis-database-1"
|
||||
CONTAINER_NAME="database"
|
||||
DB_USER="main"
|
||||
DB_NAME="main"
|
||||
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
|
||||
@@ -58,7 +58,7 @@ BEGIN
|
||||
FROM pg_tables
|
||||
WHERE schemaname = 'public'
|
||||
LOOP
|
||||
sql := sql || FORMAT('TRUNCATE TABLE public.%I CASCADE;', r.tablename);
|
||||
sql := sql || FORMAT('DROP TABLE public.%I CASCADE;', r.tablename);
|
||||
END LOOP;
|
||||
|
||||
-- Drop all sequences
|
||||
|
||||
Reference in New Issue
Block a user