From c3395bc83c4ac71e418f2f14df4df8331e959269 Mon Sep 17 00:00:00 2001 From: Stefan Date: Fri, 3 Jul 2026 10:15:04 +0200 Subject: [PATCH] Add Azure Blob Storage archive & email safety net - Add AzureBlobStorageService, DocumentArchiveSyncService, and related config for secondary PDF archiving of invoices/reminders - Add SQL procs and schema changes for archive backfill - Update invoice/reminder services to upload PDFs to blob storage - Add telemetry counters and unit tests for blob storage/archive logic - Add Fuchs:Email:OverrideRecipient config and enforce dev/test email redirect in ProcessWebComService, with tests - Improve JS date parsing (German formats), stricter JSON date detection - Increase widget SQL timeouts, update dependencies, docs, and project files --- .github/copilot-instructions.md | 11 +- CLAUDE.md | 13 +- Fuchs.Tests/AzureBlobStorageServiceTests.cs | 175 +++++++++ .../DocumentArchiveSyncServiceTests.cs | 59 +++ Fuchs.Tests/DocumentMetadataBuilderTests.cs | 206 ++++++++++ Fuchs.Tests/Fuchs.Tests.csproj | 2 +- Fuchs.Tests/ProcessWebComServiceTests.cs | 134 ++++++- Fuchs/Docs/INVOICE_LIFECYCLE.md | 359 ++++++++++++++++++ Fuchs/Fuchs.csproj | 17 +- Fuchs/Observability/FuchsTelemetry.cs | 6 +- Fuchs/Program.cs | 29 +- Fuchs/Services/AzureBlobStorageService.cs | 147 +++++++ Fuchs/Services/AzureBlobStorageSettings.cs | 33 ++ Fuchs/Services/DocumentArchiveSyncService.cs | 157 ++++++++ Fuchs/Services/DocumentMetadataBuilder.cs | 58 +++ Fuchs/Services/FuchsEmailSettings.cs | 16 + Fuchs/Services/FuchsWidgetService.cs | 8 +- Fuchs/Services/IBlobStorageService.cs | 47 +++ Fuchs/Services/InvoiceService.cs | 14 +- Fuchs/Services/ProcessWebComService.cs | 19 + Fuchs/Services/ReminderService.cs | 14 +- Fuchs/appsettings.Development.json | 14 +- Fuchs/appsettings.json | 20 +- Fuchs/js/intranet/fis_main.js | 4 +- Fuchs/js/intranet/oci_basic.js | 21 +- Fuchs/js/intranet/oci_main.js | 8 +- .../fts/glyphicons-halflings-regular.eot | Bin 35387 -> 20127 bytes .../fts/glyphicons-halflings-regular.ttf | Bin 58132 -> 45404 bytes .../fts/glyphicons-halflings-regular.woff | Bin 42816 -> 23424 bytes .../fts/glyphicons-halflings-regular.woff2 | Bin 32536 -> 18028 bytes Fuchs/wwwroot/web/fis.js | 33 +- Fuchs/wwwroot/web/fis.min.js | 2 +- Fuchs/wwwroot/web/fisb.js | 21 +- Fuchs/wwwroot/web/fisb.min.js | 2 +- Fuchs_DataService/Fuchs_DataService.csproj | 8 +- Fuchs_Database/FuchsDatabase.sqlproj | 6 +- .../fds__getInvoiceFileContent.sql | 18 + .../fds__getInvoiceFiles_ForBlobArchive.sql | 27 ++ .../fds__getReminderFileContent.sql | 18 + .../fds__getReminderFiles_ForBlobArchive.sql | 25 ++ Fuchs_Database/dbo/Tables/fds__reminder.sql | 51 +-- Fuchs_Database/fds__getInvoiceFileContent.sql | 0 .../fds__getInvoiceFiles_ForBlobArchive.sql | 0 .../fds__getReminderFileContent.sql | 0 .../fds__getReminderFiles_ForBlobArchive.sql | 0 Fuchs_Intranet.slnx | 10 + MFR_RESTClient/MFR_RESTClient.csproj | 12 +- 47 files changed, 1723 insertions(+), 101 deletions(-) create mode 100644 Fuchs.Tests/AzureBlobStorageServiceTests.cs create mode 100644 Fuchs.Tests/DocumentArchiveSyncServiceTests.cs create mode 100644 Fuchs.Tests/DocumentMetadataBuilderTests.cs create mode 100644 Fuchs/Docs/INVOICE_LIFECYCLE.md create mode 100644 Fuchs/Services/AzureBlobStorageService.cs create mode 100644 Fuchs/Services/AzureBlobStorageSettings.cs create mode 100644 Fuchs/Services/DocumentArchiveSyncService.cs create mode 100644 Fuchs/Services/DocumentMetadataBuilder.cs create mode 100644 Fuchs/Services/FuchsEmailSettings.cs create mode 100644 Fuchs/Services/IBlobStorageService.cs create mode 100644 Fuchs_Database/dbo/Stored Procedures/fds__getInvoiceFileContent.sql create mode 100644 Fuchs_Database/dbo/Stored Procedures/fds__getInvoiceFiles_ForBlobArchive.sql create mode 100644 Fuchs_Database/dbo/Stored Procedures/fds__getReminderFileContent.sql create mode 100644 Fuchs_Database/dbo/Stored Procedures/fds__getReminderFiles_ForBlobArchive.sql create mode 100644 Fuchs_Database/fds__getInvoiceFileContent.sql create mode 100644 Fuchs_Database/fds__getInvoiceFiles_ForBlobArchive.sql create mode 100644 Fuchs_Database/fds__getReminderFileContent.sql create mode 100644 Fuchs_Database/fds__getReminderFiles_ForBlobArchive.sql diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 6dc5e8d..1598105 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -31,6 +31,7 @@ - Connection strings are stored under the standard `"ConnectionStrings"` key and read via `IConfiguration.GetConnectionString(...)`. - `FuchsOcmsIntranet.Initialize(configuration)` must be called at app start (in `Program.cs`) before DI registration; `Fuchs_intranet` receives `IConfiguration` via its constructor. - `appsettings.Development.json` (git-ignored) can override secrets for local development. +- `Fuchs:Email:OverrideRecipient` (bound via `IOptions`, section `Fuchs:Email`) is a dev/test safety net: when non-empty, `ProcessWebComService.SendEmailAsync` discards the real recipient of every outbound email and redirects it to this single address instead, so a locally-enabled mailer can never reach a real tenant-owner or end-customer. Set this only in `appsettings.Development.json` — it must stay empty in Production (`appsettings.json` documents the safe empty default). ## Libraries - Do not upgrade Spire.PDF beyond version 8.10.5. @@ -41,7 +42,7 @@ ## Services & Dependency Injection - Business logic lives in **DI-registered services** under `Fuchs/Services/` behind interfaces; inject them into `IntranetController` (constructor injection). Do **not** reintroduce static God-classes or pass the whole controller into helpers. - - `IComService` (email/SMS via ProcessWeb Mailer API, attachments sent inline as base64), `IPdfService` (MigraDoc render), `IInvoiceService`, `IReminderService`, `IReportService` (SQL report engine via `FuchsVisualization`), `IWidgetService`, `IBankingService`, `IMfrClientFactory`. + - `IComService` (email/SMS via ProcessWeb Mailer API, attachments sent inline as base64; honors the `Fuchs:Email:OverrideRecipient` dev safety net — see Configuration), `IPdfService` (MigraDoc render), `IInvoiceService`, `IReminderService`, `IReportService` (SQL report engine via `FuchsVisualization`), `IWidgetService`, `IBankingService`, `IMfrClientFactory`. - Lifetimes: stateless services (`IPdfService`, `IBankingService`, `IMfrClientFactory`) are singletons; request-scoped DB services (`IInvoiceService`, `IReminderService`, `IReportService`, `IWidgetService`, `IComService`) are scoped. Register in `Program.cs`. - `FdsInvoiceData` / `FdsReminderData` are **pure data holders** (parse + properties). Loading, persistence and PDF generation belong in the services — never `Task.Run(...).Wait()` sync-over-async. - Data access stays SQL-first via OCORE helpers (`getSQLDataSet_async`, `setSQLValue_async`) + stored procedures; no EF Core. @@ -65,7 +66,13 @@ - Tracing/metrics are always collected; OTLP export is opt-in via `Fuchs:Telemetry:OtlpEndpoint`. Don't add exporters that fail hard when no collector is present. ## Testing -- xUnit in `Fuchs.Tests`. For every service/handler change add tests covering **both** an intentionally succeeding and an intentionally failing path where feasible (use stubs/mocks; the test project has `InternalsVisibleTo`). DB-bound paths that can't be unit-tested should at least have their pure logic covered. +- xUnit in `Fuchs.Tests`. Testing must be **extensive**, not superficial: + - For every service/handler change add tests covering **both** an intentionally succeeding and an intentionally failing path where feasible (use stubs/mocks; the test project has `InternalsVisibleTo`). + - Cover edge cases and boundary conditions (empty/null/invalid input, disabled/feature-flag-off states, API/network errors) via `[Theory]`/`[InlineData]`/`[MemberData]` rather than a single happy-path `[Fact]`. + - When behavior depends on configuration (e.g. `appsettings.json` vs `appsettings.Development.json`), prefer loading the **real** files layered the same way ASP.NET Core does (`ConfigurationBuilder` + `AddJsonFile`) over hand-typed literals only, so drift in the actual files is caught (see `ProcessWebComServiceTests.SendEmailAsync_OverrideRecipientFromRealAppsettings_ClearsRecipientWheneverConfigured` for the pattern). + - Assert on the observable contract (e.g. the outgoing request payload) and on emitted telemetry (counters/histograms) when the code records them — not just the boolean return value. + - Name tests `MethodName_Scenario_ExpectedResult`. + - DB-bound paths that can't be unit-tested should at least have their pure logic covered. ## Azure Key Vault — Secret Naming - Secret names must satisfy the pattern `^[0-9a-zA-Z-]+$` (alphanumerics and hyphens only; no underscores, dots, or spaces). diff --git a/CLAUDE.md b/CLAUDE.md index 618ceef..aa9f714 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,4 +1,4 @@ -# CLAUDE.md — Project instructions for Claude Code +# CLAUDE.md — Project instructions for Claude Code > ## ⚠️ Instruction Sync > This file and **`.github/copilot-instructions.md`** are two views of the same @@ -29,13 +29,14 @@ - All settings in `Fuchs/appsettings.json` — **never** `Web.config` / `System.Configuration.ConfigurationManager`. App settings nested under `"Fuchs"`; connection strings under `"ConnectionStrings"`. - `FuchsOcmsIntranet.Initialize(configuration)` runs in `Program.cs` before DI registration. - `appsettings.Development.json` (git-ignored) overrides secrets locally. +- `Fuchs:Email:OverrideRecipient` (`IOptions`, section `Fuchs:Email`) is a dev/test safety net: when non-empty, `ProcessWebComService.SendEmailAsync` discards the real recipient of every outbound email and redirects it to this single address instead, so a locally-enabled mailer can never reach a real tenant-owner or end-customer. Set only in `appsettings.Development.json` — must stay empty in Production. ## Libraries - Do **not** upgrade Spire.PDF beyond 8.10.5. Prefer OCORE / OCORE_web / OCORE_web_pdf helpers over rewriting. Do not use OCMS/OCMS_sharp — OCORE only. ## Services & Dependency Injection - Business logic lives in **DI-registered services** under `Fuchs/Services/` behind interfaces, injected into `IntranetController`. Do not reintroduce static God-classes or pass the controller into helpers. -- Services: `IComService`, `IPdfService`, `IInvoiceService`, `IReminderService`, `IReportService`, `IWidgetService`, `IBankingService`, `IMfrClientFactory`. Stateless ones are singletons; DB/request-scoped ones are scoped (see `Program.cs`). +- Services: `IComService` (ProcessWeb Mailer API; honors the `Fuchs:Email:OverrideRecipient` dev safety net — see Configuration), `IPdfService`, `IInvoiceService`, `IReminderService`, `IReportService`, `IWidgetService`, `IBankingService`, `IMfrClientFactory`. Stateless ones are singletons; DB/request-scoped ones are scoped (see `Program.cs`). - `FdsInvoiceData` / `FdsReminderData` are **pure data holders**; load/persist/render belongs in services. No `Task.Run(...).Wait()` sync-over-async. - Data access is SQL-first via OCORE helpers + stored procedures (no EF Core). @@ -57,7 +58,13 @@ - Always collected; OTLP export opt-in via `Fuchs:Telemetry:OtlpEndpoint`. No exporters that hard-fail without a collector. ## Testing -- xUnit in `Fuchs.Tests`. For each service/handler change, add tests for **both** an intentionally succeeding and an intentionally failing path where feasible (stubs/mocks; `InternalsVisibleTo` is enabled). Cover pure logic for DB-bound paths that can't be unit-tested. +- xUnit in `Fuchs.Tests`. Testing must be **extensive**, not superficial: + - For each service/handler change, cover **both** an intentionally succeeding and an intentionally failing path where feasible (stubs/mocks; `InternalsVisibleTo` is enabled). + - Cover edge cases and boundary conditions (empty/null/invalid input, disabled/feature-flag-off states, API/network errors) via `[Theory]`/`[InlineData]`/`[MemberData]` rather than a single happy-path `[Fact]`. + - When behavior depends on configuration (e.g. `appsettings.json` vs `appsettings.Development.json`), prefer loading the **real** files layered the same way ASP.NET Core does (`ConfigurationBuilder` + `AddJsonFile`) over hand-typed literals only, so drift in the actual files is caught (see `ProcessWebComServiceTests.SendEmailAsync_OverrideRecipientFromRealAppsettings_ClearsRecipientWheneverConfigured` for the pattern). + - Assert on the observable contract (e.g. the outgoing request payload) and on emitted telemetry (counters/histograms) when the code records them — not just the boolean return value. + - Name tests `MethodName_Scenario_ExpectedResult`. + - Cover pure logic for DB-bound paths that can't be unit-tested. ## Secrets (Azure Key Vault) - Full naming rules live in `.github/copilot-instructions.md` (kept in sync). In short: names match `^[0-9a-zA-Z-]+$`, hierarchy via `--` (→ `:`), underscores → `-`, app prefix `fuchs`; register new keys in `ManagedSecretKeys` in `appsettings.json`. diff --git a/Fuchs.Tests/AzureBlobStorageServiceTests.cs b/Fuchs.Tests/AzureBlobStorageServiceTests.cs new file mode 100644 index 0000000..574ff25 --- /dev/null +++ b/Fuchs.Tests/AzureBlobStorageServiceTests.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.Metrics; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Azure; +using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Models; +using Fuchs.Services; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Fuchs.Tests; + +/// +/// Tests for the Azure Blob Storage secondary-archive service. Covers the +/// disabled/unconfigured path (no client), the empty-content guard, successful +/// uploads (routing to the correct per-category container and blob name), an +/// upload that throws (must be swallowed, never break invoice/reminder storage), +/// and the emitted telemetry counters. +/// +/// Azure.Storage.Blobs clients (BlobServiceClient/BlobContainerClient/BlobClient) +/// expose a protected parameterless constructor and virtual members specifically +/// to support mocking with Moq — see Azure SDK unit-testing guidance. +/// +public class AzureBlobStorageServiceTests +{ + private const string FuchsMeterName = "Fuchs.Intranet"; + + private static AzureBlobStorageSettings CreateSettings() => new() + { + Enabled = true, + InvoiceContainer = "test-invoices", + ReminderContainer = "test-reminders" + }; + + private static (Mock service, Mock container, Mock blob) + CreateMockedClientChain() + { + var blobClientMock = new Mock(); + var containerClientMock = new Mock(); + containerClientMock.Setup(c => c.GetBlobClient(It.IsAny())).Returns(blobClientMock.Object); + containerClientMock + .Setup(c => c.CreateIfNotExistsAsync( + It.IsAny(), It.IsAny>(), + It.IsAny(), It.IsAny())) + .ReturnsAsync((Response)null!); + + var serviceClientMock = new Mock(); + serviceClientMock.Setup(s => s.GetBlobContainerClient(It.IsAny())).Returns(containerClientMock.Object); + + return (serviceClientMock, containerClientMock, blobClientMock); + } + + // ── Disabled / unconfigured (feature-flag-off) ───────────────────────────── + [Fact] + public async Task UploadInvoicePdfAsync_NoClient_ReturnsNullWithoutThrowing() + { + var svc = new AzureBlobStorageService(client: null, CreateSettings(), NullLogger.Instance); + + Uri? result = await svc.UploadInvoicePdfAsync("INV1", "Rechnung_INV1.pdf", new byte[] { 1, 2, 3 }); + + Assert.Null(result); + } + + // ── Boundary condition: empty content ────────────────────────────────────── + [Fact] + public async Task UploadReminderPdfAsync_EmptyContent_ReturnsNullWithoutCallingClient() + { + var (service, container, blob) = CreateMockedClientChain(); + var svc = new AzureBlobStorageService(service.Object, CreateSettings(), NullLogger.Instance); + + Uri? result = await svc.UploadReminderPdfAsync("REM1", "Zahlungserinnerung_REM1.pdf", Array.Empty()); + + Assert.Null(result); + container.Verify(c => c.CreateIfNotExistsAsync( + It.IsAny(), It.IsAny>(), + It.IsAny(), It.IsAny()), Times.Never); + blob.Verify(b => b.UploadAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + // ── Success path: invoice routing + counter ───────────────────────────────── + [Fact] + public async Task UploadInvoicePdfAsync_ClientSucceeds_ReturnsBlobUriAndUsesInvoiceContainer() + { + var expectedUri = new Uri("https://test.blob.core.windows.net/test-invoices/INV1/Rechnung_INV1.pdf"); + var (service, container, blob) = CreateMockedClientChain(); + blob.Setup(b => b.Uri).Returns(expectedUri); + blob.Setup(b => b.UploadAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync((Response)null!); + + long delta = 0; + using var listener = new MeterListener + { + InstrumentPublished = (inst, l) => + { + if (inst.Meter.Name == FuchsMeterName && inst.Name == "fuchs.blobstorage.uploads") + l.EnableMeasurementEvents(inst); + } + }; + listener.SetMeasurementEventCallback((_, value, _, _) => Interlocked.Add(ref delta, value)); + listener.Start(); + + var svc = new AzureBlobStorageService(service.Object, CreateSettings(), NullLogger.Instance); + Uri? result = await svc.UploadInvoicePdfAsync("INV1", "Rechnung_INV1.pdf", new byte[] { 1, 2, 3, 4 }); + + Assert.Equal(expectedUri, result); + service.Verify(s => s.GetBlobContainerClient("test-invoices"), Times.Once); + container.Verify(c => c.GetBlobClient("INV1/Rechnung_INV1.pdf"), Times.Once); + blob.Verify(b => b.UploadAsync(It.IsAny(), true, It.IsAny()), Times.Once); + Assert.True(delta >= 1, "fuchs.blobstorage.uploads counter should have been incremented on a successful upload."); + } + + // ── Success path: reminder routing (different container) ────────────────── + [Fact] + public async Task UploadReminderPdfAsync_ClientSucceeds_UsesReminderContainer() + { + var (service, container, blob) = CreateMockedClientChain(); + blob.Setup(b => b.Uri).Returns(new Uri("https://test.blob.core.windows.net/test-reminders/REM2/Zahlungserinnerung_REM2.pdf")); + blob.Setup(b => b.UploadAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync((Response)null!); + + var svc = new AzureBlobStorageService(service.Object, CreateSettings(), NullLogger.Instance); + Uri? result = await svc.UploadReminderPdfAsync("REM2", "Zahlungserinnerung_REM2.pdf", new byte[] { 5, 6 }); + + Assert.NotNull(result); + service.Verify(s => s.GetBlobContainerClient("test-reminders"), Times.Once); + container.Verify(c => c.GetBlobClient("REM2/Zahlungserinnerung_REM2.pdf"), Times.Once); + } + + // ── Boundary condition: blank filename falls back to "{id}.pdf" ─────────── + [Fact] + public async Task UploadInvoicePdfAsync_BlankFileName_FallsBackToIdPdfBlobName() + { + var (service, container, blob) = CreateMockedClientChain(); + blob.Setup(b => b.Uri).Returns(new Uri("https://test.blob.core.windows.net/test-invoices/INV3/INV3.pdf")); + blob.Setup(b => b.UploadAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync((Response)null!); + + var svc = new AzureBlobStorageService(service.Object, CreateSettings(), NullLogger.Instance); + Uri? result = await svc.UploadInvoicePdfAsync("INV3", " ", new byte[] { 7 }); + + Assert.NotNull(result); + container.Verify(c => c.GetBlobClient("INV3/INV3.pdf"), Times.Once); + } + + // ── Failure path: client throws, must not propagate ──────────────────────── + [Fact] + public async Task UploadReminderPdfAsync_ClientThrows_ReturnsNullAndIncrementsFailedCounter() + { + var (service, container, blob) = CreateMockedClientChain(); + blob.Setup(b => b.UploadAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new RequestFailedException("simulated storage failure")); + + long delta = 0; + using var listener = new MeterListener + { + InstrumentPublished = (inst, l) => + { + if (inst.Meter.Name == FuchsMeterName && inst.Name == "fuchs.blobstorage.uploads.failed") + l.EnableMeasurementEvents(inst); + } + }; + listener.SetMeasurementEventCallback((_, value, _, _) => Interlocked.Add(ref delta, value)); + listener.Start(); + + var svc = new AzureBlobStorageService(service.Object, CreateSettings(), NullLogger.Instance); + Uri? result = await svc.UploadReminderPdfAsync("REM3", "Zahlungserinnerung_REM3.pdf", new byte[] { 9, 9 }); + + Assert.Null(result); + Assert.True(delta >= 1, "fuchs.blobstorage.uploads.failed counter should have been incremented on a failed upload."); + } +} diff --git a/Fuchs.Tests/DocumentArchiveSyncServiceTests.cs b/Fuchs.Tests/DocumentArchiveSyncServiceTests.cs new file mode 100644 index 0000000..6080e2a --- /dev/null +++ b/Fuchs.Tests/DocumentArchiveSyncServiceTests.cs @@ -0,0 +1,59 @@ +using System.Threading; +using System.Threading.Tasks; +using Fuchs.intranet; +using Fuchs.Services; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Moq; +using Xunit; + +namespace Fuchs.Tests; + +/// +/// Tests for — the one-shot startup backfill for the +/// Azure Blob Storage secondary archive. Only the disabled/feature-flag-off fast path is +/// unit-testable without a real SQL Server connection (the enabled path drives +/// fds__getInvoiceFiles_ForBlobArchive / fds__getReminderFiles_ForBlobArchive against +/// fds__invoices / fds__reminder); the enabled path is exercised manually/in integration +/// environments, consistent with InvoiceService/ReminderService which are likewise DB-bound +/// and have no unit tests of their SQL-calling members. +/// +public class DocumentArchiveSyncServiceTests +{ + private static Fuchs_intranet CreateIntranet() => + new(new ConfigurationBuilder().Build()); + + [Fact] + public async Task ExecuteAsync_FeatureDisabled_NeverTouchesBlobStorageAndCompletesImmediately() + { + var blobStorage = new Mock(MockBehavior.Strict); + var settings = Options.Create(new AzureBlobStorageSettings { Enabled = false }); + using var service = new DocumentArchiveSyncService( + CreateIntranet(), blobStorage.Object, settings, NullLogger.Instance); + + await service.StartAsync(CancellationToken.None); + await service.StopAsync(CancellationToken.None); + + blobStorage.VerifyNoOtherCalls(); + } + + [Fact] + public async Task ExecuteAsync_FeatureDisabled_DoesNotThrowEvenWithUnconfiguredIntranet() + { + // The disabled fast path must return before any SQL access is attempted, so an + // intranet instance with no real connection string configured is still safe to use. + var blobStorage = new Mock(MockBehavior.Strict); + var settings = Options.Create(new AzureBlobStorageSettings { Enabled = false }); + using var service = new DocumentArchiveSyncService( + CreateIntranet(), blobStorage.Object, settings, NullLogger.Instance); + + var exception = await Record.ExceptionAsync(async () => + { + await service.StartAsync(CancellationToken.None); + await service.StopAsync(CancellationToken.None); + }); + + Assert.Null(exception); + } +} diff --git a/Fuchs.Tests/DocumentMetadataBuilderTests.cs b/Fuchs.Tests/DocumentMetadataBuilderTests.cs new file mode 100644 index 0000000..7cd869b --- /dev/null +++ b/Fuchs.Tests/DocumentMetadataBuilderTests.cs @@ -0,0 +1,206 @@ +using System; +using System.Collections.Generic; +using Fuchs.Services; +using Xunit; + +namespace Fuchs.Tests; + +/// +/// Tests for — the per-blob metadata projection used by the +/// Azure Blob Storage archive (see and +/// ). Covers the "skip if absent from the row, keep empty +/// string if present-but-empty" contract, case-insensitive column lookup (SQL rows are frequently +/// lower-cased), and value stringification (DateTime round-trip formatting, DBNull/null handling). +/// +public class DocumentMetadataBuilderTests +{ + // ── Field presence contract ────────────────────────────────────────────── + [Fact] + public void Build_FieldPresentWithValue_IncludesStringifiedValue() + { + var row = new Dictionary { ["InvoiceId"] = "INV-42" }; + + var metadata = DocumentMetadataBuilder.Build(row, new[] { "InvoiceId" }); + + Assert.Equal("INV-42", metadata["InvoiceId"]); + } + + [Fact] + public void Build_FieldAbsentFromRow_SkipsFieldEntirely() + { + // Reminders have no file_guid column — must be skipped, not stored as empty. + var row = new Dictionary { ["Id"] = "REM1" }; + + var metadata = DocumentMetadataBuilder.Build(row, new[] { "Id", "file_guid" }); + + Assert.True(metadata.ContainsKey("Id")); + Assert.False(metadata.ContainsKey("file_guid")); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void Build_FieldPresentButNullOrEmpty_StoresEmptyStringRatherThanSkipping(object? value) + { + var row = new Dictionary { ["InvoiceTitle"] = value }; + + var metadata = DocumentMetadataBuilder.Build(row, new[] { "InvoiceTitle" }); + + Assert.True(metadata.ContainsKey("InvoiceTitle")); + Assert.Equal("", metadata["InvoiceTitle"]); + } + + [Fact] + public void Build_FieldPresentButDBNull_StoresEmptyString() + { + var row = new Dictionary { ["InvoiceTitle"] = DBNull.Value }; + + var metadata = DocumentMetadataBuilder.Build(row, new[] { "InvoiceTitle" }); + + Assert.True(metadata.ContainsKey("InvoiceTitle")); + Assert.Equal("", metadata["InvoiceTitle"]); + } + + // ── Case-insensitive lookup ────────────────────────────────────────────── + [Theory] + [InlineData("invoiceid")] + [InlineData("INVOICEID")] + [InlineData("InVoIcEId")] + public void Build_CaseInsensitiveRowKey_MatchesConfiguredFieldName(string rowKey) + { + var row = new Dictionary { [rowKey] = "INV-7" }; + + var metadata = DocumentMetadataBuilder.Build(row, new[] { "InvoiceId" }); + + Assert.Equal("INV-7", metadata["InvoiceId"]); + } + + // ── Value stringification ──────────────────────────────────────────────── + [Fact] + public void Build_DateTimeValue_FormatsAsRoundTripString() + { + var dt = new DateTime(2026, 3, 14, 9, 30, 0, DateTimeKind.Utc); + var row = new Dictionary { ["DateCreated"] = dt }; + + var metadata = DocumentMetadataBuilder.Build(row, new[] { "DateCreated" }); + + Assert.Equal(dt.ToString("O"), metadata["DateCreated"]); + } + + [Theory] + [InlineData(42, "42")] + [InlineData(true, "True")] + public void Build_NonStringValue_UsesToString(object value, string expected) + { + var row = new Dictionary { ["Version"] = value }; + + var metadata = DocumentMetadataBuilder.Build(row, new[] { "Version" }); + + Assert.Equal(expected, metadata["Version"]); + } + + [Fact] + public void Build_GuidValue_UsesDefaultGuidFormat() + { + var guid = Guid.Parse("11111111-1111-1111-1111-111111111111"); + var row = new Dictionary { ["file_guid"] = guid }; + + var metadata = DocumentMetadataBuilder.Build(row, new[] { "file_guid" }); + + Assert.Equal(guid.ToString(), metadata["file_guid"]); + } + + // ── Field-list edge cases ──────────────────────────────────────────────── + [Theory] + [InlineData("")] + [InlineData(" ")] + public void Build_WhitespaceFieldName_IsSkipped(string field) + { + var row = new Dictionary { ["Id"] = "X1" }; + + var metadata = DocumentMetadataBuilder.Build(row, new[] { field, "Id" }); + + Assert.Single(metadata); + Assert.Equal("X1", metadata["Id"]); + } + + [Fact] + public void Build_EmptyFieldsList_ReturnsEmptyDictionary() + { + var row = new Dictionary { ["Id"] = "X1" }; + + var metadata = DocumentMetadataBuilder.Build(row, Array.Empty()); + + Assert.Empty(metadata); + } + + [Fact] + public void Build_EmptyRow_SkipsAllConfiguredFields() + { + var row = new Dictionary(); + + var metadata = DocumentMetadataBuilder.Build(row, new[] { "Id", "Version", "InvoiceId" }); + + Assert.Empty(metadata); + } + + [Fact] + public void Build_DuplicateFieldNamesInFieldList_ProducesSingleEntry() + { + var row = new Dictionary { ["Id"] = "X1" }; + + var metadata = DocumentMetadataBuilder.Build(row, new[] { "Id", "Id" }); + + Assert.Single(metadata); + Assert.Equal("X1", metadata["Id"]); + } + + // ── Realistic per-document-type row shapes ─────────────────────────────── + [Fact] + public void Build_InvoiceRowShape_ProjectsAllConfiguredInvoiceFieldsAndSkipsReminderOnlyColumn() + { + var row = new Dictionary + { + ["Id"] = "INV1", + ["Version"] = 2, + ["InvoiceId"] = "R-2026-001", + ["InvoiceTitle"] = "Rechnung", + ["DocumentName"] = "Rechnung_INV1.pdf", + ["file_guid"] = Guid.Parse("11111111-1111-1111-1111-111111111111") + }; + var fields = new[] { "Id", "Version", "InvoiceId", "InvoiceTitle", "InvId", "DocumentName", "file_guid" }; + + var metadata = DocumentMetadataBuilder.Build(row, fields); + + Assert.Equal("INV1", metadata["Id"]); + Assert.Equal("2", metadata["Version"]); + Assert.Equal("R-2026-001", metadata["InvoiceId"]); + Assert.Equal("Rechnung", metadata["InvoiceTitle"]); + Assert.Equal("Rechnung_INV1.pdf", metadata["DocumentName"]); + Assert.Equal("11111111-1111-1111-1111-111111111111", metadata["file_guid"]); + Assert.False(metadata.ContainsKey("InvId"), "Invoices have no InvId column — must be skipped, not empty."); + } + + [Fact] + public void Build_ReminderRowShape_SkipsInvoiceOnlyColumns() + { + var row = new Dictionary + { + ["Id"] = "REM1", + ["Version"] = 0, + ["InvId"] = "INV1", + ["DocumentName"] = "Zahlungserinnerung_REM1.pdf" + }; + var fields = new[] { "Id", "Version", "InvoiceId", "InvoiceTitle", "InvId", "DocumentName", "file_guid" }; + + var metadata = DocumentMetadataBuilder.Build(row, fields); + + Assert.Equal("REM1", metadata["Id"]); + Assert.Equal("0", metadata["Version"]); + Assert.Equal("INV1", metadata["InvId"]); + Assert.Equal("Zahlungserinnerung_REM1.pdf", metadata["DocumentName"]); + Assert.False(metadata.ContainsKey("InvoiceId")); + Assert.False(metadata.ContainsKey("InvoiceTitle")); + Assert.False(metadata.ContainsKey("file_guid")); + } +} diff --git a/Fuchs.Tests/Fuchs.Tests.csproj b/Fuchs.Tests/Fuchs.Tests.csproj index 9121014..3cfb7ed 100644 --- a/Fuchs.Tests/Fuchs.Tests.csproj +++ b/Fuchs.Tests/Fuchs.Tests.csproj @@ -9,7 +9,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Fuchs.Tests/ProcessWebComServiceTests.cs b/Fuchs.Tests/ProcessWebComServiceTests.cs index ff14a0b..ce94512 100644 --- a/Fuchs.Tests/ProcessWebComServiceTests.cs +++ b/Fuchs.Tests/ProcessWebComServiceTests.cs @@ -1,11 +1,13 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics.Metrics; +using System.IO; using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Fuchs.Services; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Newtonsoft.Json.Linq; @@ -53,7 +55,7 @@ public class ProcessWebComServiceTests public HttpClient CreateClient(string name) => new(_handler, disposeHandler: false); } - private static ProcessWebComService CreateService(StubHandler handler, bool enabled = true) + private static ProcessWebComService CreateService(StubHandler handler, bool enabled = true, string? overrideRecipient = null) { var settings = Options.Create(new ProcessWebComSettings { @@ -62,10 +64,15 @@ public class ProcessWebComServiceTests AccountId = "acct", Token = "tok" }); + var emailSettings = Options.Create(new FuchsEmailSettings + { + OverrideRecipient = overrideRecipient + }); return new ProcessWebComService( NullLogger.Instance, intranet: null!, settings, + emailSettings, new StubHttpClientFactory(handler)); } @@ -122,6 +129,129 @@ public class ProcessWebComServiceTests Assert.Equal(0, handler.CallCount); } + // ── Dev/test recipient override safety net ───────────────────────────────── + [Fact] + public async Task SendEmailAsync_OverrideRecipientSet_RedirectsToOverrideAddress() + { + var handler = new StubHandler(HttpStatusCode.OK); + var svc = CreateService(handler, overrideRecipient: "dev-inbox@example.test"); + + bool result = await svc.SendEmailAsync("inv_ov1", "Subject", "

hi

", "realcustomer@example.de", "Kunde"); + + Assert.True(result); + Assert.Equal(1, handler.CallCount); + var json = JObject.Parse(handler.LastRequestBody!); + Assert.Equal("dev-inbox@example.test", json["recipient"]!.ToString()); + } + + [Fact] + public async Task SendEmailAsync_OverrideRecipientSet_SubjectRetainsOriginalRecipientForTraceability() + { + var handler = new StubHandler(HttpStatusCode.OK); + var svc = CreateService(handler, overrideRecipient: "dev-inbox@example.test"); + + await svc.SendEmailAsync("inv_ov2", "Rechnung 123", "

hi

", "realcustomer@example.de", "Kunde"); + + var json = JObject.Parse(handler.LastRequestBody!); + string subject = json["subject"]!.ToString(); + Assert.Contains("realcustomer@example.de", subject); + Assert.Contains("Rechnung 123", subject); + } + + [Fact] + public async Task SendEmailAsync_OverrideRecipientSet_InvalidOriginalAddressIsStillRedirected() + { + var handler = new StubHandler(HttpStatusCode.OK); + var svc = CreateService(handler, overrideRecipient: "dev-inbox@example.test"); + + bool result = await svc.SendEmailAsync("inv_ov3", "Subject", "

hi

", "not-an-email", "Kunde"); + + Assert.True(result); + Assert.Equal(1, handler.CallCount); + var json = JObject.Parse(handler.LastRequestBody!); + Assert.Equal("dev-inbox@example.test", json["recipient"]!.ToString()); + } + + [Fact] + public async Task SendEmailAsync_NoOverrideConfigured_SendsToOriginalRecipient() + { + var handler = new StubHandler(HttpStatusCode.OK); + var svc = CreateService(handler); + + await svc.SendEmailAsync("inv_ov4", "Subject", "

hi

", "realcustomer@example.de", "Kunde"); + + var json = JObject.Parse(handler.LastRequestBody!); + Assert.Equal("realcustomer@example.de", json["recipient"]!.ToString()); + } + + // ── Override enforcement across every real appsettings*.json environment ─── + // Loads the ACTUAL Fuchs/appsettings*.json files the same way ASP.NET Core + // layers them (base file + optional environment-specific overlay). These files + // are copied into this test assembly's output directory via the Fuchs project + // reference (Microsoft.NET.Sdk.Web auto-includes appsettings*.json as Content + // with CopyToOutputDirectory). This proves the safety net holds for whichever + // environment/appsettings file ends up "active" at runtime - not just a + // hand-typed literal - so a future edit that silently breaks the override key + // or its value in any appsettings*.json file would fail this test. + // + // Note: this API has a single "recipient" field - there is no distinct + // to/cc/bcc concept anywhere in the codebase (see ProcessWebComService. + // SendEmailAsync / payload.recipient). "to/cc/bcc cleared" is therefore fully + // satisfied by asserting that field no longer carries the original recipient + // once an override is configured. + public static IEnumerable AppSettingsEnvironments() + { + yield return new object[] { "" }; // base appsettings.json only ("Production"-like default) + foreach (var file in Directory.EnumerateFiles(AppContext.BaseDirectory, "appsettings.*.json")) + { + string[] parts = Path.GetFileName(file).Split('.'); + if (parts.Length == 3 && parts[0] == "appsettings" && parts[2] == "json") + yield return new object[] { parts[1] }; + } + } + + private static string ResolveOverrideRecipientForEnvironment(string environmentName) + { + var builder = new ConfigurationBuilder() + .SetBasePath(AppContext.BaseDirectory) + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: false); + if (!string.IsNullOrEmpty(environmentName)) + builder.AddJsonFile($"appsettings.{environmentName}.json", optional: true, reloadOnChange: false); + return builder.Build()["Fuchs:Email:OverrideRecipient"] ?? ""; + } + + [Theory] + [MemberData(nameof(AppSettingsEnvironments))] + public async Task SendEmailAsync_OverrideRecipientFromRealAppsettings_ClearsRecipientWheneverConfigured(string environmentName) + { + string overrideRecipient = ResolveOverrideRecipientForEnvironment(environmentName); + var handler = new StubHandler(HttpStatusCode.OK); + var svc = CreateService(handler, overrideRecipient: overrideRecipient); + + const string originalRecipient = "realcustomer@tenant-owner.example"; + bool result = await svc.SendEmailAsync( + "env_" + (string.IsNullOrEmpty(environmentName) ? "base" : environmentName), + "Subject", "

hi

", originalRecipient, "Kunde"); + + Assert.True(result); + Assert.Equal(1, handler.CallCount); + var json = JObject.Parse(handler.LastRequestBody!); + string sentRecipient = json["recipient"]!.ToString(); + + if (!string.IsNullOrWhiteSpace(overrideRecipient)) + { + // Override configured for this environment: the real recipient (to/cc/bcc) + // must be fully cleared and replaced by the override - never leaked. + Assert.Equal(overrideRecipient, sentRecipient); + Assert.NotEqual(originalRecipient, sentRecipient); + } + else + { + // No override configured for this environment: real recipient is used normally. + Assert.Equal(originalRecipient, sentRecipient); + } + } + // ── Attachment payload contract ──────────────────────────────────────────── [Fact] public async Task SendEmailAsync_WithAttachment_EmbedsBase64InPayload() diff --git a/Fuchs/Docs/INVOICE_LIFECYCLE.md b/Fuchs/Docs/INVOICE_LIFECYCLE.md new file mode 100644 index 0000000..90b3cb6 --- /dev/null +++ b/Fuchs/Docs/INVOICE_LIFECYCLE.md @@ -0,0 +1,359 @@ +# Invoice Lifecycle — From First Click to Customer Email + +Concept document describing the full, end-to-end invoicing process in the +Fuchs Intranet: how an office user turns a completed service request into an +invoice, how the invoice is drafted/previewed/edited, how it is finalised, and +how it reaches the customer by email (including resend and reminders). This +complements [`INVOICE_SET_PRICING.md`](INVOICE_SET_PRICING.md) (pricing/display +rules for set items) and [`EVAL_live_invoice_editing.md`](EVAL_live_invoice_editing.md) +(why the editor is stateless). + +> Scope note: this document describes the **implemented** flow in `Fuchs` +> (ASP.NET Core MVC intranet, jQuery front-end). It does not cover the Razor +> Pages areas of the workspace — the intranet/invoice module predates those and +> is intentionally kept as-is (see `.github/copilot-instructions.md`). + +## 1. Actors & building blocks + +| Layer | Files | Responsibility | +|---|---|---| +| **Browser UI** | `js/intranet/modules/fis.req.js`, `fis.inv_shared.js`, `fis.inv.js` (bundled to `wwwroot/web/fis.req.de.js` / `fis.inv.de.js` via gulp `min:js`) | Request list, invoice editor dialog, PDF preview rendering, all user interaction | +| **Controller** | `Controllers/IntranetController.Requests.cs`, `.Invoices.cs`, `.Invoices2.cs`, `.Reminder.cs` | Thin action dispatch (`req/*`, `inv/*`, `rem/*`), auth checks, request/response shaping | +| **Services (DI)** | `Services/IInvoiceService` + `InvoiceService`, `Services/IComService` + `ProcessWebComService`, `Services/IPdfService` + `FuchsPdfService`, `Services/IReminderService` + `ReminderService` | Register/render/store invoices, send email, render PDF documents | +| **Data model** | `code/FdsInvoiceData.cs` | Pure data holder: parses the posted `invc` JSON, builds SQL parameters (`BuildInvoiceParams`), exposes registration fields | +| **PDF rendering** | `code/FuchsPdf.cs` (`ApplyInvoice`, `CreatePage_Letter`, `AddGirocode`), `code/InvoiceSetPricing.cs` | MigraDoc layout, draft watermark, GiroCode SEPA QR, set-pricing line transformation | +| **Database** | `Fuchs_Database` SSDT project — `fds__prepInvoice`, `fds__createInvoice`, `fds__setInvoice`, `fds__createInvoice_Details`, `fds__setInvoiceFinal`, `fds__setInvoiceFile`, `fds__setInvoiceSent`, `fds__getInvoice`, `fds__newInvoiceId` | SQL-first persistence, invoice numbering, finalisation, sent/paid status | + +All backend I/O is SQL-first via OCORE helpers (`getSQLDataSet_async`, +`setSQLValue_async`) and stored procedures — there is no EF Core in this path +(see `.github/instructions/ocore.instructions.md`). + +## 2. High-level lifecycle + +```mermaid +flowchart LR + A[Service request\ncompleted] --> B[Create invoice\nfrom request] + B --> C[Draft invoice\nregistered] + C --> D[Preview / Edit\nloop] + D -->|adjust items,\naddress, set-mode...| D + D -->|confirm| E[Finalise\ninvoice] + E --> F[Render + store\nfinal PDF] + F --> G[Email to\ncustomer] + G --> H[Mark as sent] + H -.optional.-> I[Resend email] + H -.optional.-> J[Reminder /\nMahnung] + E -.optional.-> K[Storno / Credit\nnote] +``` + +## 3. Entry point — from the request list + +Invoices are **not** created from a standalone "new invoice" wizard; they are +always created *from* one or more completed service requests. + +1. The office user opens the **Aufträge** (requests) list, rendered by + `fis.req.js`. `$req.init2/init3` load the list from `req/reql` + (`HandleRequestList` → `fds__getRequests_list[2]`). +2. Selecting a request row and clicking the invoice icon calls + `$inv.cInv` (bound in `fis.req.js` via `.click({ id: rw.Id }, $inv.cInv)`), + which — after an auth check (`fds_inv` level 2) — calls `$inv.cInv2({ id })`. +3. `$inv.cInv2` posts to **`req/get`** (`HandleRequestGet` → + `fds__getRequest_details`, mode `r`) to load the request(s) plus any + already-linked invoice, then renders the invoice editor dialog + (`invoice_layout`) and wires `$inv.eM` (the contextual top menu: save, + set-mode switch, §13b toggle, contact-person edit). +4. Multiple requests can be bundled onto a single invoice (the editor supports + several request "blocks", each becoming its own item group). + +```mermaid +sequenceDiagram + participant U as User (browser) + participant JS as fis.req.js / fis.inv_shared.js + participant C as IntranetController + participant DB as SQL (fds__*) + + U->>JS: click invoice icon on request row + JS->>JS: $inv.cInv -> $inv.cInv2({id}) + JS->>C: POST req/get {id, mode:'r'} + C->>DB: EXEC fds__getRequest_details + DB-->>C: admin, requests, items, inv + C-->>JS: JSON {admin, requests, inv} + JS->>U: render invoice editor dialog (items, totals, address, email) +``` + +## 4. Drafting, preview and editing + +The invoice editor is **stateless**: the browser holds the working model +(`table.invi` jQuery `.data()`), the server never caches a partial invoice +between requests. Every preview/save round-trip posts the *entire* invoice +payload; see `EVAL_live_invoice_editing.md` for the rationale. + +### 4.1 What the user can change +- **Line items** — quantities, prices, notes, combine into one sum + (`$inv.rendersrq`, `$inv.quantChange`). +- **Recipient fields** — invoice title, address, email, provision + location/period (inline edit fields, `fm(...)` helper in `fis.inv_shared.js`). +- **§13b reverse-charge** toggle (`$inv.sp13b`) — suppresses VAT lines/columns. +- **Set-pricing display mode** (`$inv.ssetmode` / `setSetmode`) — `SetPrice` + (default) / `ItemPrices` / `SetOnly`; see `INVOICE_SET_PRICING.md`. Purely + presentational — totals never change. +- **Contact person** for the invoice (`$inv.sctp`, stored in `CustomValues`). + +All of this recalculates client-side totals live via the `fds.inv` event +(`$inv.invSumUpdate`), which also builds the **backend item contract** +(`$inv.itemToContract`: `{ id, type, title, desc, qty, price_net, total_net, +vat }` plus set header/member tagging) that is posted to the server. + +### 4.2 Posting a draft / preview + +| User action | JS entry point | Endpoint | Controller handler | Effect | +|---|---|---|---|---| +| First save without preview | `$inv.ssave` | `req/save` | `Do_Process_Requests` case `save` | `RegisterInvoiceAsync(change: id present)` — creates or updates the draft row, **no PDF rendered** | +| Preview a **new** invoice | `$inv.sprev(false)` | `req/sprep` | case `sprep` | Registers draft, then `GenerateInvoicePdf` → renders preview images | +| Preview an **existing** draft | `$inv.sprev(true)` (aka `$inv.sedit`) | `req/sedit` | case `sedit` | Same as `sprep` but requires `id`, updates existing draft | +| Cancel out of preview | dialog `cancel` handler | `req/sdel` | case `sdel` | `fds__remInvoice` — deletes the (unfinalised) draft row | + +Before posting, `$inv.invcPayload(d)` normalizes the editor's internal field +names into the exact names `FdsInvoiceData.BuildInvoiceParams` reads (totals +from `sms.ttn/ttb`, `invoicetitle→title`, `loc→provisionlocation`, +`paymentterms→paymentterm`, etc. — see `INVOICE_SET_PRICING.md` for the full +mapping table). The posted shape is always `{ admin, req, sms, new }`. + +On the server, `RegisterInvoiceAsync` (in `InvoiceService`) turns the posted +JSON into SQL parameters and calls, in one batch: +- **New invoice**: `fds__createInvoice` (allocates the `Id`, returns a fresh + row) → `fds__createInvoice_Details` (service net/VAT + `InvoiceOptions`, + e.g. `setmode:itemprices`, `§13b`). +- **Existing draft**: `fds__setInvoice` (same parameter set, updates in place) + → `fds__createInvoice_Details` again. + +`GenerateInvoicePdf` (still in `InvoiceService`) builds `FuchsPdf.FdsTextBlocks` +and calls `IPdfService.WriteLetterAsync` + `ApplyInvoice`, which internally +uses `InvoiceSetPricing.Build(...)` to turn the posted item contract into +ordered, priced/unpriced lines. While the invoice is **not yet final** +(`IsDraft == true`), the rendered PDF carries a diagonal **"Entwurf"/draft +overlay watermark** (`CreatePage_Letter(..., draft: true)` stamps +`Data/overlay.png`) and — importantly — **no GiroCode payment QR** is added +(`AddGirocode` is only called `if (!inv.IsDraft && payAmount > 0 ...)`). +The preview images are returned as base64 (`DocToImageCollectionAsync`) and +shown in a modal (`$ocms.dlg(... form:false, button:'Rechnung erstellen' ...)`). + +```mermaid +sequenceDiagram + participant U as User + participant JS as fis.inv_shared.js + participant C as IntranetController.Requests + participant S as InvoiceService + participant DB as SQL + + U->>JS: edit items / address / set-mode + JS->>JS: fds.inv event -> invSumUpdate (recalculate + build items[]) + U->>JS: click "Vorschau" (preview) + JS->>C: POST req/sprep or req/sedit {invc: JSON, id?} + C->>S: RegisterInvoiceAsync(invoice, change, invId) + S->>DB: fds__createInvoice / fds__setInvoice + fds__createInvoice_Details + DB-->>S: registered invoice row (Id, ...) + S->>S: GenerateInvoicePdf (draft=true -> watermark, no GiroCode) + S-->>C: MigraDoc Document + C-->>JS: {id, img[] (base64 pages), total} + JS->>U: show PDF preview modal (confirm / cancel) +``` + +From the preview modal the user can loop back to editing (close and adjust), +**cancel** (deletes the draft via `req/sdel`), or **confirm** to finalise. + +## 5. Finalisation ("Rechnung erstellen") + +Confirming the preview modal posts to **`req/sconf`** +(`HandleRequestSconf`): + +1. `EXEC fds__setInvoiceFinal @Id, @authuser` — guarded by + `isFinal = 0 AND isSent = 0` so it can only fire once per draft. This is + also where the **real, sequential invoice number** is assigned: + `[InvoiceId] = fds__newInvoiceId(YEAR())` → format `R-<0000>` + (the draft only ever had the internal numeric `Id`). `Version` is bumped + and any linked "replaces" bookkeeping (storno/credit chains) is updated. +2. On success (`IsFinal == true` returned), the controller: + - Reloads the invoice via `LoadInvoiceAsync`. + - Calls `StoreInvoiceDocumentFileAsync` → renders the **final** PDF + (`draft` now reflects `IsFinal`, so the watermark disappears and the + GiroCode payment QR is added) → `fds__setInvoiceFile` persists the PDF + bytes on the invoice row → `IBlobStorageService.UploadInvoicePdfAsync` + archives a copy to blob storage. + - Re-fetches the invoice (`fds__getInvoice`) to get the final + `SendToEmail` / `DocumentName` / `InvoiceBalance`. +3. If a recipient email is present and the PDF rendered, the controller emails + it immediately (see §6) and marks the invoice `Sent` via + `fds__setInvoiceSent @auto=true`. +4. The browser opens the stored PDF in a new tab (`req/idoc`), returns to the + request list, and reloads it (`$ocms.init('req')`, `$inv.rReload()`). + +```mermaid +flowchart TD + A[POST req/sconf] --> B{fds__setInvoiceFinal\nisFinal=0 AND isSent=0?} + B -- no --> Z[500 - Aktion war nicht erfolgreich] + B -- yes --> C[Assign real InvoiceId\nR-yyyy-nnnn, bump Version] + C --> D[LoadInvoiceAsync] + D --> E[Render final PDF\n[no watermark, + GiroCode]] + E --> F[fds__setInvoiceFile\npersist PDF bytes] + F --> G[Upload to blob storage\nIBlobStorageService] + G --> H{SendToEmail set\nand PDF non-empty?} + H -- yes --> I[IComService.SendEmailAsync\nattach PDF inline] + I --> J[fds__setInvoiceSent auto=true] + H -- no --> K[Skip email - PDF only] + J --> L[Open PDF in new tab / reload request list] + K --> L +``` + +## 6. Sending the invoice by email + +Email delivery is handled by `IComService` / `ProcessWebComService`, which +talks to the **ProcessWeb Mailer API** (`push_com`, `comType=email`). + +- `HandleRequestSconf` builds the HTML body via `BuildInvoiceBody(balance, + paymentTerms)` — a fixed German thank-you text, the amount (if non-zero), + and payment instructions (IBAN/BIC) with the invoice's payment term + (`fdInv.PaymentTerms`, e.g. `10wd` → "10 Werktagen"). +- The rendered PDF bytes are attached as `{ [DocumentName] = filebyte }` — a + single-entry dictionary of filename → bytes. +- `SendEmailAsync(reference, subject, htmlBody, recipient, displayName, + attachments)` is called with `reference = "inv_"`, + `subject = "SanitärFuchs - "`. +- Inside `ProcessWebComService.SendEmailAsync`: + - The recipient email is validated; a configured + `Fuchs:Email:OverrideRecipient` (dev/test safety net, must stay empty in + Production) redirects **all** outbound mail to a single address. + - A signature is appended to the HTML body. + - If the mailer is disabled (`_settings.Enabled == false`), sending is a + documented no-op. + - Attachments are base64-encoded inline (`{ filename, mimeType, + contentBase64 }`) and POSTed to the Mailer API. +- Only on a **successful** send does the controller call + `fds__setInvoiceSent @auto=true`, which sets `IsSent = 1` — so a failed + mailer call leaves the invoice finalised but *not marked sent* (visible via + the "sis" — "als versendet markieren" — manual action, see §7). + +```mermaid +sequenceDiagram + participant C as IntranetController + participant Com as IComService (ProcessWebComService) + participant API as ProcessWeb Mailer API + participant DB as SQL + + C->>C: BuildInvoiceBody(balance, paymentTerms) + C->>Com: SendEmailAsync("inv_", subject, body, email, "", {pdf}) + Com->>Com: validate email, apply OverrideRecipient (dev), append signature + alt mailer enabled + Com->>API: POST push_com {comType:"email", attachments:[base64 pdf]} + API-->>Com: success/failure + else mailer disabled + Com-->>Com: no-op (logged) + end + Com-->>C: sent: true/false + opt sent == true + C->>DB: EXEC fds__setInvoiceSent @auto=true + end +``` + +## 7. After finalisation — manual actions + +Once an invoice is `IsFinal`, the request/invoice list menus +(`$inv.iMn`/`$inv.iMnr` in `fis.inv_shared.js`) expose: + +| Action | JS | Endpoint | Notes | +|---|---|---|---| +| **Resend email** | `$inv.ccInv`/context menu → *(re-)send* → `HandleRequestResend` | `req/resend` | Re-renders the stored/registered PDF bytes (`RenderInvoicePdfBytesAsync`, no re-registration) and re-sends via `IComService`, **without** re-touching `IsSent` | +| **Mark as sent manually** | `$inv.sis(id)` | `inv/sis` | `fds__setInvoiceSent @auto=false` — for invoices sent outside the system (e.g. printed/posted) | +| **View / display PDF** | `$inv.disp(id, 'inv')` | `inv/rdoc` | Renders page images for on-screen display only | +| **Download / open PDF** | `req/idoc` or `inv/pget`-derived | `req/idoc` | Serves the stored (or freshly rendered) PDF inline | +| **Mark paid / unpaid** | `$inv.setPyd`/`setUpd` | `inv/setpyd` / `inv/setupd` | `fds__setInvoicePayed` / `fds__setInvoiceUNPayed` | +| **Storno (cancel)** | `$inv.storno` → `$inv.cSt` | `inv/storno` (mode `simple`/`copy`) | `fds__createStorno_simple` / `fds__createStorno_copy`; the replaced invoice is cross-linked (`Replaces_InvId`) and cancelled once the storno itself is finalised | +| **Credit note** | `$inv.credit` → `$inv.cSt` | `inv/credit` (mode `credit`) | `fds__createCredit_simple` — same preview/finalise/email loop as a normal invoice | +| **Continue editing a draft** | `$inv.cntInv` / `clCntInv` | `inv/get` | Only available while `isFinal == false`; re-opens the same stateless editor | + +Storno/credit invoices are **new invoice drafts** created from the original +one — they go through the exact same preview → finalise → email pipeline +described in §4–§6, just seeded from `fds__createStorno_*`/`fds__createCredit_simple` +instead of from a service request. + +## 8. Reminders (Mahnungen) — downstream of a sent, unpaid invoice + +Not part of the invoice creation flow itself, but the natural continuation +once an invoice is sent and remains unpaid: + +- `$inv.ccRem(id, InvoiceId)` → `rem/lrem` (load prior reminder history) → + reminder editor (`$inv.ccRem_s2`) → `rem/get` → **preview** via `rem/prep` + (`$inv.rprev`, same stateless pattern as invoice preview) → **finalise** + via `rem/conf` → PDF opened, list reloaded. +- `$inv.dspRem(id)` lists existing reminders (`inv/getrem`); each can be + resent (`rem/resend`, mirrors `req/resend`) or downloaded. +- `$inv.srs(id)` → `rem/srs` marks a reminder as sent manually (mirrors + `inv/sis`). +- Reminder PDFs use the same draft-watermark/GiroCode rule as invoices + (`FuchsPdf.ApplyReminder`, `rem.IsDraft`). + +This is handled by `IReminderService`/`ReminderService` and +`IntranetController.Reminder.cs`, following the identical +draft-preview-finalise-email shape as invoices — intentionally, so the two +flows share the same mental model for the office user. + +## 9. End-to-end summary diagram + +```mermaid +flowchart TD + subgraph Requests + R1[Service request completed] --> R2[Open request list - req/reql] + R2 --> R3[Select request(s), click invoice icon] + end + + subgraph Draft & Edit + R3 --> D1[req/get - load request + existing invoice] + D1 --> D2[Edit items, address, email,\nset-mode, §13b, contact] + D2 --> D3[req/save - persist draft only] + D2 --> D4[req/sprep or req/sedit -\nregister + render draft PDF] + D4 --> D5[Preview modal\ndraft watermark, no GiroCode] + D5 -->|edit more| D2 + D5 -->|cancel| D6[req/sdel - delete draft] + end + + subgraph Finalise & Send + D5 -->|confirm| F1[req/sconf -\nfds__setInvoiceFinal] + F1 --> F2[Assign real InvoiceId\nR-yyyy-nnnn] + F2 --> F3[Render final PDF\nno watermark, + GiroCode] + F3 --> F4[fds__setInvoiceFile +\nblob storage upload] + F4 --> F5{SendToEmail set?} + F5 -- yes --> F6[IComService.SendEmailAsync\nProcessWeb Mailer API] + F6 --> F7[fds__setInvoiceSent auto=true] + F5 -- no --> F8[PDF stored, not emailed] + end + + subgraph After Sending + F7 --> A1[req/resend - resend email] + F7 --> A2[inv/setpyd / setupd - payment status] + F7 --> A3[inv/storno or inv/credit -\nnew linked invoice draft] + F7 --> A4[rem/* - reminder / Mahnung flow] + A3 -.re-enters.-> D2 + end +``` + +## 10. Key invariants worth remembering + +- **Stateless editor**: every preview/save/finalise call re-posts the full + `invc` JSON; the server never holds a partial invoice in memory or session + between requests (see `EVAL_live_invoice_editing.md`). +- **Totals come from the registration, not the rendered lines**: `sms.ttn` + /`sms.ttb` (posted) become `InvoiceBalance`/`InvoiceBalance_net`; display + mode (set pricing) never changes what the customer owes. +- **Numbering happens only at finalisation**: the draft has an internal `Id` + but no `InvoiceId` until `fds__setInvoiceFinal` assigns + `R-` — so previews never "burn" an invoice number. +- **Draft vs. final changes the rendered PDF**: draft = watermark overlay, no + GiroCode; final = no watermark, GiroCode payment QR added when there's a + positive balance. +- **Email is best-effort and tracked**: `IsSent` is only set `true` + automatically after a *successful* send; a failed send still leaves a + correctly finalised, stored invoice that staff can resend or mark sent + manually. +- **Storno/credit/reminder all reuse the same pipeline**: they are not special + cases in the UI/backend contract — they are just differently-seeded drafts + going through the identical preview → finalise → email sequence. +5 \ No newline at end of file diff --git a/Fuchs/Fuchs.csproj b/Fuchs/Fuchs.csproj index c0299e6..4207fe6 100644 --- a/Fuchs/Fuchs.csproj +++ b/Fuchs/Fuchs.csproj @@ -34,12 +34,12 @@ - - - - + + + + - + @@ -51,10 +51,11 @@ - + - - + + +
diff --git a/Fuchs/Observability/FuchsTelemetry.cs b/Fuchs/Observability/FuchsTelemetry.cs index 8b8027f..2920d33 100644 --- a/Fuchs/Observability/FuchsTelemetry.cs +++ b/Fuchs/Observability/FuchsTelemetry.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; using System.Diagnostics.Metrics; namespace Fuchs.Observability; @@ -41,6 +41,10 @@ public static class FuchsTelemetry Meter.CreateCounter("fuchs.banking.mt940.rows", "{row}", "Number of MT940 transaction lines parsed."); public static readonly Counter MfrCalls = Meter.CreateCounter("fuchs.mfr.calls", "{call}", "Number of MFR ERP client calls initiated."); + public static readonly Counter BlobUploadsSucceeded = + Meter.CreateCounter("fuchs.blobstorage.uploads", "{upload}", "Number of documents successfully archived to Azure Blob Storage."); + public static readonly Counter BlobUploadsFailed = + Meter.CreateCounter("fuchs.blobstorage.uploads.failed", "{upload}", "Number of documents that failed to archive to Azure Blob Storage."); // ── Performance histograms (durations in milliseconds) ─────────────────── public static readonly Histogram PdfRenderDuration = diff --git a/Fuchs/Program.cs b/Fuchs/Program.cs index d457563..3003852 100644 --- a/Fuchs/Program.cs +++ b/Fuchs/Program.cs @@ -36,8 +36,10 @@ public class Program // Key Vault + DPAPI secret management (must run before FuchsOcmsIntranet.Initialize) builder.AddSecretManagement(); - // Assemble connection strings from templates + resolved credentials - AssembleConnectionStrings(builder.Configuration); + // Assemble connection strings from templates + resolved credentials. + // In Development, "_Dev"-suffixed credential keys are preferred so a reachable + // Key Vault can never override them with production DB credentials. + AssembleConnectionStrings(builder.Configuration, builder.Environment); // Initialize the Fuchs intranet singleton with configuration FuchsOcmsIntranet.Initialize(builder.Configuration); @@ -80,6 +82,9 @@ public class Program // Communication service (email + SMS via ProcessWeb Mailer API) builder.Services.Configure(builder.Configuration.GetSection("Fuchs:Mailer")); + // Dev/test safety net: Fuchs:Email:OverrideRecipient redirects every outbound email + // (see appsettings.Development.json) so real tenant-owners/end-customers are never emailed. + builder.Services.Configure(builder.Configuration.GetSection("Fuchs:Email")); builder.Services.AddHttpClient("ProcessWebMailer"); builder.Services.AddScoped(); @@ -92,6 +97,15 @@ public class Program builder.Services.AddScoped(); builder.Services.AddScoped(); + // Secondary archive: invoice/reminder PDFs additionally stored in Azure Blob Storage. + // Disabled by default (Fuchs:AzureStorage:Enabled) — see AzureBlobStorageService. + builder.Services.Configure(builder.Configuration.GetSection("Fuchs:AzureStorage")); + builder.Services.AddSingleton(); + + // One-shot startup backfill: archives invoices/reminders that already had a file in SQL + // before Blob Storage archiving was enabled. No-ops when Fuchs:AzureStorage:Enabled is false. + builder.Services.AddHostedService(); + // ── OpenTelemetry: tracing + metrics ───────────────────────────────── // Instrumentation is always collected; OTLP export is enabled only when // an endpoint is configured (Fuchs:Telemetry:OtlpEndpoint), so a missing @@ -172,15 +186,18 @@ public class Program /// resolved credential secrets, then overrides the config entries in-place. /// When appsettings.Development.json supplies a complete connection string (no tokens), /// the replace is a no-op and the original value is preserved. + /// In Development, "{key}_Dev" credential keys are tried first. These are never populated + /// by Key Vault (no matching ManagedSecretKeys entry exists for them), so a developer whose + /// machine happens to reach the shared Key Vault can never have production DB credentials + /// silently override their local appsettings.Development.json values. /// - private static void AssembleConnectionStrings(ConfigurationManager config) + private static void AssembleConnectionStrings(ConfigurationManager config, IWebHostEnvironment environment) { const string userToken = "{username}"; const string passToken = "{password}"; (string csName, string userKey, string passKey)[] pairs = [ - ("ocms_ConnectionString", "ConnectionStrings:ocms_username", "ConnectionStrings:ocms_password"), ("fuchs_fds_ConnectionString", "ConnectionStrings:fuchs_fds_username", "ConnectionStrings:fuchs_fds_password"), ]; @@ -192,8 +209,8 @@ public class Program if (!template.Contains(userToken, StringComparison.Ordinal) && !template.Contains(passToken, StringComparison.Ordinal)) continue; - var user = config[userKey] ?? ""; - var pass = config[passKey] ?? ""; + var user = (environment.IsDevelopment() ? config[$"{userKey}_Dev"] : null) ?? config[userKey] ?? ""; + var pass = (environment.IsDevelopment() ? config[$"{passKey}_Dev"] : null) ?? config[passKey] ?? ""; overrides[$"ConnectionStrings:{csName}"] = template .Replace(userToken, user, StringComparison.Ordinal) .Replace(passToken, pass, StringComparison.Ordinal); diff --git a/Fuchs/Services/AzureBlobStorageService.cs b/Fuchs/Services/AzureBlobStorageService.cs new file mode 100644 index 0000000..f497f2e --- /dev/null +++ b/Fuchs/Services/AzureBlobStorageService.cs @@ -0,0 +1,147 @@ +using System.Diagnostics; +using Azure; +using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Models; +using Fuchs.Observability; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Fuchs.Services; + +/// +/// Archives finalized invoice/reminder PDFs (and, via , any +/// future file-bearing document type) to Azure Blob Storage, in addition to the existing SQL +/// Server storage (see and ). This is +/// a best-effort secondary archive: when is +/// false (default) or no connection string is configured, uploads are skipped and only +/// logged; upload failures are caught and logged rather than propagated, so a missing or +/// unreachable storage account never breaks invoice/reminder finalization. +/// +public class AzureBlobStorageService : IBlobStorageService +{ + private readonly ILogger _logger; + private readonly AzureBlobStorageSettings _settings; + private readonly BlobServiceClient? _client; + + public AzureBlobStorageService(IConfiguration configuration, + IOptions settings, + ILogger logger) + { + _logger = logger; + _settings = settings.Value; + + if (_settings.Enabled) + { + string? connectionString = configuration.GetConnectionString("AzureBlobStorage_ConnectionString"); + if (!string.IsNullOrWhiteSpace(connectionString) && connectionString != "MANAGED_BY_KEYVAULT") + { + _client = new BlobServiceClient(connectionString); + } + else + { + _logger.LogWarning( + "AzureBlobStorageService is enabled but ConnectionStrings:AzureBlobStorage_ConnectionString " + + "is not configured — uploads will be skipped."); + } + } + } + + /// Test-only constructor allowing an already-built (typically mocked) client to be injected. + internal AzureBlobStorageService(BlobServiceClient? client, AzureBlobStorageSettings settings, + ILogger logger) + { + _client = client; + _settings = settings; + _logger = logger; + } + + public Task UploadInvoicePdfAsync(string invoiceId, string fileName, byte[] content, + IReadOnlyDictionary? sourceRow = null, CancellationToken cancellationToken = default) + => UploadAsync("invoice", _settings.InvoiceContainer, invoiceId, fileName, content, sourceRow, cancellationToken); + + public Task UploadReminderPdfAsync(string reminderId, string fileName, byte[] content, + IReadOnlyDictionary? sourceRow = null, CancellationToken cancellationToken = default) + => UploadAsync("reminder", _settings.ReminderContainer, reminderId, fileName, content, sourceRow, cancellationToken); + + public Task UploadDocumentAsync(string category, string containerName, string documentId, string fileName, + byte[] content, IReadOnlyDictionary? sourceRow = null, CancellationToken cancellationToken = default) + => UploadAsync(category, containerName, documentId, fileName, content, sourceRow, cancellationToken); + + public async Task ExistsAsync(string containerName, string documentId, string fileName, + CancellationToken cancellationToken = default) + { + if (_client == null) return false; + + string blobName = BuildBlobName(documentId, fileName); + try + { + var containerClient = _client.GetBlobContainerClient(containerName); + var blobClient = containerClient.GetBlobClient(blobName); + Response response = await blobClient.ExistsAsync(cancellationToken); + return response.Value; + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Blob existence check failed for {Container}/{Blob} — treating as not archived.", + containerName, blobName); + return false; + } + } + + private static string BuildBlobName(string documentId, string fileName) => + $"{documentId}/{(string.IsNullOrWhiteSpace(fileName) ? $"{documentId}.pdf" : fileName)}"; + + private async Task UploadAsync(string category, string containerName, string documentId, + string fileName, byte[] content, IReadOnlyDictionary? sourceRow, CancellationToken cancellationToken) + { + if (_client == null) + { + _logger.LogDebug("Blob upload skipped for {Category} {Id} — storage disabled/unconfigured.", category, documentId); + return null; + } + if (content.Length == 0) + { + _logger.LogWarning("Blob upload skipped for {Category} {Id} — empty content.", category, documentId); + return null; + } + + using var act = FuchsTelemetry.StartActivity("blobstorage.upload"); + act?.SetTag("fuchs.blobstorage.category", category); + act?.SetTag("fuchs.blobstorage.id", documentId); + string blobName = BuildBlobName(documentId, fileName); + Dictionary? metadata = sourceRow != null + ? DocumentMetadataBuilder.Build(sourceRow, _settings.MetadataFields) + : null; + + try + { + var containerClient = _client.GetBlobContainerClient(containerName); + await containerClient.CreateIfNotExistsAsync(cancellationToken: cancellationToken); + var blobClient = containerClient.GetBlobClient(blobName); + using var stream = new MemoryStream(content, writable: false); + if (metadata is { Count: > 0 }) + { + var options = new BlobUploadOptions { Metadata = metadata }; + await blobClient.UploadAsync(stream, options, cancellationToken); + } + else + { + await blobClient.UploadAsync(stream, overwrite: true, cancellationToken); + } + + FuchsTelemetry.BlobUploadsSucceeded.Add(1, new KeyValuePair("category", category)); + _logger.LogInformation("Uploaded {Category} {Id} to container {Container} as {Blob}.", + category, documentId, containerName, blobName); + return blobClient.Uri; + } + catch (Exception ex) + { + FuchsTelemetry.BlobUploadsFailed.Add(1, new KeyValuePair("category", category)); + act?.SetStatus(ActivityStatusCode.Error, ex.Message); + _logger.LogError(ex, "Blob upload failed for {Category} {Id} in container {Container}.", + category, documentId, containerName); + return null; + } + } +} diff --git a/Fuchs/Services/AzureBlobStorageSettings.cs b/Fuchs/Services/AzureBlobStorageSettings.cs new file mode 100644 index 0000000..d4c6b96 --- /dev/null +++ b/Fuchs/Services/AzureBlobStorageSettings.cs @@ -0,0 +1,33 @@ +namespace Fuchs.Services; + +/// +/// Azure Blob Storage settings, bound from appsettings.json → "Fuchs:AzureStorage". +/// The storage account connection string itself is a secret and therefore lives +/// under the standard ConnectionStrings key (see , +/// which reads it via IConfiguration.GetConnectionString("AzureBlobStorage_ConnectionString")) +/// instead of being bound here. +/// +public class AzureBlobStorageSettings +{ + /// + /// When false (default) blob uploads are skipped and only logged, so the + /// feature is opt-in and never impacts environments that haven't configured a + /// storage account + Key Vault secret yet. Set to true to enable archiving. + /// + public bool Enabled { get; set; } = false; + + /// Blob container that stores finalized invoice PDFs. + public string InvoiceContainer { get; set; } = "fuchs-invoices"; + + /// Blob container that stores finalized reminder PDFs. + public string ReminderContainer { get; set; } = "fuchs-reminders"; + + /// + /// Column/property names considered when building the per-blob metadata dictionary + /// (see ). Not every document type has every + /// column: fields absent from a given source row are skipped entirely, while fields + /// that are present but hold an empty value are still stored as an empty string. + /// + public List MetadataFields { get; set; } = + new() { "Id", "Version", "InvoiceId", "InvoiceTitle", "InvId", "DocumentName", "file_guid" }; +} diff --git a/Fuchs/Services/DocumentArchiveSyncService.cs b/Fuchs/Services/DocumentArchiveSyncService.cs new file mode 100644 index 0000000..5174fcd --- /dev/null +++ b/Fuchs/Services/DocumentArchiveSyncService.cs @@ -0,0 +1,157 @@ +using System.Data; +using Fuchs.intranet; +using Fuchs.Observability; +using Microsoft.Data.SqlClient; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using static OCORE.commons; +using static OCORE.SQL.sql; + +namespace Fuchs.Services; + +/// +/// Startup backfill for the Azure Blob Storage secondary archive (see ). +/// When is true, this one-shot background task +/// enumerates every invoice/reminder that already has a file stored in SQL Server +/// (fds__getInvoiceFiles_ForBlobArchive / fds__getReminderFiles_ForBlobArchive), skips +/// documents already archived (), and uploads the rest — +/// fetching bytes lazily via fds__getInvoiceFileContent / fds__getReminderFileContent so the +/// enumeration query itself stays lightweight (no VARBINARY column). New invoices/reminders created after +/// startup are archived inline by / ; this service +/// only covers historical documents that predate the feature being enabled. +/// Runs once at startup (not periodic) and never throws: failures are logged so a database or storage +/// hiccup during startup can never prevent the app from serving requests. +/// +public class DocumentArchiveSyncService : BackgroundService +{ + private const int BackfillConcurrency = 4; + + private readonly Fuchs_intranet _intranet; + private readonly IBlobStorageService _blobStorage; + private readonly AzureBlobStorageSettings _settings; + private readonly ILogger _logger; + + public DocumentArchiveSyncService(Fuchs_intranet intranet, IBlobStorageService blobStorage, + IOptions settings, ILogger logger) + { + _intranet = intranet; + _blobStorage = blobStorage; + _settings = settings.Value; + _logger = logger; + } + + private string Conn => _intranet.Intranet__SQLConnectionString; + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + if (!_settings.Enabled) + { + _logger.LogDebug("DocumentArchiveSyncService skipped — Fuchs:AzureStorage:Enabled is false."); + return; + } + + using var act = FuchsTelemetry.StartActivity("blobstorage.backfill"); + _logger.LogInformation("DocumentArchiveSyncService starting startup backfill."); + try + { + int invoices = await SyncInvoicesAsync(stoppingToken); + int reminders = await SyncRemindersAsync(stoppingToken); + _logger.LogInformation( + "DocumentArchiveSyncService completed: {Invoices} invoice(s), {Reminders} reminder(s) newly archived.", + invoices, reminders); + } + catch (OperationCanceledException) + { + _logger.LogWarning("DocumentArchiveSyncService backfill cancelled (application shutting down)."); + } + catch (Exception ex) + { + _logger.LogError(ex, "DocumentArchiveSyncService backfill failed."); + } + } + + private async Task SyncInvoicesAsync(CancellationToken cancellationToken) + { + var dt = await getSQLDatatable_async( + "EXECUTE [dbo].[fds__getInvoiceFiles_ForBlobArchive];", + Conn, Security: _intranet.GetDbSecurity(), options: new FIS_SQLOptions()); + if (dt.Count == 0) return 0; + + int archived = 0; + var rows = dt.DataTable.Rows.Cast().ToList(); + await Parallel.ForEachAsync(rows, + new ParallelOptions { MaxDegreeOfParallelism = BackfillConcurrency, CancellationToken = cancellationToken }, + async (row, ct) => + { + string id = row.nz("Id"); + if (string.IsNullOrEmpty(id)) return; + try + { + string fileName = row.nz("DocumentName").ne($"Rechnung_{id}.pdf"); + if (await _blobStorage.ExistsAsync(_settings.InvoiceContainer, id, fileName, ct)) + return; + + byte[]? content = await GetFileContentAsync( + "EXECUTE [dbo].[fds__getInvoiceFileContent] @Id;", id); + if (content is not { Length: > 0 }) return; + + var uri = await _blobStorage.UploadInvoicePdfAsync( + id, fileName, content, row.toObjectDictionary(), ct); + if (uri != null) Interlocked.Increment(ref archived); + } + catch (OperationCanceledException) { throw; } + catch (Exception ex) + { + _logger.LogWarning(ex, "Invoice backfill failed for {Id} — skipping.", id); + } + }); + return archived; + } + + private async Task SyncRemindersAsync(CancellationToken cancellationToken) + { + var dt = await getSQLDatatable_async( + "EXECUTE [dbo].[fds__getReminderFiles_ForBlobArchive];", + Conn, Security: _intranet.GetDbSecurity(), options: new FIS_SQLOptions()); + if (dt.Count == 0) return 0; + + int archived = 0; + var rows = dt.DataTable.Rows.Cast().ToList(); + await Parallel.ForEachAsync(rows, + new ParallelOptions { MaxDegreeOfParallelism = BackfillConcurrency, CancellationToken = cancellationToken }, + async (row, ct) => + { + string id = row.nz("Id"); + if (string.IsNullOrEmpty(id)) return; + try + { + string fileName = row.nz("DocumentName").ne($"Zahlungserinnerung_{id}.pdf"); + if (await _blobStorage.ExistsAsync(_settings.ReminderContainer, id, fileName, ct)) + return; + + byte[]? content = await GetFileContentAsync( + "EXECUTE [dbo].[fds__getReminderFileContent] @Id;", id); + if (content is not { Length: > 0 }) return; + + var uri = await _blobStorage.UploadReminderPdfAsync( + id, fileName, content, row.toObjectDictionary(), ct); + if (uri != null) Interlocked.Increment(ref archived); + } + catch (OperationCanceledException) { throw; } + catch (Exception ex) + { + _logger.LogWarning(ex, "Reminder backfill failed for {Id} — skipping.", id); + } + }); + return archived; + } + + private async Task GetFileContentAsync(string sql, string id) + { + var pl = new List { SQL_VarChar("@Id", id) }; + var dt = await getSQLDatatable_async(sql, Conn, pl, + Security: _intranet.GetDbSecurity(), options: new FIS_SQLOptions()); + return dt.Count > 0 ? dt.FirstRow.no("file", null) as byte[] : null; + } +} diff --git a/Fuchs/Services/DocumentMetadataBuilder.cs b/Fuchs/Services/DocumentMetadataBuilder.cs new file mode 100644 index 0000000..2c04a0e --- /dev/null +++ b/Fuchs/Services/DocumentMetadataBuilder.cs @@ -0,0 +1,58 @@ +namespace Fuchs.Services; + +/// +/// Builds the per-blob metadata dictionary used when archiving documents (invoice/reminder PDFs, +/// and any future file-bearing type) to Azure Blob Storage — see +/// and . +/// Only fields configured in that are ALSO +/// present as a key on the source row are included: a field absent from a given document type's +/// row shape (e.g. reminders have no file_guid) is skipped entirely, while a field that is +/// present but holds a null/empty value is still emitted as an empty string. +/// +public static class DocumentMetadataBuilder +{ + /// + /// Projects onto . Column lookup is + /// case-insensitive because SQL-sourced rows (see toObjectDictionary / + /// GenericObjectDictionary) are frequently lower-cased. + /// + public static Dictionary Build(IReadOnlyDictionary row, IEnumerable fields) + { + var metadata = new Dictionary(); + foreach (string field in fields) + { + if (string.IsNullOrWhiteSpace(field)) continue; + if (!TryGetValue(row, field, out object? value)) continue; + metadata[field] = Stringify(value); + } + return metadata; + } + + private static bool TryGetValue(IReadOnlyDictionary row, string field, out object? value) + { + if (row.TryGetValue(field, out value)) return true; + + // Fall back to a case-insensitive match: rows built from SQL results are frequently + // lower-cased (see toObjectDictionary/GenericObjectDictionary) while MetadataFields + // entries are written using the column's natural casing (e.g. "InvoiceId"). + foreach (var kvp in row) + { + if (string.Equals(kvp.Key, field, StringComparison.OrdinalIgnoreCase)) + { + value = kvp.Value; + return true; + } + } + value = null; + return false; + } + + private static string Stringify(object? value) => + value switch + { + null => "", + DBNull => "", + DateTime dt => dt.ToString("O"), + _ => value.ToString() ?? "" + }; +} diff --git a/Fuchs/Services/FuchsEmailSettings.cs b/Fuchs/Services/FuchsEmailSettings.cs new file mode 100644 index 0000000..117818d --- /dev/null +++ b/Fuchs/Services/FuchsEmailSettings.cs @@ -0,0 +1,16 @@ +namespace Fuchs.Services; + +/// +/// Email safety-net settings, bound from appsettings.json → "Fuchs:Email". +/// +public class FuchsEmailSettings +{ + /// + /// Dev/test safety net: when set to a non-empty address, + /// discards the real recipient of every outbound email (to/cc/bcc) and redirects it to this + /// single address instead, so a locally-enabled mailer can never reach a real tenant-owner or + /// end-customer while testing. Configure this only in appsettings.Development.json — + /// it must stay empty/unset in Production. + /// + public string? OverrideRecipient { get; set; } +} diff --git a/Fuchs/Services/FuchsWidgetService.cs b/Fuchs/Services/FuchsWidgetService.cs index e645b0e..a78ac49 100644 --- a/Fuchs/Services/FuchsWidgetService.cs +++ b/Fuchs/Services/FuchsWidgetService.cs @@ -1,4 +1,4 @@ -using Fuchs.intranet; +using Fuchs.intranet; using Fuchs.Observability; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -124,7 +124,8 @@ public class FuchsWidgetService : IWidgetService { case "sql_table": { - var dt = await getSQLDatatable_async(sql, Conn, Params(userAccountId), Security: dbSec); + var dt = await getSQLDatatable_async(sql, Conn, Params(userAccountId), Security: dbSec, + options: new FIS_SQLOptions { CommandTimeout = 90 }); widgetData = new { name, @@ -141,7 +142,8 @@ public class FuchsWidgetService : IWidgetService case "sql_indicator": { - var dt = await getSQLDatatable_async(sql, Conn, Params(userAccountId), Security: dbSec); + var dt = await getSQLDatatable_async(sql, Conn, Params(userAccountId), Security: dbSec, + options: new FIS_SQLOptions { CommandTimeout = 90 }); var firstRow = dt.DataTable.Rows.Count > 0 ? dt.DataTable.Rows[0].toObjectDictionary() : new Dictionary(); diff --git a/Fuchs/Services/IBlobStorageService.cs b/Fuchs/Services/IBlobStorageService.cs new file mode 100644 index 0000000..e33be9b --- /dev/null +++ b/Fuchs/Services/IBlobStorageService.cs @@ -0,0 +1,47 @@ +namespace Fuchs.Services; + +/// +/// Abstraction for archiving finalized documents (invoice/reminder PDFs, and any future +/// file-bearing type) to Azure Blob Storage, in addition to the existing SQL Server storage +/// (fds__setInvoiceFile / fds__setReminderFile). +/// +public interface IBlobStorageService +{ + /// + /// Uploads a finalized invoice PDF to Azure Blob Storage. When is + /// supplied (typically FdsInvoiceData.InvoiceRegistration), blob metadata is projected from + /// it using — see . + /// Returns the blob URI, or null when storage is disabled/unconfigured + /// or the upload failed — failures never break the primary DB-storage flow. + /// + Task UploadInvoicePdfAsync(string invoiceId, string fileName, byte[] content, + IReadOnlyDictionary? sourceRow = null, CancellationToken cancellationToken = default); + + /// + /// Uploads a finalized reminder PDF to Azure Blob Storage. When is + /// supplied (typically FdsReminderData.ReminderRegistration), blob metadata is projected from + /// it using — see . + /// Returns the blob URI, or null when storage is disabled/unconfigured + /// or the upload failed — failures never break the primary DB-storage flow. + /// + Task UploadReminderPdfAsync(string reminderId, string fileName, byte[] content, + IReadOnlyDictionary? sourceRow = null, CancellationToken cancellationToken = default); + + /// + /// Generic upload for any document category — used by the startup archive backfill so + /// invoice/reminder/future file types can all be archived through one entry point. The + /// caller supplies the target container name and a category label (used for logging/telemetry), + /// plus the source row driving metadata projection (see ). + /// Returns the blob URI, or null when storage is disabled/unconfigured or the upload failed. + /// + Task UploadDocumentAsync(string category, string containerName, string documentId, string fileName, + byte[] content, IReadOnlyDictionary? sourceRow = null, CancellationToken cancellationToken = default); + + /// + /// Returns true if a blob already exists for the given container/document/filename + /// combination. Used by the startup backfill to skip documents that were already archived. + /// Returns false (never throws) when storage is disabled/unconfigured or the check fails. + /// + Task ExistsAsync(string containerName, string documentId, string fileName, + CancellationToken cancellationToken = default); +} diff --git a/Fuchs/Services/InvoiceService.cs b/Fuchs/Services/InvoiceService.cs index 2808515..7433436 100644 --- a/Fuchs/Services/InvoiceService.cs +++ b/Fuchs/Services/InvoiceService.cs @@ -1,4 +1,4 @@ -using System.Data; +using System.Data; using System.Diagnostics; using Fuchs.intranet; using Fuchs.Observability; @@ -22,12 +22,15 @@ public class InvoiceService : IInvoiceService { private readonly Fuchs_intranet _intranet; private readonly IPdfService _pdf; + private readonly IBlobStorageService _blobStorage; private readonly ILogger _logger; - public InvoiceService(Fuchs_intranet intranet, IPdfService pdf, ILogger logger) + public InvoiceService(Fuchs_intranet intranet, IPdfService pdf, IBlobStorageService blobStorage, + ILogger logger) { _intranet = intranet; _pdf = pdf; + _blobStorage = blobStorage; _logger = logger; } @@ -142,7 +145,12 @@ public class InvoiceService : IInvoiceService bool r = await setSQLValue_async( "EXECUTE [dbo].[fds__setInvoiceFile] @Id, @file;", Conn, pl, Security: dbSec, options: new FIS_SQLOptions()); - return r ? ba : Array.Empty(); + if (!r) return Array.Empty(); + + string fileName = invoice.InvoiceRegistration?.getString("DocumentName") + .ne($"Rechnung_{invoice.Id}.pdf") ?? $"Rechnung_{invoice.Id}.pdf"; + await _blobStorage.UploadInvoicePdfAsync(invoice.Id, fileName, ba, invoice.InvoiceRegistration); + return ba; } public async Task GetInvoiceFileAsync(FdsInvoiceData invoice, bool draft, fds.IFdsMfr mfr) diff --git a/Fuchs/Services/ProcessWebComService.cs b/Fuchs/Services/ProcessWebComService.cs index 6c5183c..2f1f658 100644 --- a/Fuchs/Services/ProcessWebComService.cs +++ b/Fuchs/Services/ProcessWebComService.cs @@ -23,6 +23,7 @@ public class ProcessWebComService : IComService private readonly ILogger _logger; private readonly Fuchs_intranet _intranet; private readonly ProcessWebComSettings _settings; + private readonly FuchsEmailSettings _emailSettings; private readonly IHttpClientFactory _httpClientFactory; private const string SignatureIntro = @@ -34,11 +35,13 @@ public class ProcessWebComService : IComService ILogger logger, Fuchs_intranet intranet, IOptions settings, + IOptions emailSettings, IHttpClientFactory httpClientFactory) { _logger = logger; _intranet = intranet; _settings = settings.Value; + _emailSettings = emailSettings.Value; _httpClientFactory = httpClientFactory; } @@ -47,6 +50,22 @@ public class ProcessWebComService : IComService { using var act = FuchsTelemetry.StartActivity("email.send"); act?.SetTag("fuchs.email.ref", reference); + + string overrideRecipient = _emailSettings.OverrideRecipient ?? ""; + if (!string.IsNullOrWhiteSpace(overrideRecipient)) + { + // Dev/test safety net: discard the real recipient (to/cc/bcc) entirely and + // redirect every outbound email to a single controlled inbox, so a locally + // enabled mailer can never reach a real tenant-owner or end-customer. + _logger.LogWarning( + "SendEmailAsync: recipient override active for ref {Reference} – redirecting from '{OriginalEmail}' to '{OverrideRecipient}'", + reference, email, overrideRecipient); + act?.SetTag("fuchs.email.overridden", true); + act?.SetTag("fuchs.email.original_recipient", email); + subject = $"[DEV \u2192 {email}] {subject}"; + email = overrideRecipient; + } + if (!IsValidEmail(email)) { _logger.LogWarning("SendEmailAsync: invalid email address '{Email}' for ref {Reference}", email, reference); diff --git a/Fuchs/Services/ReminderService.cs b/Fuchs/Services/ReminderService.cs index acebce4..1d03409 100644 --- a/Fuchs/Services/ReminderService.cs +++ b/Fuchs/Services/ReminderService.cs @@ -1,4 +1,4 @@ -using System.Data; +using System.Data; using System.Diagnostics; using Fuchs.intranet; using Fuchs.Observability; @@ -22,12 +22,15 @@ public class ReminderService : IReminderService { private readonly Fuchs_intranet _intranet; private readonly IPdfService _pdf; + private readonly IBlobStorageService _blobStorage; private readonly ILogger _logger; - public ReminderService(Fuchs_intranet intranet, IPdfService pdf, ILogger logger) + public ReminderService(Fuchs_intranet intranet, IPdfService pdf, IBlobStorageService blobStorage, + ILogger logger) { _intranet = intranet; _pdf = pdf; + _blobStorage = blobStorage; _logger = logger; } @@ -145,7 +148,12 @@ public class ReminderService : IReminderService bool r = await setSQLValue_async( "EXECUTE [dbo].[fds__setReminderFile] @Id, @file;", Conn, pl, Security: dbSec, options: new FIS_SQLOptions()); - return r ? ba : Array.Empty(); + if (!r) return Array.Empty(); + + string fileName = reminder.ReminderRegistration?.getString("DocumentName") + .ne($"Zahlungserinnerung_{reminder.Id}.pdf") ?? $"Zahlungserinnerung_{reminder.Id}.pdf"; + await _blobStorage.UploadReminderPdfAsync(reminder.Id, fileName, ba, reminder.ReminderRegistration); + return ba; } public async Task GetReminderFileAsync(FdsReminderData reminder, bool draft, diff --git a/Fuchs/appsettings.Development.json b/Fuchs/appsettings.Development.json index 76ca4d1..73a182f 100644 --- a/Fuchs/appsettings.Development.json +++ b/Fuchs/appsettings.Development.json @@ -1,7 +1,8 @@ { "ConnectionStrings": { - "ocms_ConnectionString": "Server=localhost;Database=ocms;User Id=DEV_USERNAME;Password=DEV_PASSWORD;TrustServerCertificate=True;", - "fuchs_fds_ConnectionString": "Server=localhost;Database=fuchs_fds;User Id=DEV_USERNAME;Password=DEV_PASSWORD;TrustServerCertificate=True;" + "fuchs_fds_ConnectionString": "Data Source=MSSQL4.NBG4.DOMAINXYZ.DE,10439;Initial Catalog=site_fuchs_dev;Persist Security Info=False;TrustServerCertificate=true;Encrypt=true;User ID={username};password='{password}';Connect Timeout=60;Load Balance Timeout=240;Max Pool Size=500;", + "fuchs_fds_username_Dev": "fuchs_dev", + "fuchs_fds_password_Dev": "!Po@cGZ5bUn37khO" }, "Logging": { "LogLevel": { @@ -12,9 +13,14 @@ "Fuchs": { "FDS_Intranet_DebugState": true, "DevAutoLogin": true, - "DevAutoLoginEmail": "your.email@example.com", + "DevAutoLoginEmail": "info@processweb.de", "Email": { - "DevRedirectAddress": "service@emails.processweb.de" + "OverrideRecipient": "service@emails.processweb.de" + }, + "AzureStorage": { + "Enabled": false, + "InvoiceContainer": "dev-fuchs-invoices", + "ReminderContainer": "dev-fuchs-reminders" } } } diff --git a/Fuchs/appsettings.json b/Fuchs/appsettings.json index d773025..930f754 100644 --- a/Fuchs/appsettings.json +++ b/Fuchs/appsettings.json @@ -5,10 +5,9 @@ "CacheFilePath": "secrets.cache", "SyncIntervalHours": 6, "ManagedSecretKeys": [ - "ConnectionStrings--ocms-username", - "ConnectionStrings--ocms-password", "ConnectionStrings--fuchs-fds-username", "ConnectionStrings--fuchs-fds-password", + "ConnectionStrings--AzureBlobStorage-ConnectionString", "Fuchs--SMS-APIKey", "Fuchs--Mailer--Token", "Fuchs--fuchs-captcha-TOTP", @@ -23,12 +22,10 @@ }, "AllowedHosts": "*", "ConnectionStrings": { - "ocms_ConnectionString": "Server=DB_SERVER;Database=ocms;User Id={username};Password={password};TrustServerCertificate=True;", - "fuchs_fds_ConnectionString": "Server=DB_SERVER;Database=fuchs_fds;User Id={username};Password={password};TrustServerCertificate=True;", - "ocms_username": "MANAGED_BY_KEYVAULT", - "ocms_password": "MANAGED_BY_KEYVAULT", + "fuchs_fds_ConnectionString": "Data Source=MSSQL4.NBG4.DOMAINXYZ.DE,10439;Initial Catalog=site_fuchs_dev;Persist Security Info=False;TrustServerCertificate=true;Encrypt=true;User ID={username};password='{password}';Connect Timeout=60;Load Balance Timeout=240;Max Pool Size=500;", "fuchs_fds_username": "MANAGED_BY_KEYVAULT", - "fuchs_fds_password": "MANAGED_BY_KEYVAULT" + "fuchs_fds_password": "MANAGED_BY_KEYVAULT", + "AzureBlobStorage_ConnectionString": "MANAGED_BY_KEYVAULT" }, "Fuchs": { "ocms_guid": "00094b8f-a822-4e9c-b627-87802f93fca8", @@ -45,6 +42,15 @@ "Token": "MANAGED_BY_KEYVAULT", "Enabled": false }, + "Email": { + "OverrideRecipient": "" + }, + "AzureStorage": { + "Enabled": false, + "InvoiceContainer": "fuchs-invoices", + "ReminderContainer": "fuchs-reminders", + "MetadataFields": [ "Id", "Version", "InvoiceId", "InvoiceTitle", "InvId", "DocumentName", "file_guid" ] + }, "Telemetry": { "Enabled": true, "OtlpEndpoint": "" diff --git a/Fuchs/js/intranet/fis_main.js b/Fuchs/js/intranet/fis_main.js index 1747caa..b028006 100644 --- a/Fuchs/js/intranet/fis_main.js +++ b/Fuchs/js/intranet/fis_main.js @@ -150,7 +150,7 @@ $fis.resetPass = function (id, fds) { $fis.wdg = function (options) { let wf = $(this).empty(); $ocms.postXT({ - url: $ocms.url('wdg/one'), data: { short_name: options.wdg }, success: function (response, textStatus, jqXHR) { + url: $ocms.url('wdg/one'), data: { short_name: options.wdg }, timeout: 90000, success: function (response, textStatus, jqXHR) { let wi = options.wdg, wx = response[wi]; if (!wx) { wf.ldng(0); return; } let dbl = $.inArrayRegEx('dblwidth', wx.rendering_options) > -1, tiny = $.inArrayRegEx('tiny', wx.rendering_options) > -1; @@ -175,7 +175,7 @@ $fis.wdg = function (options) { var tdr = $$.tr().appendTo(tblset.bdy); $.each(wx.columns, function (ci, col) { var tdc = $$.td().appendTo(tdr); - if (dx[col] instanceof Date || $ocms.isDateString(dx[col]) === true) { + if (dx[col] instanceof Date || $ocms.isJSONDateString(dx[col]) === true) { tdc.text(fdt(dx[col], $t.dateformat)); } else { tdc.rwText(dx[col]); diff --git a/Fuchs/js/intranet/oci_basic.js b/Fuchs/js/intranet/oci_basic.js index 03bffe6..d826cd1 100644 --- a/Fuchs/js/intranet/oci_basic.js +++ b/Fuchs/js/intranet/oci_basic.js @@ -168,21 +168,34 @@ function ne(inp, alt) { return (inp || '') === '' ? (alt || '') : inp; } function pad(i, n) { return (i || '').toString().padStart(n, '0').substr(-1 * n); } +function twoDigitYear(y) { var n = parseInt(y, 10); return n + (n < 70 ? 2000 : 1900); } +/* Parses dot-separated German short dates (dd.MM.yyyy / dd.MM.yy, optionally with a time part). + Returns null if the string does not match, so callers can fall back to other parsing. */ +function parseGermanDate(si) { + var g = si.match(/^(\d{1,2})\.(\d{1,2})\.(\d{2}|\d{4})(?:[\sT](\d{1,2}):(\d{2})(?::(\d{2}))?)?$/); + if (g === null) { return null; } + var yr = g[3].length === 2 ? twoDigitYear(g[3]) : parseInt(g[3], 10); + return new Date(yr, parseInt(g[2], 10) - 1, parseInt(g[1], 10), parseInt(g[4] || '0', 10), parseInt(g[5] || '0', 10), parseInt(g[6] || '0', 10)); +} function parseISO(s) { let si = s || ''; if (si === '') { return null }; if (/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/.test(si) === true) { return new Date(si); } else { - var b = s.split(/\D/); - return new Date(b[0], b[1] - 1, b[2], b[3], b[4], b[5]); + var gd = parseGermanDate(si); + if (gd !== null) { return gd; } + var b = si.split(/\D/); + return new Date(b[0], b[1] - 1, b[2], b[3] || 0, b[4] || 0, b[5] || 0); } } function parseISOLocal(s) { let si = s || ''; if (si === '') { return null }; - var b = s.split(/\D/); - return new Date(b[0], b[1] - 1, b[2], b[3], b[4], b[5]); + var gd = parseGermanDate(si); + if (gd !== null) { return gd; } + var b = si.split(/\D/); + return new Date(b[0], b[1] - 1, b[2], b[3] || 0, b[4] || 0, b[5] || 0); } function fnum(i, style) { /* { style: 'decimal/currency/percent', currency: 'USD/EUR', currencyDisplay: 'symbol/code/name', minimumIntegerDigits: 1, minimumFractionDigits: 2, maximumFractionDigits: 3, useGrouping: true } */ diff --git a/Fuchs/js/intranet/oci_main.js b/Fuchs/js/intranet/oci_main.js index 1650ac9..25c007a 100644 --- a/Fuchs/js/intranet/oci_main.js +++ b/Fuchs/js/intranet/oci_main.js @@ -11,9 +11,13 @@ $(this).remove(); api.rendered = false; }; - $ocms.isDateString = function (inp) { + /* Tests whether a string is a JSON/ISO-8601 date(-time) value as emitted by the + backend's JSON serializer (e.g. Newtonsoft "2021-09-09T00:00:00[.fff][Z|+hh:mm]"). + Deliberately NOT based on the native Date constructor, which guesses ambiguous + formats (e.g. dotted dd.MM.yy strings) heuristically and inconsistently. */ + $ocms.isJSONDateString = function (inp) { if (typeof inp !== 'string') { return false; } else { - return isNaN(new Date(inp)) === false; + return /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})?)?$/.test(inp); } } $ocms.failure = function (jqXHR) { diff --git a/Fuchs/wwwroot/fts/glyphicons-halflings-regular.eot b/Fuchs/wwwroot/fts/glyphicons-halflings-regular.eot index b5aab370d3be0a7ebfdea2b3463a66038c60404b..b93a4953fff68df523aa7656497ee339d6026d64 100644 GIT binary patch delta 19956 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 diff --git a/Fuchs/wwwroot/fts/glyphicons-halflings-regular.ttf b/Fuchs/wwwroot/fts/glyphicons-halflings-regular.ttf index 8dab1177e349a2035af341b04d6c9b5715950b2a..1413fc609ab6f21774de0cb7e01360095584f65b 100644 GIT binary patch literal 45404 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 diff --git a/Fuchs/wwwroot/fts/glyphicons-halflings-regular.woff b/Fuchs/wwwroot/fts/glyphicons-halflings-regular.woff index a078bce828135ffdc0b9df62412eaf8dee9d0b32..9e612858f802245ddcbf59788a0db942224bab35 100644 GIT binary patch literal 23424 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 G`u_lkUM?>H literal 42816 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 literal 32536 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 -1, tiny = $.inArrayRegEx('tiny', wx.rendering_options) > -1; @@ -3000,7 +3017,7 @@ $fis.wdg = function (options) { var tdr = $$.tr().appendTo(tblset.bdy); $.each(wx.columns, function (ci, col) { var tdc = $$.td().appendTo(tdr); - if (dx[col] instanceof Date || $ocms.isDateString(dx[col]) === true) { + if (dx[col] instanceof Date || $ocms.isJSONDateString(dx[col]) === true) { tdc.text(fdt(dx[col], $t.dateformat)); } else { tdc.rwText(dx[col]); diff --git a/Fuchs/wwwroot/web/fis.min.js b/Fuchs/wwwroot/web/fis.min.js index 3387aa7..df2359d 100644 --- a/Fuchs/wwwroot/web/fis.min.js +++ b/Fuchs/wwwroot/web/fis.min.js @@ -1,4 +1,4 @@ var $t={lng:"de-DE",dn:["So","Mo","Di","Mi","Do","Fr","Sa"],mn:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],ma:["Jan","Feb","Mrz","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],datepattern:"(0[1-9]|1[0-9]|2[0-9]|3[01]).(0[1-9]|1[012]).[0-9]{4}",datetimepattern:"(0[1-9]|1[0-9]|2[0-9]|3[01]).(0[1-9]|1[012]).[0-9]{4}\\s([0-5][0-9]):([0-5][0-9])",dateplaceholder:"dd.MM.yyyy",datetimeplaceholder:"dd.MM.yyyy HH:mm",dateformat:"dd.MM.yyyy",datetimeformat:"dd.MM.yyyy HH:mm",f1:"Der Server hat einen Fehler gemeldet: \n",f2:"Bitte versuchen Sie es erneut.",m0:"Diese Internet-Seite benötigt einen html5-kompatiblen Browser.",m0b:"Unterstützt werden bspw: Internet Explorer ab Version 10, Firefox ab Version 31, Chrome ab Version 31, Safari ab Version 7, Opera ab Version 27",m1:"Dieser Datensatz ist momentan von jemand anderem zur Bearbeitung gesperrt.",m2:"Diese Funktion ist zur Zeit nicht verfügbar",t1:"Eingabe erforderlich.",t2:"Eingabe ist nicht erforderlich.",true:"Ja",false:"Nein",alert:"Hinweis",confirm:"Bestätigen",open:"Öffnen","not implemented":"Diese Funktion in zur Zeit noch nicht verfügbar.",l0:"Anmeldung",l1:"Email / Anmeldename",l2:"Email-Adresse / Anmeldename",l3:"Passwort",l4:"Benutzer",l5:"Wird vom System ermittelt...",l6:"Anmelden",l7:"Passwort vergessen?",l7a:'Die "Passwort vergessen"-Funktion läuft in zwei Schritten ab:\n \nIm ersten Schritt wird eine SMS mit einem Code an die hinterlegte Mobilfunk-Nummer versandt.\nIm zweiten Schritt geben Sie bitte diesen Code in das Formular ein und übermitteln es erneut.\n \nIn beiden Schritten wird aus Sicherheitsgründen kein Fehler angezeigt und auch dann ein erfolgreicher Versand bestätigt, wenn die Kombination aus Email-Adresse und Nachname nicht gefunden wurde und/oder der code falsch ist.',l8:"Keinen Account?",l9:"Anmeldenamen der Email-Adresse wurde nicht erkannt.",l10:"Nachname",l11:"Email-Adresse",l12:"Passwort zusenden",l13:"Das Passwort wurde erfolgreich verschickt",l14:"Das Passwort konnte nicht verschickt werden",l15:"Sie sind nicht berechtigt, diese Funktion auszuführen.",l16:"Sie müssen zunächst einen Account angeben.",l17:"Die Kombination aus Anmeldenamen und Passwort konnte nicht bestätigt werden.",l18:"Es gibt ein Problem mit dem Formular.\nEs kann momentan nicht verarbeitet und versendet werden.",name:"Name",submit:"Senden",cancel:"Abbrechen",noop:"Diese Funktion is noch nicht verfügar."};$.extend($t,{t1:"Eingabe erforderlich",t2:"Bitte überprüfen Sie Ihre Eingaben im Formular.",b0:"Erstellt",b1:"Zuletzt geändert",b2:"von",t12:"Der Server hat einen Fehler zurückgegeben. Bitte versuchen Sie es erneut.",t17:"Eine Email mit einem Aktivierungs-Link wurde an deine Adresse versandt.",t18:"Ein Account mit deinem Namen existiert bereits. Dennoch erstellen?",t19:"Einträge sind entweder unngültig oder zu kurz.",t20:"Der Server hat einen Fehler gemeldet. Bitte versuch es erneut.",t21:"Der Zugang wurde nicht gefunden.",t30a:"Als erledigt markieren.",t30b:"Als unerledigt markieren.",t55:"Ein Email mit einem Aktivierungs-Link wurde an Ihre Adresse versandt.",t56:"Ein Zugang für diesen Namen besteht bereits. Trotzdem erstellen?",t57:"Ein bestehender Zugang wurde für diese Serie registriert.",t60:"Bitte geben Sie Email-Adresse an, die Sie hier hinterlegt haben.",t61:"Ihr Passwort wurde erfolgreich versandt.",t62:"Die angegebene Email-Adresse stimmt nicht mit der hier hinterlegten überein.",ov:"Persönliche Übersicht"});var $v={}; /*! loadCSS. [c]2020 Filament Group, Inc. MIT License */ /*! onloadCSS. (onload callback for loadCSS) [c]2017 Filament Group, Inc. MIT License */ -function onloadCSS(t,e){e=e||{};let n=function(e){return new Promise(((n,r)=>{t.addEventListener?e.addEventListener("load",newcb):t.attachEvent&&e.attachEvent("onload",newcb),"isApplicationInstalled"in navigator&&"onloadcssdefined"in t&&e.onloadcssdefined(newcb)}))};if(Array.isArray(t)){let r=t.length;Promise.all(t.map(n)).then((function(t){var n=t.reduce(((t,e)=>t+(!0===e?1:0)));!async function(t){!0===t&&"function"==typeof e.success?e.success():!0===t&&"object"==typeof e.success&&e.success instanceof Promise&&await e.success(),e.complete()}(r===n)}))}else n(t)}!function(t){"use strict";var e=function(e,n,r,i){var o,a=t.document,s=a.createElement("link");if(n)o=n;else{var l=(a.body||a.getElementsByTagName("head")[0]).childNodes;o=l[l.length-1]}var c=a.styleSheets;if(i)for(var d in i)i.hasOwnProperty(d)&&s.setAttribute(d,i[d]);s.rel="stylesheet",s.href=e,s.media="only x",function t(e){if(a.body)return e();setTimeout((function(){t(e)}))}((function(){o.parentNode.insertBefore(s,n?o:o.nextSibling)}));var u=function(t){for(var e=s.href,n=c.length;n--;)if(c[n].href===e)return t();setTimeout((function(){u(t)}))};function f(){s.addEventListener&&s.removeEventListener("load",f),s.media=r||"all"}return s.addEventListener&&s.addEventListener("load",f),s.onloadcssdefined=u,u(f),s};"undefined"!=typeof exports?exports.loadCSS=e:t.loadCSS=e}("undefined"!=typeof global?global:this);const isIE=/MSIE\/|Trident/gi.test(window.navigator.userAgent)||void 0!==window.document.documentMode,isfileapi=!!(window.File&&window.FileReader&&window.FileList&&window.Blob);var $ocms={auth:{},no:function(t){t.stopPropagation()},vmin:function(t){var e=$(window).width*(t||1),n=$(window).height*(t||1);return e($ocms.baseurl+"/"+(t||"")).replace(/\/\//,"/"),cexi:null};function deepCopy(t){var e,n,r;if("object"!=typeof t||null===t)return t;for(r in e=Array.isArray(t)?[]:{},t)n=t[r],e[r]=deepCopy(n);return e}function fields_definition(t,e,n){this.label_sng=!0===Array.isArray(t)?"":t||"",this.label_pl=!0===Array.isArray(t)?"":e||"",this.fields=!0===Array.isArray(t)?t:n||[],this.itm=function(t){for(var e=0;e0)for(var n=0;nt||"")).filter(((t,e)=>""!==t)).join(e)}function parseDt(t,e,n){t=(t||"").substr(0,e.length);var r=e,i=t.length>0&&e.split(";").some((function(e){for(var n,i=/[^yMdhms0-9]/gi,o=!0;null!==(n=i.exec(e));)o=o&&e.substr(n.index,1)===t.substr(n.index,1);var a=t.length===e.length&&o;return!0===a&&(r=e),a}));if(!0===i){for(var o,a=[0,0,0,0,0,0,0],s=/(mm{1,2}|dd{1,2}|MM{1,2}|(yy){2,4}|ss{1,2}|hh{1,2})(?!\w)/g;null!==(o=s.exec(r));)a["yMdhms".indexOf(o[0].substr(0,1))]=parseInt(("yy"===o[0]?"20":"")+t.substr(o.index,o[0].length))-("M"===o[0].substr(0,1)?1:0);var l=new(Function.prototype.bind.apply(Date,[null].concat(a)));return"string"==typeof n?fdt(l,n):l}return!1}function bool(t,e){return"boolean"==typeof t?t:"boolean"==typeof e&&e}function booln(t,e){return"boolean"==typeof t?t:"number"==typeof t?1===t:"boolean"==typeof e&&e}Date.prototype.isValid=function(){return!isNaN(this)},Date.prototype.format=function(t){return fdt(this,t)},Date.prototype.addDays=function(t){return this.setDate(this.getDate()+t),this},Date.prototype.isBetween=function(t,e){return this>t&&this section");$(window).scroll((function(e){let n=$(window).scrollTop(),r=$("body");r.toggleClass("unfocus",n>vh()-1.2*t),r.toggleClass("btb",n>.5*vh()-t)}))},$ocms.cf_reset=function(){return $("#contentframe").empty()},function(t){t.fn.scrollTo=function(e){if(t(this).length>0){var n=t(this).offset().top||0;n>0&&t("html, body").animate({scrollTop:n-hh()},2e3)}},t.fn.ldng=function(e){var n=!0;return"boolean"==typeof e?n=e:"number"==typeof e&&(n=e>0),t(this).toggleClass("loading",n)},"function"!=typeof t.noop&&(t.noop=function(){}),t.fn.hasAttr=function(e){var n=t(this).attr(e);return void 0!==n&&!1!==n},t.fn.parseCssPx=function(e){try{return parseFloat(t(this).css(e).replace("px","")||0)}catch(t){return 0}},t.max=function(t,e){return isNaN(t)&&isNaN(e)?null:isNaN(t)&&!isNaN(e)?e:!isNaN(e)&&isNaN(e)||t>=e?t:e},t.min=function(t,e){return isNaN(t)&&isNaN(e)?null:isNaN(t)&&!isNaN(e)?e:!isNaN(e)&&isNaN(e)||t<=e?t:e},t.lim=function(t,e){return isNaN(t)?null:isNaN(e)?t:e<=t?e:t},t.fn.enterKey=function(e){return this.each((function(){t(this).keypress((function(t){"13"===(t.keyCode?t.keyCode:t.which).toString()&&e.call(this,t)}))}))}}(jQuery),$ocms.defaultTimeout=3e4,$ocms.AjaxEX=function(t){var e=this;e.responseText=e.responseText||"";var n=e.getResponseHeader("x-ocms-code")||"";e.internalCode=""!==n&&!1===isNaN(n)?parseInt(n):-1,e.isInternal=e.internalCode>-1,e.internalText=decodeURIComponent((e.getResponseHeader("x-ocms-desc")||"").replace(/\+/g,"%20")||"");var r=e.internalText||t,i=e.internalCode||e.status;e.logtext=r+" ("+i+")"},$ocms.postXTS=function(t){$ocms.postXT.call(this,$.extend(t,{sync:!0}))},$ocms.postXT=function(t){if((t=t||{}).trycount=t.trycount||0,""!==(t.url||"")){t.url=-1!==t.url.indexOf("&yy=")?t.url:t.url.indexOf("?")>-1?t.url+"&yy="+(new Date).getTime():t.url+"?yy="+(new Date).getTime();var e=t.context||this;switch(t.context=e,t.retryLimit=t.retryLimit||0,t.timeout=t.timeout||$ocms.defaultTimeout,t.timeout<100&&(t.timeout=1e3*t.timeout),t.data=t.data||{},t.contentType=t.contentType||"multipart/form-data; charset=UTF-8",t.islogin="boolean"==typeof t.islogin&&t.islogin,t.contentType){case"":case"json":t.contentType="application/json; charset=utf-8";break;case"form":t.contentType="application/x-www-form-urlencoded; charset=UTF-8";break;case"multi":t.contentType="multipart/form-data";break;case"text":t.contentType="text/plain; charset=UTF-8"}if(t.form instanceof jQuery?(t.data=t.form.serializeObject(),t.contentType="form-data"):t.lzw instanceof jQuery&&(t.data.lzw=$.ccLZW(t.lzw.serializeAnything(!0)).join(",")),"multipart/form-data"!==t.contentType.substr(0,19)&&"form-data"!==t.contentType.substr(0,9)||t.data instanceof FormData!=!1)t.data instanceof FormData&&(t.contentType=!1,t.processData=!1);else{t.contentType=!1;var n=new FormData;$.each(t.files||[],(function(t,e){n.append("upload_file",e)})),$.each(t.data||{},(function(t,e){n.append(t,e)})),t.data=n,t.processData=!1}var r={type:t.method||"post",url:t.url,data:t.data,processData:"boolean"!=typeof t.processData||t.processData,contentType:t.contentType,cache:t.cache||!1,timeout:t.timeout,beforeSend:function(n){$(t.loading).ldng(),$("body").addClass("ldng"),"function"==typeof t.beforesend&&t.beforesend.apply(e,[n])},success:function(n,r,i){"false"===n||"not authorized"===n?("function"==typeof t.error&&t.error.apply(e,[i,r,n]),"function"==typeof $.status&&$.status(r+" - "+n)):"function"==typeof t.success&&t.success.apply(e,[n,r,i])},error:function(n,r,i){if($ocms.AjaxEX.call(n,r),-1===t.url.indexOf("doc.ashx")||-1!==t.url.indexOf("ftest")){if(401===n.status&&111===n.internalCode&&!1===t.islogin&&"function"==typeof $ocms.login.dlg)$ocms.login.dlg({ajo:t});else if("timeout"===r||302===n.status)return t.tryCount++,t.tryCount<=t.retryLimit?void $ocms.postXT(t):void 0;"function"==typeof t.error?t.error.apply(e,[n,r,i]):"function"==typeof $ocms.failure?$ocms.failure.apply(e,[n]):"function"==typeof $.status&&$.status("Server error: "+r+" - "+i)}},dataType:t.datatype||"json",complete:function(n,r){"function"==typeof t.complete&&t.complete.apply(e,[n,r]),$(t.loading).ldng(0),$("body").removeClass("ldng");let i=$("body > .timer");if(i.length>0){let t=new Date(n.getResponseHeader("ocms_cec")||""),e=new Date(n.getResponseHeader("ocms_cex")||"");if(t.isValid()&&e.isValid()){let n=new Date,r=Math.abs(e-t);n.setMilliseconds(n.getMilliseconds()+r),i.data({cex:n,ctt:r}),$ocms.cex_timer()}}},context:e,async:!0};"boolean"==typeof t.sync&&(r.async=!1===t.sync),!0==("boolean"==typeof t.contentType&&!1===t.contentType)&&(r.contentType=!1),$.ajax(r)}},$ocms.cex_timer=function(){$ocms.cexi||($ocms.cexi=setInterval($ocms.cex_timer,15e3));let t=$("body > .timer"),e=t.data("cex"),n=t.data("ctt"),r=new Date;if(e instanceof Date&&e.isValid()&&"number"==typeof n&&n>0&&e>r){let i=Math.abs(r-e)/n*100;t.css("width",i.toString()+"%"),i<98&&(!$ocms.cex_lp||Math.abs(r-$ocms.cex_lp)>6e5)&&$ocms.postXT({url:$ocms.url("ping"),success:()=>{$ocms.cex_lp=r},timeout:5e3,error:()=>{}})}},$ocms.vbl_send=function(t){var e=t.data||{};if(""!==(e.url||"")){var n=$("#contentframe form:first"),r={url:e.url,data:new FormData,success:function(t){"function"==typeof e.success?e.success(t):"string"==typeof e.success&&alert(e.success)},error:function(t,n,r){"function"==typeof e.error?e.error(r):"string"==typeof e.error&&alert(e.error)},complete:function(){n.ldng(0)}},i=!0;n.find("input").each((function(){var t=$(this),e=t.nza("name"),n=t.val(),o=$(this).prop("required")||!1;if(""!==e){var a=""!==n||!1===o;i=i&&a,!0===a?(r.data.append(e,n),t[0].setCustomValidity("")):""!==$(this).nza("ocms-nvnote")&&t[0].setCustomValidity($(this).nza("ocms-nvnote"))}})),!0===i&&(n.ldng(1),$ocms.postXT.call(this,r))}},function(t){t.fn.nza=function(e,n){var r=t(this).attr(e);return void 0!==r&&!1!==r?r:n||""},t.fn.serializeObject=function(e,n){var r=/\r?\n/g,i=/^(?:submit|button|image|reset|file)$/i,o=/^(?:input|select|textarea|keygen)/i,a=/^(?:checkbox|radio)$/i,s=bool((n=n||{}).typedvalues,!1),l={},c=t(this),d=c.find(':input:not([nosend],[type="file"])').addBack(":input"),u=!0;return t.each(d.not(".tinymce").get(),(function(n,c){var d=t(this),f=this,p=(this.type||"").toLowerCase(),m=d.prop("required")||!1;if(!0===(f.name&&!d.is(":disabled")&&o.test(f.nodeName)&&!i.test(p))){var h=d.val(),g=f.name,y=d.nza("data-format").split(":"),$=d.nza("pattern")||".*";if(!0===a.test(p)&&(h=f.checked?""!==h?h:"true":""),"date"===y[0].substr(0,4)&&y.length>1)"boolean"==typeof(h=parseDt(h,y.slice(1).join(":")))&&(h=null),null===h&&"date"===d.prop("type").substr(0,4)&&!1===isNaN(new Date(d.val()))&&(h=new Date(d.val())),h instanceof Date==!0&&"function"==typeof h.getMonth?!1===s&&(h=fdt(h,"date"===y[0]?"dts":"iso")):h=null;else if("number"===p&&!0===s){let t;t="integer"===y[0]?parseInt(h):parseFloat(h),h=isNaN(t)?h:t}if(!0!==m||""!==(h||"")&&null!==h.match($)?!0===bool(e,!1)&&f.setCustomValidity(""):(!0===bool(e,!1)&&f.setCustomValidity(d.nza("ocms-nvnote",$ocms.t.inv||"Invalid field")),h=null),null!=h&&"string"==typeof h){let t=l[g];null!=t?Array.isArray(t)?t.push(h.replace(r,"\r\n")):l[g]=[t,h.replace(r,"\r\n")]:l[g]=h.replace(r,"\r\n")}else if(null!=h){let t=l[g];null!=t?Array.isArray(t)?t.push(h):l[g]=[t,h]:l[g]=h}else u=!1}})),d.filter(".tinymce").each((function(e,n){var r=t(this),i=((this.type||"").toLowerCase(),r.prop("required")||!1);try{var o=tinymce.get(t(n).attr("id"));if(o){var a=t(n).attr("name"),s=o.getContent();!1===i||""!==(s||"")?l[a]=s:u=!1}}catch(e){t.noop()}})),c.toggleClass("invalid",!u),u?l:null},t.fn.sendForm=function(e,n,r){var i=t(this);r=r||{};var o={url:e,success:function(t){if(r.response=t,"function"==typeof n)n(t);i.closest("div.modal").remove()},error:function(t,e,n){"function"==typeof r.error?r.error.call(this,t):$ocms.failure.call(this,t)},complete:function(){i.ldng(0),"function"==typeof r.complete&&r.complete.call(this,jqXHR)}},a=i.find('input[type="file"]');o.data=new FormData,a.length>0&&t.each(a[0].files,(function(t,e){o.data.append(t,e),o.data.append("file_lastmodified",$ocms.isodt(e.lastModifiedDate))}));var s=i.serializeObject();t.each(s||{},(function(t,e){o.data.append(t,e)})),i.ldng(),$ocms.postXT.call(this,o)},t.fn.checkValidity=function(){var e=t(this),n=!0;return e.each((function(t,e){n=n&&e.checkValidity()})),n},t.fn.wrap=function(e,n){var r=t(this),i=$$.dc(e).attr(n||{}).insertAfter(r);return r.append(i),i}}(jQuery),$ocms.logout=function(){$ocms.postXT({url:$ocms.url("logout"),complete:function(){window.location.reload()}})},$ocms.login={send:function(t){t.preventDefault();var e=$(this);if(!0===e.find("#dbtn-confirm").hasClass("disabled"))return!1;var n=e.serializeObject();return n.loginaccount=ne(n.loginaccount,$ocms.auth.account||$ocms.auth.requestedaccount||""),n.loginaccount=ne(n.loginaccount,$ocms.auth.account||$ocms.auth.requestedaccount||""),""===ne(n.loginaccount)&&!0===bool($ocms.auth.accountrequired,!0)?(alert($t.l16),!1):($ocms.postXT({url:$ocms.url("login"),data:n,success:function(){window.location.reload()}}),!1)},uichange:function(){let t=$(this),e=t.closest("form"),n=bool($ocms.auth.accountrequired,!0),r=ne(e.find('[name="loginaccount"]').val(),$ocms.auth.account||$ocms.auth.requestedaccount||"");if(""!==r||!1===n){var i=e.find('[name="userlogin"]').empty().val(""),o=e.find('[name="username"]').empty().val(""),a=$("#dlg_userlogin_sel").empty().val(""),s=t.val()||"";if(!1===t.checkValidity()&&""===s)return;var l=t.closest("table").ldng();$ocms.postXT.call(this,{url:$ocms.url("auth"),data:{userinfo:s,account:r||""},success:function(t,e,n){if(1===t.length){var r=t[0];i.val(r.login).change().attr("required","").removeAttr("nosend"),o.val(r.name).change().attr("required","").show(),a.removeAttr("required").attr("nosend","").hide()}else t.length>0?(o.hide().removeAttr("required"),i.removeAttr("required").attr("nosend",""),0===a.length&&(a=$("").attr({name:"userlogin",size:t.length,id:"dlg_userlogin_sel",class:"form-control",required:""}).css({width:"100%","max-width":"100%",padding:"2px"}).insertAfter(o)),$.each(t,(function(t,e){var n=$("").attr({value:e.login,style:"padding-top: 2px; padding-bottom: 5px;","border-bottom":"1px solid #EEE;"}).text(e.name).appendTo(a);t%2==0&&n.css({"background-color":"#F9F9F9"})})),a.attr("required","").removeAttr("nosend")):(a.hide().attr("nosend",""),o.attr("required","").show(),i.attr("required","").removeAttr("nosend"),alert($t.l9))},error:function(t){$ocms.failure.call(this,t)},complete:function(){l.ldng(0)}})}else alert($t.l18)},sendpassword:function(t){var e=$(''),n=e.find(".form-body"),r=null;e.find("form").submit((function(t){t.preventDefault();var i=$(this).serializeObject(!0),o=null===r,a=o?"spwc":"spw";return $ocms.postXT.call(this,{url:$ocms.url(a),data:i,complete:function(){o?(n.append('
Ihnen wurde ein Code per SMS zugesandt.
Bitte tragen Sie den hier ein:
'),r=$('
').appendTo(n)):(alert($t.l13),e.remove())},error:()=>{}}),!1})),e.find(".modal-close").click((function(){e.remove()}));var i=[];$.each($t.l7a.split("\n"),((t,e)=>{Array.prototype.push.apply(i,[$("
"),$("").text(e)])})),e.find(".modal-note").append($('').text($t.alert)).append(i),e.appendTo("body"),setTimeout((function(){$(".modal").find('input[name="lastname"]').focus()}),600)}};var $$={s:function(t){return $("").text(t)},br:function(){return $("
")},sc:function(t,e){return $("").addClass(t).text(e)},td:function(t,e){var n=$("");return t instanceof jQuery==!0?n.appendTo(t):"object"==typeof t?n.attr(t):"string"==typeof t&&n.text(t),"object"==typeof e?n.attr(e):"string"==typeof e&&n.text(e),n},th:function(t,e){var n=$("");return t instanceof jQuery==!0?n.appendTo(t):"object"==typeof t?n.attr(t):"string"==typeof t&&n.text(t),"object"==typeof e?n.attr(e):"string"==typeof e&&n.text(e),n},tdc:function(t,e,n){return $$.td(e,n).addClass(t)},td2:function(t){var e=$('');return"string"===$.type(t)?e.text(t):t instanceof jQuery?e.append(t):"function"==typeof t?t.call(e):e.html(" "),e},td3:function(t){var e=$('');return"string"===$.type(t)?e.text(t):t instanceof jQuery?e.append(t):"function"==typeof t?t.call(e):e.html(" "),e},tdtr:function(t,e){var n=$$.tr().appendTo(e);return t instanceof jQuery==!0||"string"==typeof t?t.appendTo($$.td().appendTo(n)):!0===Array.isArray(t)&&$.each(t,(function(t,e){$(e).appendTo($$.td().appendTo(n))})),n},tr:function(t,e){var n=$("");return t instanceof jQuery==!0?n.appendTo(t):"object"==typeof t&&n.attr(t),"object"==typeof e&&n.attr(e),n},trc:function(t,e){var n=$("").addClass(t);return e instanceof jQuery==!0?n.appendTo(e):"object"==typeof e&&n.attr(e),n},d:function(t){return $("
").attr(t||{})},dc:function(t,e,n,r){var i=$("
").addClass(t);return e instanceof jQuery==!0?i.appendTo(e):"object"==typeof e?i.attr(e):"function"==typeof e?i.click(e):"string"==typeof e&&i.text(e),"string"==typeof n?i.text(n):"object"==typeof n?i.attr(n):"function"==typeof n&&i.click(n),"string"==typeof r?i.text(r):"object"==typeof r?i.attr(r):"function"==typeof r&&i.click(r),i},df:function(t){return $("
 
").attr(t||{})},opt:function(t,e,n){var r=$("");return"string"==typeof t?r.attr("value",t):"object"==typeof t&&r.attr(t),"string"==typeof e?r.text(e):"object"==typeof e&&r.attr(e),"object"==typeof n&&r.attr(n),r},eOpt:function(t){var e=$('');return t&&e.attr("selected","selected"),e},tbl:function(t){return $("
").attr(t||{})},tblc:function(t){return $("
").addClass(t)},thead:function(t){let e=$("");return t instanceof jQuery&&e.prependTo(t),e},tbody:function(t){let e=$("");return t instanceof jQuery&&e.appendTo(t),e},tblset:function(t,e){let n=$$.tbl(t||{});return e instanceof jQuery&&e.append(n),{tbl:n,hd:$$.thead().appendTo(n),bdy:$$.tbody().appendTo(n)}},i:function(t){return $("").attr(t||{})},img:function(t,e){return $("").attr("src",t).attr(e||{})},sel:function(t){return $("").attr(t||{})},btn:function(t){return $("").attr(t||{})},a:function(t){return $("").attr(t||{})},li:function(t){return $("
  • ").attr(t||{})},ul:function(t){return $("
      ").attr(t||{})},nav:function(t){return $("").attr(t||{})},lbl:function(t,e){var n=$("");return"string"==typeof t&&n.text(t),"object"==typeof t?n.attr(t):"object"==typeof e&&n.attr(e),n},txt:function(t){return $("").attr(t||{})},0:function(t,e){return $("<"+t+">").attr(e||{})},bbtn:function(t,e){return $$.btn({type:"button",class:"btn"}).addClass(e).text(t)},svg:t=>$(document.createElementNS("http://www.w3.org/2000/svg",t))};function getMonday(t){var e=(t=new Date(t)).getDay(),n=t.getDate()-e+(0==e?-6:1);return new Date(t.setDate(n))}function $lf(t){var e=void 0===t?null:"number"==typeof t&&1!==t||"boolean"==typeof cl&&!1===t;return $("#listframe").tC("hd",e).is(".hd")}function $nuf(t){if(t&&t.stopPropagation(),!$(this).is(".disabled")){var e=function(t){t.removeClass("vis").find("li.dropdown").removeClass("open").removeClass("vis").attr("aria-expanded","false")},n=$(this).parent("li.dropdown");if(n.length>0){n.tC("open"),navs=!0===n.is(".open")?"true":"false",n.attr("aria-expanded",navs);var r=n.closest("nav");r.find("li.dropdown").not(n.parentsUntil("nav")).not(n).removeClass("open").attr("aria-expanded","false"),!1===n.is(".open")&&n.find("li.dropdown").removeClass("open").attr("aria-expanded","false"),e($("nav").not(r))}else e($("nav"))}}function $tbr(){return $lf(0),$("#topbar").ocmsmenu([])}function $lfr(){return $("#sidebar").empty(),$("#listframe").removeClass("fix").addClass("hd").empty()}function $cfr(){return $tbr(),$("#contentframe").empty()}function jObj(t,e){let n={};if("{"===(t||"").substr(0,1))try{n=JSON.parse(t)}catch(t){n={}}return n[e]||""}function string(t,e){var n,r=t||"";return $.each(e||[],(function(t,e){n=new RegExp("\\{"+t.toString()+"\\}","ig"),r=r.replace(n,e)})),r}function init_tooltip(t){var e=!0===("boolean"==typeof t&&t)&&"mouse";$("[title]").qtip({position:{target:e,adjust:{x:2,y:2},viewport:!0},events:{hidden:$ocms.tooltip_hidden},effect:!1}),$("div.tooltiptext").each((function(){$(this).filter(":not(:empty)").parent().qtip({suppress:!1,content:{text:$(this).clone()},position:{target:e,adjust:{x:2,y:2},viewport:!0},events:{hidden:$ocms.tooltip_hidden}})}))}String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")},String.prototype.left=function(t){if("string"===$.type(t)){var e=this.indexOf(t);return e>0?this.slice(0,e):""}return this.substring(0,t)},String.prototype.right=function(t){if("string"===$.type(t)){var e=this.indexOf(t);return e>0?this.substring(this.length-e):""}return this.substring(this.length-t)},Array.prototype.move=function(t,e){if(e>=this.length)for(var n=e-this.length;1+n--;)this.push(void 0);return this.splice(e,0,this.splice(t,1)[0]),this},function(t){t.fn.appendToIf=function(e,n){var r=t(this),i="function"==typeof n?n(r):n;return!0===("boolean"!=typeof i||i)&&r.appendTo(e),r},t.fn.appendIf=function(e,n){var r=t(this),i="function"==typeof n?n(r):n;return!0===("boolean"!=typeof i||i)&&r.append(e),r},t.fn.rwText=function(e,n,r){var i=t(this).empty();r=t.extend({wrap:!0},r);var o=!0===Array.isArray(e)?e:(null==e?"":String(e)).split("\n");return t.each(o,(function(t,e){""!==(e||"")&&(t>0&&i.append($$.br()),i.append(!0===r.wrap?$$.s(e):e))})),n&&i.attr("title",n),i},t.fn.loadSel=function(e,n,r){if("SELECT"===t(this).prop("tagName").toUpperCase()){var i=t(this);$ocms.postXT.call(this,{url:e,data:n||{},success:function(e){t.each(e,(function(){i.append($$.opt(e.value,e.text))}))},complete:function(){i.ldng(0),"function"==typeof r&&r.call(i)}})}},t.fn.emptyWithEditors=function(e){var n=t(this);return n.find(":input.tinymce").each((function(e,n){try{var r=tinymce.get(t(n).attr("id"));r&&r.remove()}catch(e){t.noop()}})),n.empty()},t.fn.cssValue=function(t){if(this.length>0){var e=this.css(t)||"";if(""===e)return 0;var n=/(^[\d\.]*)(\D{1,3}$)/gi.exec(e);return null!==n?"rem"===n[2]?$ocms.rpx(parseFloat(n[1])):parseFloat(n[1]):!1===isNaN(e)?parseFloat(e):0}return 0},t.fn.veryInnerHeight=function(){let e=e=>t(this).cssValue(e);return t(this).innerHeight()-e("padding-top")-e("padding-bottom")},t.fn.veryInnerWidth=function(){let e=e=>t(this).cssValue(e);return t(this).innerWidth()-e("padding-left")-e("padding-right")},t.fn.marginWidth=function(){let e=e=>t(this).cssValue(e);return e("margin-left")+e("margin-right")},t.fn.marginHeight=function(){let e=e=>t(this).cssValue(e);return e("margin-top")+e("margin-bottom")},t.inArrayRegEx=function(e,n,r){var i="regexp"===t.type(e)?e:new RegExp(e);if(!n)return-1;for(var o=r=r||0;o7){r=e.split(","),i=(n||(t<0?"rgb(0,0,0)":"rgb(255,255,255)")).split(",");var l=s(r[0].slice(4)),c=s(r[1]),d=s(r[2]);return"rgb("+(a((s(i[0].slice(4))-l)*o)+l)+","+(a((s(i[1])-c)*o)+c)+","+(a((s(i[2])-d)*o)+d)+")"}var u=(r=s(e.slice(1),16))>>16,f=r>>8&255,p=255&r;return"#"+(16777216+65536*(a((((i=s((n||(t<0?"#000000":"#FFFFFF")).slice(1),16))>>16)-u)*o)+u)+256*(a(((i>>8&255)-f)*o)+f)+(a(((255&i)-p)*o)+p)).toString(16).slice(1)},t.fn.IN=function(e){return t(this).fadeIn(400,e),t(this)},t.fn.OUT=function(e){return t(this).fadeOut(400,e),t(this)},t.fn.tooltip=function(e,n){var r=!0===("boolean"==typeof e&&e)&&"mouse",i="boolean"==typeof n&&n,o=t(this);return o.each((function(){var e=i?t(this).find(".tooltiptext"):t(this).children(".tooltiptext");t(e).length>0?e.each((function(){var e=t(this);t(this).filter(":not(:empty)").parent().qtip({suppress:!1,content:{text:e.clone()},position:{target:r,adjust:{x:2,y:2},viewport:!0},events:{hidden:$ocms.tooltip_hidden},show:{effect:!1},hide:{effect:!1}}),e.remove()})):t(this).qtip({position:{target:r,adjust:{x:2,y:2},viewport:!0},events:{hidden:$ocms.tooltip_hidden},effect:!1})})),o},t.fn.rC=function(e){return t(this).removeClass(e)},t.fn.aC=function(e){return t(this).addClass(e)},t.fn.tC=function(e,n){return t(this).toggleClass(e,n)}}(jQuery),function(t){t.fn.ocmsmenu=function(e,n){var r=t(this);return $ocms.menu.call(r,e,n),r},t.fn.activatemenu=function(){var e=t(this).filter("nav");return e.find("a").not(".on").addClass("on").click($nuf),e.find(".nav-btn").not(".on").addClass("on").click((function(e){e.stopPropagation();var n=t(this);t(n.attr("data-target")).tC(n.attr("data-toggle"))})),e}}(jQuery);class ObjectArray extends Array{isEmpty(){return 0===this[0].length}static get[Symbol.species](){return Array}filter(t){return"function"==typeof t?new ObjectArray(this[0].filter(t)):this}remove(t){if("function"!=typeof t)return this;{let e=this[0].findIndex(t);for(;e>-1;)this[0].splice(e),e=this[0].findIndex(t)}}sortBy(t){return"function"==typeof t&&this[0].sort(t),this}sortString(t){return this[0].sort(((e,n)=>{let r=(e[t]||"").toString().toUpperCase(),i=(n[t]||"").toString().toUpperCase();return console.debug(r.localeCompare(i)),r.localeCompare(i)})),this}sortNum(t){return this[0].sort(((e,n)=>{let r=e[t],i=n[t];return!0===isNaN(i)&&!1===isNaN(r)||ri?1:0})),this}sum(t){return this[0].reduce(((e,n)=>e+(!0===isNaN(n[t])?0:n[t])),0)}groupBy(t){return this[0].reduce((function(e,n){let r=n[t];return e[r]||(e[r]=[]),e[r].push(n),e}),{})}each(t){if("function"==typeof t){let e=!1;this[0].forEach(((n,r,i)=>{if(!1===e){let o=t(n,r,i);"boolean"==typeof o&&!1===o&&(e=!0)}}))}}get toArray(){return this[0]}}class NumArray extends Array{sum(){return this.reduce(((t,e)=>t+e))}first(){return this[0]}last(){return this[this.length-1]}average(){return this.sum()/this.length}range(){let t=this.map((t=>t)).sort();return{min:t[0],max:t[this.length-1]}}static get[Symbol.species](){return Array}}$ocms.ocmsmenu=[{lbl:"",id:"m_home",ico:"glyphicon glyphicon-home",fnc:"init:home"},{fnc:"separator"}],function(t){t.multline=function(t){let e=t.split("\n"),n=$$.d();return $.each(e,((t,e)=>{n.append($$.s(e))})),n.html()},t.tooltip_hidden=function(t,e){$(this).remove(),e.rendered=!1},t.isDateString=function(t){return"string"==typeof t&&!1===isNaN(new Date(t))},t.failure=function(e){11110===(e.internalCode||-1)?t.login.dlg():alert($t.f1+"\n"+(e.internalText||""))},t.getScript=function(e,n){var r=[],i=[],o=function(t){return"string"==typeof t&&""!==(t||"")},a=function(t,e){!0===bool(e.condition,!0)&&(""!==(e.script||"")&&i.push({url:e.script,module:e.module||""}),!0===o(e.css||"")?r.push(e.css):!0===Array.isArray(e.css)&&Array.prototype.push.apply(r,e.css.filter(o)))};!0===o(e||"")?i.push(e):!0===Array.isArray(e)?$.each(e,a):"object"==typeof e&&""!==(e.script||"")&&a(0,e);let s=[];$.each(r,(function(t,e){""!==(e||"")&&s.push(loadCSS(e))}));let l=i.map((function(e,n){let r=e.url,o=e.module||"";if(""===o){return new Promise((function(t,e){try{!async function(){$.ajax({url:r,dataType:"script",success:function(){t(i)},error:function(){e(i)},timeout:3e4})}()}catch(t){console.debug(t.message+"%o",t)}}))}return t.loadmodule(o,r,e.alias)}));Promise.all(l).then(n)},t.loadmodule=function(e,n,r){return new Promise((function(i,o){!async function(){try{let a=(n.startsWith("/")||n.startsWith(".")?"":"/")+n;import(a).then((n=>{t[e]=n[r||"default"],i(e)})).catch((t=>{console.debug(t.message+"%o",t),o(e)}))}catch(t){console.debug(t.message+"%o",t)}}()}))},t.ocms_auth=function(e,n,r,i){!1===$.isPlainObject(t.auth.modules)&&(t.auth.modules={});var o=0;t.auth.modules[e+(r||"")]?((o=t.auth.modules[e+(r||"")])<2&&(r||"")===auth.guid&&(o=2),o>=(n||0)&&i(false)):t.postXT({url:t.url("auth"),data:{module:e,person_guid:r||""},success:function(a){o=a[e],t.auth.modules[e+(r||"")]=o,o<2&&(r||"")===t.auth.person_guid&&(o=2),o>=(n||0)&&i(false)},error:function(e){t.failure.call(this,e)}})},t.auth.locale="de",t.ocms_prepauth=function(e,n,r){t.postXT({url:t.url("auth"),data:{fn:"csv",modules:e,person_guid:n||""},success:function(e){t.ocms_regauth(e)},error:function(e){t.failure.call(this,e)},complete:function(){r()}})},t.ocms_regauth=function(t){$.each(t||{},(function(t,e){auth.modules[t]=parseInt(e)}))},t.init=function(e){var n="string"==typeof e?e:(e.data||{}).fn||"";""!==n&&("home"===n?($cfr(),$lfr(),$("#topbar").ocmsmenu([],!0),$("#activemodule").text($t.ov),t.ov.call($("#contentframe"))):($cfr(),$lfr(),$("#topbar").ocmsmenu([]),t.postXT({url:t.url(n+"/auth"),success:function(e){void 0===t[n]&&(t[n]={}),t[n].auth=e,e.manage>0&&t.getScript({module:n,script:["web/imdl",n,t.auth.locale||"de","js"].join("."),css:["web/imdl",n,"css"].join("."),condition:"function"!=typeof t[n].init2},(function(){t[n].init2()}))},error:function(){$("#contentframe").empty()}})))},t.menuarray=function(t){this.array=[],this.sep=function(){this.length>0&&"separator"!==this.array[array.length-1].fnc&&this.push({fnc:"separator"})},this.push=function(t){return void 0===t?null:(!0===Array.isArray(t)?Array.prototype.push.apply(this.array,t):"object"==typeof t&&this.array.push(t),t)},this.unshift=function(t){return void 0===t?null:(!0===Array.isArray(t)?Array.prototype.unshift.apply(this.array,t):"object"==typeof t&&this.array.unshift(t),t)},this.push(t)},t.menu=function(e,n){e=e||[];var r=$(this).removeClass("vis");if(!0===bool(n,!0)&&!1===r.is("#mainmenu")&&r.empty(),!1===bool(n,!1)&&r.is("#sidebar,#topbar")&&(e.unshift({id:"sbctrl",glyph:"glyphicon-th-list",aclass:"fbtn",fnc:function(){$lf()}}),$lf(0)),0===(e||[]).length)r.empty().addClass("hd");else{r.removeClass("hd");var i=!0===r.is("nav")?r:r.children("nav");1!==i.length&&(i=$("").tC("nv",r.is("#sidebar")).tC("ctxt",r.is("#topbar")).appendTo(r));var o,a=$$.ul().appendTo(i),s=function(t,e){var n=$(this).addClass("dropdown submenu");t.append($$.sc("caret dd")).addClass("dds dropdown-toggle").attr({"aria-expanded":"false"}),""!==(e.ico||"")&&t.prepend($$.sc("ico "+e.ico));var r=$$.ul({class:"dropdown-menu",role:"menu"}).appendTo(n);$.each(e.itm||[],(function(t,e){o.call(r,e)}))},l=function(t){$(this).tC("disabled","boolean"==typeof t.disabled?t.disabled:"string"==typeof t.disabled&&"subs"===t.disabled&&0===(t.itm||[]).length)};o=function(e){var n,r=$$.li({id:e.id}).attr(e.attr||{}).addClass(e.lclass).appendTo($(this)),i="string"==typeof e.fnc&&""!==e.fnc?e.fnc.split(":")[0]:"";""!==i&&"init"!==i?r.attr("role",i).appendIf($$.s(e.lbl),""!==ne(e.lbl)):(n=$$.a({class:"on",role:"button"}).addClass(e.aclass).appendTo(r).append($$.s(e.lbl)),l.call(n,e),(e.itm||[]).length>0&&s.call(r,n,e),n.click($nuf),"function"==typeof e.fnc?n.click(e.data||{},e.fnc):"init"===i&&n.click($.extend({},e.data||{},{fn:e.fnc.split(":")[1]}),t.init))},$.each(e,(function(e,n){var r,i=$$.li({id:n.id}).attr(n.attr||{}).addClass(n.lclass),s="string"==typeof n.fnc&&""!==n.fnc?n.fnc.split(":")[0]:"";if(""!==s&&"init"!==s)i.attr("role",s).appendIf($$.s(n.lbl),""!==ne(n.lbl));else{if(r=$$.a({class:"on",role:"button"}).addClass(n.aclass).appendTo(i),l.call(r,n),""!==(n.lbl||"")&&r.append($$.s(n.lbl)),""!==(n.ico||"")&&r.prepend($$.sc("ico "+n.ico)),""!==(n.glyph||"")&&r.prepend($$.sc("glyphicon "+n.glyph)),(n.itm||[]).length>0){i.addClass("dropdown"),r.append($$.sc("caret dd")).addClass("dds dropdown-toggle").attr({"aria-expanded":"false"});var c=$$.ul({class:"dropdown-menu",role:"menu"}).appendTo(i);$.each(n.itm||[],(function(t,e){o.call(c,e)}))}(n.sel||[]).length>0||(r.click($nuf),"function"==typeof n.fnc?r.click(n.data||{},n.fnc):"init"===s&&r.click($.extend({},n.data||{},{fn:n.fnc.split(":")[1]}),t.init))}i.appendTo(a)})),i.activatemenu()}},t.easytbl=(t,e)=>{e=e||{};let n=$$.tbl().addClass(e.class).css("border-collapse","collapse"),r=($$.tbody(n),!0===bool(e.frame,!1)?{padding:"5px",border:"1px solid #727272"}:{});if(!0===Array.isArray(e.header)){let t=$$.thead(n);$.each(e.header,((n,i)=>$$.th(t).css(e.cellcss||r).rwText(i)))}else if(!0===bool(e.header,!1)&&(t||[]).length>0){let i=$$.thead(n);$.each(Object.keys(t[0]),((t,n)=>$$.th(i).css(e.cellcss||r).rwText(n)))}return $.each(t||[],((t,i)=>{let o=$$.tr();$.each(i,((t,n)=>{n=n||"";let i=$$.td(o).css(e.cellcss||r);n instanceof jQuery?i.append(n):"string"==typeof n&&("<"===n.substring(0,1)?i.append(n):i.text(n))})),n.append(o)})),n},t.dlgtbl=(e,n,r)=>{r=r||{};let i=t.easytbl(e,r);t.dlg(i,$.extend({title:n},r))},t.dlg=function(t,n){n=n||{};let r=$("body > .modal").length>0,i=t=>typeof n[t],o=t=>"function"===i(t);if(!0===bool(n.exclusive,!0)&&!0===r)return void alert($t.dbldlg||"Es ist bereits ein Dialog geöffnet");let a=$$.dc("modal",$("body")),s=$$.dc("modal-dialog",a);!1===isNaN(n.zindex)?a.css("zIndex",n.zindex):!0===r&&a.css("zIndex",parseInt($("body > .modal:last").cssValue("zIndex"))+200),!1===isNaN(n.zindex_min)&&a.cssValue("zIndex")').appendTo(u)),""!==ne(n.title)&&(l=$$.dc("modal-header",u),$("

      ").text(n.title).appendTo(l));let p=$$.dc("modal-body",u),m=$$.dc("modal-footer",u);t instanceof jQuery==!0&&p.append(t);let h=function(t){t&&"function"==typeof t.stopPropagation&&t.stopPropagation(),s.removeClass("in"),!0===o("closing")&&n.closing.call(u),p.hide().emptyWithEditors(),a.remove(),!0===o("close")&&n.close.call(u)};if(u.find(":input[required]").length>0&&($$.dc("note_required",m).append($$.sc("ind_required","*")).append($$.s($t.t1||"Eingabe erforderlich")),$$.dc("note_invalid",m).append($$.s($t.t2||"Bitte überprüfen Sie Ihre Eingaben im Formular."))),!0===o("cancel")){$$.bbtn(n.cancelbutton||"Abbrechen","cancel").attr({type:"button",role:"cancel"}).appendTo(m).click((function(t){n.cancel.call(u,t);t.stopPropagation(),h()}))}if(!0===o("confirm")){let t=$$.bbtn(n.button||"OK","confirm").attr({type:!0===bool(n.form,!1)?"submit":"button",role:"confirm"}).appendTo(m);!0===f?(u.submit((function(t){try{n.confirm.call(u,t)}finally{t.preventDefault()}return!1})),u.on("modal_submit",(function(){n.confirm.call(u,e)}))):(t.click((function(t){n.confirm.call(u,t);t.stopPropagation()})),u.on("modal_submit",(function(){t.click()})))}else!0===f&&u.submit((function(t){return t.preventDefault(),!1}));return u.on("modal_close",(function(){h()})),c.click(h),!0===o("opening")&&n.opening.call(u),s.addClass("in"),ne(n.mode).indexOf("maxbody")>-1&&p.css("min-height",(d.height()-l.outerHeight()-m.outerHeight()).toString()+"px"),!0===o("open")&&n.open.call(u),{hd:l,bdy:p,ft:m,ct:d,dlg:s,c:u}},t.mform=function(e){let n=$$.dc("form-body"),r=Array.isArray(e)?e:e instanceof fields_definition?e.fields:[];return $.each(r||[],(function(e,r){let i=r.type||"";if("ignore"===i)return!0;let o=$$.dc("form-group",n),a=r.id||"dlg_"+(r.name||"")+("html"===r.type?"_"+(65536*(1+Math.random())||0).toString(16).substr(9):""),s=$$.lbl(r.label||r.name,{for:a}).appendTo($$.dc("form-itm",o)),l=$$.dc("form-itm",o),c=$$.i({id:a,name:r.name,placeholder:r.placeholder,type:r.type});switch(i){case"email":r.pattern=ne(r.pattern,"[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$");break;case"url":r.pattern=ne(r.pattern,"https?://.+");break;case"number":r.pattern=ne(r.pattern,"[-+]?[0-9]*[.,]?[0-9]*"),c.attr("step",r.precision||"any"),c.attr("data-format","float");break;case"integer":case"int":r.pattern=ne(r.pattern,"[-+]?[0-9]*"),c.attr("type","number"),c.attr("data-format","integer");break;case"date":if(""!==ne(r.pattern,$t.datepattern)&&(r.pattern=ne(r.pattern,"("+$t.datepattern+")|([0-9]{4}.(0[1-9]|1[012]).(0[1-9]|1[0-9]|2[0-9]|3[01]))")),""!==ne(r.placeholder,$t.dateplaceholder)&&c.attr("placeholder",ne(r.placeholder,$t.dateplaceholder)),"string"==typeof r.value){var d=r.value.substr(0,10);r.value="date"!==c.prop("type")?fdt(d+"T00:00:00",ne(r.dateformat,$t.dateformat)):d}c.attr("data-format","date:"+ne(r.dateformat,$t.dateformat)+";yyyy-MM-dd");break;case"datetime":c.attr("type","datetime-local"),""!==ne(r.pattern,$t.datetimepattern)&&(r.pattern=ne(r.pattern,"("+$t.datetimepattern+")|([0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])\\s([0-5][0-9]):([0-5][0-9]))")),""!==ne(r.placeholder,$t.datetimeplaceholder)&&c.attr("placeholder",ne(r.placeholder,$t.datetimeplaceholder)),"string"==typeof r.value&&"T"===r.value.substr(10,1)&&(r.value="datetime"!==c.prop("type").substr(0,8)?fdt(r.value,ne(r.datetimeformat,$t.datetimeformat)):r.value),c.attr("data-format","datetime:"+ne(r.datetimeformat,$t.datetimeformat)+";yyyy-MM-dd HH:mm:ss");break;case"hidden":o.addClass("hd");break;case"html":case"text":c=$$.txt({id:a,name:r.name,placeholder:r.placeholder,type:r.type}),c.tC("tinymce","html"===r.type);break;case"bool":case"boolean":r.url=[{value:"true",label:($t||{}).true||"Yes"},{value:"false",label:($t||{}).false||"No"}],"boolean"==typeof r.value&&(r.value=r.value?"true":"false");case"select":c=$$.sel({id:a,name:r.name,type:r.type}),!1===bool(r.required,!1)&&$$.eOpt().appendTo(c);try{var u=function(t){!0===Array.isArray(t)&&$.each(t,(function(t,e){"string"==typeof e?$$.opt(e,e).appendTo(c):!0===Array.isArray(e)?$$.opt(e[0],e[1]).appendTo(c):"object"==typeof e&&$$.opt(e.value,e.label||e.text).appendTo(c)}))};!0===Array.isArray(r.url)?u(r.url):"function"==typeof r.url?r.url.call(c):"string"==typeof r.url&&t.postXT({url:r.url,success:u})}catch(t){$.noop()}break;default:""!==ne(r["max-length"])&&c.attr("max-length",r["max-length"])}""!==ne(r.pattern)&&c.attr("pattern",r.pattern),c.val(r.value).change(),c.change((function(){$(this)[0].setCustomValidity("")})),c.addClass("form-control").prop("required",bool(r.required,!1)).prop("readonly",bool(r.readonly,!1)).appendTo(l),!0===bool(r.required,!1)&&s.append($$.sc("ind_required","*")),"object"==typeof r.attr&&c.attr(r.attr),"object"==typeof r.prop&&c.prop(r.prop),"string"==typeof r.class&&c.addClass(r.class),"function"==typeof r.change&&(c.change(r.change),!0===bool(r.applychange,!1)&&void 0!==r.value&&c.change()),""!==(r.note||"")&&$$.dc("form-note",l).rwText(r.note),"function"==typeof r.complete&&r.complete.call(c)})),n},t.initMCE=function(t,e){t=$(t),e=e||{};try{let n={target:t[0],inline:!1,width:e.width||"100%",statusbar:!1,document_base_url:window.location.origin+"/",content_style:"ph:before {content: '«'; color: #BBB; font-style:italic; } ph:after {content: '»'; color: #BBB; font-style:italic; } ph { color: #AAA; font-style:italic; }",relative_urls:!1,remove_script_host:!1};!0===bool(e.hidemenu,!1)&&(n.menubar=!1,n.menu={}),!0===bool(e.hidetoolbar,!1)&&(n.toolbar=!1),$.extend(n,e||{}),tinymce.init(n)}catch(t){alert(t.message)}},t.dlgform=function(e,n){n=n||{};let r,i=$$.dc("frm").append(t.mform(e||[]).addClass("stacked"));n.addcontent instanceof jQuery&&i.append(n.addcontent),"function"==typeof n.submit?r=n.submit:"function"==typeof n.success&&(r=function(e){var r=$(this).ldng(1),i=$.extend({loginaccount:t.auth.account||""},r.serializeObject(bool(n.checkvalidity,!0),{typedvalues:bool(n.typedvalues,!1)}));""!==(n.url||"")?t.postXT({url:n.url,data:i,success:function(t){n.success.call(this,t),r.trigger("modal_close")},error:function(){alert($t.l17)},complete:function(){r.ldng(0)},timeout:6e4}):(n.success.call(this,i),r.trigger("modal_close"))});let o={form:!0,title:n.title||"",button:n.button||$t.submit,confirm:r,size:n.size||[500,600],open:function(){let e=$(this).find(".tinymce");e.length>0&&t.initMCE(e,n.tinymce||{})}};return t.dlg.call(this,i,o)},t.login.dlg=function(e){e=e||{};let n=[{name:"userinfo",label:$t.l1,type:"string",value:t.auth.login,change:t.login.uichange,required:!0},{name:"userlogin",type:"hidden",required:!0,value:t.auth.login},{name:"username",type:"string",label:$t.l4,required:!0,readonly:!0,placeholder:$t.l5,value:t.auth.fullname_rev},{name:"userpass",type:"password",label:$t.l3,required:!0,placeholder:$t.l3}];""===(t.auth.account||"")&&n.unshift({id:"dlg_loginaccount",name:"loginaccount",type:"string",required:!0,value:t.auth.account});let r=$$.dc("frm").append(t.mform(n).addClass("stacked")),i=t.dlg.call(this,r,{form:!0,title:$t.l0,button:$t.submit,confirm:function(n){var r=$(this).ldng(1),i=$.extend({loginaccount:t.auth.account||""},r.serializeObject());t.postXT({url:"/vt/login",data:i,success:function(n){""!==((n||{}).login||"")&&(r.trigger("modal_close"),t.auth=n,"object"==typeof e.ajo&&(e.ajo.islogin,$.ajax(e.ajo)))},error:function(){alert($t.l17)},complete:function(){r.ldng(0)},timeout:6e4})},size:[500,600]}),o=$$.dc("modal-content").css("height","auto").attr("novalidate","true").append($$.dc("modal-header").appendIf($("

      ").text(t.auth.accountname),""!==(t.auth.accountname||"")).append($("

      Vereinsmanager

      ")));i.dlg.prepend(o)},t.addNoEntryInfo=function(t){$(this).append($$.dc("noentryinfo").text(t||$t.t11))}}($ocms),Element.prototype.matches||(Element.prototype.matches=Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector),Element.prototype.closest||(Element.prototype.closest=function(t){var e=this;do{if(Element.prototype.matches.call(e,t))return e;e=e.parentElement||e.parentNode}while(null!==e&&1===e.nodeType);return null}),function(t,e){var n,r;"object"==typeof window&&(window[t]=(n=function(t){var e=window,n=document.body,r=document.documentElement,i=Math.max(0,e.pageXOffset||r.scrollLeft||n.scrollLeft||0)-(r.clientLeft||0),o=Math.max(0,e.pageYOffset||r.scrollTop||n.scrollTop||0)-(r.clientTop||0);return{x:t?Math.max(0,t.pageX||t.clientX||0)-i:0,y:t?Math.max(0,t.pageY||t.clientY||0)-o:0}},(r=function(t,e){t&&t instanceof Element&&(this._container=t,this._options=e||{},this._clickItem=null,this._dragItem=null,this._showDragItem="boolean"!=typeof this._options.dragItem||!1!==this._options.dragItem,this._hovItem=null,this._sortLists=[],this._click={},this._dragging=!1,this._dragHandleClass=this._options.dragHandleClass||"",this._parentident=this._options.parentident||"",this._swapdone="function"==typeof this._options.swapdone?this._options._swapdone:null,this._container.setAttribute("data-is-sortable",1),this._container.classList.add("sortable"),this._container.style.position="static",window.addEventListener("mousedown",this._onPress.bind(this),!0),window.addEventListener("touchstart",this._onPress.bind(this),!0),window.addEventListener("mouseup",this._onRelease.bind(this),!0),window.addEventListener("touchend",this._onRelease.bind(this),!0),window.addEventListener("mousemove",this._onMove.bind(this),!0),window.addEventListener("touchmove",this._onMove.bind(this),!0))}).prototype={constructor:r,toArray:function(t){t=t||"id";for(var e=[],n="",r=0;rr.left&&er.top&&n-1)&&e.className.indexOf("nosort")<0)&&(t.preventDefault(),this._dragging=!0,this._click=n(t),this._makeDragItem(e),this._onMove(t),!0)}t&&!1===e.call(this,t.target)&&""!==this._parentident&&t.target.closest(this._parentident)&&e.call(this,t.target.closest(this._parentident))},_onRelease:function(t){this._dragging=!1,this._trashDragItem()},_onMove:function(t){if(this._dragItem&&this._dragging){t.preventDefault();var e=n(t),r=this._container;!0===this._showDragItem&&this._moveItem(this._dragItem,e.x-this._click.x,e.y-this._click.y);for(var i=0;i0?s.mousedown(l).addClass("dctrl"):a.mousedown(l).addClass("dctrl"),t(this)}}(jQuery),$(document).ready((function(){$("html").click((function(t){$nuf()})),$("#listframe").click((function(t){t.stopPropagation(),$nuf()})),$("#mainmenu").ocmsmenu($ocms.ocmsmenu),$("#mainmenu").activatemenu()})),$.extend($t,{m_inv:"Rechnungen",m_req:"Aufträge",m_rep:"Berichte",m_todo:"ToDos",m_bcd:"BankBuchungen",rsp:"Passwort ändern",pnm:"Die Passwörter stimmen nicht überein",cps:"Das neue Passwort wurde gespeichert.",pwr:"Bitte wählen Sie ein starkes Passwort (min 8 Zeichen, davon jeweils min 2 Zahlen, kleine und große Buchstaben, Sonderzeichen sind optional).",smsc:"Sie beötigen für diese Funktion einen SMS-Code.\nSoll dieser nun versandt werden?",wdc:"Doppelt klicken, um die Box zu aktualisieren.",wdg:{}}),$t.rspf={sms:"Der SMS-Code konnte nicht bestätigt werden",valid:"Das alte Passwort ist nicht korrekt",requirements:"Das Passwort entspricht nicht den Anforderungen.\n"+$t.pwr},$fd={rsp:new fields_definition("","",[{name:"opw",label:"aktuelles Passwort",type:"password",required:!0,attr:{"auto-complete":"current-password"}},{name:"npw",label:"neues Passwort",type:"password",required:!0,pattern:"(.{6,})",attr:{"auto-complete":"new-password"}},{name:"npwc",label:"neues Passwort (Bestätigung)",type:"password",required:!0,attr:{"auto-complete":"new-password"},note:$t.pwr},{name:"code",label:"SMS-Code",type:"string",required:!0,attr:{"auto-complete":"one-time-code"}}])},$ocms.init=function(t){var e="string"==typeof t?t:(t.data||{}).fn||"";""!==e&&("home"===e?($cfr(),$lfr(),$("#topbar").ocmsmenu([],!0),$("#activemodule").text($t.ov),$fis.ov()):($cfr(),$lfr(),$("#topbar").ocmsmenu([]),$ocms.postXT({url:$ocms.url(e+"/auth"),success:function(t){void 0===$ocms[e]&&($ocms[e]={}),$ocms[e].auth=t,t.manage>0&&$ocms.getScript({module:e,script:["/web/fis",e,$ocms.auth.locale||"de","js"].join("."),css:["/web/fis",e,"css"].join("."),condition:"function"!=typeof $ocms[e].init2},(function(){$ocms[e].init2()}))},error:function(){$("#contentframe").empty()}})))};var $fis={auth:{},db:function(){$("#mainmenu_activemodule").text($t.ov);let t=$(this).empty(),e=$$.d({id:"dashboard_frame"}).appendTo(t);$ocms.postXT({url:$ocms.url("wdg/my"),success:function(t){$.each(t,(function(t,n){var r=$$.dc("wdg_frame",e,{"data-wdg":n}).ldng(1);$ocms.wdg.call(r,{wdg:n})}))},loading:e})},ValidateEmail:function(t){return!!/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/.test(t)},cf:t=>{let e=$("#contentframe");return!0===bool(t,!1)&&e.empty().rC("hd"),e},lf:t=>{let e=$("#listframe");return!0===bool(t,!1)&&e.empty().aC("hd").rC("fix"),e},frm_edit:function(t){let e=$fis.cf(!1),n=e.children(".cfrm"),r=e.children(".edit_frm");return n.length<1?n=$$.dc("cfrm hd").prependTo(e):!0===bool(t,!1)&&n.empty(),r.length<1&&(r=$$.dc("edit_frm").insertAfter(n)),r.empty()},frm_list:function(t,e){let n=$fis.cf(!1),r=n.children(".cfrm"),i=n.children(".list_frm");return r.length<1?r=$$.dc("cfrm hd").prependTo(n):!0===bool(t,!1)&&r.empty(),!0===bool(e,!1)&&n.children(".edit_frm").remove(),i.length<1&&(i=$$.dc("list_frm").appendTo(n)),i.empty()},lfm:()=>{let t=$fis.lf(!1),e=t.children(".lfrm");return e.length<1&&(e=$$.dc("lfrm").prependTo(t)),e},getAuth:(t,e)=>new Promise(((n,r)=>{$fis.auth[t]&&!1===bool(e,!1)?n($fis.auth[t]||-1):$ocms.postXT({url:$ocms.url("auth"),data:{module:t},success:e=>{$fis.auth[t]=e.auth||-1,n($fis.auth[t]||-1)},error:()=>{r()}})})),prepAuth:t=>new Promise(((e,n)=>{$ocms.postXT({url:$ocms.url("auth"),data:{module:t,array:1},success:t=>{$.extend($fis.auth,t||{})},complete:()=>{e()}})})),isAuth:(t,e)=>($fis.auth[t]||-1)>=(e||1),resetPass:function(t,e){confirm($t.smsc)&&($ocms.postXT({url:$ocms.url("account/sms"),data:{fn:"pwc"}}),$ocms.dlgform($fd.rsp.clone(),{title:$t.rsp||"",submit:function(t){var e=$(this).ldng(1),n=$.extend({loginaccount:$ocms.auth.account||""},e.serializeObject(!0,{typedvalues:!0}));(n.npw||"")!==(n.npwc||"")?e.find('input[name="npw"]:first')[0].setCustomValidity($t.pnm):$ocms.postXT({url:$ocms.url("account/changepassword"),data:n,success:function(t){alert($t.cps),e.trigger("modal_close")},error:function(t){alert($t.rspf[t.getResponseHeader("x-ocms-std")])},complete:function(){e.ldng(0)},timeout:6e4})}}))},wdg:function(t){let e=$(this).empty();$ocms.postXT({url:$ocms.url("wdg/one"),data:{short_name:t.wdg},success:function(n,r,i){let o=t.wdg,a=n[o];if(!a)return void e.ldng(0);let s=$.inArrayRegEx("dblwidth",a.rendering_options)>-1,l=$.inArrayRegEx("tiny",a.rendering_options)>-1;e.toggleClass("dbl",s&&!l).toggleClass("tny",l);$$.dc("wdg_hd",e,{title:ne(a.description,$t.wdc)}).toggleClass("dbl",s).text(ne(a.name,t.wdg)).dblclick((function(t){t.stopPropagation(),$fis.wdg.call(e,{wdg:o})}));let c=$$.dc("wdg_cnt",e).toggleClass("dbl",s).hide(),d=$.inArrayRegEx("bgcolor",a.rendering_options);switch(d>-1&&c.css("backgroundColor",a.rendering_options[d].toString().right(":")),a.type){case"table":var u=$$.tblset({},c),f=$$.tr().appendTo(u.hd),p=$t.wdg[o.indexOf("wdg_ev_")>=0?"wdg_ev_":o]||{};$.each(a.columns,(function(t,e){var n=p[e]?p[e].label:e;$$.th().text(n).appendTo(f)})),$.each(a.data,(function(t,e){var n=$$.tr().appendTo(u.bdy);$.each(a.columns,(function(t,r){var i=$$.td().appendTo(n);e[r]instanceof Date||!0===$ocms.isDateString(e[r])?i.text(fdt(e[r],$t.dateformat)):i.rwText(e[r])}))})),$.inArray("firstrow_bold",a.rendering_options)>-1&&f.nextAll("tr:first").css("font-weight","bold");break;case"ind":$$.dc("ind",c).addClass("sts_"+(a.data.status||"")).append([$$.dc("ind").text(a.data.value),$$.lbl(a.data.label)]);break;case"image_url":c.css("background","url('"+a.url+"') no-repeat center center transparent");break;case"image_base64":c.css("background","url('data:image/png;base64,"+a.image+"') no-repeat center center transparent");break;case"html":if(c.html(a.html),$.inArray("reload_10min",a.rendering_options)>-1){var m=c.find("iframe");setTimeout((function(){m.attr("src",(function(t,e){return e}))}),6e5)}}$.inArray("reload_30min",a.rendering_options)>-1&&"html"!==a.type&&setTimeout((function(){$fis.wdg.call(e,{wdg:o})}),18e5),c.slideDown(150)},error:function(t){e.slideUp(150),$fis.failure.call(this,t)},complete:function(){e.ldng(0)}})},ov:function(){$fis.lf(!0);let t=$("#contentframe").empty(),e=$$.d({id:"dashboard_frame"}).appendTo(t);$ocms.postXT({url:$ocms.url("wdg/my"),success:function(t){$.each(t,(function(t,n){var r=$$.dc("wdg_frame",e,{"data-wdg":n}).ldng(1);$fis.wdg.call(r,{wdg:n})}))},loading:e})}};Array.prototype.push.apply($ocms.ocmsmenu,[{lbl:$t.m_inv,id:"m_inv",fnc:"init:inv",ico:"glyphicon glyphicon-list-alt"},{lbl:$t.m_req,id:"m_req",fnc:"init:req",ico:"glyphicon glyphicon-eur"},{lbl:$t.m_bcd,id:"m_bcd",fnc:"init:bam",ico:"glyphicon glyphicon-indent-right"},{fnc:"separator"},{lbl:$t.m_rep,id:"m_rep",fnc:"init:rep",ico:"glyphicon glyphicon-dashboard"},{fnc:"separator"},{lbl:$t.m_todo,id:"m_todo",fnc:()=>{$("#contentframe").empty().load($ocms.url("todos")),$("#listframe").rC("fix").aC("hd")},ico:"glyphicon glyphicon-sunglasses"}]),$(document).ready((function(){$fis.ov()})); \ No newline at end of file +function onloadCSS(t,e){e=e||{};let n=function(e){return new Promise(((n,r)=>{t.addEventListener?e.addEventListener("load",newcb):t.attachEvent&&e.attachEvent("onload",newcb),"isApplicationInstalled"in navigator&&"onloadcssdefined"in t&&e.onloadcssdefined(newcb)}))};if(Array.isArray(t)){let r=t.length;Promise.all(t.map(n)).then((function(t){var n=t.reduce(((t,e)=>t+(!0===e?1:0)));!async function(t){!0===t&&"function"==typeof e.success?e.success():!0===t&&"object"==typeof e.success&&e.success instanceof Promise&&await e.success(),e.complete()}(r===n)}))}else n(t)}!function(t){"use strict";var e=function(e,n,r,i){var o,a=t.document,s=a.createElement("link");if(n)o=n;else{var l=(a.body||a.getElementsByTagName("head")[0]).childNodes;o=l[l.length-1]}var c=a.styleSheets;if(i)for(var d in i)i.hasOwnProperty(d)&&s.setAttribute(d,i[d]);s.rel="stylesheet",s.href=e,s.media="only x",function t(e){if(a.body)return e();setTimeout((function(){t(e)}))}((function(){o.parentNode.insertBefore(s,n?o:o.nextSibling)}));var u=function(t){for(var e=s.href,n=c.length;n--;)if(c[n].href===e)return t();setTimeout((function(){u(t)}))};function p(){s.addEventListener&&s.removeEventListener("load",p),s.media=r||"all"}return s.addEventListener&&s.addEventListener("load",p),s.onloadcssdefined=u,u(p),s};"undefined"!=typeof exports?exports.loadCSS=e:t.loadCSS=e}("undefined"!=typeof global?global:this);const isIE=/MSIE\/|Trident/gi.test(window.navigator.userAgent)||void 0!==window.document.documentMode,isfileapi=!!(window.File&&window.FileReader&&window.FileList&&window.Blob);var $ocms={auth:{},no:function(t){t.stopPropagation()},vmin:function(t){var e=$(window).width*(t||1),n=$(window).height*(t||1);return e($ocms.baseurl+"/"+(t||"")).replace(/\/\//,"/"),cexi:null};function deepCopy(t){var e,n,r;if("object"!=typeof t||null===t)return t;for(r in e=Array.isArray(t)?[]:{},t)n=t[r],e[r]=deepCopy(n);return e}function fields_definition(t,e,n){this.label_sng=!0===Array.isArray(t)?"":t||"",this.label_pl=!0===Array.isArray(t)?"":e||"",this.fields=!0===Array.isArray(t)?t:n||[],this.itm=function(t){for(var e=0;e0)for(var n=0;nt||"")).filter(((t,e)=>""!==t)).join(e)}function parseDt(t,e,n){t=(t||"").substr(0,e.length);var r=e,i=t.length>0&&e.split(";").some((function(e){for(var n,i=/[^yMdhms0-9]/gi,o=!0;null!==(n=i.exec(e));)o=o&&e.substr(n.index,1)===t.substr(n.index,1);var a=t.length===e.length&&o;return!0===a&&(r=e),a}));if(!0===i){for(var o,a=[0,0,0,0,0,0,0],s=/(mm{1,2}|dd{1,2}|MM{1,2}|(yy){2,4}|ss{1,2}|hh{1,2})(?!\w)/g;null!==(o=s.exec(r));)a["yMdhms".indexOf(o[0].substr(0,1))]=parseInt(("yy"===o[0]?"20":"")+t.substr(o.index,o[0].length))-("M"===o[0].substr(0,1)?1:0);var l=new(Function.prototype.bind.apply(Date,[null].concat(a)));return"string"==typeof n?fdt(l,n):l}return!1}function bool(t,e){return"boolean"==typeof t?t:"boolean"==typeof e&&e}function booln(t,e){return"boolean"==typeof t?t:"number"==typeof t?1===t:"boolean"==typeof e&&e}Date.prototype.isValid=function(){return!isNaN(this)},Date.prototype.format=function(t){return fdt(this,t)},Date.prototype.addDays=function(t){return this.setDate(this.getDate()+t),this},Date.prototype.isBetween=function(t,e){return this>t&&this section");$(window).scroll((function(e){let n=$(window).scrollTop(),r=$("body");r.toggleClass("unfocus",n>vh()-1.2*t),r.toggleClass("btb",n>.5*vh()-t)}))},$ocms.cf_reset=function(){return $("#contentframe").empty()},function(t){t.fn.scrollTo=function(e){if(t(this).length>0){var n=t(this).offset().top||0;n>0&&t("html, body").animate({scrollTop:n-hh()},2e3)}},t.fn.ldng=function(e){var n=!0;return"boolean"==typeof e?n=e:"number"==typeof e&&(n=e>0),t(this).toggleClass("loading",n)},"function"!=typeof t.noop&&(t.noop=function(){}),t.fn.hasAttr=function(e){var n=t(this).attr(e);return void 0!==n&&!1!==n},t.fn.parseCssPx=function(e){try{return parseFloat(t(this).css(e).replace("px","")||0)}catch(t){return 0}},t.max=function(t,e){return isNaN(t)&&isNaN(e)?null:isNaN(t)&&!isNaN(e)?e:!isNaN(e)&&isNaN(e)||t>=e?t:e},t.min=function(t,e){return isNaN(t)&&isNaN(e)?null:isNaN(t)&&!isNaN(e)?e:!isNaN(e)&&isNaN(e)||t<=e?t:e},t.lim=function(t,e){return isNaN(t)?null:isNaN(e)?t:e<=t?e:t},t.fn.enterKey=function(e){return this.each((function(){t(this).keypress((function(t){"13"===(t.keyCode?t.keyCode:t.which).toString()&&e.call(this,t)}))}))}}(jQuery),$ocms.defaultTimeout=3e4,$ocms.AjaxEX=function(t){var e=this;e.responseText=e.responseText||"";var n=e.getResponseHeader("x-ocms-code")||"";e.internalCode=""!==n&&!1===isNaN(n)?parseInt(n):-1,e.isInternal=e.internalCode>-1,e.internalText=decodeURIComponent((e.getResponseHeader("x-ocms-desc")||"").replace(/\+/g,"%20")||"");var r=e.internalText||t,i=e.internalCode||e.status;e.logtext=r+" ("+i+")"},$ocms.postXTS=function(t){$ocms.postXT.call(this,$.extend(t,{sync:!0}))},$ocms.postXT=function(t){if((t=t||{}).trycount=t.trycount||0,""!==(t.url||"")){t.url=-1!==t.url.indexOf("&yy=")?t.url:t.url.indexOf("?")>-1?t.url+"&yy="+(new Date).getTime():t.url+"?yy="+(new Date).getTime();var e=t.context||this;switch(t.context=e,t.retryLimit=t.retryLimit||0,t.timeout=t.timeout||$ocms.defaultTimeout,t.timeout<100&&(t.timeout=1e3*t.timeout),t.data=t.data||{},t.contentType=t.contentType||"multipart/form-data; charset=UTF-8",t.islogin="boolean"==typeof t.islogin&&t.islogin,t.contentType){case"":case"json":t.contentType="application/json; charset=utf-8";break;case"form":t.contentType="application/x-www-form-urlencoded; charset=UTF-8";break;case"multi":t.contentType="multipart/form-data";break;case"text":t.contentType="text/plain; charset=UTF-8"}if(t.form instanceof jQuery?(t.data=t.form.serializeObject(),t.contentType="form-data"):t.lzw instanceof jQuery&&(t.data.lzw=$.ccLZW(t.lzw.serializeAnything(!0)).join(",")),"multipart/form-data"!==t.contentType.substr(0,19)&&"form-data"!==t.contentType.substr(0,9)||t.data instanceof FormData!=!1)t.data instanceof FormData&&(t.contentType=!1,t.processData=!1);else{t.contentType=!1;var n=new FormData;$.each(t.files||[],(function(t,e){n.append("upload_file",e)})),$.each(t.data||{},(function(t,e){n.append(t,e)})),t.data=n,t.processData=!1}var r={type:t.method||"post",url:t.url,data:t.data,processData:"boolean"!=typeof t.processData||t.processData,contentType:t.contentType,cache:t.cache||!1,timeout:t.timeout,beforeSend:function(n){$(t.loading).ldng(),$("body").addClass("ldng"),"function"==typeof t.beforesend&&t.beforesend.apply(e,[n])},success:function(n,r,i){"false"===n||"not authorized"===n?("function"==typeof t.error&&t.error.apply(e,[i,r,n]),"function"==typeof $.status&&$.status(r+" - "+n)):"function"==typeof t.success&&t.success.apply(e,[n,r,i])},error:function(n,r,i){if($ocms.AjaxEX.call(n,r),-1===t.url.indexOf("doc.ashx")||-1!==t.url.indexOf("ftest")){if(401===n.status&&111===n.internalCode&&!1===t.islogin&&"function"==typeof $ocms.login.dlg)$ocms.login.dlg({ajo:t});else if("timeout"===r||302===n.status)return t.tryCount++,t.tryCount<=t.retryLimit?void $ocms.postXT(t):void 0;"function"==typeof t.error?t.error.apply(e,[n,r,i]):"function"==typeof $ocms.failure?$ocms.failure.apply(e,[n]):"function"==typeof $.status&&$.status("Server error: "+r+" - "+i)}},dataType:t.datatype||"json",complete:function(n,r){"function"==typeof t.complete&&t.complete.apply(e,[n,r]),$(t.loading).ldng(0),$("body").removeClass("ldng");let i=$("body > .timer");if(i.length>0){let t=new Date(n.getResponseHeader("ocms_cec")||""),e=new Date(n.getResponseHeader("ocms_cex")||"");if(t.isValid()&&e.isValid()){let n=new Date,r=Math.abs(e-t);n.setMilliseconds(n.getMilliseconds()+r),i.data({cex:n,ctt:r}),$ocms.cex_timer()}}},context:e,async:!0};"boolean"==typeof t.sync&&(r.async=!1===t.sync),!0==("boolean"==typeof t.contentType&&!1===t.contentType)&&(r.contentType=!1),$.ajax(r)}},$ocms.cex_timer=function(){$ocms.cexi||($ocms.cexi=setInterval($ocms.cex_timer,15e3));let t=$("body > .timer"),e=t.data("cex"),n=t.data("ctt"),r=new Date;if(e instanceof Date&&e.isValid()&&"number"==typeof n&&n>0&&e>r){let i=Math.abs(r-e)/n*100;t.css("width",i.toString()+"%"),i<98&&(!$ocms.cex_lp||Math.abs(r-$ocms.cex_lp)>6e5)&&$ocms.postXT({url:$ocms.url("ping"),success:()=>{$ocms.cex_lp=r},timeout:5e3,error:()=>{}})}},$ocms.vbl_send=function(t){var e=t.data||{};if(""!==(e.url||"")){var n=$("#contentframe form:first"),r={url:e.url,data:new FormData,success:function(t){"function"==typeof e.success?e.success(t):"string"==typeof e.success&&alert(e.success)},error:function(t,n,r){"function"==typeof e.error?e.error(r):"string"==typeof e.error&&alert(e.error)},complete:function(){n.ldng(0)}},i=!0;n.find("input").each((function(){var t=$(this),e=t.nza("name"),n=t.val(),o=$(this).prop("required")||!1;if(""!==e){var a=""!==n||!1===o;i=i&&a,!0===a?(r.data.append(e,n),t[0].setCustomValidity("")):""!==$(this).nza("ocms-nvnote")&&t[0].setCustomValidity($(this).nza("ocms-nvnote"))}})),!0===i&&(n.ldng(1),$ocms.postXT.call(this,r))}},function(t){t.fn.nza=function(e,n){var r=t(this).attr(e);return void 0!==r&&!1!==r?r:n||""},t.fn.serializeObject=function(e,n){var r=/\r?\n/g,i=/^(?:submit|button|image|reset|file)$/i,o=/^(?:input|select|textarea|keygen)/i,a=/^(?:checkbox|radio)$/i,s=bool((n=n||{}).typedvalues,!1),l={},c=t(this),d=c.find(':input:not([nosend],[type="file"])').addBack(":input"),u=!0;return t.each(d.not(".tinymce").get(),(function(n,c){var d=t(this),p=this,f=(this.type||"").toLowerCase(),m=d.prop("required")||!1;if(!0===(p.name&&!d.is(":disabled")&&o.test(p.nodeName)&&!i.test(f))){var h=d.val(),g=p.name,$=d.nza("data-format").split(":"),y=d.nza("pattern")||".*";if(!0===a.test(f)&&(h=p.checked?""!==h?h:"true":""),"date"===$[0].substr(0,4)&&$.length>1)"boolean"==typeof(h=parseDt(h,$.slice(1).join(":")))&&(h=null),null===h&&"date"===d.prop("type").substr(0,4)&&!1===isNaN(new Date(d.val()))&&(h=new Date(d.val())),h instanceof Date==!0&&"function"==typeof h.getMonth?!1===s&&(h=fdt(h,"date"===$[0]?"dts":"iso")):h=null;else if("number"===f&&!0===s){let t;t="integer"===$[0]?parseInt(h):parseFloat(h),h=isNaN(t)?h:t}if(!0!==m||""!==(h||"")&&null!==h.match(y)?!0===bool(e,!1)&&p.setCustomValidity(""):(!0===bool(e,!1)&&p.setCustomValidity(d.nza("ocms-nvnote",$ocms.t.inv||"Invalid field")),h=null),null!=h&&"string"==typeof h){let t=l[g];null!=t?Array.isArray(t)?t.push(h.replace(r,"\r\n")):l[g]=[t,h.replace(r,"\r\n")]:l[g]=h.replace(r,"\r\n")}else if(null!=h){let t=l[g];null!=t?Array.isArray(t)?t.push(h):l[g]=[t,h]:l[g]=h}else u=!1}})),d.filter(".tinymce").each((function(e,n){var r=t(this),i=((this.type||"").toLowerCase(),r.prop("required")||!1);try{var o=tinymce.get(t(n).attr("id"));if(o){var a=t(n).attr("name"),s=o.getContent();!1===i||""!==(s||"")?l[a]=s:u=!1}}catch(e){t.noop()}})),c.toggleClass("invalid",!u),u?l:null},t.fn.sendForm=function(e,n,r){var i=t(this);r=r||{};var o={url:e,success:function(t){if(r.response=t,"function"==typeof n)n(t);i.closest("div.modal").remove()},error:function(t,e,n){"function"==typeof r.error?r.error.call(this,t):$ocms.failure.call(this,t)},complete:function(){i.ldng(0),"function"==typeof r.complete&&r.complete.call(this,jqXHR)}},a=i.find('input[type="file"]');o.data=new FormData,a.length>0&&t.each(a[0].files,(function(t,e){o.data.append(t,e),o.data.append("file_lastmodified",$ocms.isodt(e.lastModifiedDate))}));var s=i.serializeObject();t.each(s||{},(function(t,e){o.data.append(t,e)})),i.ldng(),$ocms.postXT.call(this,o)},t.fn.checkValidity=function(){var e=t(this),n=!0;return e.each((function(t,e){n=n&&e.checkValidity()})),n},t.fn.wrap=function(e,n){var r=t(this),i=$$.dc(e).attr(n||{}).insertAfter(r);return r.append(i),i}}(jQuery),$ocms.logout=function(){$ocms.postXT({url:$ocms.url("logout"),complete:function(){window.location.reload()}})},$ocms.login={send:function(t){t.preventDefault();var e=$(this);if(!0===e.find("#dbtn-confirm").hasClass("disabled"))return!1;var n=e.serializeObject();return n.loginaccount=ne(n.loginaccount,$ocms.auth.account||$ocms.auth.requestedaccount||""),n.loginaccount=ne(n.loginaccount,$ocms.auth.account||$ocms.auth.requestedaccount||""),""===ne(n.loginaccount)&&!0===bool($ocms.auth.accountrequired,!0)?(alert($t.l16),!1):($ocms.postXT({url:$ocms.url("login"),data:n,success:function(){window.location.reload()}}),!1)},uichange:function(){let t=$(this),e=t.closest("form"),n=bool($ocms.auth.accountrequired,!0),r=ne(e.find('[name="loginaccount"]').val(),$ocms.auth.account||$ocms.auth.requestedaccount||"");if(""!==r||!1===n){var i=e.find('[name="userlogin"]').empty().val(""),o=e.find('[name="username"]').empty().val(""),a=$("#dlg_userlogin_sel").empty().val(""),s=t.val()||"";if(!1===t.checkValidity()&&""===s)return;var l=t.closest("table").ldng();$ocms.postXT.call(this,{url:$ocms.url("auth"),data:{userinfo:s,account:r||""},success:function(t,e,n){if(1===t.length){var r=t[0];i.val(r.login).change().attr("required","").removeAttr("nosend"),o.val(r.name).change().attr("required","").show(),a.removeAttr("required").attr("nosend","").hide()}else t.length>0?(o.hide().removeAttr("required"),i.removeAttr("required").attr("nosend",""),0===a.length&&(a=$("").attr({name:"userlogin",size:t.length,id:"dlg_userlogin_sel",class:"form-control",required:""}).css({width:"100%","max-width":"100%",padding:"2px"}).insertAfter(o)),$.each(t,(function(t,e){var n=$("").attr({value:e.login,style:"padding-top: 2px; padding-bottom: 5px;","border-bottom":"1px solid #EEE;"}).text(e.name).appendTo(a);t%2==0&&n.css({"background-color":"#F9F9F9"})})),a.attr("required","").removeAttr("nosend")):(a.hide().attr("nosend",""),o.attr("required","").show(),i.attr("required","").removeAttr("nosend"),alert($t.l9))},error:function(t){$ocms.failure.call(this,t)},complete:function(){l.ldng(0)}})}else alert($t.l18)},sendpassword:function(t){var e=$(''),n=e.find(".form-body"),r=null;e.find("form").submit((function(t){t.preventDefault();var i=$(this).serializeObject(!0),o=null===r,a=o?"spwc":"spw";return $ocms.postXT.call(this,{url:$ocms.url(a),data:i,complete:function(){o?(n.append('
      Ihnen wurde ein Code per SMS zugesandt.
      Bitte tragen Sie den hier ein:
      '),r=$('
      ').appendTo(n)):(alert($t.l13),e.remove())},error:()=>{}}),!1})),e.find(".modal-close").click((function(){e.remove()}));var i=[];$.each($t.l7a.split("\n"),((t,e)=>{Array.prototype.push.apply(i,[$("
      "),$("").text(e)])})),e.find(".modal-note").append($('').text($t.alert)).append(i),e.appendTo("body"),setTimeout((function(){$(".modal").find('input[name="lastname"]').focus()}),600)}};var $$={s:function(t){return $("").text(t)},br:function(){return $("
      ")},sc:function(t,e){return $("").addClass(t).text(e)},td:function(t,e){var n=$("");return t instanceof jQuery==!0?n.appendTo(t):"object"==typeof t?n.attr(t):"string"==typeof t&&n.text(t),"object"==typeof e?n.attr(e):"string"==typeof e&&n.text(e),n},th:function(t,e){var n=$("");return t instanceof jQuery==!0?n.appendTo(t):"object"==typeof t?n.attr(t):"string"==typeof t&&n.text(t),"object"==typeof e?n.attr(e):"string"==typeof e&&n.text(e),n},tdc:function(t,e,n){return $$.td(e,n).addClass(t)},td2:function(t){var e=$('');return"string"===$.type(t)?e.text(t):t instanceof jQuery?e.append(t):"function"==typeof t?t.call(e):e.html(" "),e},td3:function(t){var e=$('');return"string"===$.type(t)?e.text(t):t instanceof jQuery?e.append(t):"function"==typeof t?t.call(e):e.html(" "),e},tdtr:function(t,e){var n=$$.tr().appendTo(e);return t instanceof jQuery==!0||"string"==typeof t?t.appendTo($$.td().appendTo(n)):!0===Array.isArray(t)&&$.each(t,(function(t,e){$(e).appendTo($$.td().appendTo(n))})),n},tr:function(t,e){var n=$("");return t instanceof jQuery==!0?n.appendTo(t):"object"==typeof t&&n.attr(t),"object"==typeof e&&n.attr(e),n},trc:function(t,e){var n=$("").addClass(t);return e instanceof jQuery==!0?n.appendTo(e):"object"==typeof e&&n.attr(e),n},d:function(t){return $("
      ").attr(t||{})},dc:function(t,e,n,r){var i=$("
      ").addClass(t);return e instanceof jQuery==!0?i.appendTo(e):"object"==typeof e?i.attr(e):"function"==typeof e?i.click(e):"string"==typeof e&&i.text(e),"string"==typeof n?i.text(n):"object"==typeof n?i.attr(n):"function"==typeof n&&i.click(n),"string"==typeof r?i.text(r):"object"==typeof r?i.attr(r):"function"==typeof r&&i.click(r),i},df:function(t){return $("
       
      ").attr(t||{})},opt:function(t,e,n){var r=$("");return"string"==typeof t?r.attr("value",t):"object"==typeof t&&r.attr(t),"string"==typeof e?r.text(e):"object"==typeof e&&r.attr(e),"object"==typeof n&&r.attr(n),r},eOpt:function(t){var e=$('');return t&&e.attr("selected","selected"),e},tbl:function(t){return $("
      ").attr(t||{})},tblc:function(t){return $("
      ").addClass(t)},thead:function(t){let e=$("");return t instanceof jQuery&&e.prependTo(t),e},tbody:function(t){let e=$("");return t instanceof jQuery&&e.appendTo(t),e},tblset:function(t,e){let n=$$.tbl(t||{});return e instanceof jQuery&&e.append(n),{tbl:n,hd:$$.thead().appendTo(n),bdy:$$.tbody().appendTo(n)}},i:function(t){return $("").attr(t||{})},img:function(t,e){return $("").attr("src",t).attr(e||{})},sel:function(t){return $("").attr(t||{})},btn:function(t){return $("").attr(t||{})},a:function(t){return $("").attr(t||{})},li:function(t){return $("
    • ").attr(t||{})},ul:function(t){return $("
        ").attr(t||{})},nav:function(t){return $("").attr(t||{})},lbl:function(t,e){var n=$("");return"string"==typeof t&&n.text(t),"object"==typeof t?n.attr(t):"object"==typeof e&&n.attr(e),n},txt:function(t){return $("").attr(t||{})},0:function(t,e){return $("<"+t+">").attr(e||{})},bbtn:function(t,e){return $$.btn({type:"button",class:"btn"}).addClass(e).text(t)},svg:t=>$(document.createElementNS("http://www.w3.org/2000/svg",t))};function getMonday(t){var e=(t=new Date(t)).getDay(),n=t.getDate()-e+(0==e?-6:1);return new Date(t.setDate(n))}function $lf(t){var e=void 0===t?null:"number"==typeof t&&1!==t||"boolean"==typeof cl&&!1===t;return $("#listframe").tC("hd",e).is(".hd")}function $nuf(t){if(t&&t.stopPropagation(),!$(this).is(".disabled")){var e=function(t){t.removeClass("vis").find("li.dropdown").removeClass("open").removeClass("vis").attr("aria-expanded","false")},n=$(this).parent("li.dropdown");if(n.length>0){n.tC("open"),navs=!0===n.is(".open")?"true":"false",n.attr("aria-expanded",navs);var r=n.closest("nav");r.find("li.dropdown").not(n.parentsUntil("nav")).not(n).removeClass("open").attr("aria-expanded","false"),!1===n.is(".open")&&n.find("li.dropdown").removeClass("open").attr("aria-expanded","false"),e($("nav").not(r))}else e($("nav"))}}function $tbr(){return $lf(0),$("#topbar").ocmsmenu([])}function $lfr(){return $("#sidebar").empty(),$("#listframe").removeClass("fix").addClass("hd").empty()}function $cfr(){return $tbr(),$("#contentframe").empty()}function jObj(t,e){let n={};if("{"===(t||"").substr(0,1))try{n=JSON.parse(t)}catch(t){n={}}return n[e]||""}function string(t,e){var n,r=t||"";return $.each(e||[],(function(t,e){n=new RegExp("\\{"+t.toString()+"\\}","ig"),r=r.replace(n,e)})),r}function init_tooltip(t){var e=!0===("boolean"==typeof t&&t)&&"mouse";$("[title]").qtip({position:{target:e,adjust:{x:2,y:2},viewport:!0},events:{hidden:$ocms.tooltip_hidden},effect:!1}),$("div.tooltiptext").each((function(){$(this).filter(":not(:empty)").parent().qtip({suppress:!1,content:{text:$(this).clone()},position:{target:e,adjust:{x:2,y:2},viewport:!0},events:{hidden:$ocms.tooltip_hidden}})}))}String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")},String.prototype.left=function(t){if("string"===$.type(t)){var e=this.indexOf(t);return e>0?this.slice(0,e):""}return this.substring(0,t)},String.prototype.right=function(t){if("string"===$.type(t)){var e=this.indexOf(t);return e>0?this.substring(this.length-e):""}return this.substring(this.length-t)},Array.prototype.move=function(t,e){if(e>=this.length)for(var n=e-this.length;1+n--;)this.push(void 0);return this.splice(e,0,this.splice(t,1)[0]),this},function(t){t.fn.appendToIf=function(e,n){var r=t(this),i="function"==typeof n?n(r):n;return!0===("boolean"!=typeof i||i)&&r.appendTo(e),r},t.fn.appendIf=function(e,n){var r=t(this),i="function"==typeof n?n(r):n;return!0===("boolean"!=typeof i||i)&&r.append(e),r},t.fn.rwText=function(e,n,r){var i=t(this).empty();r=t.extend({wrap:!0},r);var o=!0===Array.isArray(e)?e:(null==e?"":String(e)).split("\n");return t.each(o,(function(t,e){""!==(e||"")&&(t>0&&i.append($$.br()),i.append(!0===r.wrap?$$.s(e):e))})),n&&i.attr("title",n),i},t.fn.loadSel=function(e,n,r){if("SELECT"===t(this).prop("tagName").toUpperCase()){var i=t(this);$ocms.postXT.call(this,{url:e,data:n||{},success:function(e){t.each(e,(function(){i.append($$.opt(e.value,e.text))}))},complete:function(){i.ldng(0),"function"==typeof r&&r.call(i)}})}},t.fn.emptyWithEditors=function(e){var n=t(this);return n.find(":input.tinymce").each((function(e,n){try{var r=tinymce.get(t(n).attr("id"));r&&r.remove()}catch(e){t.noop()}})),n.empty()},t.fn.cssValue=function(t){if(this.length>0){var e=this.css(t)||"";if(""===e)return 0;var n=/(^[\d\.]*)(\D{1,3}$)/gi.exec(e);return null!==n?"rem"===n[2]?$ocms.rpx(parseFloat(n[1])):parseFloat(n[1]):!1===isNaN(e)?parseFloat(e):0}return 0},t.fn.veryInnerHeight=function(){let e=e=>t(this).cssValue(e);return t(this).innerHeight()-e("padding-top")-e("padding-bottom")},t.fn.veryInnerWidth=function(){let e=e=>t(this).cssValue(e);return t(this).innerWidth()-e("padding-left")-e("padding-right")},t.fn.marginWidth=function(){let e=e=>t(this).cssValue(e);return e("margin-left")+e("margin-right")},t.fn.marginHeight=function(){let e=e=>t(this).cssValue(e);return e("margin-top")+e("margin-bottom")},t.inArrayRegEx=function(e,n,r){var i="regexp"===t.type(e)?e:new RegExp(e);if(!n)return-1;for(var o=r=r||0;o7){r=e.split(","),i=(n||(t<0?"rgb(0,0,0)":"rgb(255,255,255)")).split(",");var l=s(r[0].slice(4)),c=s(r[1]),d=s(r[2]);return"rgb("+(a((s(i[0].slice(4))-l)*o)+l)+","+(a((s(i[1])-c)*o)+c)+","+(a((s(i[2])-d)*o)+d)+")"}var u=(r=s(e.slice(1),16))>>16,p=r>>8&255,f=255&r;return"#"+(16777216+65536*(a((((i=s((n||(t<0?"#000000":"#FFFFFF")).slice(1),16))>>16)-u)*o)+u)+256*(a(((i>>8&255)-p)*o)+p)+(a(((255&i)-f)*o)+f)).toString(16).slice(1)},t.fn.IN=function(e){return t(this).fadeIn(400,e),t(this)},t.fn.OUT=function(e){return t(this).fadeOut(400,e),t(this)},t.fn.tooltip=function(e,n){var r=!0===("boolean"==typeof e&&e)&&"mouse",i="boolean"==typeof n&&n,o=t(this);return o.each((function(){var e=i?t(this).find(".tooltiptext"):t(this).children(".tooltiptext");t(e).length>0?e.each((function(){var e=t(this);t(this).filter(":not(:empty)").parent().qtip({suppress:!1,content:{text:e.clone()},position:{target:r,adjust:{x:2,y:2},viewport:!0},events:{hidden:$ocms.tooltip_hidden},show:{effect:!1},hide:{effect:!1}}),e.remove()})):t(this).qtip({position:{target:r,adjust:{x:2,y:2},viewport:!0},events:{hidden:$ocms.tooltip_hidden},effect:!1})})),o},t.fn.rC=function(e){return t(this).removeClass(e)},t.fn.aC=function(e){return t(this).addClass(e)},t.fn.tC=function(e,n){return t(this).toggleClass(e,n)}}(jQuery),function(t){t.fn.ocmsmenu=function(e,n){var r=t(this);return $ocms.menu.call(r,e,n),r},t.fn.activatemenu=function(){var e=t(this).filter("nav");return e.find("a").not(".on").addClass("on").click($nuf),e.find(".nav-btn").not(".on").addClass("on").click((function(e){e.stopPropagation();var n=t(this);t(n.attr("data-target")).tC(n.attr("data-toggle"))})),e}}(jQuery);class ObjectArray extends Array{isEmpty(){return 0===this[0].length}static get[Symbol.species](){return Array}filter(t){return"function"==typeof t?new ObjectArray(this[0].filter(t)):this}remove(t){if("function"!=typeof t)return this;{let e=this[0].findIndex(t);for(;e>-1;)this[0].splice(e),e=this[0].findIndex(t)}}sortBy(t){return"function"==typeof t&&this[0].sort(t),this}sortString(t){return this[0].sort(((e,n)=>{let r=(e[t]||"").toString().toUpperCase(),i=(n[t]||"").toString().toUpperCase();return console.debug(r.localeCompare(i)),r.localeCompare(i)})),this}sortNum(t){return this[0].sort(((e,n)=>{let r=e[t],i=n[t];return!0===isNaN(i)&&!1===isNaN(r)||ri?1:0})),this}sum(t){return this[0].reduce(((e,n)=>e+(!0===isNaN(n[t])?0:n[t])),0)}groupBy(t){return this[0].reduce((function(e,n){let r=n[t];return e[r]||(e[r]=[]),e[r].push(n),e}),{})}each(t){if("function"==typeof t){let e=!1;this[0].forEach(((n,r,i)=>{if(!1===e){let o=t(n,r,i);"boolean"==typeof o&&!1===o&&(e=!0)}}))}}get toArray(){return this[0]}}class NumArray extends Array{sum(){return this.reduce(((t,e)=>t+e))}first(){return this[0]}last(){return this[this.length-1]}average(){return this.sum()/this.length}range(){let t=this.map((t=>t)).sort();return{min:t[0],max:t[this.length-1]}}static get[Symbol.species](){return Array}}$ocms.ocmsmenu=[{lbl:"",id:"m_home",ico:"glyphicon glyphicon-home",fnc:"init:home"},{fnc:"separator"}],function(t){t.multline=function(t){let e=t.split("\n"),n=$$.d();return $.each(e,((t,e)=>{n.append($$.s(e))})),n.html()},t.tooltip_hidden=function(t,e){$(this).remove(),e.rendered=!1},t.isJSONDateString=function(t){return"string"==typeof t&&/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})?)?$/.test(t)},t.failure=function(e){11110===(e.internalCode||-1)?t.login.dlg():alert($t.f1+"\n"+(e.internalText||""))},t.getScript=function(e,n){var r=[],i=[],o=function(t){return"string"==typeof t&&""!==(t||"")},a=function(t,e){!0===bool(e.condition,!0)&&(""!==(e.script||"")&&i.push({url:e.script,module:e.module||""}),!0===o(e.css||"")?r.push(e.css):!0===Array.isArray(e.css)&&Array.prototype.push.apply(r,e.css.filter(o)))};!0===o(e||"")?i.push(e):!0===Array.isArray(e)?$.each(e,a):"object"==typeof e&&""!==(e.script||"")&&a(0,e);let s=[];$.each(r,(function(t,e){""!==(e||"")&&s.push(loadCSS(e))}));let l=i.map((function(e,n){let r=e.url,o=e.module||"";if(""===o){return new Promise((function(t,e){try{!async function(){$.ajax({url:r,dataType:"script",success:function(){t(i)},error:function(){e(i)},timeout:3e4})}()}catch(t){console.debug(t.message+"%o",t)}}))}return t.loadmodule(o,r,e.alias)}));Promise.all(l).then(n)},t.loadmodule=function(e,n,r){return new Promise((function(i,o){!async function(){try{let a=(n.startsWith("/")||n.startsWith(".")?"":"/")+n;import(a).then((n=>{t[e]=n[r||"default"],i(e)})).catch((t=>{console.debug(t.message+"%o",t),o(e)}))}catch(t){console.debug(t.message+"%o",t)}}()}))},t.ocms_auth=function(e,n,r,i){!1===$.isPlainObject(t.auth.modules)&&(t.auth.modules={});var o=0;t.auth.modules[e+(r||"")]?((o=t.auth.modules[e+(r||"")])<2&&(r||"")===auth.guid&&(o=2),o>=(n||0)&&i(false)):t.postXT({url:t.url("auth"),data:{module:e,person_guid:r||""},success:function(a){o=a[e],t.auth.modules[e+(r||"")]=o,o<2&&(r||"")===t.auth.person_guid&&(o=2),o>=(n||0)&&i(false)},error:function(e){t.failure.call(this,e)}})},t.auth.locale="de",t.ocms_prepauth=function(e,n,r){t.postXT({url:t.url("auth"),data:{fn:"csv",modules:e,person_guid:n||""},success:function(e){t.ocms_regauth(e)},error:function(e){t.failure.call(this,e)},complete:function(){r()}})},t.ocms_regauth=function(t){$.each(t||{},(function(t,e){auth.modules[t]=parseInt(e)}))},t.init=function(e){var n="string"==typeof e?e:(e.data||{}).fn||"";""!==n&&("home"===n?($cfr(),$lfr(),$("#topbar").ocmsmenu([],!0),$("#activemodule").text($t.ov),t.ov.call($("#contentframe"))):($cfr(),$lfr(),$("#topbar").ocmsmenu([]),t.postXT({url:t.url(n+"/auth"),success:function(e){void 0===t[n]&&(t[n]={}),t[n].auth=e,e.manage>0&&t.getScript({module:n,script:["web/imdl",n,t.auth.locale||"de","js"].join("."),css:["web/imdl",n,"css"].join("."),condition:"function"!=typeof t[n].init2},(function(){t[n].init2()}))},error:function(){$("#contentframe").empty()}})))},t.menuarray=function(t){this.array=[],this.sep=function(){this.length>0&&"separator"!==this.array[array.length-1].fnc&&this.push({fnc:"separator"})},this.push=function(t){return void 0===t?null:(!0===Array.isArray(t)?Array.prototype.push.apply(this.array,t):"object"==typeof t&&this.array.push(t),t)},this.unshift=function(t){return void 0===t?null:(!0===Array.isArray(t)?Array.prototype.unshift.apply(this.array,t):"object"==typeof t&&this.array.unshift(t),t)},this.push(t)},t.menu=function(e,n){e=e||[];var r=$(this).removeClass("vis");if(!0===bool(n,!0)&&!1===r.is("#mainmenu")&&r.empty(),!1===bool(n,!1)&&r.is("#sidebar,#topbar")&&(e.unshift({id:"sbctrl",glyph:"glyphicon-th-list",aclass:"fbtn",fnc:function(){$lf()}}),$lf(0)),0===(e||[]).length)r.empty().addClass("hd");else{r.removeClass("hd");var i=!0===r.is("nav")?r:r.children("nav");1!==i.length&&(i=$("").tC("nv",r.is("#sidebar")).tC("ctxt",r.is("#topbar")).appendTo(r));var o,a=$$.ul().appendTo(i),s=function(t,e){var n=$(this).addClass("dropdown submenu");t.append($$.sc("caret dd")).addClass("dds dropdown-toggle").attr({"aria-expanded":"false"}),""!==(e.ico||"")&&t.prepend($$.sc("ico "+e.ico));var r=$$.ul({class:"dropdown-menu",role:"menu"}).appendTo(n);$.each(e.itm||[],(function(t,e){o.call(r,e)}))},l=function(t){$(this).tC("disabled","boolean"==typeof t.disabled?t.disabled:"string"==typeof t.disabled&&"subs"===t.disabled&&0===(t.itm||[]).length)};o=function(e){var n,r=$$.li({id:e.id}).attr(e.attr||{}).addClass(e.lclass).appendTo($(this)),i="string"==typeof e.fnc&&""!==e.fnc?e.fnc.split(":")[0]:"";""!==i&&"init"!==i?r.attr("role",i).appendIf($$.s(e.lbl),""!==ne(e.lbl)):(n=$$.a({class:"on",role:"button"}).addClass(e.aclass).appendTo(r).append($$.s(e.lbl)),l.call(n,e),(e.itm||[]).length>0&&s.call(r,n,e),n.click($nuf),"function"==typeof e.fnc?n.click(e.data||{},e.fnc):"init"===i&&n.click($.extend({},e.data||{},{fn:e.fnc.split(":")[1]}),t.init))},$.each(e,(function(e,n){var r,i=$$.li({id:n.id}).attr(n.attr||{}).addClass(n.lclass),s="string"==typeof n.fnc&&""!==n.fnc?n.fnc.split(":")[0]:"";if(""!==s&&"init"!==s)i.attr("role",s).appendIf($$.s(n.lbl),""!==ne(n.lbl));else{if(r=$$.a({class:"on",role:"button"}).addClass(n.aclass).appendTo(i),l.call(r,n),""!==(n.lbl||"")&&r.append($$.s(n.lbl)),""!==(n.ico||"")&&r.prepend($$.sc("ico "+n.ico)),""!==(n.glyph||"")&&r.prepend($$.sc("glyphicon "+n.glyph)),(n.itm||[]).length>0){i.addClass("dropdown"),r.append($$.sc("caret dd")).addClass("dds dropdown-toggle").attr({"aria-expanded":"false"});var c=$$.ul({class:"dropdown-menu",role:"menu"}).appendTo(i);$.each(n.itm||[],(function(t,e){o.call(c,e)}))}(n.sel||[]).length>0||(r.click($nuf),"function"==typeof n.fnc?r.click(n.data||{},n.fnc):"init"===s&&r.click($.extend({},n.data||{},{fn:n.fnc.split(":")[1]}),t.init))}i.appendTo(a)})),i.activatemenu()}},t.easytbl=(t,e)=>{e=e||{};let n=$$.tbl().addClass(e.class).css("border-collapse","collapse"),r=($$.tbody(n),!0===bool(e.frame,!1)?{padding:"5px",border:"1px solid #727272"}:{});if(!0===Array.isArray(e.header)){let t=$$.thead(n);$.each(e.header,((n,i)=>$$.th(t).css(e.cellcss||r).rwText(i)))}else if(!0===bool(e.header,!1)&&(t||[]).length>0){let i=$$.thead(n);$.each(Object.keys(t[0]),((t,n)=>$$.th(i).css(e.cellcss||r).rwText(n)))}return $.each(t||[],((t,i)=>{let o=$$.tr();$.each(i,((t,n)=>{n=n||"";let i=$$.td(o).css(e.cellcss||r);n instanceof jQuery?i.append(n):"string"==typeof n&&("<"===n.substring(0,1)?i.append(n):i.text(n))})),n.append(o)})),n},t.dlgtbl=(e,n,r)=>{r=r||{};let i=t.easytbl(e,r);t.dlg(i,$.extend({title:n},r))},t.dlg=function(t,n){n=n||{};let r=$("body > .modal").length>0,i=t=>typeof n[t],o=t=>"function"===i(t);if(!0===bool(n.exclusive,!0)&&!0===r)return void alert($t.dbldlg||"Es ist bereits ein Dialog geöffnet");let a=$$.dc("modal",$("body")),s=$$.dc("modal-dialog",a);!1===isNaN(n.zindex)?a.css("zIndex",n.zindex):!0===r&&a.css("zIndex",parseInt($("body > .modal:last").cssValue("zIndex"))+200),!1===isNaN(n.zindex_min)&&a.cssValue("zIndex")').appendTo(u)),""!==ne(n.title)&&(l=$$.dc("modal-header",u),$("

        ").text(n.title).appendTo(l));let f=$$.dc("modal-body",u),m=$$.dc("modal-footer",u);t instanceof jQuery==!0&&f.append(t);let h=function(t){t&&"function"==typeof t.stopPropagation&&t.stopPropagation(),s.removeClass("in"),!0===o("closing")&&n.closing.call(u),f.hide().emptyWithEditors(),a.remove(),!0===o("close")&&n.close.call(u)};if(u.find(":input[required]").length>0&&($$.dc("note_required",m).append($$.sc("ind_required","*")).append($$.s($t.t1||"Eingabe erforderlich")),$$.dc("note_invalid",m).append($$.s($t.t2||"Bitte überprüfen Sie Ihre Eingaben im Formular."))),!0===o("cancel")){$$.bbtn(n.cancelbutton||"Abbrechen","cancel").attr({type:"button",role:"cancel"}).appendTo(m).click((function(t){n.cancel.call(u,t);t.stopPropagation(),h()}))}if(!0===o("confirm")){let t=$$.bbtn(n.button||"OK","confirm").attr({type:!0===bool(n.form,!1)?"submit":"button",role:"confirm"}).appendTo(m);!0===p?(u.submit((function(t){try{n.confirm.call(u,t)}finally{t.preventDefault()}return!1})),u.on("modal_submit",(function(){n.confirm.call(u,e)}))):(t.click((function(t){n.confirm.call(u,t);t.stopPropagation()})),u.on("modal_submit",(function(){t.click()})))}else!0===p&&u.submit((function(t){return t.preventDefault(),!1}));return u.on("modal_close",(function(){h()})),c.click(h),!0===o("opening")&&n.opening.call(u),s.addClass("in"),ne(n.mode).indexOf("maxbody")>-1&&f.css("min-height",(d.height()-l.outerHeight()-m.outerHeight()).toString()+"px"),!0===o("open")&&n.open.call(u),{hd:l,bdy:f,ft:m,ct:d,dlg:s,c:u}},t.mform=function(e){let n=$$.dc("form-body"),r=Array.isArray(e)?e:e instanceof fields_definition?e.fields:[];return $.each(r||[],(function(e,r){let i=r.type||"";if("ignore"===i)return!0;let o=$$.dc("form-group",n),a=r.id||"dlg_"+(r.name||"")+("html"===r.type?"_"+(65536*(1+Math.random())||0).toString(16).substr(9):""),s=$$.lbl(r.label||r.name,{for:a}).appendTo($$.dc("form-itm",o)),l=$$.dc("form-itm",o),c=$$.i({id:a,name:r.name,placeholder:r.placeholder,type:r.type});switch(i){case"email":r.pattern=ne(r.pattern,"[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$");break;case"url":r.pattern=ne(r.pattern,"https?://.+");break;case"number":r.pattern=ne(r.pattern,"[-+]?[0-9]*[.,]?[0-9]*"),c.attr("step",r.precision||"any"),c.attr("data-format","float");break;case"integer":case"int":r.pattern=ne(r.pattern,"[-+]?[0-9]*"),c.attr("type","number"),c.attr("data-format","integer");break;case"date":if(""!==ne(r.pattern,$t.datepattern)&&(r.pattern=ne(r.pattern,"("+$t.datepattern+")|([0-9]{4}.(0[1-9]|1[012]).(0[1-9]|1[0-9]|2[0-9]|3[01]))")),""!==ne(r.placeholder,$t.dateplaceholder)&&c.attr("placeholder",ne(r.placeholder,$t.dateplaceholder)),"string"==typeof r.value){var d=r.value.substr(0,10);r.value="date"!==c.prop("type")?fdt(d+"T00:00:00",ne(r.dateformat,$t.dateformat)):d}c.attr("data-format","date:"+ne(r.dateformat,$t.dateformat)+";yyyy-MM-dd");break;case"datetime":c.attr("type","datetime-local"),""!==ne(r.pattern,$t.datetimepattern)&&(r.pattern=ne(r.pattern,"("+$t.datetimepattern+")|([0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])\\s([0-5][0-9]):([0-5][0-9]))")),""!==ne(r.placeholder,$t.datetimeplaceholder)&&c.attr("placeholder",ne(r.placeholder,$t.datetimeplaceholder)),"string"==typeof r.value&&"T"===r.value.substr(10,1)&&(r.value="datetime"!==c.prop("type").substr(0,8)?fdt(r.value,ne(r.datetimeformat,$t.datetimeformat)):r.value),c.attr("data-format","datetime:"+ne(r.datetimeformat,$t.datetimeformat)+";yyyy-MM-dd HH:mm:ss");break;case"hidden":o.addClass("hd");break;case"html":case"text":c=$$.txt({id:a,name:r.name,placeholder:r.placeholder,type:r.type}),c.tC("tinymce","html"===r.type);break;case"bool":case"boolean":r.url=[{value:"true",label:($t||{}).true||"Yes"},{value:"false",label:($t||{}).false||"No"}],"boolean"==typeof r.value&&(r.value=r.value?"true":"false");case"select":c=$$.sel({id:a,name:r.name,type:r.type}),!1===bool(r.required,!1)&&$$.eOpt().appendTo(c);try{var u=function(t){!0===Array.isArray(t)&&$.each(t,(function(t,e){"string"==typeof e?$$.opt(e,e).appendTo(c):!0===Array.isArray(e)?$$.opt(e[0],e[1]).appendTo(c):"object"==typeof e&&$$.opt(e.value,e.label||e.text).appendTo(c)}))};!0===Array.isArray(r.url)?u(r.url):"function"==typeof r.url?r.url.call(c):"string"==typeof r.url&&t.postXT({url:r.url,success:u})}catch(t){$.noop()}break;default:""!==ne(r["max-length"])&&c.attr("max-length",r["max-length"])}""!==ne(r.pattern)&&c.attr("pattern",r.pattern),c.val(r.value).change(),c.change((function(){$(this)[0].setCustomValidity("")})),c.addClass("form-control").prop("required",bool(r.required,!1)).prop("readonly",bool(r.readonly,!1)).appendTo(l),!0===bool(r.required,!1)&&s.append($$.sc("ind_required","*")),"object"==typeof r.attr&&c.attr(r.attr),"object"==typeof r.prop&&c.prop(r.prop),"string"==typeof r.class&&c.addClass(r.class),"function"==typeof r.change&&(c.change(r.change),!0===bool(r.applychange,!1)&&void 0!==r.value&&c.change()),""!==(r.note||"")&&$$.dc("form-note",l).rwText(r.note),"function"==typeof r.complete&&r.complete.call(c)})),n},t.initMCE=function(t,e){t=$(t),e=e||{};try{let n={target:t[0],inline:!1,width:e.width||"100%",statusbar:!1,document_base_url:window.location.origin+"/",content_style:"ph:before {content: '«'; color: #BBB; font-style:italic; } ph:after {content: '»'; color: #BBB; font-style:italic; } ph { color: #AAA; font-style:italic; }",relative_urls:!1,remove_script_host:!1};!0===bool(e.hidemenu,!1)&&(n.menubar=!1,n.menu={}),!0===bool(e.hidetoolbar,!1)&&(n.toolbar=!1),$.extend(n,e||{}),tinymce.init(n)}catch(t){alert(t.message)}},t.dlgform=function(e,n){n=n||{};let r,i=$$.dc("frm").append(t.mform(e||[]).addClass("stacked"));n.addcontent instanceof jQuery&&i.append(n.addcontent),"function"==typeof n.submit?r=n.submit:"function"==typeof n.success&&(r=function(e){var r=$(this).ldng(1),i=$.extend({loginaccount:t.auth.account||""},r.serializeObject(bool(n.checkvalidity,!0),{typedvalues:bool(n.typedvalues,!1)}));""!==(n.url||"")?t.postXT({url:n.url,data:i,success:function(t){n.success.call(this,t),r.trigger("modal_close")},error:function(){alert($t.l17)},complete:function(){r.ldng(0)},timeout:6e4}):(n.success.call(this,i),r.trigger("modal_close"))});let o={form:!0,title:n.title||"",button:n.button||$t.submit,confirm:r,size:n.size||[500,600],open:function(){let e=$(this).find(".tinymce");e.length>0&&t.initMCE(e,n.tinymce||{})}};return t.dlg.call(this,i,o)},t.login.dlg=function(e){e=e||{};let n=[{name:"userinfo",label:$t.l1,type:"string",value:t.auth.login,change:t.login.uichange,required:!0},{name:"userlogin",type:"hidden",required:!0,value:t.auth.login},{name:"username",type:"string",label:$t.l4,required:!0,readonly:!0,placeholder:$t.l5,value:t.auth.fullname_rev},{name:"userpass",type:"password",label:$t.l3,required:!0,placeholder:$t.l3}];""===(t.auth.account||"")&&n.unshift({id:"dlg_loginaccount",name:"loginaccount",type:"string",required:!0,value:t.auth.account});let r=$$.dc("frm").append(t.mform(n).addClass("stacked")),i=t.dlg.call(this,r,{form:!0,title:$t.l0,button:$t.submit,confirm:function(n){var r=$(this).ldng(1),i=$.extend({loginaccount:t.auth.account||""},r.serializeObject());t.postXT({url:"/vt/login",data:i,success:function(n){""!==((n||{}).login||"")&&(r.trigger("modal_close"),t.auth=n,"object"==typeof e.ajo&&(e.ajo.islogin,$.ajax(e.ajo)))},error:function(){alert($t.l17)},complete:function(){r.ldng(0)},timeout:6e4})},size:[500,600]}),o=$$.dc("modal-content").css("height","auto").attr("novalidate","true").append($$.dc("modal-header").appendIf($("

        ").text(t.auth.accountname),""!==(t.auth.accountname||"")).append($("

        Vereinsmanager

        ")));i.dlg.prepend(o)},t.addNoEntryInfo=function(t){$(this).append($$.dc("noentryinfo").text(t||$t.t11))}}($ocms),Element.prototype.matches||(Element.prototype.matches=Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector),Element.prototype.closest||(Element.prototype.closest=function(t){var e=this;do{if(Element.prototype.matches.call(e,t))return e;e=e.parentElement||e.parentNode}while(null!==e&&1===e.nodeType);return null}),function(t,e){var n,r;"object"==typeof window&&(window[t]=(n=function(t){var e=window,n=document.body,r=document.documentElement,i=Math.max(0,e.pageXOffset||r.scrollLeft||n.scrollLeft||0)-(r.clientLeft||0),o=Math.max(0,e.pageYOffset||r.scrollTop||n.scrollTop||0)-(r.clientTop||0);return{x:t?Math.max(0,t.pageX||t.clientX||0)-i:0,y:t?Math.max(0,t.pageY||t.clientY||0)-o:0}},(r=function(t,e){t&&t instanceof Element&&(this._container=t,this._options=e||{},this._clickItem=null,this._dragItem=null,this._showDragItem="boolean"!=typeof this._options.dragItem||!1!==this._options.dragItem,this._hovItem=null,this._sortLists=[],this._click={},this._dragging=!1,this._dragHandleClass=this._options.dragHandleClass||"",this._parentident=this._options.parentident||"",this._swapdone="function"==typeof this._options.swapdone?this._options._swapdone:null,this._container.setAttribute("data-is-sortable",1),this._container.classList.add("sortable"),this._container.style.position="static",window.addEventListener("mousedown",this._onPress.bind(this),!0),window.addEventListener("touchstart",this._onPress.bind(this),!0),window.addEventListener("mouseup",this._onRelease.bind(this),!0),window.addEventListener("touchend",this._onRelease.bind(this),!0),window.addEventListener("mousemove",this._onMove.bind(this),!0),window.addEventListener("touchmove",this._onMove.bind(this),!0))}).prototype={constructor:r,toArray:function(t){t=t||"id";for(var e=[],n="",r=0;rr.left&&er.top&&n-1)&&e.className.indexOf("nosort")<0)&&(t.preventDefault(),this._dragging=!0,this._click=n(t),this._makeDragItem(e),this._onMove(t),!0)}t&&!1===e.call(this,t.target)&&""!==this._parentident&&t.target.closest(this._parentident)&&e.call(this,t.target.closest(this._parentident))},_onRelease:function(t){this._dragging=!1,this._trashDragItem()},_onMove:function(t){if(this._dragItem&&this._dragging){t.preventDefault();var e=n(t),r=this._container;!0===this._showDragItem&&this._moveItem(this._dragItem,e.x-this._click.x,e.y-this._click.y);for(var i=0;i0?s.mousedown(l).addClass("dctrl"):a.mousedown(l).addClass("dctrl"),t(this)}}(jQuery),$(document).ready((function(){$("html").click((function(t){$nuf()})),$("#listframe").click((function(t){t.stopPropagation(),$nuf()})),$("#mainmenu").ocmsmenu($ocms.ocmsmenu),$("#mainmenu").activatemenu()})),$.extend($t,{m_inv:"Rechnungen",m_req:"Aufträge",m_rep:"Berichte",m_todo:"ToDos",m_bcd:"BankBuchungen",rsp:"Passwort ändern",pnm:"Die Passwörter stimmen nicht überein",cps:"Das neue Passwort wurde gespeichert.",pwr:"Bitte wählen Sie ein starkes Passwort (min 8 Zeichen, davon jeweils min 2 Zahlen, kleine und große Buchstaben, Sonderzeichen sind optional).",smsc:"Sie beötigen für diese Funktion einen SMS-Code.\nSoll dieser nun versandt werden?",wdc:"Doppelt klicken, um die Box zu aktualisieren.",wdg:{}}),$t.rspf={sms:"Der SMS-Code konnte nicht bestätigt werden",valid:"Das alte Passwort ist nicht korrekt",requirements:"Das Passwort entspricht nicht den Anforderungen.\n"+$t.pwr},$fd={rsp:new fields_definition("","",[{name:"opw",label:"aktuelles Passwort",type:"password",required:!0,attr:{"auto-complete":"current-password"}},{name:"npw",label:"neues Passwort",type:"password",required:!0,pattern:"(.{6,})",attr:{"auto-complete":"new-password"}},{name:"npwc",label:"neues Passwort (Bestätigung)",type:"password",required:!0,attr:{"auto-complete":"new-password"},note:$t.pwr},{name:"code",label:"SMS-Code",type:"string",required:!0,attr:{"auto-complete":"one-time-code"}}])},$ocms.init=function(t){var e="string"==typeof t?t:(t.data||{}).fn||"";""!==e&&("home"===e?($cfr(),$lfr(),$("#topbar").ocmsmenu([],!0),$("#activemodule").text($t.ov),$fis.ov()):($cfr(),$lfr(),$("#topbar").ocmsmenu([]),$ocms.postXT({url:$ocms.url(e+"/auth"),success:function(t){void 0===$ocms[e]&&($ocms[e]={}),$ocms[e].auth=t,t.manage>0&&$ocms.getScript({module:e,script:["/web/fis",e,$ocms.auth.locale||"de","js"].join("."),css:["/web/fis",e,"css"].join("."),condition:"function"!=typeof $ocms[e].init2},(function(){$ocms[e].init2()}))},error:function(){$("#contentframe").empty()}})))};var $fis={auth:{},db:function(){$("#mainmenu_activemodule").text($t.ov);let t=$(this).empty(),e=$$.d({id:"dashboard_frame"}).appendTo(t);$ocms.postXT({url:$ocms.url("wdg/my"),success:function(t){$.each(t,(function(t,n){var r=$$.dc("wdg_frame",e,{"data-wdg":n}).ldng(1);$ocms.wdg.call(r,{wdg:n})}))},loading:e})},ValidateEmail:function(t){return!!/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/.test(t)},cf:t=>{let e=$("#contentframe");return!0===bool(t,!1)&&e.empty().rC("hd"),e},lf:t=>{let e=$("#listframe");return!0===bool(t,!1)&&e.empty().aC("hd").rC("fix"),e},frm_edit:function(t){let e=$fis.cf(!1),n=e.children(".cfrm"),r=e.children(".edit_frm");return n.length<1?n=$$.dc("cfrm hd").prependTo(e):!0===bool(t,!1)&&n.empty(),r.length<1&&(r=$$.dc("edit_frm").insertAfter(n)),r.empty()},frm_list:function(t,e){let n=$fis.cf(!1),r=n.children(".cfrm"),i=n.children(".list_frm");return r.length<1?r=$$.dc("cfrm hd").prependTo(n):!0===bool(t,!1)&&r.empty(),!0===bool(e,!1)&&n.children(".edit_frm").remove(),i.length<1&&(i=$$.dc("list_frm").appendTo(n)),i.empty()},lfm:()=>{let t=$fis.lf(!1),e=t.children(".lfrm");return e.length<1&&(e=$$.dc("lfrm").prependTo(t)),e},getAuth:(t,e)=>new Promise(((n,r)=>{$fis.auth[t]&&!1===bool(e,!1)?n($fis.auth[t]||-1):$ocms.postXT({url:$ocms.url("auth"),data:{module:t},success:e=>{$fis.auth[t]=e.auth||-1,n($fis.auth[t]||-1)},error:()=>{r()}})})),prepAuth:t=>new Promise(((e,n)=>{$ocms.postXT({url:$ocms.url("auth"),data:{module:t,array:1},success:t=>{$.extend($fis.auth,t||{})},complete:()=>{e()}})})),isAuth:(t,e)=>($fis.auth[t]||-1)>=(e||1),resetPass:function(t,e){confirm($t.smsc)&&($ocms.postXT({url:$ocms.url("account/sms"),data:{fn:"pwc"}}),$ocms.dlgform($fd.rsp.clone(),{title:$t.rsp||"",submit:function(t){var e=$(this).ldng(1),n=$.extend({loginaccount:$ocms.auth.account||""},e.serializeObject(!0,{typedvalues:!0}));(n.npw||"")!==(n.npwc||"")?e.find('input[name="npw"]:first')[0].setCustomValidity($t.pnm):$ocms.postXT({url:$ocms.url("account/changepassword"),data:n,success:function(t){alert($t.cps),e.trigger("modal_close")},error:function(t){alert($t.rspf[t.getResponseHeader("x-ocms-std")])},complete:function(){e.ldng(0)},timeout:6e4})}}))},wdg:function(t){let e=$(this).empty();$ocms.postXT({url:$ocms.url("wdg/one"),data:{short_name:t.wdg},timeout:9e4,success:function(n,r,i){let o=t.wdg,a=n[o];if(!a)return void e.ldng(0);let s=$.inArrayRegEx("dblwidth",a.rendering_options)>-1,l=$.inArrayRegEx("tiny",a.rendering_options)>-1;e.toggleClass("dbl",s&&!l).toggleClass("tny",l);$$.dc("wdg_hd",e,{title:ne(a.description,$t.wdc)}).toggleClass("dbl",s).text(ne(a.name,t.wdg)).dblclick((function(t){t.stopPropagation(),$fis.wdg.call(e,{wdg:o})}));let c=$$.dc("wdg_cnt",e).toggleClass("dbl",s).hide(),d=$.inArrayRegEx("bgcolor",a.rendering_options);switch(d>-1&&c.css("backgroundColor",a.rendering_options[d].toString().right(":")),a.type){case"table":var u=$$.tblset({},c),p=$$.tr().appendTo(u.hd),f=$t.wdg[o.indexOf("wdg_ev_")>=0?"wdg_ev_":o]||{};$.each(a.columns,(function(t,e){var n=f[e]?f[e].label:e;$$.th().text(n).appendTo(p)})),$.each(a.data,(function(t,e){var n=$$.tr().appendTo(u.bdy);$.each(a.columns,(function(t,r){var i=$$.td().appendTo(n);e[r]instanceof Date||!0===$ocms.isJSONDateString(e[r])?i.text(fdt(e[r],$t.dateformat)):i.rwText(e[r])}))})),$.inArray("firstrow_bold",a.rendering_options)>-1&&p.nextAll("tr:first").css("font-weight","bold");break;case"ind":$$.dc("ind",c).addClass("sts_"+(a.data.status||"")).append([$$.dc("ind").text(a.data.value),$$.lbl(a.data.label)]);break;case"image_url":c.css("background","url('"+a.url+"') no-repeat center center transparent");break;case"image_base64":c.css("background","url('data:image/png;base64,"+a.image+"') no-repeat center center transparent");break;case"html":if(c.html(a.html),$.inArray("reload_10min",a.rendering_options)>-1){var m=c.find("iframe");setTimeout((function(){m.attr("src",(function(t,e){return e}))}),6e5)}}$.inArray("reload_30min",a.rendering_options)>-1&&"html"!==a.type&&setTimeout((function(){$fis.wdg.call(e,{wdg:o})}),18e5),c.slideDown(150)},error:function(t){e.slideUp(150),$fis.failure.call(this,t)},complete:function(){e.ldng(0)}})},ov:function(){$fis.lf(!0);let t=$("#contentframe").empty(),e=$$.d({id:"dashboard_frame"}).appendTo(t);$ocms.postXT({url:$ocms.url("wdg/my"),success:function(t){$.each(t,(function(t,n){var r=$$.dc("wdg_frame",e,{"data-wdg":n}).ldng(1);$fis.wdg.call(r,{wdg:n})}))},loading:e})}};Array.prototype.push.apply($ocms.ocmsmenu,[{lbl:$t.m_inv,id:"m_inv",fnc:"init:inv",ico:"glyphicon glyphicon-list-alt"},{lbl:$t.m_req,id:"m_req",fnc:"init:req",ico:"glyphicon glyphicon-eur"},{lbl:$t.m_bcd,id:"m_bcd",fnc:"init:bam",ico:"glyphicon glyphicon-indent-right"},{fnc:"separator"},{lbl:$t.m_rep,id:"m_rep",fnc:"init:rep",ico:"glyphicon glyphicon-dashboard"},{fnc:"separator"},{lbl:$t.m_todo,id:"m_todo",fnc:()=>{$("#contentframe").empty().load($ocms.url("todos")),$("#listframe").rC("fix").aC("hd")},ico:"glyphicon glyphicon-sunglasses"}]),$(document).ready((function(){$fis.ov()})); \ No newline at end of file diff --git a/Fuchs/wwwroot/web/fisb.js b/Fuchs/wwwroot/web/fisb.js index aee91b3..8eb9fc4 100644 --- a/Fuchs/wwwroot/web/fisb.js +++ b/Fuchs/wwwroot/web/fisb.js @@ -222,21 +222,34 @@ function ne(inp, alt) { return (inp || '') === '' ? (alt || '') : inp; } function pad(i, n) { return (i || '').toString().padStart(n, '0').substr(-1 * n); } +function twoDigitYear(y) { var n = parseInt(y, 10); return n + (n < 70 ? 2000 : 1900); } +/* Parses dot-separated German short dates (dd.MM.yyyy / dd.MM.yy, optionally with a time part). + Returns null if the string does not match, so callers can fall back to other parsing. */ +function parseGermanDate(si) { + var g = si.match(/^(\d{1,2})\.(\d{1,2})\.(\d{2}|\d{4})(?:[\sT](\d{1,2}):(\d{2})(?::(\d{2}))?)?$/); + if (g === null) { return null; } + var yr = g[3].length === 2 ? twoDigitYear(g[3]) : parseInt(g[3], 10); + return new Date(yr, parseInt(g[2], 10) - 1, parseInt(g[1], 10), parseInt(g[4] || '0', 10), parseInt(g[5] || '0', 10), parseInt(g[6] || '0', 10)); +} function parseISO(s) { let si = s || ''; if (si === '') { return null }; if (/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/.test(si) === true) { return new Date(si); } else { - var b = s.split(/\D/); - return new Date(b[0], b[1] - 1, b[2], b[3], b[4], b[5]); + var gd = parseGermanDate(si); + if (gd !== null) { return gd; } + var b = si.split(/\D/); + return new Date(b[0], b[1] - 1, b[2], b[3] || 0, b[4] || 0, b[5] || 0); } } function parseISOLocal(s) { let si = s || ''; if (si === '') { return null }; - var b = s.split(/\D/); - return new Date(b[0], b[1] - 1, b[2], b[3], b[4], b[5]); + var gd = parseGermanDate(si); + if (gd !== null) { return gd; } + var b = si.split(/\D/); + return new Date(b[0], b[1] - 1, b[2], b[3] || 0, b[4] || 0, b[5] || 0); } function fnum(i, style) { /* { style: 'decimal/currency/percent', currency: 'USD/EUR', currencyDisplay: 'symbol/code/name', minimumIntegerDigits: 1, minimumFractionDigits: 2, maximumFractionDigits: 3, useGrouping: true } */ diff --git a/Fuchs/wwwroot/web/fisb.min.js b/Fuchs/wwwroot/web/fisb.min.js index 1a9f864..f10f9f6 100644 --- a/Fuchs/wwwroot/web/fisb.min.js +++ b/Fuchs/wwwroot/web/fisb.min.js @@ -1 +1 @@ -var $t={lng:"de-DE",dn:["So","Mo","Di","Mi","Do","Fr","Sa"],mn:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],ma:["Jan","Feb","Mrz","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],datepattern:"(0[1-9]|1[0-9]|2[0-9]|3[01]).(0[1-9]|1[012]).[0-9]{4}",datetimepattern:"(0[1-9]|1[0-9]|2[0-9]|3[01]).(0[1-9]|1[012]).[0-9]{4}\\s([0-5][0-9]):([0-5][0-9])",dateplaceholder:"dd.MM.yyyy",datetimeplaceholder:"dd.MM.yyyy HH:mm",dateformat:"dd.MM.yyyy",datetimeformat:"dd.MM.yyyy HH:mm",f1:"Der Server hat einen Fehler gemeldet: \n",f2:"Bitte versuchen Sie es erneut.",m0:"Diese Internet-Seite benötigt einen html5-kompatiblen Browser.",m0b:"Unterstützt werden bspw: Internet Explorer ab Version 10, Firefox ab Version 31, Chrome ab Version 31, Safari ab Version 7, Opera ab Version 27",m1:"Dieser Datensatz ist momentan von jemand anderem zur Bearbeitung gesperrt.",m2:"Diese Funktion ist zur Zeit nicht verfügbar",t1:"Eingabe erforderlich.",t2:"Eingabe ist nicht erforderlich.",true:"Ja",false:"Nein",alert:"Hinweis",confirm:"Bestätigen",open:"Öffnen","not implemented":"Diese Funktion in zur Zeit noch nicht verfügbar.",l0:"Anmeldung",l1:"Email / Anmeldename",l2:"Email-Adresse / Anmeldename",l3:"Passwort",l4:"Benutzer",l5:"Wird vom System ermittelt...",l6:"Anmelden",l7:"Passwort vergessen?",l7a:'Die "Passwort vergessen"-Funktion läuft in zwei Schritten ab:\n \nIm ersten Schritt wird eine SMS mit einem Code an die hinterlegte Mobilfunk-Nummer versandt.\nIm zweiten Schritt geben Sie bitte diesen Code in das Formular ein und übermitteln es erneut.\n \nIn beiden Schritten wird aus Sicherheitsgründen kein Fehler angezeigt und auch dann ein erfolgreicher Versand bestätigt, wenn die Kombination aus Email-Adresse und Nachname nicht gefunden wurde und/oder der code falsch ist.',l8:"Keinen Account?",l9:"Anmeldenamen der Email-Adresse wurde nicht erkannt.",l10:"Nachname",l11:"Email-Adresse",l12:"Passwort zusenden",l13:"Das Passwort wurde erfolgreich verschickt",l14:"Das Passwort konnte nicht verschickt werden",l15:"Sie sind nicht berechtigt, diese Funktion auszuführen.",l16:"Sie müssen zunächst einen Account angeben.",l17:"Die Kombination aus Anmeldenamen und Passwort konnte nicht bestätigt werden.",l18:"Es gibt ein Problem mit dem Formular.\nEs kann momentan nicht verarbeitet und versendet werden.",name:"Name",submit:"Senden",cancel:"Abbrechen",noop:"Diese Funktion is noch nicht verfügar."};const isIE=/MSIE\/|Trident/gi.test(window.navigator.userAgent)||void 0!==window.document.documentMode,isfileapi=!!(window.File&&window.FileReader&&window.FileList&&window.Blob);var $ocms={auth:{},no:function(e){e.stopPropagation()},vmin:function(e){var t=$(window).width*(e||1),n=$(window).height*(e||1);return t($ocms.baseurl+"/"+(e||"")).replace(/\/\//,"/"),cexi:null};function deepCopy(e){var t,n,i;if("object"!=typeof e||null===e)return e;for(i in t=Array.isArray(e)?[]:{},e)n=e[i],t[i]=deepCopy(n);return t}function fields_definition(e,t,n){this.label_sng=!0===Array.isArray(e)?"":e||"",this.label_pl=!0===Array.isArray(e)?"":t||"",this.fields=!0===Array.isArray(e)?e:n||[],this.itm=function(e){for(var t=0;t0)for(var n=0;ne||"")).filter(((e,t)=>""!==e)).join(t)}function parseDt(e,t,n){e=(e||"").substr(0,t.length);var i=t,r=e.length>0&&t.split(";").some((function(t){for(var n,r=/[^yMdhms0-9]/gi,o=!0;null!==(n=r.exec(t));)o=o&&t.substr(n.index,1)===e.substr(n.index,1);var a=e.length===t.length&&o;return!0===a&&(i=t),a}));if(!0===r){for(var o,a=[0,0,0,0,0,0,0],s=/(mm{1,2}|dd{1,2}|MM{1,2}|(yy){2,4}|ss{1,2}|hh{1,2})(?!\w)/g;null!==(o=s.exec(i));)a["yMdhms".indexOf(o[0].substr(0,1))]=parseInt(("yy"===o[0]?"20":"")+e.substr(o.index,o[0].length))-("M"===o[0].substr(0,1)?1:0);var l=new(Function.prototype.bind.apply(Date,[null].concat(a)));return"string"==typeof n?fdt(l,n):l}return!1}function bool(e,t){return"boolean"==typeof e?e:"boolean"==typeof t&&t}function booln(e,t){return"boolean"==typeof e?e:"number"==typeof e?1===e:"boolean"==typeof t&&t}Date.prototype.isValid=function(){return!isNaN(this)},Date.prototype.format=function(e){return fdt(this,e)},Date.prototype.addDays=function(e){return this.setDate(this.getDate()+e),this},Date.prototype.isBetween=function(e,t){return this>e&&this section");$(window).scroll((function(t){let n=$(window).scrollTop(),i=$("body");i.toggleClass("unfocus",n>vh()-1.2*e),i.toggleClass("btb",n>.5*vh()-e)}))},$ocms.cf_reset=function(){return $("#contentframe").empty()},function(e){e.fn.scrollTo=function(t){if(e(this).length>0){var n=e(this).offset().top||0;n>0&&e("html, body").animate({scrollTop:n-hh()},2e3)}},e.fn.ldng=function(t){var n=!0;return"boolean"==typeof t?n=t:"number"==typeof t&&(n=t>0),e(this).toggleClass("loading",n)},"function"!=typeof e.noop&&(e.noop=function(){}),e.fn.hasAttr=function(t){var n=e(this).attr(t);return void 0!==n&&!1!==n},e.fn.parseCssPx=function(t){try{return parseFloat(e(this).css(t).replace("px","")||0)}catch(e){return 0}},e.max=function(e,t){return isNaN(e)&&isNaN(t)?null:isNaN(e)&&!isNaN(t)?t:!isNaN(t)&&isNaN(t)||e>=t?e:t},e.min=function(e,t){return isNaN(e)&&isNaN(t)?null:isNaN(e)&&!isNaN(t)?t:!isNaN(t)&&isNaN(t)||e<=t?e:t},e.lim=function(e,t){return isNaN(e)?null:isNaN(t)?e:t<=e?t:e},e.fn.enterKey=function(t){return this.each((function(){e(this).keypress((function(e){"13"===(e.keyCode?e.keyCode:e.which).toString()&&t.call(this,e)}))}))}}(jQuery),$ocms.defaultTimeout=3e4,$ocms.AjaxEX=function(e){var t=this;t.responseText=t.responseText||"";var n=t.getResponseHeader("x-ocms-code")||"";t.internalCode=""!==n&&!1===isNaN(n)?parseInt(n):-1,t.isInternal=t.internalCode>-1,t.internalText=decodeURIComponent((t.getResponseHeader("x-ocms-desc")||"").replace(/\+/g,"%20")||"");var i=t.internalText||e,r=t.internalCode||t.status;t.logtext=i+" ("+r+")"},$ocms.postXTS=function(e){$ocms.postXT.call(this,$.extend(e,{sync:!0}))},$ocms.postXT=function(e){if((e=e||{}).trycount=e.trycount||0,""!==(e.url||"")){e.url=-1!==e.url.indexOf("&yy=")?e.url:e.url.indexOf("?")>-1?e.url+"&yy="+(new Date).getTime():e.url+"?yy="+(new Date).getTime();var t=e.context||this;switch(e.context=t,e.retryLimit=e.retryLimit||0,e.timeout=e.timeout||$ocms.defaultTimeout,e.timeout<100&&(e.timeout=1e3*e.timeout),e.data=e.data||{},e.contentType=e.contentType||"multipart/form-data; charset=UTF-8",e.islogin="boolean"==typeof e.islogin&&e.islogin,e.contentType){case"":case"json":e.contentType="application/json; charset=utf-8";break;case"form":e.contentType="application/x-www-form-urlencoded; charset=UTF-8";break;case"multi":e.contentType="multipart/form-data";break;case"text":e.contentType="text/plain; charset=UTF-8"}if(e.form instanceof jQuery?(e.data=e.form.serializeObject(),e.contentType="form-data"):e.lzw instanceof jQuery&&(e.data.lzw=$.ccLZW(e.lzw.serializeAnything(!0)).join(",")),"multipart/form-data"!==e.contentType.substr(0,19)&&"form-data"!==e.contentType.substr(0,9)||e.data instanceof FormData!=!1)e.data instanceof FormData&&(e.contentType=!1,e.processData=!1);else{e.contentType=!1;var n=new FormData;$.each(e.files||[],(function(e,t){n.append("upload_file",t)})),$.each(e.data||{},(function(e,t){n.append(e,t)})),e.data=n,e.processData=!1}var i={type:e.method||"post",url:e.url,data:e.data,processData:"boolean"!=typeof e.processData||e.processData,contentType:e.contentType,cache:e.cache||!1,timeout:e.timeout,beforeSend:function(n){$(e.loading).ldng(),$("body").addClass("ldng"),"function"==typeof e.beforesend&&e.beforesend.apply(t,[n])},success:function(n,i,r){"false"===n||"not authorized"===n?("function"==typeof e.error&&e.error.apply(t,[r,i,n]),"function"==typeof $.status&&$.status(i+" - "+n)):"function"==typeof e.success&&e.success.apply(t,[n,i,r])},error:function(n,i,r){if($ocms.AjaxEX.call(n,i),-1===e.url.indexOf("doc.ashx")||-1!==e.url.indexOf("ftest")){if(401===n.status&&111===n.internalCode&&!1===e.islogin&&"function"==typeof $ocms.login.dlg)$ocms.login.dlg({ajo:e});else if("timeout"===i||302===n.status)return e.tryCount++,e.tryCount<=e.retryLimit?void $ocms.postXT(e):void 0;"function"==typeof e.error?e.error.apply(t,[n,i,r]):"function"==typeof $ocms.failure?$ocms.failure.apply(t,[n]):"function"==typeof $.status&&$.status("Server error: "+i+" - "+r)}},dataType:e.datatype||"json",complete:function(n,i){"function"==typeof e.complete&&e.complete.apply(t,[n,i]),$(e.loading).ldng(0),$("body").removeClass("ldng");let r=$("body > .timer");if(r.length>0){let e=new Date(n.getResponseHeader("ocms_cec")||""),t=new Date(n.getResponseHeader("ocms_cex")||"");if(e.isValid()&&t.isValid()){let n=new Date,i=Math.abs(t-e);n.setMilliseconds(n.getMilliseconds()+i),r.data({cex:n,ctt:i}),$ocms.cex_timer()}}},context:t,async:!0};"boolean"==typeof e.sync&&(i.async=!1===e.sync),!0==("boolean"==typeof e.contentType&&!1===e.contentType)&&(i.contentType=!1),$.ajax(i)}},$ocms.cex_timer=function(){$ocms.cexi||($ocms.cexi=setInterval($ocms.cex_timer,15e3));let e=$("body > .timer"),t=e.data("cex"),n=e.data("ctt"),i=new Date;if(t instanceof Date&&t.isValid()&&"number"==typeof n&&n>0&&t>i){let r=Math.abs(i-t)/n*100;e.css("width",r.toString()+"%"),r<98&&(!$ocms.cex_lp||Math.abs(i-$ocms.cex_lp)>6e5)&&$ocms.postXT({url:$ocms.url("ping"),success:()=>{$ocms.cex_lp=i},timeout:5e3,error:()=>{}})}},$ocms.vbl_send=function(e){var t=e.data||{};if(""!==(t.url||"")){var n=$("#contentframe form:first"),i={url:t.url,data:new FormData,success:function(e){"function"==typeof t.success?t.success(e):"string"==typeof t.success&&alert(t.success)},error:function(e,n,i){"function"==typeof t.error?t.error(i):"string"==typeof t.error&&alert(t.error)},complete:function(){n.ldng(0)}},r=!0;n.find("input").each((function(){var e=$(this),t=e.nza("name"),n=e.val(),o=$(this).prop("required")||!1;if(""!==t){var a=""!==n||!1===o;r=r&&a,!0===a?(i.data.append(t,n),e[0].setCustomValidity("")):""!==$(this).nza("ocms-nvnote")&&e[0].setCustomValidity($(this).nza("ocms-nvnote"))}})),!0===r&&(n.ldng(1),$ocms.postXT.call(this,i))}},function(e){e.fn.nza=function(t,n){var i=e(this).attr(t);return void 0!==i&&!1!==i?i:n||""},e.fn.serializeObject=function(t,n){var i=/\r?\n/g,r=/^(?:submit|button|image|reset|file)$/i,o=/^(?:input|select|textarea|keygen)/i,a=/^(?:checkbox|radio)$/i,s=bool((n=n||{}).typedvalues,!1),l={},c=e(this),d=c.find(':input:not([nosend],[type="file"])').addBack(":input"),u=!0;return e.each(d.not(".tinymce").get(),(function(n,c){var d=e(this),f=this,m=(this.type||"").toLowerCase(),p=d.prop("required")||!1;if(!0===(f.name&&!d.is(":disabled")&&o.test(f.nodeName)&&!r.test(m))){var h=d.val(),g=f.name,y=d.nza("data-format").split(":"),v=d.nza("pattern")||".*";if(!0===a.test(m)&&(h=f.checked?""!==h?h:"true":""),"date"===y[0].substr(0,4)&&y.length>1)"boolean"==typeof(h=parseDt(h,y.slice(1).join(":")))&&(h=null),null===h&&"date"===d.prop("type").substr(0,4)&&!1===isNaN(new Date(d.val()))&&(h=new Date(d.val())),h instanceof Date==!0&&"function"==typeof h.getMonth?!1===s&&(h=fdt(h,"date"===y[0]?"dts":"iso")):h=null;else if("number"===m&&!0===s){let e;e="integer"===y[0]?parseInt(h):parseFloat(h),h=isNaN(e)?h:e}if(!0!==p||""!==(h||"")&&null!==h.match(v)?!0===bool(t,!1)&&f.setCustomValidity(""):(!0===bool(t,!1)&&f.setCustomValidity(d.nza("ocms-nvnote",$ocms.t.inv||"Invalid field")),h=null),null!=h&&"string"==typeof h){let e=l[g];null!=e?Array.isArray(e)?e.push(h.replace(i,"\r\n")):l[g]=[e,h.replace(i,"\r\n")]:l[g]=h.replace(i,"\r\n")}else if(null!=h){let e=l[g];null!=e?Array.isArray(e)?e.push(h):l[g]=[e,h]:l[g]=h}else u=!1}})),d.filter(".tinymce").each((function(t,n){var i=e(this),r=((this.type||"").toLowerCase(),i.prop("required")||!1);try{var o=tinymce.get(e(n).attr("id"));if(o){var a=e(n).attr("name"),s=o.getContent();!1===r||""!==(s||"")?l[a]=s:u=!1}}catch(t){e.noop()}})),c.toggleClass("invalid",!u),u?l:null},e.fn.sendForm=function(t,n,i){var r=e(this);i=i||{};var o={url:t,success:function(e){if(i.response=e,"function"==typeof n)n(e);r.closest("div.modal").remove()},error:function(e,t,n){"function"==typeof i.error?i.error.call(this,e):$ocms.failure.call(this,e)},complete:function(){r.ldng(0),"function"==typeof i.complete&&i.complete.call(this,jqXHR)}},a=r.find('input[type="file"]');o.data=new FormData,a.length>0&&e.each(a[0].files,(function(e,t){o.data.append(e,t),o.data.append("file_lastmodified",$ocms.isodt(t.lastModifiedDate))}));var s=r.serializeObject();e.each(s||{},(function(e,t){o.data.append(e,t)})),r.ldng(),$ocms.postXT.call(this,o)},e.fn.checkValidity=function(){var t=e(this),n=!0;return t.each((function(e,t){n=n&&t.checkValidity()})),n},e.fn.wrap=function(t,n){var i=e(this),r=$$.dc(t).attr(n||{}).insertAfter(i);return i.append(r),r}}(jQuery),$ocms.logout=function(){$ocms.postXT({url:$ocms.url("logout"),complete:function(){window.location.reload()}})},$ocms.login={send:function(e){e.preventDefault();var t=$(this);if(!0===t.find("#dbtn-confirm").hasClass("disabled"))return!1;var n=t.serializeObject();return n.loginaccount=ne(n.loginaccount,$ocms.auth.account||$ocms.auth.requestedaccount||""),n.loginaccount=ne(n.loginaccount,$ocms.auth.account||$ocms.auth.requestedaccount||""),""===ne(n.loginaccount)&&!0===bool($ocms.auth.accountrequired,!0)?(alert($t.l16),!1):($ocms.postXT({url:$ocms.url("login"),data:n,success:function(){window.location.reload()}}),!1)},uichange:function(){let e=$(this),t=e.closest("form"),n=bool($ocms.auth.accountrequired,!0),i=ne(t.find('[name="loginaccount"]').val(),$ocms.auth.account||$ocms.auth.requestedaccount||"");if(""!==i||!1===n){var r=t.find('[name="userlogin"]').empty().val(""),o=t.find('[name="username"]').empty().val(""),a=$("#dlg_userlogin_sel").empty().val(""),s=e.val()||"";if(!1===e.checkValidity()&&""===s)return;var l=e.closest("table").ldng();$ocms.postXT.call(this,{url:$ocms.url("auth"),data:{userinfo:s,account:i||""},success:function(e,t,n){if(1===e.length){var i=e[0];r.val(i.login).change().attr("required","").removeAttr("nosend"),o.val(i.name).change().attr("required","").show(),a.removeAttr("required").attr("nosend","").hide()}else e.length>0?(o.hide().removeAttr("required"),r.removeAttr("required").attr("nosend",""),0===a.length&&(a=$("").attr({name:"userlogin",size:e.length,id:"dlg_userlogin_sel",class:"form-control",required:""}).css({width:"100%","max-width":"100%",padding:"2px"}).insertAfter(o)),$.each(e,(function(e,t){var n=$("").attr({value:t.login,style:"padding-top: 2px; padding-bottom: 5px;","border-bottom":"1px solid #EEE;"}).text(t.name).appendTo(a);e%2==0&&n.css({"background-color":"#F9F9F9"})})),a.attr("required","").removeAttr("nosend")):(a.hide().attr("nosend",""),o.attr("required","").show(),r.attr("required","").removeAttr("nosend"),alert($t.l9))},error:function(e){$ocms.failure.call(this,e)},complete:function(){l.ldng(0)}})}else alert($t.l18)},sendpassword:function(e){var t=$(''),n=t.find(".form-body"),i=null;t.find("form").submit((function(e){e.preventDefault();var r=$(this).serializeObject(!0),o=null===i,a=o?"spwc":"spw";return $ocms.postXT.call(this,{url:$ocms.url(a),data:r,complete:function(){o?(n.append('
        Ihnen wurde ein Code per SMS zugesandt.
        Bitte tragen Sie den hier ein:
        '),i=$('
        ').appendTo(n)):(alert($t.l13),t.remove())},error:()=>{}}),!1})),t.find(".modal-close").click((function(){t.remove()}));var r=[];$.each($t.l7a.split("\n"),((e,t)=>{Array.prototype.push.apply(r,[$("
        "),$("").text(t)])})),t.find(".modal-note").append($('').text($t.alert)).append(r),t.appendTo("body"),setTimeout((function(){$(".modal").find('input[name="lastname"]').focus()}),600)}},$(document).ready((function(){$("#loginform").submit($ocms.login.send)})); \ No newline at end of file +var $t={lng:"de-DE",dn:["So","Mo","Di","Mi","Do","Fr","Sa"],mn:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],ma:["Jan","Feb","Mrz","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],datepattern:"(0[1-9]|1[0-9]|2[0-9]|3[01]).(0[1-9]|1[012]).[0-9]{4}",datetimepattern:"(0[1-9]|1[0-9]|2[0-9]|3[01]).(0[1-9]|1[012]).[0-9]{4}\\s([0-5][0-9]):([0-5][0-9])",dateplaceholder:"dd.MM.yyyy",datetimeplaceholder:"dd.MM.yyyy HH:mm",dateformat:"dd.MM.yyyy",datetimeformat:"dd.MM.yyyy HH:mm",f1:"Der Server hat einen Fehler gemeldet: \n",f2:"Bitte versuchen Sie es erneut.",m0:"Diese Internet-Seite benötigt einen html5-kompatiblen Browser.",m0b:"Unterstützt werden bspw: Internet Explorer ab Version 10, Firefox ab Version 31, Chrome ab Version 31, Safari ab Version 7, Opera ab Version 27",m1:"Dieser Datensatz ist momentan von jemand anderem zur Bearbeitung gesperrt.",m2:"Diese Funktion ist zur Zeit nicht verfügbar",t1:"Eingabe erforderlich.",t2:"Eingabe ist nicht erforderlich.",true:"Ja",false:"Nein",alert:"Hinweis",confirm:"Bestätigen",open:"Öffnen","not implemented":"Diese Funktion in zur Zeit noch nicht verfügbar.",l0:"Anmeldung",l1:"Email / Anmeldename",l2:"Email-Adresse / Anmeldename",l3:"Passwort",l4:"Benutzer",l5:"Wird vom System ermittelt...",l6:"Anmelden",l7:"Passwort vergessen?",l7a:'Die "Passwort vergessen"-Funktion läuft in zwei Schritten ab:\n \nIm ersten Schritt wird eine SMS mit einem Code an die hinterlegte Mobilfunk-Nummer versandt.\nIm zweiten Schritt geben Sie bitte diesen Code in das Formular ein und übermitteln es erneut.\n \nIn beiden Schritten wird aus Sicherheitsgründen kein Fehler angezeigt und auch dann ein erfolgreicher Versand bestätigt, wenn die Kombination aus Email-Adresse und Nachname nicht gefunden wurde und/oder der code falsch ist.',l8:"Keinen Account?",l9:"Anmeldenamen der Email-Adresse wurde nicht erkannt.",l10:"Nachname",l11:"Email-Adresse",l12:"Passwort zusenden",l13:"Das Passwort wurde erfolgreich verschickt",l14:"Das Passwort konnte nicht verschickt werden",l15:"Sie sind nicht berechtigt, diese Funktion auszuführen.",l16:"Sie müssen zunächst einen Account angeben.",l17:"Die Kombination aus Anmeldenamen und Passwort konnte nicht bestätigt werden.",l18:"Es gibt ein Problem mit dem Formular.\nEs kann momentan nicht verarbeitet und versendet werden.",name:"Name",submit:"Senden",cancel:"Abbrechen",noop:"Diese Funktion is noch nicht verfügar."};const isIE=/MSIE\/|Trident/gi.test(window.navigator.userAgent)||void 0!==window.document.documentMode,isfileapi=!!(window.File&&window.FileReader&&window.FileList&&window.Blob);var $ocms={auth:{},no:function(e){e.stopPropagation()},vmin:function(e){var t=$(window).width*(e||1),n=$(window).height*(e||1);return t($ocms.baseurl+"/"+(e||"")).replace(/\/\//,"/"),cexi:null};function deepCopy(e){var t,n,i;if("object"!=typeof e||null===e)return e;for(i in t=Array.isArray(e)?[]:{},e)n=e[i],t[i]=deepCopy(n);return t}function fields_definition(e,t,n){this.label_sng=!0===Array.isArray(e)?"":e||"",this.label_pl=!0===Array.isArray(e)?"":t||"",this.fields=!0===Array.isArray(e)?e:n||[],this.itm=function(e){for(var t=0;t0)for(var n=0;ne||"")).filter(((e,t)=>""!==e)).join(t)}function parseDt(e,t,n){e=(e||"").substr(0,t.length);var i=t,r=e.length>0&&t.split(";").some((function(t){for(var n,r=/[^yMdhms0-9]/gi,o=!0;null!==(n=r.exec(t));)o=o&&t.substr(n.index,1)===e.substr(n.index,1);var a=e.length===t.length&&o;return!0===a&&(i=t),a}));if(!0===r){for(var o,a=[0,0,0,0,0,0,0],s=/(mm{1,2}|dd{1,2}|MM{1,2}|(yy){2,4}|ss{1,2}|hh{1,2})(?!\w)/g;null!==(o=s.exec(i));)a["yMdhms".indexOf(o[0].substr(0,1))]=parseInt(("yy"===o[0]?"20":"")+e.substr(o.index,o[0].length))-("M"===o[0].substr(0,1)?1:0);var l=new(Function.prototype.bind.apply(Date,[null].concat(a)));return"string"==typeof n?fdt(l,n):l}return!1}function bool(e,t){return"boolean"==typeof e?e:"boolean"==typeof t&&t}function booln(e,t){return"boolean"==typeof e?e:"number"==typeof e?1===e:"boolean"==typeof t&&t}Date.prototype.isValid=function(){return!isNaN(this)},Date.prototype.format=function(e){return fdt(this,e)},Date.prototype.addDays=function(e){return this.setDate(this.getDate()+e),this},Date.prototype.isBetween=function(e,t){return this>e&&this section");$(window).scroll((function(t){let n=$(window).scrollTop(),i=$("body");i.toggleClass("unfocus",n>vh()-1.2*e),i.toggleClass("btb",n>.5*vh()-e)}))},$ocms.cf_reset=function(){return $("#contentframe").empty()},function(e){e.fn.scrollTo=function(t){if(e(this).length>0){var n=e(this).offset().top||0;n>0&&e("html, body").animate({scrollTop:n-hh()},2e3)}},e.fn.ldng=function(t){var n=!0;return"boolean"==typeof t?n=t:"number"==typeof t&&(n=t>0),e(this).toggleClass("loading",n)},"function"!=typeof e.noop&&(e.noop=function(){}),e.fn.hasAttr=function(t){var n=e(this).attr(t);return void 0!==n&&!1!==n},e.fn.parseCssPx=function(t){try{return parseFloat(e(this).css(t).replace("px","")||0)}catch(e){return 0}},e.max=function(e,t){return isNaN(e)&&isNaN(t)?null:isNaN(e)&&!isNaN(t)?t:!isNaN(t)&&isNaN(t)||e>=t?e:t},e.min=function(e,t){return isNaN(e)&&isNaN(t)?null:isNaN(e)&&!isNaN(t)?t:!isNaN(t)&&isNaN(t)||e<=t?e:t},e.lim=function(e,t){return isNaN(e)?null:isNaN(t)?e:t<=e?t:e},e.fn.enterKey=function(t){return this.each((function(){e(this).keypress((function(e){"13"===(e.keyCode?e.keyCode:e.which).toString()&&t.call(this,e)}))}))}}(jQuery),$ocms.defaultTimeout=3e4,$ocms.AjaxEX=function(e){var t=this;t.responseText=t.responseText||"";var n=t.getResponseHeader("x-ocms-code")||"";t.internalCode=""!==n&&!1===isNaN(n)?parseInt(n):-1,t.isInternal=t.internalCode>-1,t.internalText=decodeURIComponent((t.getResponseHeader("x-ocms-desc")||"").replace(/\+/g,"%20")||"");var i=t.internalText||e,r=t.internalCode||t.status;t.logtext=i+" ("+r+")"},$ocms.postXTS=function(e){$ocms.postXT.call(this,$.extend(e,{sync:!0}))},$ocms.postXT=function(e){if((e=e||{}).trycount=e.trycount||0,""!==(e.url||"")){e.url=-1!==e.url.indexOf("&yy=")?e.url:e.url.indexOf("?")>-1?e.url+"&yy="+(new Date).getTime():e.url+"?yy="+(new Date).getTime();var t=e.context||this;switch(e.context=t,e.retryLimit=e.retryLimit||0,e.timeout=e.timeout||$ocms.defaultTimeout,e.timeout<100&&(e.timeout=1e3*e.timeout),e.data=e.data||{},e.contentType=e.contentType||"multipart/form-data; charset=UTF-8",e.islogin="boolean"==typeof e.islogin&&e.islogin,e.contentType){case"":case"json":e.contentType="application/json; charset=utf-8";break;case"form":e.contentType="application/x-www-form-urlencoded; charset=UTF-8";break;case"multi":e.contentType="multipart/form-data";break;case"text":e.contentType="text/plain; charset=UTF-8"}if(e.form instanceof jQuery?(e.data=e.form.serializeObject(),e.contentType="form-data"):e.lzw instanceof jQuery&&(e.data.lzw=$.ccLZW(e.lzw.serializeAnything(!0)).join(",")),"multipart/form-data"!==e.contentType.substr(0,19)&&"form-data"!==e.contentType.substr(0,9)||e.data instanceof FormData!=!1)e.data instanceof FormData&&(e.contentType=!1,e.processData=!1);else{e.contentType=!1;var n=new FormData;$.each(e.files||[],(function(e,t){n.append("upload_file",t)})),$.each(e.data||{},(function(e,t){n.append(e,t)})),e.data=n,e.processData=!1}var i={type:e.method||"post",url:e.url,data:e.data,processData:"boolean"!=typeof e.processData||e.processData,contentType:e.contentType,cache:e.cache||!1,timeout:e.timeout,beforeSend:function(n){$(e.loading).ldng(),$("body").addClass("ldng"),"function"==typeof e.beforesend&&e.beforesend.apply(t,[n])},success:function(n,i,r){"false"===n||"not authorized"===n?("function"==typeof e.error&&e.error.apply(t,[r,i,n]),"function"==typeof $.status&&$.status(i+" - "+n)):"function"==typeof e.success&&e.success.apply(t,[n,i,r])},error:function(n,i,r){if($ocms.AjaxEX.call(n,i),-1===e.url.indexOf("doc.ashx")||-1!==e.url.indexOf("ftest")){if(401===n.status&&111===n.internalCode&&!1===e.islogin&&"function"==typeof $ocms.login.dlg)$ocms.login.dlg({ajo:e});else if("timeout"===i||302===n.status)return e.tryCount++,e.tryCount<=e.retryLimit?void $ocms.postXT(e):void 0;"function"==typeof e.error?e.error.apply(t,[n,i,r]):"function"==typeof $ocms.failure?$ocms.failure.apply(t,[n]):"function"==typeof $.status&&$.status("Server error: "+i+" - "+r)}},dataType:e.datatype||"json",complete:function(n,i){"function"==typeof e.complete&&e.complete.apply(t,[n,i]),$(e.loading).ldng(0),$("body").removeClass("ldng");let r=$("body > .timer");if(r.length>0){let e=new Date(n.getResponseHeader("ocms_cec")||""),t=new Date(n.getResponseHeader("ocms_cex")||"");if(e.isValid()&&t.isValid()){let n=new Date,i=Math.abs(t-e);n.setMilliseconds(n.getMilliseconds()+i),r.data({cex:n,ctt:i}),$ocms.cex_timer()}}},context:t,async:!0};"boolean"==typeof e.sync&&(i.async=!1===e.sync),!0==("boolean"==typeof e.contentType&&!1===e.contentType)&&(i.contentType=!1),$.ajax(i)}},$ocms.cex_timer=function(){$ocms.cexi||($ocms.cexi=setInterval($ocms.cex_timer,15e3));let e=$("body > .timer"),t=e.data("cex"),n=e.data("ctt"),i=new Date;if(t instanceof Date&&t.isValid()&&"number"==typeof n&&n>0&&t>i){let r=Math.abs(i-t)/n*100;e.css("width",r.toString()+"%"),r<98&&(!$ocms.cex_lp||Math.abs(i-$ocms.cex_lp)>6e5)&&$ocms.postXT({url:$ocms.url("ping"),success:()=>{$ocms.cex_lp=i},timeout:5e3,error:()=>{}})}},$ocms.vbl_send=function(e){var t=e.data||{};if(""!==(t.url||"")){var n=$("#contentframe form:first"),i={url:t.url,data:new FormData,success:function(e){"function"==typeof t.success?t.success(e):"string"==typeof t.success&&alert(t.success)},error:function(e,n,i){"function"==typeof t.error?t.error(i):"string"==typeof t.error&&alert(t.error)},complete:function(){n.ldng(0)}},r=!0;n.find("input").each((function(){var e=$(this),t=e.nza("name"),n=e.val(),o=$(this).prop("required")||!1;if(""!==t){var a=""!==n||!1===o;r=r&&a,!0===a?(i.data.append(t,n),e[0].setCustomValidity("")):""!==$(this).nza("ocms-nvnote")&&e[0].setCustomValidity($(this).nza("ocms-nvnote"))}})),!0===r&&(n.ldng(1),$ocms.postXT.call(this,i))}},function(e){e.fn.nza=function(t,n){var i=e(this).attr(t);return void 0!==i&&!1!==i?i:n||""},e.fn.serializeObject=function(t,n){var i=/\r?\n/g,r=/^(?:submit|button|image|reset|file)$/i,o=/^(?:input|select|textarea|keygen)/i,a=/^(?:checkbox|radio)$/i,s=bool((n=n||{}).typedvalues,!1),l={},c=e(this),u=c.find(':input:not([nosend],[type="file"])').addBack(":input"),d=!0;return e.each(u.not(".tinymce").get(),(function(n,c){var u=e(this),f=this,m=(this.type||"").toLowerCase(),p=u.prop("required")||!1;if(!0===(f.name&&!u.is(":disabled")&&o.test(f.nodeName)&&!r.test(m))){var h=u.val(),g=f.name,y=u.nza("data-format").split(":"),v=u.nza("pattern")||".*";if(!0===a.test(m)&&(h=f.checked?""!==h?h:"true":""),"date"===y[0].substr(0,4)&&y.length>1)"boolean"==typeof(h=parseDt(h,y.slice(1).join(":")))&&(h=null),null===h&&"date"===u.prop("type").substr(0,4)&&!1===isNaN(new Date(u.val()))&&(h=new Date(u.val())),h instanceof Date==!0&&"function"==typeof h.getMonth?!1===s&&(h=fdt(h,"date"===y[0]?"dts":"iso")):h=null;else if("number"===m&&!0===s){let e;e="integer"===y[0]?parseInt(h):parseFloat(h),h=isNaN(e)?h:e}if(!0!==p||""!==(h||"")&&null!==h.match(v)?!0===bool(t,!1)&&f.setCustomValidity(""):(!0===bool(t,!1)&&f.setCustomValidity(u.nza("ocms-nvnote",$ocms.t.inv||"Invalid field")),h=null),null!=h&&"string"==typeof h){let e=l[g];null!=e?Array.isArray(e)?e.push(h.replace(i,"\r\n")):l[g]=[e,h.replace(i,"\r\n")]:l[g]=h.replace(i,"\r\n")}else if(null!=h){let e=l[g];null!=e?Array.isArray(e)?e.push(h):l[g]=[e,h]:l[g]=h}else d=!1}})),u.filter(".tinymce").each((function(t,n){var i=e(this),r=((this.type||"").toLowerCase(),i.prop("required")||!1);try{var o=tinymce.get(e(n).attr("id"));if(o){var a=e(n).attr("name"),s=o.getContent();!1===r||""!==(s||"")?l[a]=s:d=!1}}catch(t){e.noop()}})),c.toggleClass("invalid",!d),d?l:null},e.fn.sendForm=function(t,n,i){var r=e(this);i=i||{};var o={url:t,success:function(e){if(i.response=e,"function"==typeof n)n(e);r.closest("div.modal").remove()},error:function(e,t,n){"function"==typeof i.error?i.error.call(this,e):$ocms.failure.call(this,e)},complete:function(){r.ldng(0),"function"==typeof i.complete&&i.complete.call(this,jqXHR)}},a=r.find('input[type="file"]');o.data=new FormData,a.length>0&&e.each(a[0].files,(function(e,t){o.data.append(e,t),o.data.append("file_lastmodified",$ocms.isodt(t.lastModifiedDate))}));var s=r.serializeObject();e.each(s||{},(function(e,t){o.data.append(e,t)})),r.ldng(),$ocms.postXT.call(this,o)},e.fn.checkValidity=function(){var t=e(this),n=!0;return t.each((function(e,t){n=n&&t.checkValidity()})),n},e.fn.wrap=function(t,n){var i=e(this),r=$$.dc(t).attr(n||{}).insertAfter(i);return i.append(r),r}}(jQuery),$ocms.logout=function(){$ocms.postXT({url:$ocms.url("logout"),complete:function(){window.location.reload()}})},$ocms.login={send:function(e){e.preventDefault();var t=$(this);if(!0===t.find("#dbtn-confirm").hasClass("disabled"))return!1;var n=t.serializeObject();return n.loginaccount=ne(n.loginaccount,$ocms.auth.account||$ocms.auth.requestedaccount||""),n.loginaccount=ne(n.loginaccount,$ocms.auth.account||$ocms.auth.requestedaccount||""),""===ne(n.loginaccount)&&!0===bool($ocms.auth.accountrequired,!0)?(alert($t.l16),!1):($ocms.postXT({url:$ocms.url("login"),data:n,success:function(){window.location.reload()}}),!1)},uichange:function(){let e=$(this),t=e.closest("form"),n=bool($ocms.auth.accountrequired,!0),i=ne(t.find('[name="loginaccount"]').val(),$ocms.auth.account||$ocms.auth.requestedaccount||"");if(""!==i||!1===n){var r=t.find('[name="userlogin"]').empty().val(""),o=t.find('[name="username"]').empty().val(""),a=$("#dlg_userlogin_sel").empty().val(""),s=e.val()||"";if(!1===e.checkValidity()&&""===s)return;var l=e.closest("table").ldng();$ocms.postXT.call(this,{url:$ocms.url("auth"),data:{userinfo:s,account:i||""},success:function(e,t,n){if(1===e.length){var i=e[0];r.val(i.login).change().attr("required","").removeAttr("nosend"),o.val(i.name).change().attr("required","").show(),a.removeAttr("required").attr("nosend","").hide()}else e.length>0?(o.hide().removeAttr("required"),r.removeAttr("required").attr("nosend",""),0===a.length&&(a=$("").attr({name:"userlogin",size:e.length,id:"dlg_userlogin_sel",class:"form-control",required:""}).css({width:"100%","max-width":"100%",padding:"2px"}).insertAfter(o)),$.each(e,(function(e,t){var n=$("").attr({value:t.login,style:"padding-top: 2px; padding-bottom: 5px;","border-bottom":"1px solid #EEE;"}).text(t.name).appendTo(a);e%2==0&&n.css({"background-color":"#F9F9F9"})})),a.attr("required","").removeAttr("nosend")):(a.hide().attr("nosend",""),o.attr("required","").show(),r.attr("required","").removeAttr("nosend"),alert($t.l9))},error:function(e){$ocms.failure.call(this,e)},complete:function(){l.ldng(0)}})}else alert($t.l18)},sendpassword:function(e){var t=$(''),n=t.find(".form-body"),i=null;t.find("form").submit((function(e){e.preventDefault();var r=$(this).serializeObject(!0),o=null===i,a=o?"spwc":"spw";return $ocms.postXT.call(this,{url:$ocms.url(a),data:r,complete:function(){o?(n.append('
        Ihnen wurde ein Code per SMS zugesandt.
        Bitte tragen Sie den hier ein:
        '),i=$('
        ').appendTo(n)):(alert($t.l13),t.remove())},error:()=>{}}),!1})),t.find(".modal-close").click((function(){t.remove()}));var r=[];$.each($t.l7a.split("\n"),((e,t)=>{Array.prototype.push.apply(r,[$("
        "),$("").text(t)])})),t.find(".modal-note").append($('').text($t.alert)).append(r),t.appendTo("body"),setTimeout((function(){$(".modal").find('input[name="lastname"]').focus()}),600)}},$(document).ready((function(){$("#loginform").submit($ocms.login.send)})); \ No newline at end of file diff --git a/Fuchs_DataService/Fuchs_DataService.csproj b/Fuchs_DataService/Fuchs_DataService.csproj index 14d81cb..530a636 100644 --- a/Fuchs_DataService/Fuchs_DataService.csproj +++ b/Fuchs_DataService/Fuchs_DataService.csproj @@ -37,9 +37,9 @@ - - - - + + + +
        diff --git a/Fuchs_Database/FuchsDatabase.sqlproj b/Fuchs_Database/FuchsDatabase.sqlproj index b9fbe26..cd90244 100644 --- a/Fuchs_Database/FuchsDatabase.sqlproj +++ b/Fuchs_Database/FuchsDatabase.sqlproj @@ -1,4 +1,4 @@ - + Debug @@ -329,6 +329,8 @@ + + @@ -336,6 +338,8 @@ + + diff --git a/Fuchs_Database/dbo/Stored Procedures/fds__getInvoiceFileContent.sql b/Fuchs_Database/dbo/Stored Procedures/fds__getInvoiceFileContent.sql new file mode 100644 index 0000000..301015e --- /dev/null +++ b/Fuchs_Database/dbo/Stored Procedures/fds__getInvoiceFileContent.sql @@ -0,0 +1,18 @@ + +-- ============================================= +-- Author: +-- Create date: +-- Description: Returns the stored file bytes for a single invoice, for use by +-- the Azure Blob Storage startup backfill after the row has been +-- selected via fds__getInvoiceFiles_ForBlobArchive. +-- ============================================= +CREATE PROCEDURE [dbo].[fds__getInvoiceFileContent] + @Id varchar(10) +AS +BEGIN + SET NOCOUNT ON; + + SELECT TOP(1) [Id], [file] + FROM [dbo].[fds__invoices] + WHERE [Id] = @Id AND @Id is not null AND [file] IS NOT NULL; +END diff --git a/Fuchs_Database/dbo/Stored Procedures/fds__getInvoiceFiles_ForBlobArchive.sql b/Fuchs_Database/dbo/Stored Procedures/fds__getInvoiceFiles_ForBlobArchive.sql new file mode 100644 index 0000000..8dd0ed8 --- /dev/null +++ b/Fuchs_Database/dbo/Stored Procedures/fds__getInvoiceFiles_ForBlobArchive.sql @@ -0,0 +1,27 @@ + +-- ============================================= +-- Author: +-- Create date: +-- Description: Enumerates invoices that already have a stored file, returning +-- lightweight metadata only (no file bytes) so the Azure Blob +-- Storage startup backfill (see AzureBlobStorageService / +-- DocumentArchiveSyncService) can enumerate candidates cheaply +-- before fetching each file's content individually via +-- fds__getInvoiceFileContent. +-- ============================================= +CREATE PROCEDURE [dbo].[fds__getInvoiceFiles_ForBlobArchive] +AS +BEGIN + SET NOCOUNT ON; + + SELECT + [Id] + ,[Version] + ,[InvoiceId] + ,[InvoiceTitle] + ,[DocumentName] + ,[file_guid] + FROM [dbo].[fds__invoices] + WHERE [file] IS NOT NULL + ORDER BY [Id]; +END diff --git a/Fuchs_Database/dbo/Stored Procedures/fds__getReminderFileContent.sql b/Fuchs_Database/dbo/Stored Procedures/fds__getReminderFileContent.sql new file mode 100644 index 0000000..a7f817b --- /dev/null +++ b/Fuchs_Database/dbo/Stored Procedures/fds__getReminderFileContent.sql @@ -0,0 +1,18 @@ + +-- ============================================= +-- Author: +-- Create date: +-- Description: Returns the stored file bytes for a single reminder, for use by +-- the Azure Blob Storage startup backfill after the row has been +-- selected via fds__getReminderFiles_ForBlobArchive. +-- ============================================= +CREATE PROCEDURE [dbo].[fds__getReminderFileContent] + @Id varchar(10) +AS +BEGIN + SET NOCOUNT ON; + + SELECT TOP(1) [Id], [file] + FROM [dbo].[fds__reminder] + WHERE [Id] = @Id AND @Id is not null AND [file] IS NOT NULL; +END diff --git a/Fuchs_Database/dbo/Stored Procedures/fds__getReminderFiles_ForBlobArchive.sql b/Fuchs_Database/dbo/Stored Procedures/fds__getReminderFiles_ForBlobArchive.sql new file mode 100644 index 0000000..c438e84 --- /dev/null +++ b/Fuchs_Database/dbo/Stored Procedures/fds__getReminderFiles_ForBlobArchive.sql @@ -0,0 +1,25 @@ + +-- ============================================= +-- Author: +-- Create date: +-- Description: Enumerates reminders that already have a stored file, returning +-- lightweight metadata only (no file bytes) so the Azure Blob +-- Storage startup backfill (see AzureBlobStorageService / +-- DocumentArchiveSyncService) can enumerate candidates cheaply +-- before fetching each file's content individually via +-- fds__getReminderFileContent. +-- ============================================= +CREATE PROCEDURE [dbo].[fds__getReminderFiles_ForBlobArchive] +AS +BEGIN + SET NOCOUNT ON; + + SELECT + [Id] + ,[Version] + ,[InvId] + ,[DocumentName] + FROM [dbo].[fds__reminder] + WHERE [file] IS NOT NULL + ORDER BY [Id]; +END diff --git a/Fuchs_Database/dbo/Tables/fds__reminder.sql b/Fuchs_Database/dbo/Tables/fds__reminder.sql index 7c3a3f5..d2d6a0a 100644 --- a/Fuchs_Database/dbo/Tables/fds__reminder.sql +++ b/Fuchs_Database/dbo/Tables/fds__reminder.sql @@ -1,29 +1,30 @@ CREATE TABLE [dbo].[fds__reminder] ( - [Id] VARCHAR (10) NOT NULL, - [Version] INT CONSTRAINT [DF_fds__reminder_Version] DEFAULT ((0)) NOT NULL, - [DocumentName] VARCHAR (100) NULL, - [InvId] VARCHAR (15) NOT NULL, - [CustomerId] BIGINT NULL, - [SendToAddress] NVARCHAR (1000) NULL, - [SendToEmail] NVARCHAR (255) NULL, - [type] VARCHAR (3) NOT NULL, - [amount] NUMERIC (10, 3) NULL, - [amount_payed] NUMERIC (10, 3) NULL, - [amount_open] AS (CONVERT([numeric](10,3),isnull([amount],(0))-isnull([amount_payed],(0)))), - [subject] NVARCHAR (255) NULL, - [text] NVARCHAR (2000) NULL, - [IsSent] BIT CONSTRAINT [DF_fds__reminder_IsSent] DEFAULT ((0)) NOT NULL, - [IsFinal] AS (CONVERT([bit],case when [DateFinalized] IS NULL then (0) else (1) end)), - [CustomValues] NVARCHAR (MAX) NULL, - [DateSent] DATETIME NULL, - [UserSent] VARCHAR (25) NULL, - [DateFinalized] DATETIME NULL, - [UserFinalized] VARCHAR (25) NULL, - [DateCreated] DATETIME NOT NULL, - [UserCreated] VARCHAR (25) NOT NULL, - [DateModified] DATETIME NOT NULL, - [UserModified] VARCHAR (25) NOT NULL, - [file] VARBINARY (MAX) NULL, + [Id] VARCHAR (10) NOT NULL, + [Version] INT CONSTRAINT [DF_fds__reminder_Version] DEFAULT ((0)) NOT NULL, + [DocumentName] VARCHAR (100) NULL, + [InvId] VARCHAR (15) NOT NULL, + [CustomerId] BIGINT NULL, + [SendToAddress] NVARCHAR (1000) NULL, + [SendToEmail] NVARCHAR (255) NULL, + [type] VARCHAR (3) NOT NULL, + [amount] NUMERIC (10, 3) NULL, + [amount_payed] NUMERIC (10, 3) NULL, + [amount_open] AS (CONVERT([numeric](10,3),isnull([amount],(0))-isnull([amount_payed],(0)))), + [subject] NVARCHAR (255) NULL, + [text] NVARCHAR (2000) NULL, + [IsSent] BIT CONSTRAINT [DF_fds__reminder_IsSent] DEFAULT ((0)) NOT NULL, + [IsFinal] AS (CONVERT([bit],case when [DateFinalized] IS NULL then (0) else (1) end)), + [CustomValues] NVARCHAR (MAX) NULL, + [DateSent] DATETIME NULL, + [UserSent] VARCHAR (25) NULL, + [DateFinalized] DATETIME NULL, + [UserFinalized] VARCHAR (25) NULL, + [DateCreated] DATETIME NOT NULL, + [UserCreated] VARCHAR (25) NOT NULL, + [DateModified] DATETIME NOT NULL, + [UserModified] VARCHAR (25) NOT NULL, + [file] VARBINARY (MAX) NULL, + [file_guid] UNIQUEIDENTIFIER CONSTRAINT [DF_fds__reminder_file_guid] DEFAULT (newid()) NOT NULL, CONSTRAINT [PK_fds__reminder] PRIMARY KEY CLUSTERED ([Id] ASC) ); diff --git a/Fuchs_Database/fds__getInvoiceFileContent.sql b/Fuchs_Database/fds__getInvoiceFileContent.sql new file mode 100644 index 0000000..e69de29 diff --git a/Fuchs_Database/fds__getInvoiceFiles_ForBlobArchive.sql b/Fuchs_Database/fds__getInvoiceFiles_ForBlobArchive.sql new file mode 100644 index 0000000..e69de29 diff --git a/Fuchs_Database/fds__getReminderFileContent.sql b/Fuchs_Database/fds__getReminderFileContent.sql new file mode 100644 index 0000000..e69de29 diff --git a/Fuchs_Database/fds__getReminderFiles_ForBlobArchive.sql b/Fuchs_Database/fds__getReminderFiles_ForBlobArchive.sql new file mode 100644 index 0000000..e69de29 diff --git a/Fuchs_Intranet.slnx b/Fuchs_Intranet.slnx index 2d27b9e..b490604 100644 --- a/Fuchs_Intranet.slnx +++ b/Fuchs_Intranet.slnx @@ -24,6 +24,16 @@ + + + + + + + + + + diff --git a/MFR_RESTClient/MFR_RESTClient.csproj b/MFR_RESTClient/MFR_RESTClient.csproj index 5340e2a..6d45cd3 100644 --- a/MFR_RESTClient/MFR_RESTClient.csproj +++ b/MFR_RESTClient/MFR_RESTClient.csproj @@ -26,17 +26,17 @@ - + - + - - - - + + + +