diff --git a/Fuchs.Tests/ReminderDraftCalculatorTests.cs b/Fuchs.Tests/ReminderDraftCalculatorTests.cs
new file mode 100644
index 0000000..21bd9eb
--- /dev/null
+++ b/Fuchs.Tests/ReminderDraftCalculatorTests.cs
@@ -0,0 +1,92 @@
+using Fuchs.intranet;
+using Newtonsoft.Json.Linq;
+using Xunit;
+
+namespace Fuchs.Tests;
+
+///
+/// Exhaustively exercises the pure reminder-draft aggregation/validation (ADR 0006,
+/// the reminder mirror of ). Being static/pure,
+/// the open-amount math and the plausibility checks are unit-testable without a DB.
+///
+public class ReminderDraftCalculatorTests
+{
+ private static ReminderDraftSession Session(string newJson) =>
+ new() { New = JObject.Parse(newJson) };
+
+ [Theory]
+ [InlineData("{'amount':119,'amount_payed':0}", 119, 0, 119)]
+ [InlineData("{'amount':119,'amount_payed':20}", 119, 20, 99)]
+ [InlineData("{'amount':'119,50','amount_payed':'19,50'}", 119.50, 19.50, 100)] // German decimals
+ [InlineData("{'amount':'100.00','amount_payed':'40.00'}", 100, 40, 60)] // invariant decimals
+ [InlineData("{}", 0, 0, 0)] // missing → 0
+ [InlineData("{'amount':50,'amount_payed':80}", 50, 80, -30)] // overpaid → negative
+ public void RecomputeTotals_ComputesOpenAmount(string newJson, double total, double payed, double open)
+ {
+ var s = Session(newJson);
+ ReminderDraftCalculator.RecomputeTotals(s);
+ Assert.Equal((decimal)total, s.Sums.AmountTotal);
+ Assert.Equal((decimal)payed, s.Sums.AmountPayed);
+ Assert.Equal((decimal)open, s.Sums.AmountOpen);
+ }
+
+ [Fact]
+ public void Validate_EmptyEmail_Warns()
+ {
+ var s = Session("{'amount':119,'invoiceaddress':'Weg 1','subject':'X'}");
+ ReminderDraftCalculator.RecomputeTotals(s);
+ ReminderDraftCalculator.Validate(s);
+ Assert.Contains(s.ValidationMessages, m => m.Field == "email" && m.Severity == "warning");
+ }
+
+ [Theory]
+ [InlineData("bad")]
+ [InlineData("no-at-sign.de")]
+ [InlineData("trailing@dot.")]
+ public void Validate_InvalidEmail_Errors(string email)
+ {
+ var s = Session($"{{'amount':119,'invoiceemail':'{email}','invoiceaddress':'Weg 1','subject':'X'}}");
+ ReminderDraftCalculator.RecomputeTotals(s);
+ ReminderDraftCalculator.Validate(s);
+ Assert.Contains(s.ValidationMessages, m => m.Field == "email" && m.Severity == "error");
+ }
+
+ [Fact]
+ public void Validate_ValidEmail_NoEmailMessage()
+ {
+ var s = Session("{'amount':119,'invoiceemail':'a@b.de','invoiceaddress':'Weg 1','subject':'X'}");
+ ReminderDraftCalculator.RecomputeTotals(s);
+ ReminderDraftCalculator.Validate(s);
+ Assert.DoesNotContain(s.ValidationMessages, m => m.Field == "email");
+ }
+
+ [Fact]
+ public void Validate_EmptyAddressAndSubject_Warn()
+ {
+ var s = Session("{'amount':119,'invoiceemail':'a@b.de'}");
+ ReminderDraftCalculator.RecomputeTotals(s);
+ ReminderDraftCalculator.Validate(s);
+ Assert.Contains(s.ValidationMessages, m => m.Field == "address" && m.Severity == "warning");
+ Assert.Contains(s.ValidationMessages, m => m.Field == "subject" && m.Severity == "warning");
+ }
+
+ [Theory]
+ [InlineData("{'amount':0,'amount_payed':0,'invoiceemail':'a@b.de','invoiceaddress':'W','subject':'X'}")]
+ [InlineData("{'amount':50,'amount_payed':80,'invoiceemail':'a@b.de','invoiceaddress':'W','subject':'X'}")]
+ public void Validate_NonPositiveOpenAmount_Warns(string newJson)
+ {
+ var s = Session(newJson);
+ ReminderDraftCalculator.RecomputeTotals(s);
+ ReminderDraftCalculator.Validate(s);
+ Assert.Contains(s.ValidationMessages, m => m.Field == "amount" && m.Severity == "warning");
+ }
+
+ [Fact]
+ public void Validate_HealthyDraft_HasNoMessages()
+ {
+ var s = Session("{'amount':119,'amount_payed':0,'invoiceemail':'a@b.de','invoiceaddress':'Weg 1','subject':'Zahlungserinnerung'}");
+ ReminderDraftCalculator.RecomputeTotals(s);
+ ReminderDraftCalculator.Validate(s);
+ Assert.Empty(s.ValidationMessages);
+ }
+}
diff --git a/Fuchs.Tests/ReminderDraftServiceTests.cs b/Fuchs.Tests/ReminderDraftServiceTests.cs
new file mode 100644
index 0000000..f846db5
--- /dev/null
+++ b/Fuchs.Tests/ReminderDraftServiceTests.cs
@@ -0,0 +1,307 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using Fuchs.intranet;
+using Fuchs.Services;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging.Abstractions;
+using MigraDoc.DocumentObjectModel;
+using Newtonsoft.Json.Linq;
+using OCORE.security;
+using Xunit;
+using static OCORE.OCORE_dictionaries;
+
+namespace Fuchs.Tests;
+
+///
+/// Exercises the reminder draft edit orchestrator's pure paths (open/patch/history/flush)
+/// without a database — the reminder mirror of ,
+/// proving the backend-authoritative model behaves correctly at the service seam (ADR 0006).
+///
+public class ReminderDraftServiceTests
+{
+ /// Captures the reminder handed to registration and returns it with a fake DB id — no SQL.
+ private sealed class FakeReminderService : IReminderService
+ {
+ public FdsReminderData? Registered;
+ public bool? LastChange;
+ public FdsReminderData? PreviewReminder;
+ public bool? PreviewDraft;
+
+ public Task RegisterReminderAsync(FdsReminderData reminder, bool change, string remId, string userAccountId, DatabaseSecurity dbSec)
+ {
+ Registered = reminder;
+ LastChange = change;
+ reminder.ReminderRegistration = new GenericObjectDictionary(new System.Collections.Generic.Dictionary { ["Id"] = "REM42" });
+ return Task.FromResult(reminder);
+ }
+ public Document GenerateReminderPdf(FdsReminderData reminder, bool draft) { PreviewReminder = reminder; PreviewDraft = draft; return new Document(); }
+ public Task LoadReminderAsync(string id, string u, DatabaseSecurity s) => throw new NotSupportedException();
+ public Task RenderReminderPdfBytesAsync(FdsReminderData r, bool d) => throw new NotSupportedException();
+ public Task StoreReminderDocumentFileAsync(FdsReminderData r, bool d, string u, DatabaseSecurity s) => throw new NotSupportedException();
+ public Task GetReminderFileAsync(FdsReminderData r, bool d, fds.IFdsMfr m, string u, DatabaseSecurity s) => throw new NotSupportedException();
+ public Task<(System.IO.FileInfo? file, byte[]? content)> GetStoredFileAsync(string id, string u, DatabaseSecurity s) => throw new NotSupportedException();
+ }
+
+ private static (ReminderDraftEditService svc, FakeReminderService rem) NewService()
+ {
+ var cache = new ReminderDraftCache(new ConfigurationBuilder().Build());
+ var rem = new FakeReminderService();
+ var svc = new ReminderDraftEditService(cache, rem, NullLogger.Instance);
+ return (svc, rem);
+ }
+
+ private static JObject Payload() => JObject.Parse(@"{
+ 'rem':{'invid':'INV5','type':'R','invoiceid':'R2026-1','invoicedate':'2026-06-01'},
+ 'new':{'invoiceemail':'a@b.de','invoiceaddress':'Weg 1','subject':'Zahlungserinnerung','amount':119,'amount_payed':0}
+ }");
+
+ [Fact]
+ public void OpenFromPayload_SeedsSessionAndComputesOpenAmount()
+ {
+ var (svc, _) = NewService();
+ var s = svc.OpenFromPayload(Payload(), "user1");
+ Assert.False(string.IsNullOrEmpty(s.Token));
+ Assert.Equal(0, s.Version);
+ Assert.Equal(119m, s.Sums.AmountTotal);
+ Assert.Equal(119m, s.Sums.AmountOpen);
+ }
+
+ [Fact]
+ public void ApplyPatch_Email_MutatesBumpsVersionAndRecordsHistory()
+ {
+ var (svc, _) = NewService();
+ var s = svc.OpenFromPayload(Payload(), "user1");
+
+ var s2 = svc.ApplyPatch(s.Token, new ReminderDraftDelta { Target = "email", Value = JToken.FromObject("neu@x.de") });
+
+ Assert.NotNull(s2);
+ Assert.Equal(1, s2!.Version);
+ Assert.Equal("neu@x.de", s2.New["invoiceemail"]!.Value());
+ var h = Assert.Single(s2.History);
+ Assert.Equal("email", h.Target);
+ Assert.Equal("a@b.de", h.OldValue);
+ Assert.Equal("neu@x.de", h.NewValue);
+ }
+
+ [Fact]
+ public void ApplyPatch_Amount_RecomputesOpenAmount()
+ {
+ var (svc, _) = NewService();
+ var s = svc.OpenFromPayload(Payload(), "user1");
+
+ var s2 = svc.ApplyPatch(s.Token, new ReminderDraftDelta { Target = "amount", Value = JToken.FromObject(200) });
+
+ Assert.Equal(200m, s2!.Sums.AmountTotal);
+ Assert.Equal(200m, s2.Sums.AmountOpen);
+ }
+
+ [Fact]
+ public void ApplyPatch_AmountPayed_RecomputesOpenAmount()
+ {
+ var (svc, _) = NewService();
+ var s = svc.OpenFromPayload(Payload(), "user1");
+
+ var s2 = svc.ApplyPatch(s.Token, new ReminderDraftDelta { Target = "amount_payed", Value = JToken.FromObject(19) });
+
+ Assert.Equal(100m, s2!.Sums.AmountOpen); // 119 - 19
+ }
+
+ [Fact]
+ public void ApplyPatch_AmountFromGermanString_NormalisesToInvariant()
+ {
+ var (svc, _) = NewService();
+ var s = svc.OpenFromPayload(Payload(), "user1");
+
+ var s2 = svc.ApplyPatch(s.Token, new ReminderDraftDelta { Target = "amount", Value = JToken.FromObject("249,90") });
+
+ Assert.Equal("249.90", s2!.New["amount"]!.Value()); // stored invariant
+ Assert.Equal(249.90m, s2.Sums.AmountTotal);
+ }
+
+ [Fact]
+ public void ApplyPatch_UnknownToken_ReturnsNull()
+ {
+ var (svc, _) = NewService();
+ Assert.Null(svc.ApplyPatch("ghost", new ReminderDraftDelta { Target = "email", Value = JToken.FromObject("x@y.de") }));
+ }
+
+ [Fact]
+ public void ApplyPatch_UnknownTarget_IsNoOp()
+ {
+ var (svc, _) = NewService();
+ var s = svc.OpenFromPayload(Payload(), "user1");
+
+ var s2 = svc.ApplyPatch(s.Token, new ReminderDraftDelta { Target = "nonsense", Value = JToken.FromObject("x") });
+
+ Assert.Equal(0, s2!.Version);
+ Assert.Empty(s2.History);
+ }
+
+ [Theory]
+ [InlineData("subject", "subject")]
+ [InlineData("address", "invoiceaddress")]
+ [InlineData("text", "text")]
+ public void ApplyPatch_ScalarFieldDeltas_UpdateNew(string target, string newKey)
+ {
+ var (svc, _) = NewService();
+ var s = svc.OpenFromPayload(Payload(), "user1");
+
+ var s2 = svc.ApplyPatch(s.Token, new ReminderDraftDelta { Target = target, Value = JToken.FromObject("X-VALUE") });
+
+ Assert.Equal("X-VALUE", s2!.New[newKey]!.Value());
+ }
+
+ [Theory]
+ [InlineData("subject", "subject")]
+ [InlineData("email", "invoiceemail")]
+ public void ApplyPatch_ScalarField_StripsHtmlWrapper(string target, string newKey)
+ {
+ var (svc, _) = NewService();
+ var s = svc.OpenFromPayload(Payload(), "user1");
+
+ var s2 = svc.ApplyPatch(s.Token, new ReminderDraftDelta { Target = target, Value = JToken.FromObject("clean me
") });
+
+ Assert.Equal("clean me", s2!.New[newKey]!.Value());
+ Assert.DoesNotContain("<", s2.New[newKey]!.Value());
+ }
+
+ [Fact]
+ public void ApplyPatch_Address_MultilineHtml_KeepsLineBreaks()
+ {
+ var (svc, _) = NewService();
+ var s = svc.OpenFromPayload(Payload(), "user1");
+
+ var s2 = svc.ApplyPatch(s.Token, new ReminderDraftDelta
+ {
+ Target = "address",
+ Value = JToken.FromObject("Firma AG
Weg 1
40000 Düsseldorf
")
+ });
+
+ Assert.Equal("Firma AG\nWeg 1\n40000 Düsseldorf", s2!.New["invoiceaddress"]!.Value());
+ }
+
+ [Fact]
+ public void ApplyPatch_Contact_BuildsCustomValuesJson()
+ {
+ var (svc, _) = NewService();
+ var s = svc.OpenFromPayload(Payload(), "user1");
+
+ var s2 = svc.ApplyPatch(s.Token, new ReminderDraftDelta
+ {
+ Target = "contact",
+ Value = JObject.Parse(@"{'name':'Max Mustermann','email':'max@kunde.de'}")
+ });
+
+ var cv = JObject.Parse(s2!.New["CustomValues"]!.Value()!);
+ Assert.Equal("Max Mustermann", cv["contactName"]!.Value());
+ Assert.Equal("max@kunde.de", cv["contactEmail"]!.Value());
+ }
+
+ [Fact]
+ public void ApplyPatch_MultipleEdits_AccumulateHistoryInOrder()
+ {
+ var (svc, _) = NewService();
+ var s = svc.OpenFromPayload(Payload(), "user1");
+
+ svc.ApplyPatch(s.Token, new ReminderDraftDelta { Target = "email", Value = JToken.FromObject("a1@x.de") });
+ svc.ApplyPatch(s.Token, new ReminderDraftDelta { Target = "subject", Value = JToken.FromObject("Mahnung 2") });
+ var s3 = svc.ApplyPatch(s.Token, new ReminderDraftDelta { Target = "amount", Value = JToken.FromObject(200) });
+
+ Assert.Equal(3, s3!.Version);
+ Assert.Equal(new[] { "email", "subject", "amount" }, s3.History.Select(h => h.Target).ToArray());
+ Assert.Equal(new[] { 1, 2, 3 }, s3.History.Select(h => h.Version).ToArray());
+ }
+
+ [Fact]
+ public void BuildState_ExposesPayloadSumsValidationAndVersion()
+ {
+ var (svc, _) = NewService();
+ var s = svc.OpenFromPayload(Payload(), "user1");
+ svc.ApplyPatch(s.Token, new ReminderDraftDelta { Target = "amount_payed", Value = JToken.FromObject(19) });
+
+ var state = JObject.FromObject(svc.BuildState(svc.Get(s.Token)!));
+
+ Assert.Equal(1, state["version"]!.Value());
+ Assert.Equal(119m, state["sums"]!["amount_total"]!.Value());
+ Assert.Equal(100m, state["sums"]!["amount_open"]!.Value());
+ Assert.Equal(1, state["historyCount"]!.Value());
+ Assert.NotNull(state["validation"]);
+ }
+
+ [Fact]
+ public async Task FlushToDbAsync_RegistersAndSetsRemId_CreatePath()
+ {
+ var (svc, rem) = NewService();
+ var s = svc.OpenFromPayload(Payload(), "user1");
+
+ var result = await svc.FlushToDbAsync(s.Token, "user1", null!);
+
+ Assert.NotNull(result);
+ Assert.Equal("REM42", result!.Id);
+ Assert.False(rem.LastChange); // new draft (no prior RemId) → create
+ Assert.Equal("REM42", svc.Get(s.Token)!.RemId);
+ // the email/subject the editor set must reach registration
+ Assert.Equal("a@b.de", rem.Registered!.RawInvoiceEmail);
+ Assert.Equal("Zahlungserinnerung", rem.Registered!.NewValues!.getString("subject"));
+ Assert.Equal("INV5", rem.Registered!.RawInvId);
+ }
+
+ [Fact]
+ public async Task FlushToDbAsync_ExistingRemId_UpdatePath()
+ {
+ var (svc, rem) = NewService();
+ var payload = Payload();
+ payload["remid"] = "REM7";
+ var s = svc.OpenFromPayload(payload, "user1");
+
+ await svc.FlushToDbAsync(s.Token, "user1", null!);
+
+ Assert.True(rem.LastChange); // prior RemId → update path
+ }
+
+ [Fact]
+ public void RenderPreview_SynthesizesDraftRegistrationFromSession()
+ {
+ var (svc, rem) = NewService();
+ var s = svc.OpenFromPayload(Payload(), "user1");
+
+ var doc = svc.RenderPreview(s.Token);
+
+ Assert.NotNull(doc);
+ Assert.True(rem.PreviewDraft);
+ Assert.True(rem.PreviewReminder!.IsDraft);
+ var reg = rem.PreviewReminder!.ReminderRegistration!;
+ Assert.Equal("Zahlungserinnerung", reg.getString("subject"));
+ Assert.Equal("Weg 1", reg.getString("SendToAddress"));
+ Assert.Equal("a@b.de", reg.getString("SendToEmail"));
+ Assert.Equal("R2026-1", reg.getString("InvoiceId"));
+ // the synthesised single-invoice row the reminder table renders
+ Assert.Single(rem.PreviewReminder!.ReminderItems);
+ }
+
+ [Fact]
+ public void RenderPreview_UnknownToken_ReturnsNull()
+ {
+ var (svc, _) = NewService();
+ Assert.Null(svc.RenderPreview("ghost"));
+ }
+
+ [Fact]
+ public void GetHistory_UnknownToken_IsEmpty()
+ {
+ var (svc, _) = NewService();
+ Assert.Empty(svc.GetHistory("ghost"));
+ }
+
+ [Fact]
+ public void Close_RemovesSession_ThenReportsFalse()
+ {
+ var (svc, _) = NewService();
+ var s = svc.OpenFromPayload(Payload(), "user1");
+
+ Assert.True(svc.Close(s.Token));
+ Assert.Null(svc.Get(s.Token));
+ Assert.False(svc.Close(s.Token));
+ }
+}
diff --git a/Fuchs/Controllers/IntranetController.Reminder.cs b/Fuchs/Controllers/IntranetController.Reminder.cs
index 18b5eed..a4cefbf 100644
--- a/Fuchs/Controllers/IntranetController.Reminder.cs
+++ b/Fuchs/Controllers/IntranetController.Reminder.cs
@@ -97,6 +97,15 @@ public partial class IntranetController
case "idoc": return await HandleReminderIdoc(fn, id, code);
case "resend": return await HandleReminderResend(fn, id, code);
+ // ── Live backend-authoritative draft editing (ADR 0006) ───────────
+ case "dopen": return await HandleReminderDraftOpen(fn, id, code);
+ case "dstate": return await HandleReminderDraftState(fn, id, code);
+ case "dpatch": return await HandleReminderDraftPatch(fn, id, code);
+ case "dpreview": return await HandleReminderDraftPreview(fn, id, code);
+ case "dsave": return await HandleReminderDraftSave(fn, id, code);
+ case "dhistory": return await HandleReminderDraftHistory(fn, id, code);
+ case "dclose": return await HandleReminderDraftClose(fn, id, code);
+
case "lrem":
{
if (!HasForm("id")) { _logger.LogWarning("Reminder lrem: missing form field 'id', user={User}", UserAccountID); return BadRequest400(); }
diff --git a/Fuchs/Controllers/IntranetController.ReminderDraft.cs b/Fuchs/Controllers/IntranetController.ReminderDraft.cs
new file mode 100644
index 0000000..320609d
--- /dev/null
+++ b/Fuchs/Controllers/IntranetController.ReminderDraft.cs
@@ -0,0 +1,122 @@
+using Fuchs.Services;
+using Microsoft.AspNetCore.Mvc;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using static OCORE.web.mvc_helper_async;
+
+namespace Fuchs.Controllers;
+
+// Partial class: live, backend-authoritative reminder draft editing (ADR 0006) — the
+// reminder mirror of IntranetController.InvoiceDraft.cs. The browser posts single edits
+// here; the server mutates the in-memory session (the source of truth), recomputes the
+// open amount / validates, and pings the editing browser over the shared DraftPreviewHub
+// (draftReady) to re-fetch. Commands are ordinary POSTs — the hub carries only signals.
+public partial class IntranetController
+{
+ // POST rem/dopen — { payload } → { token, version }
+ private async Task HandleReminderDraftOpen(string fn, string id, string code)
+ {
+ if (!HasForm("payload"))
+ {
+ _logger.LogWarning("Reminder draft dopen: 'payload' missing user={User}", UserAccountID);
+ return BadRequest400();
+ }
+ JObject payload;
+ try { payload = JObject.Parse(Form("payload")); }
+ catch (JsonException ex)
+ {
+ _logger.LogWarning(ex, "Reminder draft dopen: invalid payload JSON user={User}", UserAccountID);
+ return BadRequest400();
+ }
+ var session = _reminderDrafts.OpenFromPayload(payload, UserAccountID);
+ _logger.LogInformation("Reminder draft dopen: session {Token} (remId={RemId}) user={User}", session.Token, session.RemId, UserAccountID);
+ // The browser holds the token from this response and fetches dstate directly; there is
+ // no server 'draftReady' on open (it would race the client's group-join).
+ return await JSONAsync(new { token = session.Token, version = session.Version });
+ }
+
+ // POST rem/dstate — { token } → full view state
+ private async Task HandleReminderDraftState(string fn, string id, string code)
+ {
+ if (!HasForm("token")) return BadRequest400();
+ var session = _reminderDrafts.Get(Form("token"));
+ if (session == null) return DraftGone();
+ return await JSONAsync(_reminderDrafts.BuildState(session));
+ }
+
+ // POST rem/dpatch — { token, delta } → { ok, version }; signals draftReady
+ private async Task HandleReminderDraftPatch(string fn, string id, string code)
+ {
+ if (!HasForm("token", "delta")) return BadRequest400();
+ ReminderDraftDelta? delta;
+ try { delta = JsonConvert.DeserializeObject(Form("delta")); }
+ catch (JsonException ex)
+ {
+ _logger.LogWarning(ex, "Reminder draft dpatch: invalid delta JSON user={User}", UserAccountID);
+ return BadRequest400();
+ }
+ if (delta == null || string.IsNullOrEmpty(delta.Target)) return BadRequest400();
+
+ var session = _reminderDrafts.ApplyPatch(Form("token"), delta);
+ if (session == null) return DraftGone();
+ await _draftNotifier.SignalDraftReadyAsync(session.Token, session.Version);
+ return await JSONAsync(new { ok = true, version = session.Version });
+ }
+
+ // POST rem/dpreview — { token } → { img[], total } (rendered straight from the cache)
+ private async Task HandleReminderDraftPreview(string fn, string id, string code)
+ {
+ if (!HasForm("token")) return BadRequest400();
+ var doc = _reminderDrafts.RenderPreview(Form("token"));
+ if (doc == null) return DraftGone();
+ var imgcol = await _pdf.DocToImageCollectionAsync(doc);
+ return await JSONAsync(new { img = imgcol.ImgB64Array, total = imgcol.TotalPages });
+ }
+
+ // POST rem/dsave — { token } → { ok, remid }; flush cache→DB + business event + draftReady
+ private async Task HandleReminderDraftSave(string fn, string id, string code)
+ {
+ if (!HasForm("token")) return BadRequest400();
+ string token = Form("token");
+ var before = _reminderDrafts.Get(token);
+ if (before == null) return DraftGone();
+ bool existed = !string.IsNullOrEmpty(before.RemId);
+
+ var fdRem = await _reminderDrafts.FlushToDbAsync(token, UserAccountID, DbSec);
+ if (fdRem == null) return DraftGone();
+ if (string.IsNullOrEmpty(fdRem.Id))
+ return await ReminderIssueResult("Der Zwischenstand konnte aufgrund eines Fehlers nicht gespeichert werden.");
+
+ await _events.ReminderDraftRegisteredAsync(fdRem, existed, UserAccountID);
+ var after = _reminderDrafts.Get(token);
+ if (after != null) await _draftNotifier.SignalDraftReadyAsync(after.Token, after.Version);
+ return await JSONAsync(new { ok = true, remid = fdRem.Id });
+ }
+
+ // POST rem/dhistory — { token } → { history[] }
+ private async Task HandleReminderDraftHistory(string fn, string id, string code)
+ {
+ if (!HasForm("token")) return BadRequest400();
+ if (_reminderDrafts.Get(Form("token")) == null) return DraftGone();
+ var history = _reminderDrafts.GetHistory(Form("token"))
+ .Select(h => new
+ {
+ timestamp = h.TimestampUtc,
+ target = h.Target,
+ @ref = h.Ref,
+ oldValue = h.OldValue,
+ newValue = h.NewValue,
+ version = h.Version
+ });
+ return await JSONAsync(new { history });
+ }
+
+ // POST rem/dclose — { token } → { ok }
+ private async Task HandleReminderDraftClose(string fn, string id, string code)
+ {
+ if (!HasForm("token")) return BadRequest400();
+ bool ok = _reminderDrafts.Close(Form("token"));
+ _logger.LogDebug("Reminder draft dclose token={Token} removed={Removed} user={User}", Form("token"), ok, UserAccountID);
+ return await JSONAsync(new { ok });
+ }
+}
diff --git a/Fuchs/Controllers/IntranetController.cs b/Fuchs/Controllers/IntranetController.cs
index 8062128..cbe4390 100644
--- a/Fuchs/Controllers/IntranetController.cs
+++ b/Fuchs/Controllers/IntranetController.cs
@@ -36,6 +36,7 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
private readonly IReminderService _reminders;
private readonly IEventService _events;
private readonly IInvoiceDraftService _invoiceDrafts;
+ private readonly IReminderDraftService _reminderDrafts;
private readonly IDraftNotifier _draftNotifier;
private readonly List _allowedNonAuth = new() { "spwc", "spw" };
private readonly List _allowedGet = new()
@@ -66,6 +67,7 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
IReminderService reminders,
IEventService events,
IInvoiceDraftService invoiceDrafts,
+ IReminderDraftService reminderDrafts,
IDraftNotifier draftNotifier)
{
_intranet = intranet;
@@ -81,6 +83,7 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
_reminders = reminders;
_events = events;
_invoiceDrafts = invoiceDrafts;
+ _reminderDrafts = reminderDrafts;
_draftNotifier = draftNotifier;
}
diff --git a/Fuchs/Docs/Concepts/live-draft-editing.md b/Fuchs/Docs/Concepts/live-draft-editing.md
index b3e4cf1..d1ec7d9 100644
--- a/Fuchs/Docs/Concepts/live-draft-editing.md
+++ b/Fuchs/Docs/Concepts/live-draft-editing.md
@@ -4,11 +4,16 @@ lastUpdated: 2026-07-10
applyTo:
- "Fuchs/Services/InvoiceDraft*"
- "Fuchs/Services/IInvoiceDraft*"
+ - "Fuchs/Services/ReminderDraft*"
+ - "Fuchs/Services/IReminderDraft*"
- "Fuchs/code/InvoiceDraftSession.cs"
- "Fuchs/code/InvoiceDraftCalculator.cs"
+ - "Fuchs/code/ReminderDraftSession.cs"
+ - "Fuchs/code/ReminderDraftCalculator.cs"
- "Fuchs/Notifications/DraftPreviewHub.cs"
- "Fuchs/Notifications/*DraftNotifier*"
- "Fuchs/Controllers/IntranetController.InvoiceDraft.cs"
+ - "Fuchs/Controllers/IntranetController.ReminderDraft.cs"
- "Fuchs/js/intranet/**"
relatedDecisions:
- "0006-backend-authoritative-draft-editing.md"
@@ -23,8 +28,8 @@ server memory, not in the browser. The browser posts single edits, the server mu
the cached record, recomputes totals/VAT and re-validates, then pushes a "state changed"
signal so the browser re-fetches and re-renders. This makes the backend the single source
of truth (server-computed sums, consistency checks, in-place PDF preview, change history,
-explicit discard), reversing the earlier stateless editor. Invoices are the pilot;
-reminders are intended to mirror the same design.
+explicit discard), reversing the earlier stateless editor. Invoices were the pilot;
+reminders now mirror the same design (see "Reminders" below).
## How it works
@@ -92,6 +97,50 @@ Expiry: Server (timer) --SignalR draftExpiring{token,secondsLeft}--> warn "bit
- `Fuchs/Controllers/IntranetController.InvoiceDraft.cs` — `inv/d*` endpoints.
- `Fuchs/js/intranet/fis_main.js`, `Fuchs/js/intranet/modules/fis.inv_shared.js` — client.
+## Reminders (Zahlungserinnerung)
+
+Reminders mirror the same backend-authoritative model with a reminder-shaped session. A
+reminder chases a single invoiced amount, so the machinery is simpler than an invoice's:
+there are no line-item blocks, VAT grouping or reordering — just recipient fields and the
+amount pair.
+
+- **Endpoints** are `rem/d*` (`dopen`/`dstate`/`dpatch`/`dpreview`/`dsave`/`dhistory`/`dclose`),
+ dispatched from `Do_Process_Reminder`. Finalise + email still runs through the existing
+ `rem/conf` (`HandleReminderConf`), exactly as invoices finalise through `req/sconf`.
+- **Session** (`ReminderDraftSession`) holds the editor's `new` (subject / invoiceaddress /
+ invoiceemail / text / amount / amount_payed / CustomValues) and `rem` (invid / type /
+ invoiceid / invoicedate) blocks, plus server-computed `Sums` (`AmountTotal`, `AmountPayed`,
+ `AmountOpen`). It reuses the shared `ChangeHistoryEntry`; validation uses
+ `ReminderDraftValidationMessage`.
+- **Calculation** (`ReminderDraftCalculator`, static/pure): `AmountOpen = AmountTotal − AmountPayed`,
+ plus email/address/subject/open-amount plausibility checks. Exhaustively unit-tested.
+- **Deltas** (`ReminderDraftDelta`): scalar `email`/`address`/`subject`/`text` (HTML-sanitised via
+ the shared `InvoiceDraftEditService.HtmlToPlain`), the numeric `amount`/`amount_payed`
+ (normalised to an invariant decimal string), and `contact` (→ `CustomValues`).
+- **Orchestration** (`ReminderDraftEditService`, scoped) flushes to the DB by reusing
+ `IReminderService.RegisterReminderAsync`, and renders previews from a synthesised
+ `ReminderRegistration` (including the single-invoice `invoices` row the reminder PDF table
+ renders) so a preview needs no DB round-trip. **Note:** `RegisterReminderAsync` is create-only
+ (there is no `fds__setReminder` update proc), so a re-saved reminder draft does not update the
+ prior DB row — the primary flow (preview → confirm) flushes once immediately before finalising.
+- **Cache/expiry** (`ReminderDraftCache` singleton + `ReminderDraftExpiryService`) mirror the
+ invoice ones and share the same `Fuchs:DraftEditing` TTL config.
+- **Signals** reuse the shared `DraftPreviewHub` + `IDraftNotifier` unchanged — the token-keyed
+ groups serve invoice and reminder drafts alike.
+- **Frontend** (`$inv.rd` in `fis.inv_shared.js`) opens/joins on `rem/dopen`, posts one delta per
+ inline edit and per item-row amount change, renders the open-amount footer + validation from the
+ server state, and previews/finalises through `rem/dpreview` → `rem/dsave` → `rem/conf`. It shares
+ the invoice editor DOM; `$inv.d` and `$inv.rd` each key off their own token, so the shared inline
+ editor safely no-ops for whichever mode is inactive.
+
+### Reminder key files
+- `Fuchs/code/ReminderDraftSession.cs` — session + `ReminderDraftSums` + `ReminderDraftValidationMessage`.
+- `Fuchs/code/ReminderDraftCalculator.cs` — pure open-amount recompute + validate.
+- `Fuchs/Services/ReminderDraftCache.cs` / `IReminderDraftCache.cs` — in-memory store + TTL.
+- `Fuchs/Services/ReminderDraftEditService.cs` / `IReminderDraftService.cs` — orchestration + delta contract.
+- `Fuchs/Services/ReminderDraftExpiryService.cs` — idle warn/evict monitor.
+- `Fuchs/Controllers/IntranetController.ReminderDraft.cs` — `rem/d*` endpoints.
+
## Related decisions
- [0006 — Backend-authoritative draft editing](../Decisions/0006-backend-authoritative-draft-editing.md)
- [0007 — Targeted draft SignalR groups](../Decisions/0007-targeted-draft-signalr-groups.md)
diff --git a/Fuchs/Notifications/DomainEvent.cs b/Fuchs/Notifications/DomainEvent.cs
index aaada0b..b0faaae 100644
--- a/Fuchs/Notifications/DomainEvent.cs
+++ b/Fuchs/Notifications/DomainEvent.cs
@@ -12,6 +12,7 @@ public enum DomainEventType
InvoiceFileCreationFailed,
InvoiceSendFailed,
ReminderDraftCreated,
+ ReminderDraftUpdated,
ReminderFileCreated,
ReminderSentToCustomer,
ReminderResentToCustomer,
diff --git a/Fuchs/Notifications/EventService.cs b/Fuchs/Notifications/EventService.cs
index 4a11c37..a8def66 100644
--- a/Fuchs/Notifications/EventService.cs
+++ b/Fuchs/Notifications/EventService.cs
@@ -76,6 +76,12 @@ public sealed class EventService : IEventService
public Task ReminderDraftCreatedAsync(FdsReminderData reminder, string userAccountId)
=> PublishAsync(new DomainEvent(DomainEventType.ReminderDraftCreated, userAccountId, "Mahnentwurf", ReminderContext(reminder)));
+ public Task ReminderDraftRegisteredAsync(FdsReminderData reminder, bool changed, string userAccountId)
+ {
+ var type = changed ? DomainEventType.ReminderDraftUpdated : DomainEventType.ReminderDraftCreated;
+ return PublishAsync(new DomainEvent(type, userAccountId, "Mahnentwurf", ReminderContext(reminder)));
+ }
+
public Task ReminderFileCreatedAsync(FdsReminderData reminder, string fileName, string userAccountId)
{
var ctx = ReminderContext(reminder);
@@ -176,6 +182,8 @@ public sealed class EventService : IEventService
Ctx(domainEvent, "message"),
DomainEventType.ReminderDraftCreated =>
$"Mahnentwurf {Ctx(domainEvent, "title")} wurde erstellt.",
+ DomainEventType.ReminderDraftUpdated =>
+ $"Mahnentwurf {Ctx(domainEvent, "title")} wurde aktualisiert.",
DomainEventType.ReminderFileCreated =>
$"Mahndatei {Ctx(domainEvent, "fileName")} wurde erstellt.",
DomainEventType.ReminderSentToCustomer =>
diff --git a/Fuchs/Notifications/IEventService.cs b/Fuchs/Notifications/IEventService.cs
index 93e2c88..54704f4 100644
--- a/Fuchs/Notifications/IEventService.cs
+++ b/Fuchs/Notifications/IEventService.cs
@@ -13,6 +13,7 @@ public interface IEventService
Task InvoiceIssueAsync(string message, string userAccountId, string invoiceId = "");
Task ReminderDraftCreatedAsync(FdsReminderData reminder, string userAccountId);
+ Task ReminderDraftRegisteredAsync(FdsReminderData reminder, bool changed, string userAccountId);
Task ReminderFileCreatedAsync(FdsReminderData reminder, string fileName, string userAccountId);
Task ReminderSentToCustomerAsync(FdsReminderData reminder, string email, string userAccountId, bool resent = false);
Task ReminderMarkedSentAsync(string reminderId, string reminderTitle, string userAccountId);
diff --git a/Fuchs/Program.cs b/Fuchs/Program.cs
index 7a36eb7..2e376c0 100644
--- a/Fuchs/Program.cs
+++ b/Fuchs/Program.cs
@@ -118,6 +118,12 @@ public class Program
builder.Services.AddScoped();
builder.Services.AddHostedService();
+ // Live, backend-authoritative reminder draft editing (ADR 0006) — the reminder
+ // mirror of the invoice draft services above, sharing the DraftPreviewHub/notifier.
+ builder.Services.AddSingleton();
+ builder.Services.AddScoped();
+ builder.Services.AddHostedService();
+
// 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"));
diff --git a/Fuchs/Services/IReminderDraftCache.cs b/Fuchs/Services/IReminderDraftCache.cs
new file mode 100644
index 0000000..2fa0876
--- /dev/null
+++ b/Fuchs/Services/IReminderDraftCache.cs
@@ -0,0 +1,27 @@
+using Fuchs.intranet;
+
+namespace Fuchs.Services;
+
+///
+/// In-memory store of live reminder draft editing sessions (see ADR 0006, mirroring
+/// ). Singleton, single-instance only — scale-out would
+/// need a distributed cache / sticky sessions (documented limitation). Keyed by the
+/// session token.
+///
+public interface IReminderDraftCache
+{
+ /// Stores (or replaces) a session under its token.
+ void Set(ReminderDraftSession session);
+
+ /// Returns the session for the token, or null if absent/evicted. Touches LastAccessUtc on hit.
+ ReminderDraftSession? Get(string token);
+
+ /// Removes the session (explicit close/discard/finalise). Returns the removed session, if any.
+ ReminderDraftSession? Remove(string token);
+
+ /// Snapshot of all live sessions — used by the expiry monitor. Does not touch access time.
+ IReadOnlyList Snapshot();
+
+ /// The configured idle time-to-live before a session is eligible for eviction.
+ TimeSpan IdleTtl { get; }
+}
diff --git a/Fuchs/Services/IReminderDraftService.cs b/Fuchs/Services/IReminderDraftService.cs
new file mode 100644
index 0000000..916f079
--- /dev/null
+++ b/Fuchs/Services/IReminderDraftService.cs
@@ -0,0 +1,73 @@
+using Fuchs.intranet;
+using MigraDoc.DocumentObjectModel;
+using Newtonsoft.Json.Linq;
+using OCORE.security;
+
+namespace Fuchs.Services;
+
+///
+/// Orchestrates a live, backend-authoritative reminder draft editing session (ADR 0006,
+/// mirroring ). Owns the lifecycle around a
+/// : open (seed the cache), apply single edits, build the
+/// view state, render a PDF preview from the cache, flush to the DB ("Zwischenspeichern")
+/// and expose the change history. The open amount is aggregated by
+/// — the browser never sums.
+///
+/// Reload/discard is handled by the client (re-fetch the DB draft / prep data via the
+/// existing rem/get path and re-seed), so there is no server-side DB reshaping here.
+///
+public interface IReminderDraftService
+{
+ ///
+ /// Seeds a new cache session from the editor's assembled payload (new / rem
+ /// blocks). Computes the open amount + validation and returns the session (with its fresh
+ /// token/version). A remid in the payload marks it as an update of an existing DB draft.
+ ///
+ ReminderDraftSession OpenFromPayload(JObject payload, string userAccountId);
+
+ /// Returns the cached session for the token (touching its TTL), or null if absent/expired.
+ ReminderDraftSession? Get(string token);
+
+ ///
+ /// Applies one editor change to the cached session: mutates the payload, re-aggregates the
+ /// open amount, re-validates, appends a history entry and bumps the version. Returns the
+ /// mutated session, or null if the token is unknown.
+ ///
+ ReminderDraftSession? ApplyPatch(string token, ReminderDraftDelta delta);
+
+ /// Builds the JSON view-state DTO the frontend renders (payload + server sums + validation + version).
+ object BuildState(ReminderDraftSession session);
+
+ /// The draft's change history for the "Änderungshistorie" dialog (empty if the token is unknown).
+ IReadOnlyList GetHistory(string token);
+
+ ///
+ /// Persists the cached session to the DB via the existing reminder registration path
+ /// ("Zwischenspeichern"). Sets on success.
+ /// Returns the registered reminder data (for the success event), or null if the token is unknown.
+ ///
+ Task FlushToDbAsync(string token, string userAccountId, DatabaseSecurity dbSec);
+
+ /// Renders a draft PDF straight from the cached session (no client upload). Null if token unknown.
+ Document? RenderPreview(string token);
+
+ /// Removes the session from the cache (explicit close/discard/finalise). Returns true if one was present.
+ bool Close(string token);
+}
+
+///
+/// A single editor change posted to rem/dpatch. names the
+/// field/operation (e.g. "email", "subject", "amount"); is reserved for
+/// future per-item edits; is the new value (a scalar for fields, or a
+/// small object for contact).
+///
+public sealed class ReminderDraftDelta
+{
+ public string Target { get; set; } = "";
+ public string Ref { get; set; } = "";
+ public JToken? Value { get; set; }
+
+ /// The new value as a string (empty when null), for history and simple field assignments.
+ public string ValueString =>
+ Value == null || Value.Type == JTokenType.Null ? "" : Value.Type == JTokenType.String ? Value.Value() ?? "" : Value.ToString();
+}
diff --git a/Fuchs/Services/ReminderDraftCache.cs b/Fuchs/Services/ReminderDraftCache.cs
new file mode 100644
index 0000000..bcd13c5
--- /dev/null
+++ b/Fuchs/Services/ReminderDraftCache.cs
@@ -0,0 +1,61 @@
+using System.Collections.Concurrent;
+using Fuchs.intranet;
+using Microsoft.Extensions.Configuration;
+
+namespace Fuchs.Services;
+
+///
+/// Single-instance, in-memory implementation of backed
+/// by a keyed by session token — the
+/// reminder mirror of . A plain dictionary (rather than
+/// IMemoryCache) is used on purpose: the
+/// needs to enumerate sessions and warn the user before eviction, which opaque
+/// cache-entry expiry does not allow.
+///
+/// Idle TTL and the pre-expiry warning lead time are shared with invoices under
+/// Fuchs:DraftEditing (IdleMinutes / ExpiryWarnMinutes).
+///
+public sealed class ReminderDraftCache : IReminderDraftCache
+{
+ private readonly ConcurrentDictionary _sessions = new(StringComparer.Ordinal);
+
+ public TimeSpan IdleTtl { get; }
+ /// How long before the idle TTL a warning is emitted to the user.
+ public TimeSpan ExpiryWarnLead { get; }
+
+ public ReminderDraftCache(IConfiguration configuration)
+ {
+ int idleMinutes = configuration.GetValue("Fuchs:DraftEditing:IdleMinutes", 30);
+ int warnMinutes = configuration.GetValue("Fuchs:DraftEditing:ExpiryWarnMinutes", 5);
+ IdleTtl = TimeSpan.FromMinutes(Math.Max(1, idleMinutes));
+ ExpiryWarnLead = TimeSpan.FromMinutes(Math.Clamp(warnMinutes, 1, Math.Max(1, idleMinutes - 1)));
+ }
+
+ public void Set(ReminderDraftSession session)
+ {
+ if (string.IsNullOrEmpty(session.Token)) throw new ArgumentException("Session has no token.", nameof(session));
+ session.Touch();
+ _sessions[session.Token] = session;
+ }
+
+ public ReminderDraftSession? Get(string token)
+ {
+ if (string.IsNullOrEmpty(token)) return null;
+ if (_sessions.TryGetValue(token, out var s))
+ {
+ s.Touch();
+ // A touch resets the idle window, so a fresh warning is due next time it lapses.
+ s.ExpiryWarningSent = false;
+ return s;
+ }
+ return null;
+ }
+
+ public ReminderDraftSession? Remove(string token)
+ {
+ if (string.IsNullOrEmpty(token)) return null;
+ return _sessions.TryRemove(token, out var s) ? s : null;
+ }
+
+ public IReadOnlyList Snapshot() => _sessions.Values.ToList();
+}
diff --git a/Fuchs/Services/ReminderDraftEditService.cs b/Fuchs/Services/ReminderDraftEditService.cs
new file mode 100644
index 0000000..3a51d34
--- /dev/null
+++ b/Fuchs/Services/ReminderDraftEditService.cs
@@ -0,0 +1,275 @@
+using System.Globalization;
+using Fuchs.intranet;
+using Microsoft.Extensions.Logging;
+using MigraDoc.DocumentObjectModel;
+using Newtonsoft.Json.Linq;
+using OCORE.security;
+using static OCORE.commons;
+using static OCORE.OCORE_dictionaries;
+
+namespace Fuchs.Services;
+
+///
+/// Backend-authoritative reminder draft editing (ADR 0006) — the reminder mirror of
+/// . Holds the truth in a
+/// (via ), applies
+/// single edits, aggregates the open amount with ,
+/// renders previews and flushes to the DB by reusing the existing
+/// registration path — no new persistence. The session
+/// stores the editor's own block shape (new/rem), which the PDF/persistence
+/// already consume, so nothing is re-shaped server-side.
+///
+public sealed class ReminderDraftEditService : IReminderDraftService
+{
+ private readonly IReminderDraftCache _cache;
+ private readonly IReminderService _reminders;
+ private readonly ILogger _logger;
+
+ public ReminderDraftEditService(IReminderDraftCache cache, IReminderService reminders,
+ ILogger logger)
+ {
+ _cache = cache;
+ _reminders = reminders;
+ _logger = logger;
+ }
+
+ // ── Open ─────────────────────────────────────────────────────────────────
+ public ReminderDraftSession OpenFromPayload(JObject payload, string userAccountId)
+ {
+ var session = new ReminderDraftSession
+ {
+ Token = NewToken(),
+ UserAccountId = userAccountId,
+ RemId = payload["remid"]?.Value() ?? payload["id"]?.Value() ?? ""
+ };
+ session.New = payload["new"] as JObject ?? new JObject();
+ session.Rem = payload["rem"] as JObject ?? new JObject();
+ Refresh(session);
+ _cache.Set(session);
+ _logger.LogInformation("Reminder draft session {Token} opened from payload (remId={RemId}, user={User})",
+ session.Token, session.RemId, userAccountId);
+ return session;
+ }
+
+ public ReminderDraftSession? Get(string token) => _cache.Get(token);
+
+ // ── Patch ──────────────────────────────────────────────────────────────────
+ public ReminderDraftSession? ApplyPatch(string token, ReminderDraftDelta delta)
+ {
+ var session = _cache.Get(token);
+ if (session == null) return null;
+
+ string oldValue = "", newValue = "";
+ bool mutated = ApplyDelta(session, delta, ref oldValue, ref newValue);
+ if (!mutated)
+ {
+ _logger.LogDebug("Reminder draft {Token}: no-op patch target={Target} ref={Ref}", token, delta.Target, delta.Ref);
+ return session;
+ }
+
+ Refresh(session);
+ session.Version++;
+ session.History.Add(new ChangeHistoryEntry
+ {
+ UserAccountId = session.UserAccountId,
+ Target = delta.Target,
+ Ref = delta.Ref,
+ OldValue = oldValue,
+ NewValue = newValue,
+ Version = session.Version
+ });
+ _cache.Set(session);
+ return session;
+ }
+
+ ///
+ /// Applies one delta to the payload; returns whether anything changed and captures the prior
+ /// and new value for the change history. Scalar text fields are sanitised from the editor's
+ /// HTML (TinyMCE wraps inline edits in <p>…</p>) to plain text (via
+ /// ) — the backend is the single source of
+ /// truth (ADR 0006), so no HTML ever reaches the DB or the PDF.
+ ///
+ private static bool ApplyDelta(ReminderDraftSession s, ReminderDraftDelta d, ref string oldValue, ref string newValue)
+ {
+ switch (d.Target)
+ {
+ case "email": return SetNewText(s, "invoiceemail", d, ref oldValue, ref newValue);
+ case "address": return SetNewText(s, "invoiceaddress", d, ref oldValue, ref newValue);
+ case "subject": return SetNewText(s, "subject", d, ref oldValue, ref newValue);
+ case "text": return SetNewText(s, "text", d, ref oldValue, ref newValue);
+ case "amount": return SetNewNumber(s, "amount", d, ref oldValue, ref newValue);
+ case "amount_payed": return SetNewNumber(s, "amount_payed", d, ref oldValue, ref newValue);
+ case "contact": return SetContact(s, d, ref oldValue, ref newValue);
+ default: return false;
+ }
+ }
+
+ private static bool SetNewText(ReminderDraftSession s, string key, ReminderDraftDelta d, ref string oldValue, ref string newValue)
+ {
+ oldValue = Str(s.New[key]);
+ newValue = InvoiceDraftEditService.HtmlToPlain(d.ValueString);
+ s.New[key] = newValue;
+ return true;
+ }
+
+ /// Stores a numeric field, normalising German/invariant input to an invariant decimal string.
+ private static bool SetNewNumber(ReminderDraftSession s, string key, ReminderDraftDelta d, ref string oldValue, ref string newValue)
+ {
+ oldValue = Str(s.New[key]);
+ decimal parsed = ReminderDraftCalculator.Dec(d.Value ?? JValue.CreateString(InvoiceDraftEditService.HtmlToPlain(d.ValueString)));
+ newValue = parsed.ToString(CultureInfo.InvariantCulture);
+ s.New[key] = newValue;
+ return true;
+ }
+
+ private static bool SetContact(ReminderDraftSession s, ReminderDraftDelta d, ref string oldValue, ref string newValue)
+ {
+ JObject prev = TryParseObject(Str(s.New["CustomValues"]));
+ oldValue = ContactLabel(Str(prev["contactName"]), Str(prev["contactEmail"]));
+ JObject cvo = (JObject)prev.DeepClone();
+ if (d.Value is JObject vo)
+ {
+ cvo["contactName"] = vo["name"] ?? vo["contactName"] ?? "";
+ cvo["contactEmail"] = vo["email"] ?? vo["contactEmail"] ?? "";
+ }
+ s.New["CustomValues"] = cvo.ToString(Newtonsoft.Json.Formatting.None);
+ newValue = ContactLabel(Str(cvo["contactName"]), Str(cvo["contactEmail"]));
+ return true;
+ }
+
+ private static string ContactLabel(string name, string email) =>
+ string.IsNullOrEmpty(name) ? email : string.IsNullOrEmpty(email) ? name : $"{name} <{email}>";
+
+ // ── View state / history ────────────────────────────────────────────────
+ public object BuildState(ReminderDraftSession session)
+ {
+ session.Touch();
+ return new
+ {
+ token = session.Token,
+ version = session.Version,
+ remid = session.RemId,
+ isDraft = session.IsDraft,
+ @new = session.New,
+ rem = session.Rem,
+ sums = new
+ {
+ amount_total = session.Sums.AmountTotal,
+ amount_payed = session.Sums.AmountPayed,
+ amount_open = session.Sums.AmountOpen
+ },
+ validation = session.ValidationMessages.Select(v => new { field = v.Field, severity = v.Severity, message = v.Message }),
+ historyCount = session.History.Count
+ };
+ }
+
+ public IReadOnlyList GetHistory(string token) =>
+ _cache.Get(token)?.History ?? (IReadOnlyList)Array.Empty();
+
+ // ── Flush / preview ────────────────────────────────────────────────────────
+ public async Task FlushToDbAsync(string token, string userAccountId, DatabaseSecurity dbSec)
+ {
+ var session = _cache.Get(token);
+ if (session == null) return null;
+
+ var fds = BuildReminderData(session);
+ bool change = !string.IsNullOrEmpty(session.RemId);
+ var reg = await _reminders.RegisterReminderAsync(fds, change, session.RemId, userAccountId, dbSec);
+ if (!string.IsNullOrEmpty(reg.Id))
+ {
+ session.RemId = reg.Id;
+ _cache.Set(session);
+ _logger.LogInformation("Reminder draft {Token} flushed to DB reminder {RemId} (change={Change}, user={User})",
+ token, reg.Id, change, userAccountId);
+ }
+ return reg;
+ }
+
+ public Document? RenderPreview(string token)
+ {
+ var session = _cache.Get(token);
+ if (session == null) return null;
+ var fds = BuildReminderData(session);
+ fds.ReminderRegistration = SynthesizeRegistration(session);
+ fds.IsDraft = true;
+ return _reminders.GenerateReminderPdf(fds, draft: true);
+ }
+
+ public bool Close(string token) => _cache.Remove(token) != null;
+
+ // ── Internals ──────────────────────────────────────────────────────────────
+ private static void Refresh(ReminderDraftSession session)
+ {
+ ReminderDraftCalculator.RecomputeTotals(session);
+ ReminderDraftCalculator.Validate(session);
+ }
+
+ private static string NewToken() => Guid.NewGuid().ToString("N");
+
+ ///
+ /// Builds the from the session — the server-side equivalent of
+ /// the editor's remc payload. The session already holds the editor's new/rem
+ /// shape that registration consumes, so the blocks pass through unchanged.
+ ///
+ private static FdsReminderData BuildReminderData(ReminderDraftSession session)
+ {
+ var jobj = new JObject
+ {
+ ["new"] = session.New.DeepClone(),
+ ["rem"] = session.Rem.DeepClone()
+ };
+ return new FdsReminderData(jobj);
+ }
+
+ ///
+ /// Synthesises the ReminderRegistration dictionary a draft PDF render needs, straight
+ /// from the cached session — so a preview requires no DB round-trip and no client upload.
+ /// Mirrors the columns fds__getReminder/fds__createReminder would return for a
+ /// draft, including the single-invoice invoices row the reminder table renders.
+ ///
+ private static GenericObjectDictionary SynthesizeRegistration(ReminderDraftSession session)
+ {
+ string invoiceId = Str(session.Rem["invoiceid"]).ne(Str(session.Rem["InvoiceId"]));
+ var invoices = new JArray
+ {
+ new JObject
+ {
+ ["InvoiceDate"] = Str(session.Rem["invoicedate"]),
+ ["DocumentName"] = "",
+ ["InvoiceTitle"] = string.IsNullOrEmpty(invoiceId) ? "" : $"Rechnung {invoiceId}",
+ ["InvoiceBalance"] = session.Sums.AmountTotal,
+ ["amount_open"] = session.Sums.AmountOpen
+ }
+ };
+
+ var d = new Dictionary
+ {
+ ["Id"] = session.RemId,
+ ["type"] = Str(session.Rem["type"]).ne("R"),
+ ["subject"] = Str(session.New["subject"]),
+ ["SendToAddress"] = Str(session.New["invoiceaddress"]),
+ ["SendToEmail"] = Str(session.New["invoiceemail"]),
+ ["InvoiceId"] = invoiceId,
+ ["amount_open"] = session.Sums.AmountOpen,
+ ["PaymentTerm"] = Str(session.Rem["paymentterm"]),
+ ["invoices"] = invoices,
+ ["CustomValues"] = Str(session.New["CustomValues"]),
+ ["IsFinal"] = false,
+ ["DateCreated"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture)
+ };
+ return new GenericObjectDictionary(d);
+ }
+
+ // ── token helpers ─────────────────────────────────────────────────────────
+ private static string Str(JToken? t) =>
+ t == null || t.Type == JTokenType.Null ? "" : t.Type == JTokenType.String ? t.Value() ?? "" : t.ToString();
+
+ private static JObject TryParseObject(string json)
+ {
+ if (!string.IsNullOrWhiteSpace(json) && json.TrimStart().StartsWith('{'))
+ {
+ try { return JObject.Parse(json); } catch { /* fall through */ }
+ }
+ return new JObject();
+ }
+}
diff --git a/Fuchs/Services/ReminderDraftExpiryService.cs b/Fuchs/Services/ReminderDraftExpiryService.cs
new file mode 100644
index 0000000..e031bc2
--- /dev/null
+++ b/Fuchs/Services/ReminderDraftExpiryService.cs
@@ -0,0 +1,69 @@
+using Fuchs.Notifications;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+
+namespace Fuchs.Services;
+
+///
+/// Background monitor for the reminder draft cache (ADR 0006) — the reminder mirror of
+/// . Because a draft's truth lives only in server
+/// memory until the user saves, idle sessions must not vanish silently: this service warns
+/// the editing browser before a session's idle TTL lapses ("bitte zwischenspeichern"),
+/// and when the TTL is finally reached it evicts the session and tells the browser to close
+/// the editor with a reason. All hints travel over the shared
+/// via (the token-keyed groups serve invoices and reminders alike).
+///
+public sealed class ReminderDraftExpiryService : BackgroundService
+{
+ private readonly IReminderDraftCache _cache;
+ private readonly IDraftNotifier _notifier;
+ private readonly ILogger _logger;
+ private readonly TimeSpan _warnLead;
+ private readonly TimeSpan _interval;
+
+ public ReminderDraftExpiryService(IReminderDraftCache cache, IDraftNotifier notifier,
+ IConfiguration configuration, ILogger logger)
+ {
+ _cache = cache;
+ _notifier = notifier;
+ _logger = logger;
+ int warnMinutes = configuration.GetValue("Fuchs:DraftEditing:ExpiryWarnMinutes", 5);
+ _warnLead = TimeSpan.FromMinutes(Math.Clamp(warnMinutes, 1, Math.Max(1, (int)cache.IdleTtl.TotalMinutes - 1)));
+ _interval = TimeSpan.FromSeconds(30);
+ }
+
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+ {
+ using var timer = new PeriodicTimer(_interval);
+ try
+ {
+ while (await timer.WaitForNextTickAsync(stoppingToken))
+ await SweepAsync(stoppingToken);
+ }
+ catch (OperationCanceledException) { /* shutting down */ }
+ }
+
+ /// One pass over all live sessions. Internal so it can be driven directly from unit tests.
+ internal async Task SweepAsync(CancellationToken cancellationToken)
+ {
+ DateTime now = DateTime.UtcNow;
+ foreach (var session in _cache.Snapshot())
+ {
+ TimeSpan idle = now - session.LastAccessUtc;
+ if (idle >= _cache.IdleTtl)
+ {
+ _cache.Remove(session.Token);
+ _logger.LogInformation("Reminder draft {Token} evicted after {Idle} idle (user={User})",
+ session.Token, idle, session.UserAccountId);
+ await _notifier.SignalClosedAsync(session.Token, "expired", cancellationToken);
+ }
+ else if (idle >= _cache.IdleTtl - _warnLead && !session.ExpiryWarningSent)
+ {
+ session.ExpiryWarningSent = true;
+ int secondsLeft = (int)Math.Max(0, (_cache.IdleTtl - idle).TotalSeconds);
+ await _notifier.SignalExpiringAsync(session.Token, secondsLeft, cancellationToken);
+ }
+ }
+ }
+}
diff --git a/Fuchs/appsettings.Development.json b/Fuchs/appsettings.Development.json
index 56b599e..05befc1 100644
--- a/Fuchs/appsettings.Development.json
+++ b/Fuchs/appsettings.Development.json
@@ -26,6 +26,9 @@
"CheckMfr": false,
"CheckPdfLicense": true
},
+ "Mailer": {
+ "Enabled": true
+ },
"Email": {
"OverrideRecipient": "service@emails.processweb.de"
},
diff --git a/Fuchs/code/ReminderDraftCalculator.cs b/Fuchs/code/ReminderDraftCalculator.cs
new file mode 100644
index 0000000..899d888
--- /dev/null
+++ b/Fuchs/code/ReminderDraftCalculator.cs
@@ -0,0 +1,92 @@
+using System.Globalization;
+using Newtonsoft.Json.Linq;
+
+namespace Fuchs.intranet;
+
+///
+/// Server-side, pure aggregation of a reminder draft's open amount — the authoritative
+/// replacement for the browser's inline figure (ADR 0006, mirroring
+/// ). The user's requirement is that the computed
+/// figure lives in the backend cache, not the frontend.
+///
+/// A reminder chases a single invoiced amount: AmountOpen = AmountTotal - AmountPayed
+/// (both read from the editor's new block). Static/pure, hence exhaustively
+/// unit-testable.
+///
+public static class ReminderDraftCalculator
+{
+ /// Recomputes the reminder's open amount from the edited amount / amount_payed.
+ public static void RecomputeTotals(ReminderDraftSession session)
+ {
+ decimal total = Dec(session.New["amount"]);
+ decimal payed = Dec(session.New["amount_payed"]);
+ session.Sums = new ReminderDraftSums
+ {
+ AmountTotal = total,
+ AmountPayed = payed,
+ AmountOpen = total - payed
+ };
+ }
+
+ ///
+ /// Refreshes the draft's plausibility / consistency findings. "error" severity marks
+ /// issues that should block a clean finalise; "warning" is advisory. Kept in German,
+ /// user-readable, so the frontend can render them directly.
+ ///
+ public static void Validate(ReminderDraftSession session)
+ {
+ session.ValidationMessages.Clear();
+ void Add(string field, string sev, string msg) =>
+ session.ValidationMessages.Add(new ReminderDraftValidationMessage(field, sev, msg));
+
+ string email = Str(session.New["invoiceemail"]).Trim();
+ if (email.Length == 0)
+ Add("email", "warning", "Es ist keine E-Mail-Adresse hinterlegt — die Mahnung kann nicht per E-Mail versandt werden.");
+ else if (!IsValidEmail(email))
+ Add("email", "error", "Die E-Mail-Adresse ist ungültig.");
+
+ if (Str(session.New["invoiceaddress"]).Trim().Length == 0)
+ Add("address", "warning", "Es ist keine Anschrift hinterlegt.");
+
+ if (Str(session.New["subject"]).Trim().Length == 0)
+ Add("subject", "warning", "Es ist kein Betreff hinterlegt.");
+
+ if (session.Sums.AmountOpen <= 0)
+ Add("amount", "warning", "Der offene Betrag ist null oder negativ — es besteht keine offene Forderung.");
+ }
+
+ // ── helpers ──────────────────────────────────────────────────────────────
+ /// Parses a JToken to a decimal, tolerating German ("12,50" / "1.234,56") and invariant ("12.50") strings.
+ internal static decimal Dec(JToken? token)
+ {
+ if (token == null || token.Type == JTokenType.Null) return 0;
+ if (token.Type is JTokenType.Float or JTokenType.Integer) return token.Value();
+ return ParseAmount(Str(token));
+ }
+
+ ///
+ /// Parses a currency string, resolving the German/invariant ambiguity: a value with both
+ /// separators treats "." as thousands and "," as decimal ("1.234,56"); a value with only ","
+ /// treats it as the decimal separator ("12,50"); otherwise it is parsed invariant ("1234.56").
+ ///
+ internal static decimal ParseAmount(string? raw)
+ {
+ string s = (raw ?? "").Trim();
+ if (s.Length == 0) return 0;
+ bool hasComma = s.Contains(','), hasDot = s.Contains('.');
+ if (hasComma && hasDot) s = s.Replace(".", "").Replace(',', '.'); // German "1.234,56"
+ else if (hasComma) s = s.Replace(',', '.'); // German "12,50"
+ return decimal.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out decimal d) ? d : 0;
+ }
+
+ private static string Str(JToken? token) =>
+ token == null || token.Type == JTokenType.Null ? "" : token.Type == JTokenType.String ? token.Value() ?? "" : token.ToString();
+
+ private static bool IsValidEmail(string email)
+ {
+ int at = email.IndexOf('@');
+ if (at <= 0 || at != email.LastIndexOf('@')) return false;
+ int dot = email.IndexOf('.', at);
+ return dot > at + 1 && dot < email.Length - 1;
+ }
+}
diff --git a/Fuchs/code/ReminderDraftSession.cs b/Fuchs/code/ReminderDraftSession.cs
new file mode 100644
index 0000000..2654042
--- /dev/null
+++ b/Fuchs/code/ReminderDraftSession.cs
@@ -0,0 +1,81 @@
+using Newtonsoft.Json.Linq;
+
+namespace Fuchs.intranet;
+
+///
+/// Server-side, in-memory editing state for a single reminder (Zahlungserinnerung)
+/// draft — the authoritative source of truth while a back-office user edits a draft in
+/// the browser. This mirrors for reminders (ADR 0006):
+/// the browser is a pure view/input layer that posts single changes
+/// (); the server mutates this session,
+/// recomputes the open amount and validates, then signals the browser to re-fetch.
+///
+/// This is a data holder only — all calculation, validation, persistence and
+/// rendering live in (mirroring the
+/// / split).
+/// The editable payload is kept as the exact JSON shape the editor already speaks
+/// (new / rem), so flushing to the DB can reuse
+/// unchanged.
+/// The change-history record type () is shared with the
+/// invoice draft; validation messages use the reminder-specific
+/// .
+///
+public sealed class ReminderDraftSession
+{
+ /// Opaque per-editor token; also the SignalR group name for targeted signals.
+ public string Token { get; init; } = "";
+
+ /// Owning user account id (drafts are single-user; used for auth + events).
+ public string UserAccountId { get; init; } = "";
+
+ /// DB reminder id once the session has been flushed (Zwischenspeichern); empty while cache-only.
+ public string RemId { get; set; } = "";
+
+ /// Always true here — sessions only ever hold unfinalised drafts.
+ public bool IsDraft { get; set; } = true;
+
+ /// Bumped on every applied mutation; the browser refetches when the signalled version changes.
+ public int Version { get; set; }
+
+ /// UTC of the last read/write; drives the idle sliding-TTL and expiry warnings.
+ public DateTime LastAccessUtc { get; set; } = DateTime.UtcNow;
+
+ /// Guards against sending more than one expiry warning per idle window.
+ public bool ExpiryWarningSent { get; set; }
+
+ // ── Editable payload (exact editor JSON shape) ───────────────────────────
+ /// Recipient/new fields: subject, invoiceaddress, invoiceemail, text, amount, amount_payed, CustomValues…
+ public JObject New { get; set; } = new();
+
+ /// Reference fields: invid, type, level, invoiceid, invoicedate, sender…
+ public JObject Rem { get; set; } = new();
+
+ // ── Computed (by the draft service; never trusted from the client) ───────
+ /// Server-computed open-amount aggregation — the values the client used to compute inline.
+ public ReminderDraftSums Sums { get; set; } = new();
+
+ /// Plausibility / consistency results, refreshed on every recompute.
+ public List ValidationMessages { get; } = new();
+
+ /// Automatic change history, appended on every applied patch. Cache-only (never persisted).
+ public List History { get; } = new();
+
+ public void Touch() => LastAccessUtc = DateTime.UtcNow;
+}
+
+/// Server-computed reminder totals — the authoritative open-amount for the draft.
+public sealed class ReminderDraftSums
+{
+ /// Invoiced amount (gross) the reminder chases.
+ public decimal AmountTotal { get; set; }
+ /// Amount already paid against the invoice.
+ public decimal AmountPayed { get; set; }
+ /// Still-open amount (AmountTotal - AmountPayed) — the reminder's headline figure.
+ public decimal AmountOpen { get; set; }
+}
+
+/// A single plausibility/consistency finding for the reminder draft.
+/// Logical field the message relates to (e.g. "email", "address", "amount").
+/// "error" blocks a clean finalise; "warning"/"info" are advisory.
+/// German, user-readable text.
+public readonly record struct ReminderDraftValidationMessage(string Field, string Severity, string Message);
diff --git a/Fuchs/js/intranet/modules/fis.inv_shared.js b/Fuchs/js/intranet/modules/fis.inv_shared.js
index e6c393a..63dfc82 100644
--- a/Fuchs/js/intranet/modules/fis.inv_shared.js
+++ b/Fuchs/js/intranet/modules/fis.inv_shared.js
@@ -313,6 +313,161 @@ $inv.d = {
$inv.d.tbl().removeData('dtoken');
}
};
+/* ── Backend-authoritative reminder draft editing (ADR 0006/0007) ─────────────
+ The reminder mirror of $inv.d: the server holds the truth for a reminder draft in
+ an in-memory session; this object seeds it (rem/dopen), sends single edits as deltas
+ (rem/dpatch), and renders the open-amount footer + validation from the authoritative
+ server state (rem/dstate). Preview renders straight from the cache (rem/dpreview);
+ confirm flushes (rem/dsave) then finalises + emails (rem/conf). It coexists with $inv.d
+ on the same DOM: each keys off its own token (rdtoken vs dtoken), so the shared inline
+ editor safely no-ops for the mode that is not active. */
+$inv.rd = {
+ tbl: () => $('div.invoice_layout table.invi'),
+ layout: () => $('div.invoice_layout'),
+ token: function () { return $inv.rd.tbl().data('rdtoken') || ''; },
+ /* Seed the authoritative server session from the assembled reminder editor payload. */
+ seed: function (payload) {
+ let l = $inv.rd.layout(); l.aC('freeze');
+ $ocms.postXT({
+ url: $ocms.url('rem/dopen'), data: { payload: JSON.stringify(payload) }, success: (r) => {
+ $inv.rd.tbl().data('rdtoken', r.token).data('rdver', r.version);
+ $fis.draft.bind(r.token, {
+ onReady: () => $inv.rd.refresh(),
+ onExpiring: (s) => $inv.rd.warnExpiry(s),
+ onClosed: (reason) => $inv.rd.closed(reason)
+ });
+ $inv.rd.refresh();
+ }, error: () => { l.rC('freeze'); }
+ });
+ },
+ /* Re-fetch the authoritative state and render the open-amount footer + validation from it. */
+ refresh: function (cb) {
+ let t = $inv.rd.token(); if (t === '') { return; }
+ $ocms.postXT({
+ url: $ocms.url('rem/dstate'), data: { token: t }, success: (state) => {
+ $inv.rd.applyState(state); if (typeof cb === 'function') { cb(state); }
+ }, error: (xhr) => { if (xhr && xhr.status === 410) { $inv.rd.closed('expired'); } },
+ complete: () => { $inv.rd.layout().rC('freeze'); }
+ });
+ },
+ applyState: function (state) {
+ let tbl = $inv.rd.tbl(); if (tbl.length < 1) { return; }
+ tbl.data('rdver', state.version).data('serverSums', state.sums).data('remid', state.remid || '');
+ $inv.rd.footer(tbl, state.sums || {});
+ $inv.rd.validation(state.validation || []);
+ },
+ /* Send one change to the server; the draftReady signal and this success both refresh. */
+ sync: function (delta) {
+ let t = $inv.rd.token(); if (t === '') { return; }
+ $inv.rd.layout().aC('freeze');
+ $ocms.postXT({
+ url: $ocms.url('rem/dpatch'), data: { token: t, delta: JSON.stringify(delta) },
+ success: () => { $inv.rd.refresh(); },
+ error: (xhr) => { $inv.rd.layout().rC('freeze'); if (xhr && xhr.status === 410) { $inv.rd.closed('expired'); } }
+ });
+ },
+ /* Map an inline recipient field to its delta target and send it. */
+ syncField: function (nme, val) {
+ if ($inv.rd.token() === '') { return; }
+ let map = { subject: 'subject', invoiceaddress: 'address', invoiceemail: 'email', text: 'text' };
+ let target = map[nme]; if (!target) { return; }
+ $inv.rd.sync({ Target: target, Value: val });
+ },
+ /* Amount / amount-paid come from the item-row dialog; send both as their own deltas. */
+ syncAmount: function (amount, amount_payed) {
+ if ($inv.rd.token() === '') { return; }
+ $inv.rd.sync({ Target: 'amount', Value: (amount != null ? amount : 0).toString() });
+ $inv.rd.sync({ Target: 'amount_payed', Value: (amount_payed != null ? amount_payed : 0).toString() });
+ },
+ /* Render the open-amount footer from the server sums. */
+ footer: function (tbl, sums) {
+ let ft = tbl.children('tfoot').empty();
+ let tr = $$.tr(ft, { class: 'tsum' }).append([$$.tdc('aux'), $$.td({ colspan: 3 }).text('Offener Betrag')]);
+ $$.tdc('currency', tr, fnum(sums.amount_open || 0, $rct.cst));
+ },
+ validation: function (msgs) {
+ let frm = $inv.rd.layout(); if (frm.length < 1) { return; }
+ let box = frm.children('.dvalidation');
+ if (box.length < 1) { box = $$.dc('dvalidation'); frm.prepend(box); }
+ box.empty().tC('hidden', (msgs || []).length < 1);
+ $.each(msgs || [], (i, m) => $$.dc('dvmsg', box).aC(m.severity).text(m.message));
+ },
+ /* PDF preview straight from the cache; confirm = flush + finalise + email, cancel = discard. */
+ preview: function () {
+ let t = $inv.rd.token(); if (t === '') { return; }
+ let l = $inv.rd.layout();
+ let email = (($inv.rd.tbl().data('new') || {}).invoiceemail) || '';
+ if ($fis.ValidateEmail(email) === false) { if (bool(confirm($ict.ivE + $ict.ivEc), false) === false) { return; } }
+ l.aC('freeze');
+ $ocms.postXT({
+ url: $ocms.url('rem/dpreview'), data: { token: t }, success: (response) => {
+ l.rC('freeze');
+ let c = $$.dc('imagecollection pdfpreview'), vhr = Math.round(vh() * 0.88);
+ $.each(response.img || [], (ii, img) => { $$.dc('pdfp', c).append($$.img(img).css('max-height', (vhr - rpx(6)).toString() + 'px')); });
+ $ocms.dlg(c, {
+ size: [vhr, Math.round(vw() * 0.88)], zindex: 50, form: false, button: $ict.remd,
+ confirm: function (e) {
+ let ct = $(this); l.aC('freeze');
+ $ocms.postXT({
+ url: $ocms.url('rem/dsave'), data: { token: t }, success: (sv) => {
+ $ocms.postXT({
+ url: $ocms.url('rem/conf'), data: { id: sv.remid }, success: () => {
+ ct.trigger('modal_close');
+ window.open($ocms.url('rem/idoc') + '?id=' + sv.remid, '_blank');
+ $inv.rd.close();
+ $ocms.init('req'); $inv.rReload();
+ }, error: () => { alert($t.f1); ct.trigger('modal_close'); }, complete: () => { l.rC('freeze'); }
+ });
+ }, error: () => { l.rC('freeze'); alert($t.f1); }
+ });
+ },
+ cancel: function (e) { if (confirm($ict.cdI)) { $inv.rd.close(); $inv.rReload(); } }
+ });
+ }, error: () => { l.rC('freeze'); alert($t.f1); }
+ });
+ },
+ /* Zwischenspeichern: flush the cache to the DB (no re-upload); stay in the editor. */
+ save: function () {
+ let t = $inv.rd.token(); if (t === '') { return; }
+ let l = $inv.rd.layout(); l.aC('freeze');
+ $ocms.postXT({
+ url: $ocms.url('rem/dsave'), data: { token: t }, success: (r) => { $inv.rd.tbl().data('remid', r.remid); },
+ error: () => { alert($t.f1); }, complete: () => { l.rC('freeze'); }
+ });
+ },
+ history: function () {
+ let t = $inv.rd.token(); if (t === '') { return; }
+ $ocms.postXT({
+ url: $ocms.url('rem/dhistory'), data: { token: t }, success: (r) => {
+ let c = $$.dc('dhist');
+ if ((r.history || []).length < 1) { $$.dc('note', c).text('Noch keine Änderungen erfasst.'); }
+ else {
+ let ts = $$.tblset({ class: 'invtbl fullwidth' }, c);
+ $$.tr(ts.hd).append([$$.th().text('Zeit'), $$.th().text('Feld'), $$.th().text('Alt'), $$.th().text('Neu')]);
+ $.each(r.history, (i, h) => $$.tr(ts.bdy).append([$$.tdc('keep', fdt(h.timestamp)), $$.td().text(h.target), $$.td().text(h.oldValue), $$.td().text(h.newValue)]));
+ }
+ $ocms.dlg(c, { width: 800, form: false });
+ }
+ });
+ },
+ warnExpiry: function (secondsLeft) {
+ let mins = Math.max(1, Math.round((secondsLeft || 0) / 60));
+ $fis.notifications.push({ severity: 'info', title: 'Entwurf läuft ab', message: 'Der Mahnentwurf läuft in etwa ' + mins + ' Minute(n) ab. Bitte zwischenspeichern, sonst gehen die Änderungen verloren.' });
+ },
+ closed: function (reason) {
+ let t = $inv.rd.token();
+ $inv.rd.tbl().removeData('rdtoken');
+ if (t !== '') { $fis.draft.release(t); }
+ $fis.frm_edit().remove(); $fis.lf(true);
+ $fis.notifications.push({ severity: 'error', title: 'Entwurf geschlossen', message: reason === 'expired' ? 'Der Mahnentwurf ist wegen Inaktivität abgelaufen. Nicht gespeicherte Änderungen sind verloren.' : 'Der Mahnentwurf wurde geschlossen.' });
+ try { $inv.rReload(); } catch (e) { }
+ },
+ close: function () {
+ let t = $inv.rd.token();
+ if (t !== '') { $ocms.postXT({ url: $ocms.url('rem/dclose'), data: { token: t } }); $fis.draft.release(t); }
+ $inv.rd.tbl().removeData('rdtoken');
+ }
+};
$inv.cInv2 = function (data) {
let fr = $$.dc('rfrm').ldng(1);
let o = $ocms.dlg(fr, { width: 1000 });
@@ -711,8 +866,11 @@ $inv.eHtml = function (ev) {
if (typeof change === 'function') {
change(response.txt);
}
- /* backend-authoritative: mirror the inline recipient-field edit to the server session */
+ /* backend-authoritative: mirror the inline recipient-field edit to the server session.
+ Invoice and reminder editors share this DOM; each syncField no-ops unless its own
+ draft token is present, so only the active mode's session receives the delta. */
$inv.d.syncField(ev.data.nme, isPlainText ? (response.txt || '') : response.txt);
+ $inv.rd.syncField(ev.data.nme, isPlainText ? (response.txt || '') : response.txt);
},
tinymce: { valid_elements: 'br', hidemenu: true, hidetoolbar: true }
}
@@ -1367,6 +1525,8 @@ $inv.eRowR = function (ev) {
$.extend(tdta.rm, res);
tbl.data(tdta);
$inv.rRemRw.call(row, tdta);
+ /* backend-authoritative: mirror the edited amount / amount-paid to the server session */
+ $inv.rd.syncAmount(tdta.rm.amount, tdta.rm.amount_payed);
}, typedvalues: true
});
};
@@ -1407,57 +1567,26 @@ $inv.ccRem_s2 = function (id, sets) { //reminder creation
rif.tbl.children('tbody').each($inv.bdysort);
rif.tbl.trigger('fds.inv'); /* trigger calculations */
+ /* Seed the authoritative server session (ADR 0006). Amounts join the recipient
+ fields in the 'new' block; the reference invoice data goes into 'rem'. From here
+ the backend owns the open-amount computation and validation; inline edits and the
+ item-row dialog post single deltas (see $inv.rd). */
+ let nw = rif.tbl.data('new');
+ nw.amount = rem.amount; nw.amount_payed = rem.amount_payed;
+ $inv.rd.seed({
+ rem: { invid: rem.invid, type: rem.type, invoiceid: rem.invoiceid, invoicedate: rem.invoicedate },
+ new: nw
+ });
}, complete: () => {
//o.c.trigger('modal_close');
}
});
};
$inv.rprev = () => {
- var l = $('div.invoice_layout'), tbl = l.find('table.invi'), d = tbl.data();
- $.extend(d.new, tbl.find('tbody > tr:first').data());
- l.aC('freeze');
- //console.debug({ rem: d.rm, new: d.new });
- if ($fis.ValidateEmail(d.new.invoiceemail || '') === false) {
- if (bool(confirm($ict.ivE + $ict.ivEc), false) === false) {
- l.rC('freeze');
- return;
- }
- }
- $ocms.postXT({
- url: $ocms.url('rem/prep'), data: { remc: JSON.stringify({ rem: d.rm, new: d.new }), id: d.invid || '' }, success: (response) => {
- l.rC('freeze');
- let c = $$.dc('imagecollection pdfpreview'), vhr = Math.round(vh() * 0.88), remid = response.id;
- $.each(response.img || [], function (ii, img) {
- $$.dc('pdfp', c).append($$.img(img).css('max-height', (vhr - rpx(6)).toString() + 'px'));
- });
- $ocms.dlg(c, {
- size: [vhr, Math.round(vw() * 0.88)], zindex: 50, form: false, button: $ict.remd, confirm: function (e) {
- let ct = $(this);
- $ocms.postXT({
- url: $ocms.url('rem/conf'), data: { id: remid }, success: () => {
- ct.trigger('modal_close');
- window.open($ocms.url('rem/idoc') + '?id=' + remid, '_blank'); /* open pdf in new tab */
- $ocms.init('req'); /* go back to request list */
- $inv.rReload();
- }, error: () => {
- alert($t.f1);
- ct.trigger('modal_close');
- }
- });
- }, cancel: function (e) {
- let ct = $(this);
- if (confirm($ict.cdI)) {
- $ocms.postXT({
- url: $ocms.url('rem/del'), data: {
- id: remid
- }
- });
- }
- $inv.rReload();
- }
- });
- }
- });
+ /* Preview + finalise now run through the backend-authoritative session ($inv.rd):
+ the PDF renders straight from the server cache (no rem/prep DB write), and confirm
+ flushes (rem/dsave) then finalises + emails (rem/conf). */
+ $inv.rd.preview();
};
$inv.sis = (id) => {
if (confirm($ict.sisc)) {
diff --git a/Fuchs/wwwroot/web/fis.inv.de.js b/Fuchs/wwwroot/web/fis.inv.de.js
index 7c45e3a..c67871c 100644
--- a/Fuchs/wwwroot/web/fis.inv.de.js
+++ b/Fuchs/wwwroot/web/fis.inv.de.js
@@ -860,6 +860,161 @@ $inv.d = {
$inv.d.tbl().removeData('dtoken');
}
};
+/* ── Backend-authoritative reminder draft editing (ADR 0006/0007) ─────────────
+ The reminder mirror of $inv.d: the server holds the truth for a reminder draft in
+ an in-memory session; this object seeds it (rem/dopen), sends single edits as deltas
+ (rem/dpatch), and renders the open-amount footer + validation from the authoritative
+ server state (rem/dstate). Preview renders straight from the cache (rem/dpreview);
+ confirm flushes (rem/dsave) then finalises + emails (rem/conf). It coexists with $inv.d
+ on the same DOM: each keys off its own token (rdtoken vs dtoken), so the shared inline
+ editor safely no-ops for the mode that is not active. */
+$inv.rd = {
+ tbl: () => $('div.invoice_layout table.invi'),
+ layout: () => $('div.invoice_layout'),
+ token: function () { return $inv.rd.tbl().data('rdtoken') || ''; },
+ /* Seed the authoritative server session from the assembled reminder editor payload. */
+ seed: function (payload) {
+ let l = $inv.rd.layout(); l.aC('freeze');
+ $ocms.postXT({
+ url: $ocms.url('rem/dopen'), data: { payload: JSON.stringify(payload) }, success: (r) => {
+ $inv.rd.tbl().data('rdtoken', r.token).data('rdver', r.version);
+ $fis.draft.bind(r.token, {
+ onReady: () => $inv.rd.refresh(),
+ onExpiring: (s) => $inv.rd.warnExpiry(s),
+ onClosed: (reason) => $inv.rd.closed(reason)
+ });
+ $inv.rd.refresh();
+ }, error: () => { l.rC('freeze'); }
+ });
+ },
+ /* Re-fetch the authoritative state and render the open-amount footer + validation from it. */
+ refresh: function (cb) {
+ let t = $inv.rd.token(); if (t === '') { return; }
+ $ocms.postXT({
+ url: $ocms.url('rem/dstate'), data: { token: t }, success: (state) => {
+ $inv.rd.applyState(state); if (typeof cb === 'function') { cb(state); }
+ }, error: (xhr) => { if (xhr && xhr.status === 410) { $inv.rd.closed('expired'); } },
+ complete: () => { $inv.rd.layout().rC('freeze'); }
+ });
+ },
+ applyState: function (state) {
+ let tbl = $inv.rd.tbl(); if (tbl.length < 1) { return; }
+ tbl.data('rdver', state.version).data('serverSums', state.sums).data('remid', state.remid || '');
+ $inv.rd.footer(tbl, state.sums || {});
+ $inv.rd.validation(state.validation || []);
+ },
+ /* Send one change to the server; the draftReady signal and this success both refresh. */
+ sync: function (delta) {
+ let t = $inv.rd.token(); if (t === '') { return; }
+ $inv.rd.layout().aC('freeze');
+ $ocms.postXT({
+ url: $ocms.url('rem/dpatch'), data: { token: t, delta: JSON.stringify(delta) },
+ success: () => { $inv.rd.refresh(); },
+ error: (xhr) => { $inv.rd.layout().rC('freeze'); if (xhr && xhr.status === 410) { $inv.rd.closed('expired'); } }
+ });
+ },
+ /* Map an inline recipient field to its delta target and send it. */
+ syncField: function (nme, val) {
+ if ($inv.rd.token() === '') { return; }
+ let map = { subject: 'subject', invoiceaddress: 'address', invoiceemail: 'email', text: 'text' };
+ let target = map[nme]; if (!target) { return; }
+ $inv.rd.sync({ Target: target, Value: val });
+ },
+ /* Amount / amount-paid come from the item-row dialog; send both as their own deltas. */
+ syncAmount: function (amount, amount_payed) {
+ if ($inv.rd.token() === '') { return; }
+ $inv.rd.sync({ Target: 'amount', Value: (amount != null ? amount : 0).toString() });
+ $inv.rd.sync({ Target: 'amount_payed', Value: (amount_payed != null ? amount_payed : 0).toString() });
+ },
+ /* Render the open-amount footer from the server sums. */
+ footer: function (tbl, sums) {
+ let ft = tbl.children('tfoot').empty();
+ let tr = $$.tr(ft, { class: 'tsum' }).append([$$.tdc('aux'), $$.td({ colspan: 3 }).text('Offener Betrag')]);
+ $$.tdc('currency', tr, fnum(sums.amount_open || 0, $rct.cst));
+ },
+ validation: function (msgs) {
+ let frm = $inv.rd.layout(); if (frm.length < 1) { return; }
+ let box = frm.children('.dvalidation');
+ if (box.length < 1) { box = $$.dc('dvalidation'); frm.prepend(box); }
+ box.empty().tC('hidden', (msgs || []).length < 1);
+ $.each(msgs || [], (i, m) => $$.dc('dvmsg', box).aC(m.severity).text(m.message));
+ },
+ /* PDF preview straight from the cache; confirm = flush + finalise + email, cancel = discard. */
+ preview: function () {
+ let t = $inv.rd.token(); if (t === '') { return; }
+ let l = $inv.rd.layout();
+ let email = (($inv.rd.tbl().data('new') || {}).invoiceemail) || '';
+ if ($fis.ValidateEmail(email) === false) { if (bool(confirm($ict.ivE + $ict.ivEc), false) === false) { return; } }
+ l.aC('freeze');
+ $ocms.postXT({
+ url: $ocms.url('rem/dpreview'), data: { token: t }, success: (response) => {
+ l.rC('freeze');
+ let c = $$.dc('imagecollection pdfpreview'), vhr = Math.round(vh() * 0.88);
+ $.each(response.img || [], (ii, img) => { $$.dc('pdfp', c).append($$.img(img).css('max-height', (vhr - rpx(6)).toString() + 'px')); });
+ $ocms.dlg(c, {
+ size: [vhr, Math.round(vw() * 0.88)], zindex: 50, form: false, button: $ict.remd,
+ confirm: function (e) {
+ let ct = $(this); l.aC('freeze');
+ $ocms.postXT({
+ url: $ocms.url('rem/dsave'), data: { token: t }, success: (sv) => {
+ $ocms.postXT({
+ url: $ocms.url('rem/conf'), data: { id: sv.remid }, success: () => {
+ ct.trigger('modal_close');
+ window.open($ocms.url('rem/idoc') + '?id=' + sv.remid, '_blank');
+ $inv.rd.close();
+ $ocms.init('req'); $inv.rReload();
+ }, error: () => { alert($t.f1); ct.trigger('modal_close'); }, complete: () => { l.rC('freeze'); }
+ });
+ }, error: () => { l.rC('freeze'); alert($t.f1); }
+ });
+ },
+ cancel: function (e) { if (confirm($ict.cdI)) { $inv.rd.close(); $inv.rReload(); } }
+ });
+ }, error: () => { l.rC('freeze'); alert($t.f1); }
+ });
+ },
+ /* Zwischenspeichern: flush the cache to the DB (no re-upload); stay in the editor. */
+ save: function () {
+ let t = $inv.rd.token(); if (t === '') { return; }
+ let l = $inv.rd.layout(); l.aC('freeze');
+ $ocms.postXT({
+ url: $ocms.url('rem/dsave'), data: { token: t }, success: (r) => { $inv.rd.tbl().data('remid', r.remid); },
+ error: () => { alert($t.f1); }, complete: () => { l.rC('freeze'); }
+ });
+ },
+ history: function () {
+ let t = $inv.rd.token(); if (t === '') { return; }
+ $ocms.postXT({
+ url: $ocms.url('rem/dhistory'), data: { token: t }, success: (r) => {
+ let c = $$.dc('dhist');
+ if ((r.history || []).length < 1) { $$.dc('note', c).text('Noch keine Änderungen erfasst.'); }
+ else {
+ let ts = $$.tblset({ class: 'invtbl fullwidth' }, c);
+ $$.tr(ts.hd).append([$$.th().text('Zeit'), $$.th().text('Feld'), $$.th().text('Alt'), $$.th().text('Neu')]);
+ $.each(r.history, (i, h) => $$.tr(ts.bdy).append([$$.tdc('keep', fdt(h.timestamp)), $$.td().text(h.target), $$.td().text(h.oldValue), $$.td().text(h.newValue)]));
+ }
+ $ocms.dlg(c, { width: 800, form: false });
+ }
+ });
+ },
+ warnExpiry: function (secondsLeft) {
+ let mins = Math.max(1, Math.round((secondsLeft || 0) / 60));
+ $fis.notifications.push({ severity: 'info', title: 'Entwurf läuft ab', message: 'Der Mahnentwurf läuft in etwa ' + mins + ' Minute(n) ab. Bitte zwischenspeichern, sonst gehen die Änderungen verloren.' });
+ },
+ closed: function (reason) {
+ let t = $inv.rd.token();
+ $inv.rd.tbl().removeData('rdtoken');
+ if (t !== '') { $fis.draft.release(t); }
+ $fis.frm_edit().remove(); $fis.lf(true);
+ $fis.notifications.push({ severity: 'error', title: 'Entwurf geschlossen', message: reason === 'expired' ? 'Der Mahnentwurf ist wegen Inaktivität abgelaufen. Nicht gespeicherte Änderungen sind verloren.' : 'Der Mahnentwurf wurde geschlossen.' });
+ try { $inv.rReload(); } catch (e) { }
+ },
+ close: function () {
+ let t = $inv.rd.token();
+ if (t !== '') { $ocms.postXT({ url: $ocms.url('rem/dclose'), data: { token: t } }); $fis.draft.release(t); }
+ $inv.rd.tbl().removeData('rdtoken');
+ }
+};
$inv.cInv2 = function (data) {
let fr = $$.dc('rfrm').ldng(1);
let o = $ocms.dlg(fr, { width: 1000 });
@@ -1258,8 +1413,11 @@ $inv.eHtml = function (ev) {
if (typeof change === 'function') {
change(response.txt);
}
- /* backend-authoritative: mirror the inline recipient-field edit to the server session */
+ /* backend-authoritative: mirror the inline recipient-field edit to the server session.
+ Invoice and reminder editors share this DOM; each syncField no-ops unless its own
+ draft token is present, so only the active mode's session receives the delta. */
$inv.d.syncField(ev.data.nme, isPlainText ? (response.txt || '') : response.txt);
+ $inv.rd.syncField(ev.data.nme, isPlainText ? (response.txt || '') : response.txt);
},
tinymce: { valid_elements: 'br', hidemenu: true, hidetoolbar: true }
}
@@ -1914,6 +2072,8 @@ $inv.eRowR = function (ev) {
$.extend(tdta.rm, res);
tbl.data(tdta);
$inv.rRemRw.call(row, tdta);
+ /* backend-authoritative: mirror the edited amount / amount-paid to the server session */
+ $inv.rd.syncAmount(tdta.rm.amount, tdta.rm.amount_payed);
}, typedvalues: true
});
};
@@ -1954,57 +2114,26 @@ $inv.ccRem_s2 = function (id, sets) { //reminder creation
rif.tbl.children('tbody').each($inv.bdysort);
rif.tbl.trigger('fds.inv'); /* trigger calculations */
+ /* Seed the authoritative server session (ADR 0006). Amounts join the recipient
+ fields in the 'new' block; the reference invoice data goes into 'rem'. From here
+ the backend owns the open-amount computation and validation; inline edits and the
+ item-row dialog post single deltas (see $inv.rd). */
+ let nw = rif.tbl.data('new');
+ nw.amount = rem.amount; nw.amount_payed = rem.amount_payed;
+ $inv.rd.seed({
+ rem: { invid: rem.invid, type: rem.type, invoiceid: rem.invoiceid, invoicedate: rem.invoicedate },
+ new: nw
+ });
}, complete: () => {
//o.c.trigger('modal_close');
}
});
};
$inv.rprev = () => {
- var l = $('div.invoice_layout'), tbl = l.find('table.invi'), d = tbl.data();
- $.extend(d.new, tbl.find('tbody > tr:first').data());
- l.aC('freeze');
- //console.debug({ rem: d.rm, new: d.new });
- if ($fis.ValidateEmail(d.new.invoiceemail || '') === false) {
- if (bool(confirm($ict.ivE + $ict.ivEc), false) === false) {
- l.rC('freeze');
- return;
- }
- }
- $ocms.postXT({
- url: $ocms.url('rem/prep'), data: { remc: JSON.stringify({ rem: d.rm, new: d.new }), id: d.invid || '' }, success: (response) => {
- l.rC('freeze');
- let c = $$.dc('imagecollection pdfpreview'), vhr = Math.round(vh() * 0.88), remid = response.id;
- $.each(response.img || [], function (ii, img) {
- $$.dc('pdfp', c).append($$.img(img).css('max-height', (vhr - rpx(6)).toString() + 'px'));
- });
- $ocms.dlg(c, {
- size: [vhr, Math.round(vw() * 0.88)], zindex: 50, form: false, button: $ict.remd, confirm: function (e) {
- let ct = $(this);
- $ocms.postXT({
- url: $ocms.url('rem/conf'), data: { id: remid }, success: () => {
- ct.trigger('modal_close');
- window.open($ocms.url('rem/idoc') + '?id=' + remid, '_blank'); /* open pdf in new tab */
- $ocms.init('req'); /* go back to request list */
- $inv.rReload();
- }, error: () => {
- alert($t.f1);
- ct.trigger('modal_close');
- }
- });
- }, cancel: function (e) {
- let ct = $(this);
- if (confirm($ict.cdI)) {
- $ocms.postXT({
- url: $ocms.url('rem/del'), data: {
- id: remid
- }
- });
- }
- $inv.rReload();
- }
- });
- }
- });
+ /* Preview + finalise now run through the backend-authoritative session ($inv.rd):
+ the PDF renders straight from the server cache (no rem/prep DB write), and confirm
+ flushes (rem/dsave) then finalises + emails (rem/conf). */
+ $inv.rd.preview();
};
$inv.sis = (id) => {
if (confirm($ict.sisc)) {
diff --git a/Fuchs/wwwroot/web/fis.inv.de.min.js b/Fuchs/wwwroot/web/fis.inv.de.min.js
index dbceaf4..594facd 100644
--- a/Fuchs/wwwroot/web/fis.inv.de.min.js
+++ b/Fuchs/wwwroot/web/fis.inv.de.min.js
@@ -1 +1 @@
-let $rct={mdl:"Aufträge",or:"offene Aufträge",orr:"offene Aufträge (4 W)",rn:"Auftragsnummer",iov:{all:"Auftragsübersicht (alle)","":"Auftragsübersicht"},wk:"Woche",nd:"Keine Daten gefunden.",h:"Uhr",rq1:"Auftragsdaten werden von MFR abgerufen.\nDer Vorgang kann bis zu 90Sek dauern.",rq2:"Auftragsdaten werden geladen",rq1f:"Die Auftragsdaten von MFR konnten nicht oder nicht schnell genug abgerufen werde.\nMöchten Sie mit den bestehenden Daten trotzdem weitermachen?",note1:"Im Bruttobetrag sind {0} Lohnkosten enthalten (netto {1}). Die darin enthaltene Umsatzsteuer beträgt {2}.",note2:"Bitte beachten Sie, nach §14 Abs. 1 Umsatzsteuergesetz ist diese Rechnung ein Zahlungsbeleg oder eine andere beweiskräftige Unterlage für 2 Jahre nach Ablauf des Kalenderjahres der Ausstellung dieser Rechnung aufzubewahren, soweit nicht aufgrund anderer gesetzlicher Regelungen andere ggf.längere Aufbewahrungsfristen gelten.",note3:"Privathaushalten erstattet das Finanzamt bis zu {0} des Arbeitslohns mit der nächsten Steuererklärung.",note4:"Für bereits erbrachte Arbeiten, Dienstleistungen, Materiallieferungen und getätigte Bestellvorgänge zum oben genannten Bauvorhaben, die sich aus dem mit Ihnen geschlossenen Vertrag ergeben, stellen wir Ihnen vertragsgemäß unsere Akontozahlung in Rechnung. Eine Endabrechnung erhalten Sie als Schlussrechnung nach Abschluss des gesamten Bauvorhabens. Das Ausführungsdatum entnehmen Sie bitte dem Schlusstext dieser Rechnung. Wir danken Ihnen herzlich für das entgegengebrachte Vertrauen und bitten Sie um kurzfristigen Ausgleich der Akontorechnung.",note13b:"Gem. §13b Umsatzsteuergesetz unterliegen Sie der Steuerschuldnerschaft des Leistungsempfängers zur Umsatzsteuer aus dieser Rechnung mit einem Steuersatz von 19%.",crI:"Rechnung erstellen",crII:"Abschlagsrechnung erstellen",dII:"Für eine Abschlagsrechnung darf nur ein Auftrag gewählt werden.",dnS:"Für eine Rechnung muss mindestens ein Auftrag gewählt werden.",inv:"Rechnung",invs:"Rechnungen",req:"Auftrag",provP:"Leistungszeitraum",provD:"Leistungsdatum",cP:"Position ändern",iRb:"Zeile darunter einfügen",dR:"Zeile löschen",sV:"USt festlegen",cD:"Löschen?",mR:"Zeile verschieben",svcPart:"Service-Anteil",vat:"Umsatzsteuer",combP:"Positionen zusammenfassen",iSum:"Zwischensumme",dtRel:"Freigegeben am: ",dtCr:"Erstellt am: ",rqV:"USt des Auftrags?",cthd:"wirklich aus-/einblenden ?",cst:{style:"currency",currency:"EUR"},sts:{IsWorkDone:"Arbeiten erledigt",Closed:"Auftrag geschlossen",SubcontractorPendingConfirmation:"Warten auf Bestätigung (Unterauftrag)",Scheduled:"Geplant",OfferIsRejected:"Angebot abgelehnt",OfferIsSend:"Offen (Angebot versandt)",CollaborationWaitingConfirmation:"Warten auf Bestätigung (Zusammenarbeit)",Released:"Freigegeben",OfferIsConfirmed:"Bestätigt",InProgress:"In Bearbeitung",ReadyForScheduling:"Zur Planung",Created:"Erstellt",Rejected:"Abgebrochen",Invoiced:"Rechnung gestellt","-":"-"},invHR:["Pos.","Menge","Artikelbezeichnung","VK","Summe"],frm:{invoiceaddress:"Adresse",loc:"Leistungsort / Lieferadresse",invoiceemail:"Email"}},$rcol={req:new fields_definition("Auftrag","Aufträge",[{name:"tags",label:"",type:"string",dfnc:function(e,t){""!==(e||"")&&($(this).aC("tags"),e.split(",").forEach((e=>{""!==e&&$(this).append($$.sc("tag "+e.replace(" ","_").replace("/","_").toLowerCase(),e))})))}},{name:"DateOfCreation",label:"Datum",type:"date",title:function(e){$(this).attr("title",$rct.dtCr+fdt(e.DateOfCreation).ne("-")+" \n"+$rct.dtRel+fdt(e.DateReleased).ne("-"))}},{name:"CustomerName",label:"Kunde (Firma)",type:"string"},{name:"Name",label:"Auftragsname",type:"string"},{name:"ExternalId",label:"Auftragsnummer",type:"string"},{name:"ParentExtenalId",label:"PAuftrag",type:"string"},{name:"InvoiceId",label:"RNummer",type:"string",dfnc:function(e,t){$(this).rwText(e," ").find("span").each((function(){$(this).aC("cla").click({id:$(this).text()},$inv.jdbn)}))}},{name:"State",label:"Status",type:"string"},{name:"WorkDoneAt",label:"Erledigt am",type:"date"},{name:"Description",label:"Beschreibung",type:"html"}]),itm:new fields_definition("Auftragsposition","Auftragspositionen",[{name:"NameOrNumber",label:"Bezeichnung",type:"string"},{name:"Type",label:"Typ",type:"select",required:!0,value:"Text",url:[{value:"Text",label:"Text"},{value:"Equipment",label:"Ausrüstung"},{value:"Material",label:"Material"},{value:"Service",label:"Arbeitsleistung"}],change:function(e){$req.quantChange.call(this,e)}},{name:"quantityhours",label:"Anzahl / Menge",type:"number",precision:"0.01",value:1,change:function(e){$inv.quantChange.call(this,e)}},{name:"UnitString",label:"Einheit",type:"select",url:["LFDM","Stck","Std.","QM","AW","Pauschal"],change:function(e){$inv.quantChange.call(this,e)}},{name:"net",label:"EinzelPreis netto",type:"number",precision:"0.01",value:0,change:function(e){$inv.quantChange.call(this,e)}},{name:"net_val",label:"GesamtPreis netto",type:"number",precision:"0.01",value:0},{name:"vat_val",label:"GesamtPreis USt",type:"number",precision:"0.01",value:0},{name:"svcnet_val",label:"Arbeitslohn netto",type:"number",precision:"0.01",value:0},{name:"svcvat_val",label:"Arbeitslohn USt",type:"number",precision:"0.01",value:0},{name:"net_pos",label:"Netto",type:"string"},{name:"bo_pos",label:"Brutto",type:"string"},{name:"vat",label:"USt",type:"string",value:"19,0%",change:function(e){$inv.quantChange.call(this,e)}},{name:"Note",label:"Details",type:"html",tinymce:!0}])},$ict={mdl:"Rechnungen",iov:{all:"Rechnungen (alle)","":"Rechnungen (nur fertige)","#d":"Rechnungen (nur Entwürfe)","#u":"Rechnungen (nur unbezahlt)","#r":"Rechnungen (nur angemahnt)","#a":"Rechnungen (nur Akonto)","#c":"Rechnungen (nur Storno)","#ru":"Rechnungen (nur angemahnt + unbez.)"},uba:", gesamter Zeitraum)",req:"Auftrag",inv:"Rechnung",rem:"Mahnung",in:"Rechnungsnummer",cc:"Kunde",wk:"Woche",nd:"Keine Daten gefunden.",dl:"Herunterladen",ed:"Bearbeiten",ced:"Bearbeitung fortsetzen",sItm:"Einzelheiten anzeigen",sPay:"Zahlungen anzeigen",cdI:"Entwurf der Rechnung löschen?",rel:"Neu Laden",relm:"Bitte laden Sie Liste manuell neu, um die Änderungen zu sehen.",dsp:"Rechnung anzeigen",storno:"Storno-Rechnung erstellen",credit:"Gutschrift erstellen",remd:"Mahnung erstellen",remdt:"Mahnung erstellen zur Rechnung {0}",remlst:"Mahnungen anzeigen",remdsp:"Mahnung anzeigen",remres:"Mahnung erneut senden",remresc:"Mahnung {0} wirklich erneut senden?",remresr:"Mahnung {0} wurde erfolgreich versandt.",setpyd:"Bezahlt markieren",cpyd:"Rechnung wirklich als bezahlt markieren?",setupd:"Bezahlt-Markierung aufheben",cupd:"Bezahlt-Markierung wirklich aufheben?",ivE:"Die Email-Adresse ist vermutlich nicht gültig.",ivEc:"\nMöchten Sie fortfahren?",pna:"Diese Seite ist in der Vorschau nicht verfügbar",tpe:"Die Anzahl von {0} Seiten wird aktuell nicht unterstützt",eis:"Der Rechnungsentwurf konnte nicht gespeichert werden.",iss:"Zwischenstand speichern.",p13b:"USt -> §13b",setm:"Set-Preisanzeige",setmo:{setprice:"Set mit Preis – Positionen ohne Preis",itemprices:"Positionen mit Preis – Set als Überschrift",setonly:"Nur Set mit Preis – Positionen ausgeblendet"},ctp:"Ansprechpartner festlegen",mfr:"Von MFR neu abrufen",rq1:"Auftragsdaten werden von MFR abgerufen.\nDer Vorgang kann bis zu 90Sek dauern.",rq2:"Auftragsdaten werden geladen",iq1:"Rechnungsdaten werden von MFR abgerufen.\nDer Vorgang kann bis zu 90Sek dauern.",iq2:"Rechnungsdaten werden geladen",sis:"Rechnung als versandt markieren",srs:"Mahnung als versandt markieren",sisc:"Rechnung wirklich als versandt markieren?",srsc:"Mahnung wirklich als versandt markieren?",iSt:{dft:"Entwurf",uns:"nicht versandt",pyd:"bezahlt",cc:"storniert",op:"offen",due:"fällig",ovd:"überfällig",rem:"angemahnt"},rSt:["","Überfällig","2. Mahnung","3. Stufe"],pSt:{a:"Vollst.",p:"Teilz."},ivT:{i:"AbschlagsR.",f:"SchlussR",r:"Rechnung",c:"StornoR."},rovlh:"Übersicht der bisherigen Mahnungen",rovl:["Betreff","Betrag","Betrag gezahlt","fertiggestellt am"],remHR:["Rechnung","vom","Rechnungsbetrag","bereits bezahlt","noch offen"],remt:{f:["Sehr geehrte Damen und Herren,","ein Mahnschreiben sollte kurz, freundlich und erfolgreich sein. Kurz ist es, freundlich sowieso; ob es auch erfolgreich ist, hängt von Ihnen ab."],m:["Sehr geehrte Damen und Herren,","nun müssen wir Sie noch einmal anschreiben.","Wahrscheinlich haben Sie triftige Gründe dafür, warum Sie die Zahlung unserer Forderung nicht vornehmen und auch nicht auf unsere Mahnung reagieren. Sollten wir darüber nicht einmal sprechen?","Bitte nehmen Sie umgehend in dieser Sache mit uns Kontakt auf."],l:["Sehr geehrte Damen und Herren,",'Eine DRITTE MAHNUNG zu erhalten bereitet Ihnen bestimmt ebenso wenig Freude wie uns, sie zu verschicken. Leider haben wir auf unsere zweite Mahnung noch keine Antwort von Ihnen erhalten.", "Wir bitten Sie, den offenen Betrag innerhalb der nächsten 7 Werktage nach Erhalt dieses Schreibens zu begleichen. Nach Ablauf dieser Frist erfolgt keine weitere Mahnung mehr.',"Sollte die Forderung bis dahin nicht beglichen sein, eröffnen wir das gerichtliche Mahnverfahren. Sollten Sie die Rechnung inzwischen beglichen haben, so betrachten Sie bitte dieses Schreiben als gegenstandslos."]},remt2:{f:["Wir bitten Sie, den noch offenen Rechnungsbetrag innerhalb einer Woche auf unser Konto zu überweisen.","Sollten Sie den Betrag bereits überwiesen haben, so bitten wir Sie, diese Zahlungserinnerung als gegenstandslos zu betrachten."],m:["Um Ihnen zusätzliche Kosten für weitere Mahnungen zu ersparen, bitten wir Sie nunmehr um die Überweisung des noch zu zahlenden Gesamtbetrages inklusive der ggf. bereits fälligen Mahnzinsen und Mahngebühren innerhalb von einer Woche."],l:[]},payi:{account:"Konto",name:"Zahler",text:"Verw.Zweck",InvoiceID:"Rechnung",amount:"Betrag",date:"Datum",manual:"Typ"}},$invcol={datev:new fields_definition("Rechnung","Rechnungen",[{name:"Umsatz (ohne Soll/Haben-Kz)",label:"Umsatz (ohne Soll/Haben-Kz)",type:"string"},{name:"vf",label:"vf",type:"string"},{name:"Soll/Haben-Kennzeichen",label:"Soll/Haben-Kennzeichen",type:"string"},{name:"Konto",label:"Konto",type:"string"},{name:"Gegenkonto",label:"Gegenkonto",type:"string"},{name:"BU-Schlüssel",label:"BU-Schlüssel",type:"string"},{name:"Belegdatum",label:"Belegdatum",type:"string"},{name:"Belegfeld 1",label:"Belegfeld 1",type:"string"},{name:"Belegfeld 2",label:"Belegfeld 2",type:"string"},{name:"Buchungstext",label:"Buchungstext",type:"string"}]),inv:new fields_definition("Rechnung","Rechnungen",[{name:"invstatus",label:"Status",type:"select",url:$ict.iSt},{name:"balance",label:"Umsatz",type:"string",dtype:"currency"},{name:"CustomerName",label:"Kunde",type:"string"},{name:"InvoiceId",label:"RNummer",type:"string"},{name:"InvoiceType",label:"Typ",type:"select",url:$ict.ivT},{name:"request",label:"Auftrag",type:"string",dtype:"num"},{name:"vat",label:"MwSt",type:"string",dtype:"num"},{name:"deb_cred",label:"Soll/Haben",type:"string"},{name:"customer",label:"Konto",type:"string",dtype:"num"},{name:"contra_account",label:"Gegenkonto",type:"string",dtype:"num"},{name:"Belegdatum",label:"Belegdatum",type:"date"},{name:"reminderstatus",label:"MahnStatus",type:"select",url:$ict.rSt},{name:"reminder",label:"# Mahnungen",type:"integer"},{name:"Buchungstext",label:"Buchungstext",type:"string"},{name:"Payment",label:"Zahlung",type:"string"}]),rem:new fields_definition("Zahlungserinnerung","Zahlungserinnerung",[{name:"amount",label:"Rechnungsbetrag",type:"number",precision:"0.01",value:1},{name:"amount_payed",label:"bereits bezahlt",type:"number",precision:"0.01",value:1}]),rem2:new fields_definition("Zahlungserinnerung","Zahlungserinnerung",[{name:"DocumentName",label:"Name",type:"string"},{name:"subject",label:"Betreff",type:"string"},{name:"DateSent",label:"Versanddatum",type:"date"},{name:"status",label:"Status",type:"string"},{name:"amount_open",label:"offener Betrag",type:"number",precision:"0.01"},{name:"InvoiceId",label:"RNummer",type:"string"}]),rid:new fields_definition("Zahlungserinnerung","Zahlungserinnerung",[{name:"type",label:"Typ",type:"select",url:[["f","einfache Zahlungserinnerung"],["m","Mahnung"],["l","letzte Mahnung"]],required:!0},{name:"level",label:"Stufe",type:"select",url:[["1","Stufe 1"],["2","Stufe 2"],["3","Stufe 3"],["4","Stufe 4"],["5","Stufe 5"],["6","Stufe 6"]],required:!0}]),ctp:new fields_definition("Ansprechpartner","Ansprechpartner",[{name:"name",label:"Name",type:"string"},{name:"email",label:"Email",type:"string"}])},gi=(e,t)=>$$.sc("glyphicon glyphicon-"+e).aC(t),$inv={init2:function(e,t){e=e||"inv",t=t||{},$ocms.getScript([],(function(){$inv.init3(e,t)}))},init3:async function(e,t){$fis.cf(!0);let n=$fis.lf(!0);$("#topbar").ocmsmenu([]),$("#activemodule").text($ict.mdl);let i=[(async()=>{await $fis.getAuth("fds_inv")>0&&($inv.prepLst(""),n.aC("fix"))})(),new Promise(((e,t)=>{$fis.prepAuth(["fds_reminder"])}))];await Promise.all(i)},prepLst:function(e){let t=new Date,n=$fis.lf(!0).ldng(1),i=new Date("2021-01-01");$fis.frm_list().IN((function(){}));let a=[];$.each($ict.iov,((e,t)=>{a.push({lbl:t,fnc:()=>{$inv.prepLst(e),n.aC("fix")}})})),$fis.lfm().ocmsmenu([{lbl:"Filter",itm:a}]);$$.i({placeholder:$ict.in}).appendTo($$.dc("mth ivn",n)).enterKey((function(e){let t=$(this),n=t.val()||"";e.stopPropagation(),t.parent().siblings().rC("selected"),n.length>3&&(t.parent().aC("selected"),$inv.renderinv("i:"+n,"s","all"),t.val(""))})),$$.i({placeholder:$ict.cc}).appendTo($$.dc("mth ivc",n)).enterKey((function(e){let t=$(this),n=t.val()||"";e.stopPropagation(),t.parent().siblings().rC("selected"),n.length>=3&&(t.parent().aC("selected"),$inv.renderinv("c:"+n,"s","all"),t.val(""))}));"#"===e.substr(0,1)&&$$.dc("mth extra",n).text($ict.iov[e].replace(")",$ict.uba)).click((function(t){let n=$(this);if(t.stopPropagation(),n.siblings().rC("selected"),!0===n.is(".selected")){n.toggleClass("selected");let t=fdt(new Date,"yy-MM-dd");$inv.renderinv(t,"a",e)}n.aC("selected")})),n.append("
");let r=$$.dc("mthl",n),l=t.getFullYear(),s=t.getMonth()+1;for(let t=i.getFullYear();t<=l;t++){let n=$$.dc("yr").prependTo(r).text($ict.iov[e]+" - "+t.toString()).toggleClass("selected",t===l);n.click({yr:t},(function(e){e.stopPropagation(),n.siblings().rC("selected"),n.aC("selected")}));let a=$$.dc("mfrm",n);for(let n=0;n<(t!==l?12:s);n++){i=new Date(t,n,1);let r=$$.dc("mth").prependTo(a).text($ict.iov[e]+" - "+fdt(i,"MMM yyyy"));if(r.click({yr:t,mt:n},(function(t){if(t.stopPropagation(),r.siblings().rC("selected"),!0===r.is(".selected")){r.toggleClass("selected");let n=fdt(new Date(t.data.yr,t.data.mt,1),"yy-MM-dd");$inv.renderinv(n,"m",e)}r.aC("selected")})),""===e){$$.dc("mthdl",r).append(gi("compressed","ico")).click({yr:t,mt:n},(function(e){e.stopPropagation();let t=fdt(new Date(e.data.yr,e.data.mt,1),"yy-MM-dd");$inv.downloadzip(t,"m")}))}let l=getMonday(i),s=new Date(i);s.setMonth(s.getMonth()+1),s.setDate(0),s=getMonday(s);let d=$$.dc("wfrm",r);for(;l<=s;){let t=$$.dc("wk",d).text(($ict.wk||"W")+" "+fdt(l,"dd.MM.yy"));t.click({rd:new Date(l)},(function(n){n.stopPropagation();let i=fdt(n.data.rd,"yy-MM-dd");$inv.renderinv(i,"w",e),r.siblings().rC("selected").find(".wk").rC("selected"),r.aC("selected").find(".wk").rC("selected"),t.aC("selected")})),$$.dc("wkdl",t).append(gi("compressed","ico")).click({rd:new Date(l)},(function(e){e.stopPropagation();let t=fdt(e.data.rd,"yy-MM-dd");$inv.downloadzip(t,"w")})),l.setDate(l.getDate()+7)}}}n.ldng(0)},rerenderinv:function(){let e=$("#contentframe .invfrm:first");if(e.length>0){let t=e.data("sets")||{};t.mode&&$inv.renderinv(t.tgt,t.mode,t.includes)}},renderinv:function(e,t,n){let i=$fis.frm_list(!0,!0).ldng(1),a=$$.dc("invfrm",i).aC("md"+t).data("sets",$.extend({},{tgt:e,mode:t,includes:n})),r=$fis.lf();$ocms.postXT({url:$ocms.url("inv/invl"),data:{mode:t,tgt:e,includes:n},success:i=>{r.rC("fix").aC("hd"),$$.dc("ovhd",a).text(i.admin.title);let l=$$.tblset({},a),s=$invcol.inv,d=$$.tr(l.hd);$$.th(d);$.each(s.fields||[],((e,t)=>{$$.th(d).text(t.label),"vat"===t.name&&$$.th(d)})),$.each(i.invoices||[],((d,c)=>{let o=$$.tr(l.bdy);o.click((function(){r.rC("fix").aC("hd"),o.toggleClass("selected").siblings().rC("selected").find("td.av").rC("av"),o.find("td.av").rC("av"),!0===o.is(".selected")?$inv.iMn(c):$inv.eM()}));let u=$$.td(o,{class:"raux"});c.hasFile?($$.dc("idl ilbtn",u,{title:$ict.dl+"\n"+c.DocumentName}).append(gi("save-file","ico")).click({id:c.Id},$inv.downloadinv),$$.dc("idl ilbtn",u,{title:$ict.dsp+"\n"+c.DocumentName}).append(gi("eye-open","ico")).click({id:c.Id,typ:"inv"},$inv.jdisp)):!1===c.isFinal&&!0===$fis.isAuth("fds_inv",2)&&$$.dc("idl ilbtn",u,{title:$ict.ed}).append(gi("edit","ico")).click({id:c.Id},$inv.doContInv),$$.dc("iitm ilbtn",u,{title:$ict.sItm}).append(gi("list","ico")).click({id:c.Id},$inv.showitm),$$.dc("iitm ilbtn",u,{title:$ict.sPay}).append(gi("euro","ico")).click({id:c.Id},$inv.showpay),$.each(s.fields||[],((r,l)=>{let s,d,u=$$.td(o).aC(l.dtype);switch("select"===(l.type||"")?u.text((l.url||{})[c[l.name]]||""):u.text(c[l.name]),l.name||""){case"vat":s=$$.sel().appendTo($$.td(o,{class:"vsel"})),d=(i.admin.ust_options||"19,0%;16,0%;0,0%").split(";"),$.each(d,((e,t)=>{$$.opt(t,t).appendTo(s)})),s.click((function(e){e.stopPropagation()})).val(c[l.name]).change().change({frm:a,tgt:e,mode:t,id:c.Id,td:u,includes:n},$inv.setvat),u.toggleClass("hl",c[l.name].substr(0,2)!==d[0].substr(0,2)).click((function(e){e.stopPropagation(),$(this).toggleClass("av")}));break;case"balance":u.aC("sh_"+(c.SollHaben||"").toLowerCase());break;case"invstatus":case"reminderstatus":u.aC(("invstatus"===l.name?"is_":"rs_")+c[l.name])}}))}))},complete:()=>{i.ldng(0)}})},setvat:function(e){let t=$(this),n=e.data||{};$ocms.postXT({url:$ocms.url("inv/setvat"),data:{id:n.id,val:t.val()},success:e=>{n.td.rC("av"),$inv.renderinv(n.tgt,n.mode,n.includes)}})},downloadzip:function(e,t){$(this).empty();window.open($ocms.url("inv/datevzip?mode="+t+"&tgt="+encodeURIComponent(e)),"_blank")},showitm:function(e){let t=$(this).closest("tr");e.stopPropagation(),!1!==t.is(".selected")&&$ocms.postXT({url:$ocms.url("inv/rqi"),data:{id:e.data.id},success:e=>{let t=$$.dc("rfrm");(e.requests||[]).length<1?t.text($ict.nd):$.each(e.requests||[],(function(e,n){let i=$$.dc("srq",t);$$.dc("nme",i).text(n.name);let a=$$.tblset({class:"if"},i);$.each(n.items||[],((e,t)=>{let n=$$.tr({id:"itm"+t.Id}).appendTo(a.bdy);$$.td(n).text(t.NameOrNumber),$$.td(n).text(t.Type),$$.td(n).aC("currency").text(t.net_pos),$$.td(n).aC("currency").text(t.bo_pos),$$.td(n).aC("num").text(t.vat)}))})),$ocms.dlg(t,{width:1e3})}})},showpay:function(e){let t=$(this).closest("tr");e.stopPropagation(),!1!==t.is(".selected")&&$ocms.postXT({url:$ocms.url("inv/pyi"),data:{id:e.data.id},success:e=>{let t=$$.dc("rfrm");if((e.payments||[]).length<1)t.text($ict.nd);else{let n=$$.tblset({class:"if"},t),i=$$.tr(n.hd);$.each(["date","account","name","text","InvoiceID","amount","manual"],((e,t)=>{$$.th(i,$ict.payi[t])})),$.each(e.payments,((e,t)=>{let i=$$.tr({id:"itm"+t.banking_uid}).appendTo(n.bdy);$$.td(i).aC("date").text(t.date),$$.td(i).text(t.account),$$.td(i).text(t.name),$$.td(i).text(t.text),$$.td(i).text(t.InvoiceID),$$.td(i).aC("currency").text(t.amount),$$.td(i).text(t.manual)}))}$ocms.dlg(t,{width:1e3,title:"Übersicht der Zahlungen"})}})},downloadinv:function(e){let t=$(this).closest("tr");e.stopPropagation(),!1!==t.is(".selected")&&window.open($ocms.url("inv/rdoc?id="+e.data.id),"_blank")},doContInv:function(e){let t=$(this).closest("tr");e.stopPropagation(),!1!==t.is(".selected")&&$inv.cntInv({id:e.data.id})}},$$inv={init2:$inv.init2,auth:{}};export default $$inv;$inv.cInv=function(e){let t=$(this).closest("tr");e.stopPropagation(),!1!==t.is(".selected")&&!1!==$fis.isAuth("fds_inv",2)&&$inv.cInv2({id:e.data.id})},$inv.rMn=e=>{let t=[{lbl:$ict.req,itm:[]}];return!0===bool(e,!1)&&!0===$fis.isAuth("fds_inv",2)&&Array.prototype.push.apply(t[0].itm,[{lbl:$rct.crI,fnc:$inv.ccInv,data:{typ:"r"}},{lbl:$rct.crII,fnc:$inv.ccInv,data:{typ:"i"}}]),t.push({lbl:$ict.rel,fnc:$inv.rReload}),$("#topbar").ocmsmenu(t)},$inv.iMnr=e=>{let t=booln(e.isFinal,!0),n=e.Id,i=booln(e.fds,!1),a=[{glyph:"glyphicon-menu-left",fnc:()=>{$fis.frm_edit().remove()}},{lbl:$ict.inv,itm:[]},{lbl:$ict.rem,itm:[]}];return!1===t&&!0===$fis.isAuth("fds_inv",2)?a[1].itm.push({lbl:$ict.ced,fnc:$inv.clCntInv}):!0===$fis.isAuth("fds_inv",1)&&a[1].itm.push({lbl:$ict.dsp,fnc:()=>$inv.disp(n,"inv")}),!0===i&&!0===t&&!0===$fis.isAuth("fds_inv",2)&&(a[1].itm.push({lbl:$ict.storno,fnc:()=>$inv.storno(n,i)}),a[1].itm.push({lbl:$ict.credit,fnc:()=>$inv.credit(n,i)})),!0===t&&!0===$fis.isAuth("fds_reminder",2)&&(a[2].itm.push({lbl:$ict.remd,fnc:()=>$inv.ccRem(n,e.InvoiceId)}),a[2].itm.push({lbl:$ict.remlst,fnc:()=>$inv.dspRem(n)})),!0===t&&!0===$fis.isAuth("fds_reminder",2)&&!1===booln(e.IsSent,!1)&&a[2].itm.push({lbl:$ict.srs,fnc:()=>$inv.srs(n)}),a.push({lbl:$ict.rel,fnc:$inv.rReload}),$("#topbar").ocmsmenu(a)},$inv.iMn=e=>{let t=booln(e.isFinal,!0),n=e.Id,i=booln(e.fds,!1),a=[{glyph:"glyphicon-menu-left",fnc:()=>{$fis.frm_edit().remove()}},{lbl:$ict.inv,itm:[]},{lbl:$ict.rem,itm:[]}];return!1===t&&!0===$fis.isAuth("fds_inv",2)?a[1].itm.push({lbl:$ict.ced,fnc:()=>{$inv.cntInv({id:n})}}):!0===$fis.isAuth("fds_inv",1)&&a[1].itm.push({lbl:$ict.dsp,fnc:()=>$inv.disp(n,"inv")}),!0===$fis.isAuth("fds_inv",2)&&(a[1].itm.push({lbl:$ict.storno,fnc:()=>$inv.storno(n,i)}),a[1].itm.push({lbl:$ict.credit,fnc:()=>$inv.credit(n,i)})),!0===t&&!1===booln(e.IsPayed,!1)?(!0===$fis.isAuth("fds_reminder",2)&&a[2].itm.push({lbl:$ict.remd,fnc:()=>$inv.ccRem(n,e.InvoiceId)}),!0===$fis.isAuth("fds_inv",2)&&a[1].itm.push({lbl:$ict.setpyd,fnc:()=>$inv.setPyd(n)})):!0===t&&!0===booln(e.IsPayed,!1)&&"m"===(e.PaymentStatus||"")&&!0===$fis.isAuth("fds_inv",2)&&a[1].itm.push({lbl:$ict.setupd,fnc:()=>$inv.setUpd(n)}),!0===$fis.isAuth("fds_reminder",2)&&a[2].itm.push({lbl:$ict.remlst,fnc:()=>$inv.dspRem(n)}),!0===t&&!0===$fis.isAuth("fds_inv",2)&&!1===booln(e.IsSent,!1)&&a[1].itm.push({lbl:$ict.sis,fnc:()=>$inv.sis(n)}),!1===i&&a[1].itm.push({lbl:$ict.mfr,fnc:()=>$inv.mfrrel(n)}),$("#topbar").ocmsmenu(a)},$inv.eM=(e,t,n)=>{let i=[];return!0!==booln(e,!1)&&!0!==booln(t,!1)||i.push({glyph:"glyphicon-menu-left",fnc:()=>{$fis.lf(!0),$fis.frm_edit().remove()}}),!0===(n||"").split(",").includes("iss")&&i.push({lbl:$ict.iss,fnc:$inv.ssave}),!0===(n||"").split(",").includes("ctp")&&i.push({lbl:$ict.ctp,fnc:$inv.sctp}),!0===(n||"").split(",").includes("p13b")&&i.push({lbl:$ict.p13b,fnc:$inv.sp13b}),!0===(n||"").split(",").includes("setm")&&i.push({lbl:$ict.setm,fnc:$inv.ssetmode}),!0===(n||"").split(",").includes("iss")&&(i.push({lbl:"Änderungshistorie",fnc:()=>$inv.d.history()}),i.push({lbl:"Änderungen verwerfen",fnc:()=>$inv.d.discard()})),!0===booln(e,!1)&&i.push({lbl:$ict.rel,fnc:$inv.rReload}),$("#topbar").ocmsmenu(i)},$inv.d={tbl:()=>$("div.invoice_layout table.invi"),layout:()=>$("div.invoice_layout"),token:function(){return $inv.d.tbl().data("dtoken")||""},hashes:function(){let e=$inv.d.tbl().data("bai")||[],t={};return $.each(e,((e,n)=>{t[(n.Id||"").toString()]=JSON.stringify(n)})),t},seed:function(e){let t=$inv.d.layout();t.aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dopen"),data:{payload:JSON.stringify(e)},success:e=>{$inv.d.tbl().data("dtoken",e.token).data("dver",e.version).data("dhashes",$inv.d.hashes()).data("dorder",$inv.d.order()),$fis.draft.bind(e.token,{onReady:()=>$inv.d.refresh(),onExpiring:e=>$inv.d.warnExpiry(e),onClosed:e=>$inv.d.closed(e)}),$inv.d.refresh()},error:()=>{t.rC("freeze")},complete:()=>{$inv.d.tbl().removeData("dseeding")}})},refresh:function(e){let t=$inv.d.token();""!==t&&$ocms.postXT({url:$ocms.url("inv/dstate"),data:{token:t},success:t=>{$inv.d.applyState(t),"function"==typeof e&&e(t)},error:e=>{e&&410===e.status&&$inv.d.closed("expired")},complete:()=>{$inv.d.layout().rC("freeze")}})},applyState:function(e){let t=$inv.d.tbl();t.length<1||(t.data("dver",e.version).data("serverSums",e.sums),$inv.d.footer(t,e.sums||{},e.admin||{}),$inv.d.validation(e.validation||[]),$inv.d.applyPositions(t,e.req||[]))},applyPositions:function(e,t){(t||[]).forEach((t=>(t&&t.itm||[]).forEach((t=>{if(!t||""===(t.id||""))return;let n=e.find("#itm"+t.id+" td.keep").first();n.length&&n.text(null!=t.p?t.p:"")}))))},sync:function(e){let t=$inv.d.token();""!==t&&($inv.d.layout().aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dpatch"),data:{token:t,delta:JSON.stringify(e)},success:()=>{$inv.d.refresh()},error:e=>{$inv.d.layout().rC("freeze"),e&&410===e.status&&$inv.d.closed("expired")}}))},order:function(){return($inv.d.tbl().data("bai")||[]).map((e=>(e.Id||"").toString()))},syncChanged:function(e){if(""===$inv.d.token())return;let t=e.data("bai")||[],n=e.data("dhashes")||{},i={},a=[],r=[];$.each(t,((e,t)=>{let r=(t.Id||"").toString(),l=JSON.stringify(t);i[r]=l,n[r]!==l&&a.push(t)})),$.each(n,(e=>{void 0===i[e]&&r.push(e)}));let l=$inv.d.order(),s=e.data("dorder")||[];e.data("dhashes",i).data("dorder",l),a.forEach((e=>$inv.d.sync({Target:"block.replace",Ref:(e.Id||"").toString(),Value:e}))),r.forEach((e=>$inv.d.sync({Target:"block.remove",Ref:e}))),s.length===l.length&&s.slice().sort().join(",")===l.slice().sort().join(",")&&s.join(",")!==l.join(",")&&$inv.d.sync({Target:"block.order",Value:l})},syncField:function(e,t){if(""===$inv.d.token())return;let n={invoicetitle:"title",invoiceaddress:"address",invoiceemail:"email",loc:"provisionlocation",provisionlocation:"provisionlocation",provisionperiod:"provisionperiod"}[e];n&&$inv.d.sync({Target:n,Value:t})},footer:function(e,t,n){let i=e.children("tfoot").empty();e.nextAll(".fnote").remove();let a=bool(n.p13b,!1),r=(e,t,n)=>$$.tdc("currency",$$.tr(i,{class:n||"tsum"}).append([$$.tdc("aux"),$$.td({colspan:4}).text(e)]),fnum(t,$rct.cst)),l=t=>$$.dc("fnote").insertAfter(e).rwText(t);r("Netto",t.total_net||0),!1===a&&$.each(t.vat||{},((e,t)=>r($rct.vat+" "+e+"%",t,"tvat"))),r("Summe",t.total_gross||0);let s=n.type||"";"i"===s?(l($rct.note2),l($rct.note4)):"c"===s?l($rct.note2):(l(string($rct.note3,[fnum(((t.service_net||0)+(t.service_vat||0))*(n.tax_servicerefund||0),$rct.cst)])).aC("ntax"),l($rct.note2),l(string($rct.note1,[fnum((t.service_net||0)+(t.service_vat||0),$rct.cst),fnum(t.service_net||0,$rct.cst),fnum(t.service_vat||0,$rct.cst)]))),!0===a&&l($rct.note13b)},validation:function(e){let t=$("div.invoice_layout");if(t.length<1)return;let n=t.children(".dvalidation");n.length<1&&(n=$$.dc("dvalidation"),t.prepend(n)),n.empty().tC("hidden",(e||[]).length<1),$.each(e||[],((e,t)=>$$.dc("dvmsg",n).aC(t.severity).text(t.message)))},preview:function(){let e=$inv.d.token();if(""===e)return;let t=$inv.d.layout(),n=($inv.d.tbl().data("new")||{}).invoiceemail||"";!1===$fis.ValidateEmail(n)&&!1===bool(confirm($ict.ivE+$ict.ivEc),!1)||(t.aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dpreview"),data:{token:e},success:n=>{t.rC("freeze");let i=$$.dc("imagecollection pdfpreview"),a=Math.round(.88*vh()),r=n.total;r>10&&$$.dc("note warn",i).text($ict.tpe),$.each(n.img||[],((e,t)=>{$$.dc("pdfp",i).append($$.img(t).css("max-height",(a-rpx(6)).toString()+"px"))}));for(let e=(n.img||[]).length+1;e<=r;e++)$$.dc("pdfp ph",i).append($$.dc("note",$ict.pna));$ocms.dlg(i,{size:[a,Math.round(.88*vw())],zindex:50,form:!1,button:$rct.crI,confirm:function(n){let i=$(this);t.aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dsave"),data:{token:e},success:e=>{$ocms.postXT({url:$ocms.url("req/sconf"),data:{id:e.invid},success:t=>{i.trigger("modal_close"),!0===t.hasFile&&window.open($ocms.url("req/idoc")+"?id="+e.invid,"_blank"),$inv.d.close(),$ocms.init("req"),$inv.rReload()},error:()=>{alert($t.f1),i.trigger("modal_close")},complete:()=>{t.rC("freeze")}})},error:()=>{t.rC("freeze"),alert($ict.eis)}})},cancel:function(e){confirm($ict.cdI)&&($inv.d.close(),$inv.rReload())}})},error:()=>{t.rC("freeze"),alert($ict.eis)}}))},save:function(){let e=$inv.d.token();if(""===e)return;let t=$inv.d.layout();t.aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dsave"),data:{token:e},success:e=>{$inv.d.tbl().data("invid",e.invid)},error:()=>{alert($ict.eis)},complete:()=>{t.rC("freeze")}})},history:function(){let e=$inv.d.token();""!==e&&$ocms.postXT({url:$ocms.url("inv/dhistory"),data:{token:e},success:e=>{let t=$$.dc("dhist");if((e.history||[]).length<1)$$.dc("note",t).text("Noch keine Änderungen erfasst.");else{let n=$$.tblset({class:"invtbl fullwidth"},t);$$.tr(n.hd).append([$$.th().text("Zeit"),$$.th().text("Feld"),$$.th().text("Alt"),$$.th().text("Neu")]),$.each(e.history,((e,t)=>$$.tr(n.bdy).append([$$.tdc("keep",fdt(t.timestamp)),$$.td().text(t.target),$$.td().text(t.oldValue),$$.td().text(t.newValue)])))}$ocms.dlg(t,{width:800,form:!1})}})},discard:function(){let e=$inv.d.tbl().data("invid")||"";""!==e?!1!==confirm("Alle Änderungen verwerfen und den zuletzt gespeicherten Stand neu laden?")&&($inv.d.close(),$inv.cntInv({id:e})):alert("Es wurde noch kein Zwischenstand gespeichert, der wiederhergestellt werden könnte.")},warnExpiry:function(e){let t=Math.max(1,Math.round((e||0)/60));$fis.notifications.push({severity:"info",title:"Entwurf läuft ab",message:"Der Rechnungsentwurf läuft in etwa "+t+" Minute(n) ab. Bitte zwischenspeichern, sonst gehen die Änderungen verloren."})},closed:function(e){let t=$inv.d.token();$inv.d.tbl().removeData("dtoken"),""!==t&&$fis.draft.release(t),$fis.frm_edit().remove(),$fis.lf(!0),$fis.notifications.push({severity:"error",title:"Entwurf geschlossen",message:"expired"===e?"Der Rechnungsentwurf ist wegen Inaktivität abgelaufen. Nicht gespeicherte Änderungen sind verloren.":"Der Rechnungsentwurf wurde geschlossen."});try{$inv.rReload()}catch(e){}},close:function(){let e=$inv.d.token();""!==e&&($ocms.postXT({url:$ocms.url("inv/dclose"),data:{token:e}}),$fis.draft.release(e)),$inv.d.tbl().removeData("dtoken")}},$inv.cInv2=function(e){let t=$$.dc("rfrm").ldng(1),n=$ocms.dlg(t,{width:1e3});n&&n.ft.rwText($rct.rq1);let i=()=>{$ocms.postXT({url:$ocms.url("req/get"),timeout:60,data:{id:e.id,mode:"r"},success:t=>{t.admin=t.admin||{};let n=$fis.lf(!0).aC("fix").rC("hd");if($fis.frm_edit().IN(),$inv.eM(!0,!0),(t.requests||[]).length<1)n.aC("fix").text($rct.nd);else{$$.dc("lh",n,$rct.mdl);let i=$$.d(),a=$$.ul({class:"rql"}).data({search:e.id,parent:t.admin.parent}).appendTo(n),r={},l=$rcol.req.lbl();$.each(t.requests||[],(function(e,t){let n=$$.li({class:"cli rli"}).data($.extend({},t)).appendTo(a),s=$$.dc("lihd",n).addClass(t.state);!0===booln(t.open,!1)&&s.append($$.sc("cbox").click((()=>{n.tC("checked"),i.find("li").rC("checked"),!0===n.is(".checked")?$inv.rMn(t.open):$inv.eM(!0)}))),s.append([$$.sc("eid",t.ExternalId),$$.sc("nme",t.Name)]),$$.dc("lidt",n).append([$$.dc("rqs").append([$$.s(l.State+": "),$$.s($rct.sts[t.State||"-"])]),$$.dc("ivn").append([$$.s(l.InvoiceId+": "),$$.s(t.InvoiceId||"- -")]),$$.dc("wda").append([$$.s(l.WorkDoneAt+": "),$$.s(fdt(t.WorkDoneAt,"dd.MM.yyyy"))])]),r[t.Id]=n})),(t.inv||[]).length>0&&($$.dc("lh",n,$rct.invs),i=$$.ul({class:"ivl"}).appendTo(n),$.each(t.inv||[],((e,t)=>{let n=$$.li({class:"cli ili"}).data($.extend({},t)).appendTo(i),r=$$.dc("lihd",n).addClass(t.invstatus);!1===booln(t.isFinal,!0)?r.append($$.sc("cbox").click((()=>{""!==(t.Id||"")&&(n.tC("checked").siblings().rC("checked"),a.find("li").rC("checked"),!0===n.is(".checked")?$inv.iMnr(t):$inv.eM(!0))}))):["","dft"].indexOf(t.invstatus)<0&&r.append($$.sc("dli").click((function(){$inv.disp(t.Id,"inv")}))),r.append($$.sc("nme",t.DocumentName||t.Id)),$$.dc("lidt",n).append([$$.dc("wda").append([$$.s(fdt(t.DateCreated,"dd.MM.yyyy"))]),$$.d().text($ict.iSt[t.invstatus]||t.invstatus)])})))}},complete:()=>{n&&n.c.trigger("modal_close")}})};$ocms.postXT({url:$ocms.url("req/pget"),timeout:90,data:{id:e.id},success:e=>{n&&n.ft.rwText($rct.rq2),i()},error:()=>{confirm($rct.rq1f)?(n&&n.ft.rwText($rct.rq2),i()):n&&n.c.trigger("modal_close")}})},$inv.ccInv=function(e){let t=(e.data||{}).typ||"r",n=$fis.lf(),i=n.children("ul.rql"),a=i.data("parent"),r=[];if(i.find("li.rli.checked").each((function(){r.push($(this).data("Id"))})),r.length<1)return void alert($rct.dnS);if("i"===t&&r.length>1)return void alert($rct.dII);let l=$fis.frm_edit(),s=$$.dc("invoice_layout",l).append($$.dc("btn sprev").click($inv.sprev)),d=$fis.cf().width()>s.width()+n.width()+20;n.tC("fix",d).tC("hd",!d),$inv.eM(!1,!0);let c=$$.dc("rfrm").ldng(1),o=$ocms.dlg(c,{width:1e3});o.ft.rwText($rct.rq2),$ocms.postXT({url:$ocms.url("req/iget"),timeout:60,data:{id:a,mode:"ful",typ:t,sel:r.join(",")},success:e=>{let t=$$.dc("srq",s),n=$$.tblset({class:"invi"},t);n.bdy.remove(),n.ft=$$[0]("tfoot"),e.admin=e.admin||{},e.admin.p13b=bool(e.admin.p13b||"",!0===((e.inv||{}).InvoiceOptions||"").split(",").includes("§13b")),n.tbl.data($.extend({new:{},sms:{},itm:{}},{admin:e.admin,companies:e.companies,locations:e.locations}));let i=$$.tr(n.hd).aC("shd").append([$$.th().aC("aux")]);$rct.invHR.forEach((e=>$$.th(i,e))),n.tbl.on("fds.inv",$inv.invSumUpdate),$.each(e.requests||[],(function(t,i){if(0!==(i.Id||0)){let t=$inv.worknotes(i);i.text="i"===e.admin.type?$rct.req+jine([i.ExternalId,i.Name],": ").eine(" ",""):jine([jine([fdt(i.WorkDoneAt,"dd.MM.yy"),i.ExternalId]," - "+$rct.req+" "),t.ne(i.Name)],": \n");let a=$$.tbody(n.tbl).data($.extend({},i));$inv.rendersrq.call(a)}}));let a=$$.tr($$.tbody(n.tbl),{class:"placeholder"}).data({net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0});$inv.rrw.call(a),n.ft.appendTo(n.tbl);let r,l,d=e.admin||{},c=(e,t,i,a,r)=>{let l=$$.dc("inpfrm",s).aC(e).append("string"==typeof a?$$.dc("ahd",a):a>0?$$.dc("ahd",$rct.frm[i]):null),d=$$.dc("content",l).rwText(t);$$.dc("axf",l).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:d,nme:i,change:e=>{n.tbl.data("new")[i]=e}},r),$inv.eHtml)),n.tbl.data("new")[i]=t};c("tfrm",d.invoicetitle,"invoicetitle",0,null),c("adrfrm",d.invoiceaddress,"invoiceaddress",0,null),c("locfrm","","loc",1,{list:deepCopy(e.locations),lbl:"ref",property:"address"}),c("emailfrm",d.invoiceemail,"invoiceemail",0,null),$$.dc("sndfrm",s).append($$.dc("content").text(d.sender)),d.provisionend&&(l=d.provisionstart?$rct.provP:$rct.provD,r=d.provisionstart?fdt(d.provisionstart,"dd.MM.yyyy")+" - "+fdt(d.provisionend,"dd.MM.yyyy"):fdt(d.provisionend,"dd.MM.yyyy")),c("admfrm",r,"provisionperiod",l,1),n.tbl.data("new").CustomValues=d.CustomValues||"",$$.dc("inpfrm ctpfrm",s).text(jObj(d.CustomValues,"contactName")),n.tbl.children("tbody").each($inv.bdysort),n.tbl.trigger("fds.inv"),$inv.eM(!1,!0,"iss,p13b,setm,ctp")},complete:()=>{o.c.trigger("modal_close")}})},$inv.ccStInv=function(e){let t=e.data||{},n=$fis.lf(),i=t.id,a=$$.dc("invoice_layout",$fis.frm_edit()).append($$.dc("btn sprev").click($inv.sprev)),r=$fis.cf().width()>a.width()+n.width()+20;n.tC("fix",r).tC("hd",!r),$inv.eM(!1,!0);let l=$$.dc("rfrm").ldng(1),s=$ocms.dlg(l,{width:1e3});s.ft.rwText($ict.iq1),$ocms.postXT({url:$ocms.url("inv/pget"),timeout:90,data:{id:t.id},success:e=>{s&&s.ft.rwText($ict.iq2),$ocms.postXT({url:$ocms.url("inv/icget"),timeout:60,data:{id:i},success:e=>{let t=$$.dc("srq",a),n=$$.tblset({class:"invi"},t);n.bdy.remove(),n.ft=$$[0]("tfoot"),e.admin=e.admin||{},e.admin.p13b=bool(e.admin.p13b||"",!0===((e.inv||{}).InvoiceOptions||"").split(",").includes("§13b")),n.tbl.data($.extend({new:{},sms:{},itm:{}},{admin:e.admin,companies:e.companies,locations:e.locations}));let i=$$.tr(n.hd).aC("shd").append([$$.th().aC("aux")]);$rct.invHR.forEach((e=>$$.th(i,e))),n.tbl.on("fds.inv",$inv.invSumUpdate),$.each(e.requests||[],(function(t,i){if(0!==(i.Id||0)){let t=$inv.worknotes(i);i.text="i"===e.admin.type?$rct.req+jine([i.ExternalId,i.Name],": ").eine(" ",""):jine([fdt(i.WorkDoneAt,"dd.MM.yy")+t.ne(i.Name)],": ");let a=$$.tbody(n.tbl).data($.extend({},i));$inv.rendersrq.call(a)}}));let r=$$.tr($$.tbody(n.tbl),{class:"placeholder"}).data({net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0});$inv.rrw.call(r),n.ft.appendTo(n.tbl);let l,s,d=e.admin||{},c=(e,t,i,r,l)=>{let s=$$.dc("inpfrm",a).aC(e).append("string"==typeof r?$$.dc("ahd",r):r>0?$$.dc("ahd",$rct.frm[i]):null),d=$$.dc("content",s).rwText(t);$$.dc("axf",s).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:d,nme:i,change:e=>{n.tbl.data("new")[i]=e}},l),$inv.eHtml)),n.tbl.data("new")[i]=t};c("tfrm",d.invoicetitle,"invoicetitle",0,null),c("adrfrm",d.invoiceaddress,"invoiceaddress",0,null),c("locfrm",d.provisionlocation,"loc",1,{list:deepCopy(e.locations),lbl:"ref",property:"address"}),c("emailfrm",d.invoiceemail,"invoiceemail",0,null),$$.dc("sndfrm",a).append($$.dc("content").text(d.sender)),d.provisionend&&(s=d.provisionstart?$rct.provP:$rct.provD,l=d.provisionstart?fdt(d.provisionstart,"dd.MM.yyyy")+" - "+fdt(d.provisionend,"dd.MM.yyyy"):fdt(d.provisionend,"dd.MM.yyyy")),c("admfrm",l,"provisionperiod",s,1),n.tbl.data("new").CustomValues=d.CustomValues||"",$$.dc("inpfrm ctpfrm",a).text(jObj(d.CustomValues,"contactName")),n.tbl.children("tbody").each($inv.bdysort),n.tbl.trigger("fds.inv")},complete:()=>{s.c.trigger("modal_close")}})},error:()=>{s&&s.c.trigger("modal_close")}})},$inv.clCntInv=function(e){let t=$fis.lf(!1),n=[];t.find("li.ili.checked").each((function(){n.push($(this).data("Id"))})),1===n.length&&$inv.cntInv({id:n[0]})},$inv.cntInv=function(e){e=e||{};$fis.lf(!1).rC("fix").aC("hd");let t=$$.dc("invoice_layout",$fis.frm_edit()).append($$.dc("btn sprev").click($inv.sedit));$inv.eM(!1,!0);let n=$$.dc("rfrm").ldng(1),i=$ocms.dlg(n,{width:1e3});i.ft.rwText($rct.rq2),$ocms.postXT({url:$ocms.url("inv/get"),timeout:60,data:{id:e.id},success:e=>{e.admin=e.admin||{};let n=e.inv||{},i=$$.dc("srq",t),a=$$.tblset({class:"invi"},i);a.bdy.remove(),a.ft=$$[0]("tfoot"),a.tbl.data($.extend({invid:n.Id,new:{},sms:{},itm:{},bai:[]},e));let r=$$.tr(a.hd).aC("shd").append([$$.th().aC("aux")]);$rct.invHR.forEach((e=>$$.th(r,e))),a.tbl.on("fds.inv",$inv.invSumUpdate),$.each(e.req||[],(function(e,t){let n=$$.tbody(a.tbl).data($.extend({},t));$inv.rendersrq.call(n)}));let l=$$.tr($$.tbody(a.tbl),{class:"placeholder"}).data({net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0});$inv.rrw.call(l),a.ft.appendTo(a.tbl);let s=(e,n,i,r,l)=>{let s=$$.dc("inpfrm",t).aC(e).append("string"==typeof r?$$.dc("ahd",r):r>0?$$.dc("ahd",$rct.frm[i]):null),d=$$.dc("content",s).rwText(n);$$.dc("axf",s).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:d,nme:i,change:e=>{a.tbl.data("new")[i]=e}},l),$inv.eHtml)),a.tbl.data("new")[i]=n};s("tfrm",n.InvoiceTitle,"invoicetitle",0,null),s("adrfrm",n.SendToAddress,"invoiceaddress",0,null),s("locfrm",n.ProvisionLocation,"loc",1,null),s("emailfrm",n.SendToEmail,"invoiceemail",0,null),$$.dc("sndfrm",t).append($$.dc("content").text(e.admin.sender)),s("admfrm",n.ProvisionPeriod,"provisionperiod",!0===(n.ProvisionPeriod||"").includes("-")?$rct.provP:$rct.provD,1),a.tbl.data("new").CustomValues=n.CustomValues||"",$$.dc("inpfrm ctpfrm",t).text(jObj(n.CustomValues,"contactName")),a.tbl.children("tbody").each($inv.bdysort),a.tbl.trigger("fds.inv"),$inv.eM(!1,!0,"iss,p13b,setm,ctp")},complete:()=>{i.c.trigger("modal_close")}})},$inv.cSt=function(e){e=e||{};let t=$fis.lf(),n=$$.dc("invoice_layout",$fis.frm_edit()).append($$.dc("btn sprev").click($inv.sedit)),i=$fis.cf().width()>n.width()+t.width()+20;t.tC("fix",i).tC("hd",!i),$inv.eM(!1,!0);let a=$$.dc("rfrm").ldng(1),r=$ocms.dlg(a,{width:1e3});r.ft.rwText($ict.iq1),$ocms.postXT({url:$ocms.url("inv/pget"),data:{id:e.id},success:t=>{r&&r.ft.rwText($ict.iq2),$ocms.postXT({url:$ocms.url("inv/storno"),data:{id:e.id,mode:e.mode},success:e=>{e.admin=e.admin||{},e.admin.p13b=bool(e.admin.p13b||"",!0===((e.inv||{}).InvoiceOptions||"").split(",").includes("§13b"));let t=e.inv||{},i=$$.dc("srq",n),a=$$.tblset({class:"invi"},i);a.bdy.remove(),a.ft=$$[0]("tfoot"),a.tbl.data($.extend({invid:t.Id,new:{},sms:{},itm:{},bai:[]},e));let r=$$.tr(a.hd).aC("shd").append([$$.th().aC("aux")]);$rct.invHR.forEach((e=>$$.th(r,e))),a.tbl.on("fds.inv",$inv.invSumUpdate),$.each(e.req||[],(function(e,t){let n=$$.tbody(a.tbl).data($.extend({},t));$inv.rendersrq.call(n)}));let l=$$.tr($$.tbody(a.tbl),{class:"placeholder"}).data({net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0});$inv.rrw.call(l),a.ft.appendTo(a.tbl);let s=(e,t,i,r,l)=>{let s=$$.dc("inpfrm",n).aC(e).append("string"==typeof r?$$.dc("ahd",r):r>0?$$.dc("ahd",$rct.frm[i]):null),d=$$.dc("content",s).rwText(t);$$.dc("axf",s).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:d,nme:i,change:e=>{a.tbl.data("new")[i]=e}},l),$inv.eHtml)),a.tbl.data("new")[i]=t};s("tfrm",t.InvoiceTitle,"invoicetitle",0,null),s("adrfrm",t.SendToAddress,"invoiceaddress",0,null),s("locfrm",t.ProvisionLocation,"loc",1,null),s("emailfrm",t.SendToEmail,"invoiceemail",0,null),$$.dc("sndfrm",n).append($$.dc("content").text(e.admin.sender)),s("admfrm",t.ProvisionPeriod,"provisionperiod",!0===(t.ProvisionPeriod||"").includes("-")?$rct.provP:$rct.provD,1),a.tbl.data("new").CustomValues=t.CustomValues||"",$$.dc("inpfrm ctpfrm",n).text(jObj(t.CustomValues,"contactName")),a.tbl.children("tbody").each($inv.bdysort),a.tbl.trigger("fds.inv")},complete:()=>{r.c.trigger("modal_close")}})},error:()=>{r&&r.c.trigger("modal_close")}})},$inv.eHtml=function(e){let t=$(this),n=e.data instanceof jQuery?e.data:e.data.t,i=["invoiceemail","provisionperiod","invoicetitle"].includes(e.data.nme),a=i?[{name:"txt",label:"Text",type:"text",value:n.text()}]:[{name:"txt",label:"Text",type:"html",value:n.html(),tinymce:!0,attr:{style:"height: 300px"}}],r=e.data.change||null,l={title:t.data("dialog")||"",success:function(t){i?n.text(t.txt||""):n.html(t.txt),"function"==typeof r&&r(t.txt),$inv.d.syncField(e.data.nme,i?t.txt||"":t.txt)},tinymce:{valid_elements:"br",hidemenu:!0,hidetoolbar:!0}};if(Array.isArray(e.data.list)){let t=$$.dc("lstfrm");$.each(e.data.list,((n,i)=>{let a=$$.dc("li",t).append(""!==(e.data.lbl||"")?$$.dc("lbl").rwText(i[e.data.lbl]):null);$$.dc("adr",a).rwText(i[e.data.property]).data("val",i[e.data.property]).click((function(){let e=$(this),t=e.closest(".modal-body").find(':input[name="txt"]');t.is(".tinymce")?tinymce.get(t.attr("id")).setContent($$.s().rwText(e.data("val")).html()):"TEXTAREA"===t.prop("tagName")?t.val(e.data("val")).change():t.rwText(e.data("val"))}))})),l.addcontent=t}$ocms.dlgform(a,l)},$inv.setVat=function(e){$(this);let t=e.data,n=prompt($rct.rqV);n&&(n=parseFloat(n.replace("%","")),n>1&&(n*=.01),!1===isNaN(n)&&(t.siblings(".itm").each((function(){let e=$(this).data();e.vat=fnum(n,{style:"percent"}).replace(" ",""),(e.net_val||0)>0&&(e.vat_val=e.net_val*n),(e.svcnet_val||0)>0&&(e.svcvat_val=e.svcnet_val*n)})),$inv.t_fds_inv()))},$inv.inRow=function(e){let t=$(this),n=e.data,i={},a=$rcol.itm.clone(["SortOrder","NameOrNumber","Type","quantityhours","UnitString","net","svcnet_val","svcvat_val","net_val","vat_val","vat","Note"]),r="N"+(65536*(1+Math.random())||0).toString(16).substr(6),l=$$.tr({id:"itm_"+r.toString(),class:"itm"});$ocms.dlgform(a,{title:t.data("dialog")||"",success:function(e){l.data($.extend({Id:r},i,e)),$inv.rrw.call(l),l.insertAfter(n),$inv.t_fds_inv()},typedvalues:!0})},$inv.eRow=function(e){let t=$(this),n=e.data,i=n.data()||{},a=["SortOrder","NameOrNumber","Type","quantityhours","UnitString","net","svcnet_val","svcvat_val","net_val","vat_val","vat","Note"];i.id||""!==(i.Type||"")||a.unshift("Type");let r=$rcol.itm.clone(a).applyValues(i);r.set("Type","hidden","type"),$inv.eRw.call(t,n,i,r)},$inv.eRw=function(e,t,n){let i=$(this);$ocms.dlgform(n,{title:i.data("dialog")||"",success:function(n){let i={};""===(t.Id||"")&&(i.Id="N"+(65536*(1+Math.random())||0).toString(16).substr(6),e.attr("id","itm_"+i.Id.toString())),i.quantity=((n.quantityhours||"").toString()+" "+(n.UnitString||"").toString()).trimEnd(),e.data($.extend({},t,n,i)),console.debug("eRw success %o",e.data()),$inv.rrw.call(e),$inv.t_fds_inv()},typedvalues:!0})},$inv.bdysort=(e,t)=>{$(t).Sortable({dragItem:!1,dragHandleClass:"ico",parentident:"tr",onend:()=>{$inv.t_fds_inv()}})},$inv.rrw=function(){let e=$(this),t=e.data(),n={},i=e.is(".placeholder"),a=e.is(".hidenote"),r=e=>$$.d().append(e).html(),l=[$$.dc("ibtn insb",{title:$rct.iRb}).append(gi("indent-left")).click(e,$inv.inRow)];!1===i&&(l.unshift($$.dc("ibtn edit",{title:$rct.cP}).append(gi("pencil")).click(e,$inv.eRow)),l.push($$.dc("ibtn del",{title:$rct.dR}).append(gi("trash")).click((function(t){confirm($rct.cD)&&(e.remove(),$inv.t_fds_inv())}))));let s=$$.dc("axf").append(l);!0===i?n={id:"",typ:"placeholder"}:!0===e.is(".itm.osum")?n={invrqid:t.InvRqId,id:"osum"+e.index(),typ:"osum",p:"",q:null,t:r(t.tbl.tbl),tt:null,v:null,vt:t.net_val,vs:t.svcnet_val,vat:t.vat,vv:t.vat_val,vsv:t.svcvat_val,det:!1}:(n={invrqid:t.InvRqId,id:t.Id||"",typ:t.Type||"other",p:"",q:null,t:"",tt:null,v:null,vt:t.net_val,vs:t.svcnet_val,vat:t.vat,vv:t.vat_val,vsv:t.svcvat_val,det:""!==(t.Note||"")&&!1===a},$$.dc("ibtn ico move",s,{title:$rct.mR}),n.p=t.position||t.SortOrder||"",""===n.id?n.t="":["Text","Title"].includes(n.typ)&&0===(t.net_val||0)?n.t=t.htmltext||("#"!==(t.NameOrNumber||"").substr(0,1)?r($$[0]("p").text(t.NameOrNumber)):"")+(t.Note||""):(n.tt=n.det?"":$$.s(t.Note||"").text(),n.q=t.quantity||fnum(t.quantityhours)+" "+(t.UnitString||""),n.t=t.htmltext||(n.det?r($$.s(t.NameOrNumber||""))+r($$.dc("desc").html(t.Note)):r($$.s(t.NameOrNumber||""))),n.v=t.net,n.vt=t.net_val)),""!==(t.Note||"")&&$$.dc("ibtn add",s).append(gi("object-align-left")).click((function(t){$inv.rrw.call(e.tC("hidenote"))}));let d=[$$.tdc("aux").append(s),$$.tdc("keep").text(n.p)];""===n.id?d.push($$.td(e,{colspan:4}).append(n.t)):(Array.prototype.push.apply(d,n.q?[$$.tdc("keep").text(n.q)]:[]),Array.prototype.push.apply(d,[$$.tdc("txt",{colspan:n.q?1:2,title:n.tt}).append(n.t),$$.tdc("currency").text(fnum(n.v,$rct.cst)),$$.tdc("currency inetval").text(fnum(n.vt,$rct.cst)).attr("title",$rct.svcPart+": "+fnum(n.vs,$rct.cst))])),e.empty().attr("class",i?"placeholder":"itm").aC(n.Typ).tC("hidenote",a).append(d),t.co=n},$inv.invSumUpdate=function(){let e=$(this),t=e.children("tfoot").empty(),n=bool((e.data().admin||{}).p13b||"",!1);e.nextAll(".fnote").remove();let i={ttn:0,ttb:0,ttvat:0,tscn:0,tscvat:0,vat:{},itmnet:{}},a=[],r=(e,n,i)=>$$.tdc("currency",$$.tr(t,{class:i||"tsum"}).append([$$.tdc("aux"),$$.td({colspan:4}).text(e)]),fnum(n,$rct.cst)),l=t=>$$.dc("fnote").insertAfter(e).rwText(t),s=e.children("tbody");s.each(((e,t)=>{let n=$(t),r=n.data()||{},l=[],s=[],d=null,c=0,o=n.find("tr.itm"),u=0;n.tC("empty",o.length<1),o.each(((e,t)=>{let n=$(t).data()||{};!function(e,t,n){t.tscn+=e.svcnet_val||0,t.tscvat+=e.svcvat_val||0,t.ttn+=e.net_val||0,t.ttvat+=e.vat_val||0,t.ttb+=(e.net_val||0)+(e.vat_val||0),""!==(e.vat||"")&&(t.vat[e.vat]=(t.vat[e.vat]||0)+(e.vat_val||0))}(n,i,r.Id),c+=n.net_val||0,l.push(n.co);let a=$inv.itemToContract(n);"set"===a.type&&""!==a.id?d=a.id:null!==d&&""!==(a.id||"")&&(a.setId=d),s.push(a),(void 0===n.SortOrder||null===n.SortOrder?-1:n.SortOrder)>-1&&(!1===["text","title"].includes((n.Type||"other").toLowerCase())&&u++,n.SortOrder=0,n.position=u,$inv.rrw.call(t))})),n.find("tr.isum > td.isumval").text(fnum(c,$rct.cst)),a.push({Id:r.Id,nme:r.Name,text:r.text,itm:l,items:s,netval:c})}));let d=e.find("tbody:not(.empty)").length;s.find("tr.isum").tC("hidden",d<2),r("Netto",i.ttn),!1===n?$.each(i.vat,((e,t)=>{r($rct.vat+" "+e,t,"tvat")})):i.ttb=i.ttn,r("Summe",i.ttb);let c=e.data().admin.type;"i"===c?(l($rct.note2),l($rct.note4)):"c"===c?l($rct.note2):(l(string($rct.note3,[fnum((i.tscn+i.tscvat)*(e.data().admin.tax_servicerefund||0),$rct.cst)])).aC("ntax"),l($rct.note2),l(string($rct.note1,[fnum(i.tscn+i.tscvat,$rct.cst),fnum(i.tscn,$rct.cst),fnum(i.tscvat,$rct.cst)]))),!0===n&&l($rct.note13b),e.data("sms",i),e.data("bai",a),""===(e.data("dtoken")||"")&&!1===bool(e.data("dseeding"),!1)&&null!=(e.data("admin")||{}).type&&(e.data("dseeding",!0),$inv.d.seed($.extend($inv.invcPayload(e.data()),{invid:e.data("invid")||""})))},$inv.worknotes=function(e){let t="";return e.steps.forEach(((e,n)=>{let i;try{i=JSON.parse(e.Data||{}).fields||[]}catch(e){console.debug(e),i=[]}!0!==Array.isArray(i||"")&&(i="object"==typeof i&&!0===Array.isArray(i.field||"")?i.field:[]),i.forEach(((e,n)=>{"Ausgeführte Arbeiten"===e.name&&(t=e.result||"")}))})),t},$inv.rendersrq=function(){let e=$(this).empty(),t=e.is(".onesum"),n=e.data(),i=$$.tr(e,{id:"srq"+n.Id}).aC("title nosort"),a=($rcol.itm.lbl(),$$.dc("axf").appendTo($$.tdc("aux",i)));$$.dc("ibtn osum",a,{title:$rct.combP}).append(gi("euro")).click((function(t){e.tC("onesum"),$inv.rendersrq.call(e),$inv.t_fds_inv()})),$$.dc("ibtn setvat",a,{title:$rct.sV}).append(gi("gbp")).click(i,$inv.setVat),$$.dc("ibtn insb",a,{title:$rct.iRb}).append(gi("indent-left")).click(i,$inv.inRow);let r,l=$$.sc("text",n.text),s=($$.td(i,{colspan:t?4:5}).append(l),["net_val","vat_val","svcnet_val","svcvat_val","net"]);if($$.dc("ibtn edit",a).data("dialog",$rcol.req.lbl().Name).append(gi("pencil")).click({t:l,change:e=>{n.text=e,$inv.t_fds_inv()}},$inv.eHtml),t&&($$.tdc("currency isumval",i),r={Id:n.Id.toString()+"_osum",net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0},r.tbl=$$.tblset({class:"stbl"})),$.each(n.items||[],((n,i)=>{let a,l={Id:i.Id,net_val:i.net_val||0,vat_val:i.vat_val||0,svcnet_val:0,svcvat_val:0,net:i.net||0,Note:i.Note||""};if("service"===i.Type.toLowerCase())l.svcnet_val=i.net_val||0,l.svcvat_val=i.vat_val||0;t?(a=$$.tr(r.tbl.bdy,{id:"itm"+i.Id,class:"sitm"}).aC(i.Type),"Text"===i.Type||"Title"===i.Type?$$.td(a,{colspan:2}).html(i.htmltext||i.Note):($$.tdc("keep",a).text(i.quantity||((i.quantityhours||0)>0?fnum(i.quantityhours)+(i.UnitString||"").eine(" ",""):"")),i.htmltext?$$.tdc("txt",a).html(i.htmltext):$$.tdc("txt",a).text(i.NameOrNumber).attr("title",i.Note)),$.each(s,((e,t)=>{r[t]+=l[t]})),a.data(l)):($.extend(l,i),a=$$.tr(e,{id:"itm"+i.Id,class:"itm"}),a.data(l),$inv.rrw.call(a))})),t){let t=$$.tr(e,{id:"itmsq"+n.Id,class:"itm osum"}).data(r);$inv.rrw.call(t)}else{let t=$$.tr(e).aC("isum nosort");$$.tdc("aux",t),$$.td(t,{colspan:4}).text($rct.iSum),$$.tdc("currency isumval",t)}},$inv.t_fds_inv=()=>{let e=$("div.invoice_layout table.invi");e.trigger("fds.inv"),""!==(e.data("dtoken")||"")&&$inv.d.syncChanged(e)},$inv.sedit=()=>{$inv.sprev(!0)},$inv.jdisp=function(e){e.stopPropagation(),e.data.id&&$inv.disp(e.data.id,e.data.typ||"")},$inv.disp=(e,t)=>{let n="";switch(t){case"inv":n="inv/rdoc";break;case"rem":n="rem/rdoc"}""!==n&&$ocms.postXT({url:$ocms.url(n),data:{id:e||"",typ:"img"},success:e=>{let t=$$.dc("imagecollection pdfpreview"),n=Math.round(.88*vh());e.id;$.each(e.img||[],(function(e,i){$$.dc("pdfp",t).append($$.img(i).css("max-height",(n-rpx(6)).toString()+"px"))})),$ocms.dlg(t,{size:[n,Math.round(.88*vw())],zindex_min:50,form:!1,exclusive:!1})}})},$inv.jdbn=function(e){$ocms.postXT({url:$ocms.url("inv/rdocn"),data:{name:e.data.id||"",typ:"img"},success:e=>{let t=$$.dc("imagecollection pdfpreview"),n=Math.round(.88*vh());e.id;$.each(e.img||[],(function(e,i){$$.dc("pdfp",t).append($$.img(i).css("max-height",(n-rpx(6)).toString()+"px"))})),$ocms.dlg(t,{size:[n,Math.round(.88*vw())],zindex:50,form:!1})}})},$inv.sp13b=()=>{var e=$("div.invoice_layout").find("table.invi"),t=e.data();t.admin.p13b=!0,!1===(t.inv.InvoiceOptions||"").split(",").includes("§13b")&&(t.inv.InvoiceOptions+=",§13b"),e.trigger("fds.inv"),$inv.d.sync({Target:"p13b",Value:t.admin.p13b})},$inv.itemToContract=function(e){let t=((e=e||{}).Type||"").toString().toLowerCase(),n={id:(e.Id||"").toString(),type:t,title:"",desc:"",qty:"",price_net:"",total_net:e.net_val||0,vat:e.vat||""};var i;return e.co&&"osum"===e.co.typ?(n.desc=e.co.t||"",n.total_net=e.net_val||0):["text","title"].includes(t)&&0===(e.net_val||0)?(n.desc=e.htmltext||("#"!==(e.NameOrNumber||"").substr(0,1)?(i=$$[0]("p").text(e.NameOrNumber||""),$$.d().append(i).html()):"")+(e.Note||""),n.total_net=""):(e.htmltext?n.desc=e.htmltext:(n.title=e.NameOrNumber||"",n.desc=e.Note||""),n.qty=e.quantity||(0!==(e.quantityhours||0)?fnum(e.quantityhours)+(e.UnitString?" "+e.UnitString:""):""),n.price_net=e.net||0,n.total_net=e.net_val||0),n},$inv.ssetmode=()=>{let e=$("div.invoice_layout").find("table.invi").data();e.admin=e.admin||{};let t,n=e.admin.setmode||"setprice",i=e=>$$.dc("btn",$ict.setmo[e]).tC("selected",n===e).click((()=>{t.c.trigger("modal_close"),$inv.setSetmode(e)})),a=$$.dc("choicefrm").append([i("setprice"),i("itemprices"),i("setonly")]);t=$ocms.dlg(a,{width:800})},$inv.setSetmode=e=>{let t=$("div.invoice_layout").find("table.invi").data();t.admin=t.admin||{},t.admin.setmode=e,t.inv=t.inv||{};let n=(t.inv.InvoiceOptions||"").split(",").filter((e=>""!==e&&0!==e.indexOf("setmode:")));e&&"setprice"!==e&&n.push("setmode:"+e),t.inv.InvoiceOptions=n.join(","),$inv.d.sync({Target:"setmode",Value:e})},$inv.sctp=()=>{let e=$invcol.ctp;$ocms.dlgform(e,{title:$ict.ctp,success:function(e){var t=$("div.invoice_layout"),n=t.find("table.invi").data();let i={};void 0!==n.new&&"{"===(n.new.CustomValues||"").substr(0,1)&&(i=JSON.parse(n.inv.CustomValues)),i.contactName=e.name,i.contactEmail=e.email,n.new.CustomValues=JSON.stringify(i),t.find(".ctpfrm").text(ne(e.name,e.email)),$inv.d.sync({Target:"contact",Value:{name:e.name,email:e.email}})},typedvalues:!0})},$inv.invcPayload=function(e){let t=(e=e||{}).sms||{},n=$.extend({},e.new),i=$.extend({},e.admin);return n.total_net=t.ttn||0,n.total_gross=t.ttb||0,n.title=null!=n.invoicetitle?n.invoicetitle:n.title||"",n.provisionlocation=null!=n.loc?n.loc:n.provisionlocation||"",n.paymentterm=null!=i.paymentterms?i.paymentterms:n.paymentterm||"",i.customerid=null!=i.customerid?i.customerid:i.CustomerId,{admin:i,req:e.bai,sms:e.sms,new:n}},$inv.ssave=()=>{$inv.d.save()},$inv.sprev=e=>{$inv.d.preview()},$inv.rReload=()=>{try{let e=$("#listframe ul.rql:first").data();$inv.cInv2({id:e.search})}catch(e){}},$inv.quantChange=function(e){let t=$(this).closest("form"),n={},i=e=>parseFloat(e.toString().replace("%","").replace(",",".")),a=e=>e.toFixed(2);t.find(":input").each(((e,t)=>{n[$(t).attr("name")]=$(t)}));let r=parseInt(n.quantityhours.val()||"0"),l=i(n.net.val()||"0"),s=.01*i(n.vat.val());r>0&&l>0&&(n.net_val.val(a(r*l)),n.vat_val.val(a(r*l*s)),["Service"].includes(n.Type.val())&&(n.svcnet_val.val(a(r*l)),n.svcvat_val.val(a(r*l*s))))},$inv.storno=function(e,t){let n,i=$$.dc("choicefrm").append([$$.dc("btn","Storno ohne Details").click({id:e,mode:"simple"},(e=>{n.c.trigger("modal_close"),$inv.cSt(e.data)})),$$.dc("btn","Storno mit neuer Rechnung").click({id:e},(e=>{n.c.trigger("modal_close"),$inv.ccStInv(e)})),$$.dc("btn","Storno mit best. Rechnung").tC("inactive",!1===bool(t,!1)).click({id:e,mode:"copy"},(e=>{!0===bool(t,!1)&&(n.c.trigger("modal_close"),$inv.cSt(e.data))}))]);n=$ocms.dlg(i,{width:1e3})},$inv.credit=function(e,t){let n,i=$$.dc("choicefrm").append([$$.dc("btn","Gutschrift").click({id:e,mode:"credit"},(e=>{n.c.trigger("modal_close"),$inv.cSt(e.data)}))]);n=$ocms.dlg(i,{width:1e3})},$inv.setPyd=function(e){confirm($ict.cpyd)&&$ocms.postXT({url:$ocms.url("inv/setpyd"),timeout:60,data:{id:e},success:e=>{alert($ict.relm)},error:()=>{alert($t.f1)}})},$inv.setUpd=function(e){confirm($ict.cupd)&&$ocms.postXT({url:$ocms.url("inv/setupd"),timeout:60,data:{id:e},success:e=>{alert($ict.relm)},error:()=>{alert($t.f1)}})},$inv.resendRem=function(e){e.stopPropagation(),e.data.id&&confirm(string($ict.remresc,[e.data.name]))&&$ocms.postXT({url:$ocms.url("rem/resend"),timeout:60,data:{id:e.data.id},success:t=>{alert(string($ict.remresr,[e.data.name]))},error:()=>{alert($t.f1)}})},$inv.dspRem=function(e){let t=$$.dc("rfrm").ldng(1),n=$ocms.dlg(t,{width:1e3});n.ft.rwText($rct.rq2),$ocms.postXT({url:$ocms.url("inv/getrem"),timeout:60,data:{id:e,drafts:!1},success:e=>{n.ft.empty();let i=$$.tblset({class:"invtbl"},t.empty()),a=$invcol.rem2,r=$$.tr(i.hd);$$.th(r);$.each(a.fields||[],((e,t)=>{$$.th(r).text(t.label)}));let l=!1;$.each(e,((e,t)=>{l=!l;let n=$$.tr(i.bdy).tC("alt",l),r=$$.td(n);n.click((function(){n.tC("selected").siblings().rC("selected")})),!0===bool(t.hasFile,!1)&&($$.dc("idl ilbtn",r,{title:$ict.dl+"\n"+t.DocumentName}).append(gi("save-file","ico")).click({id:t.Id},$inv.downloadrem),$$.dc("idl ilbtn",r,{title:$ict.remdsp+"\n"+t.DocumentName}).append(gi("eye-open","ico")).click({id:t.Id,typ:"rem"},$inv.jdisp),$$.dc("idl ilbtn",r,{title:$ict.remres+"\n"+t.DocumentName}).append(gi("refresh","ico")).click({id:t.Id,typ:"rem",name:t.DocumentName},$inv.resendRem)),$.each(a.fields||[],((e,i)=>{let a=$$.td(n).aC(i.dtype),r=t[i.name];if("function"==typeof i.dfnc)i.dfnc.call(a,r,t);else switch(i.type||""){case"date":a.text(fdt(t[i.name],"dd.MM.yy"));break;case"datetime":a.text(fdt(t[i.name]));break;case"html":a.append($$.dc("ctw").html(r)),a.append($$.dc("ttip").html(r));break;default:a.text(t[i.name])}if("InvoiceId"===(i.name||""))a.aC("keep");switch(typeof i.title){case"function":i.title.call(a,t);break;case"string":a.attr("title",cs.title)}}))}))},error:()=>{t.empty(),n.ft.rwText($t.f1)},complete:()=>{t.ldng(0)}})},$inv.ccRem=function(e,t){$(this);$ocms.postXT({url:$ocms.url("rem/lrem"),timeout:60,data:{id:e},success:n=>{let i=$invcol.rid.clone();i.applyValues(n.ov);let a=$$.dc("ac"),r=$$.tblset({class:"fullgrid fullwidth"},a);if((n.lst||[]).length>0){$$.d({style:"margin: 1.5rem 0 1rem 0;font-size: 110%;text-decoration: underline;"}).prependTo(a).text($ict.rovlh);let e=$$.tr(r.hd);$ict.rovl.forEach(((t,n)=>$$.th(e,t))),$.each(n.lst,((e,t)=>{$$.tr(r.bdy).append([$$.tdc("keep",t.subject),$$.tdc("currency",fnum(t.amount,$rct.cst)),$$.tdc("currency",fnum(t.amount_payed,$rct.cst)),$$.tdc("keep",fdt(t.DateFinalized,"dd.MM.yy"))])}))}else $$.td($$.tr(r.bdy),$ict.nd);$ocms.dlgform(i,{addcontent:a,title:string($ict.remdt,[t||"?"]),success:function(t){$inv.ccRem_s2(e,t)},typedvalues:!0})}})},$inv.rRemRw=function(e){let t=$(this),n=e.rm||{};t.empty().data({invoiceid:n.invoiceid,invoicedate:n.invoicedate,amount:n.amount,amount_payed:n.amount_payed});let i=$$.dc("axf").append($$.dc("ibtn edit",{title:$rct.cP}).append(gi("pencil")).click(t,$inv.eRowR));t.append([$$.tdc("aux").append(i),$$.tdc("keep",n.invoiceid),$$.tdc("keep",fdt(n.invoicedate,"dd.MM.yy")),$$.tdc("currency",fnum(n.amount,$rct.cst)),$$.tdc("currency",fnum(n.amount_payed,$rct.cst)),$$.tdc("currency",fnum(n.amount-n.amount_payed,$rct.cst))])},$inv.eRowR=function(e){let t=$(this),n=e.data,i=n.data()||{},a=$invcol.rem.clone().applyValues(i);$ocms.dlgform(a,{title:t.data("dialog")||"",success:function(e){let i=t.closest("table"),a=i.data();$.extend(a.rm,e),i.data(a),$inv.rRemRw.call(n,a)},typedvalues:!0})},$inv.ccRem_s2=function(e,t){$fis.lf(!1).rC("fix").aC("hd");let n=$$.dc("invoice_layout",$fis.frm_edit()).append($$.dc("btn sprev").click($inv.rprev));$inv.eM(!1,!0);$$.dc("rfrm").ldng(1);$ocms.postXT({url:$ocms.url("rem/get"),timeout:60,data:$.extend({id:e},t),success:e=>{let t=e.rm||{},i=$$.dc("srq",n);$ict.remt[t.type].forEach((e=>$$[0]("p").rwText(e).appendTo(i)));let a=$$.tblset({class:"invi"},i);a.ft=$$[0]("tfoot"),a.tbl.data($.extend({invid:t.invid,new:{}},e));let r=$$.tr(a.hd).aC("shd").append([$$.th().aC("aux")]);$ict.remHR.forEach((e=>$$.th(r,e))),$inv.rRemRw.call($$.tr(a.bdy),a.tbl.data()),a.ft.appendTo(a.tbl),$ict.remt2[t.type].forEach((e=>$$[0]("p").rwText(e).appendTo(i)));let l=(e,t,i,r,l)=>{let s=$$.dc("inpfrm",n).aC(e).append("string"==typeof r?$$.dc("ahd",r):r>0?$$.dc("ahd",$rct.frm[i]):null),d=$$.dc("content",s).rwText(t);$$.dc("axf",s).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:d,nme:i,change:e=>{a.tbl.data("new")[i]=e}},l),$inv.eHtml)),a.tbl.data("new")[i]=t};l("tfrm",t.subject,"subject",0,null),l("adrfrm",t.invoiceaddress,"invoiceaddress",0,null),l("emailfrm",t.invoiceemail,"invoiceemail",0,null),$$.dc("sndfrm",n).append($$.dc("content").text(t.sender)),a.tbl.children("tbody").each($inv.bdysort),a.tbl.trigger("fds.inv")},complete:()=>{}})},$inv.rprev=()=>{var e=$("div.invoice_layout"),t=e.find("table.invi"),n=t.data();$.extend(n.new,t.find("tbody > tr:first").data()),e.aC("freeze"),!1!==$fis.ValidateEmail(n.new.invoiceemail||"")||!1!==bool(confirm($ict.ivE+$ict.ivEc),!1)?$ocms.postXT({url:$ocms.url("rem/prep"),data:{remc:JSON.stringify({rem:n.rm,new:n.new}),id:n.invid||""},success:t=>{e.rC("freeze");let n=$$.dc("imagecollection pdfpreview"),i=Math.round(.88*vh()),a=t.id;$.each(t.img||[],(function(e,t){$$.dc("pdfp",n).append($$.img(t).css("max-height",(i-rpx(6)).toString()+"px"))})),$ocms.dlg(n,{size:[i,Math.round(.88*vw())],zindex:50,form:!1,button:$ict.remd,confirm:function(e){let t=$(this);$ocms.postXT({url:$ocms.url("rem/conf"),data:{id:a},success:()=>{t.trigger("modal_close"),window.open($ocms.url("rem/idoc")+"?id="+a,"_blank"),$ocms.init("req"),$inv.rReload()},error:()=>{alert($t.f1),t.trigger("modal_close")}})},cancel:function(e){$(this);confirm($ict.cdI)&&$ocms.postXT({url:$ocms.url("rem/del"),data:{id:a}}),$inv.rReload()}})}}):e.rC("freeze")},$inv.sis=e=>{confirm($ict.sisc)&&$ocms.postXT({url:$ocms.url("inv/sis"),data:{id:e||""},success:e=>{}})},$inv.srs=e=>{confirm($ict.srsc)&&$ocms.postXT({url:$ocms.url("rem/srs"),data:{id:e||""},success:e=>{}})},$inv.mfrrel=e=>{$("#contentframe").ldng(),$ocms.postXT({url:$ocms.url("inv/mfrrel"),data:{id:e||""},success:e=>{$inv.rerenderinv()},complete:()=>{$("#contentframe").ldng(0)}})};
\ No newline at end of file
+let $rct={mdl:"Aufträge",or:"offene Aufträge",orr:"offene Aufträge (4 W)",rn:"Auftragsnummer",iov:{all:"Auftragsübersicht (alle)","":"Auftragsübersicht"},wk:"Woche",nd:"Keine Daten gefunden.",h:"Uhr",rq1:"Auftragsdaten werden von MFR abgerufen.\nDer Vorgang kann bis zu 90Sek dauern.",rq2:"Auftragsdaten werden geladen",rq1f:"Die Auftragsdaten von MFR konnten nicht oder nicht schnell genug abgerufen werde.\nMöchten Sie mit den bestehenden Daten trotzdem weitermachen?",note1:"Im Bruttobetrag sind {0} Lohnkosten enthalten (netto {1}). Die darin enthaltene Umsatzsteuer beträgt {2}.",note2:"Bitte beachten Sie, nach §14 Abs. 1 Umsatzsteuergesetz ist diese Rechnung ein Zahlungsbeleg oder eine andere beweiskräftige Unterlage für 2 Jahre nach Ablauf des Kalenderjahres der Ausstellung dieser Rechnung aufzubewahren, soweit nicht aufgrund anderer gesetzlicher Regelungen andere ggf.längere Aufbewahrungsfristen gelten.",note3:"Privathaushalten erstattet das Finanzamt bis zu {0} des Arbeitslohns mit der nächsten Steuererklärung.",note4:"Für bereits erbrachte Arbeiten, Dienstleistungen, Materiallieferungen und getätigte Bestellvorgänge zum oben genannten Bauvorhaben, die sich aus dem mit Ihnen geschlossenen Vertrag ergeben, stellen wir Ihnen vertragsgemäß unsere Akontozahlung in Rechnung. Eine Endabrechnung erhalten Sie als Schlussrechnung nach Abschluss des gesamten Bauvorhabens. Das Ausführungsdatum entnehmen Sie bitte dem Schlusstext dieser Rechnung. Wir danken Ihnen herzlich für das entgegengebrachte Vertrauen und bitten Sie um kurzfristigen Ausgleich der Akontorechnung.",note13b:"Gem. §13b Umsatzsteuergesetz unterliegen Sie der Steuerschuldnerschaft des Leistungsempfängers zur Umsatzsteuer aus dieser Rechnung mit einem Steuersatz von 19%.",crI:"Rechnung erstellen",crII:"Abschlagsrechnung erstellen",dII:"Für eine Abschlagsrechnung darf nur ein Auftrag gewählt werden.",dnS:"Für eine Rechnung muss mindestens ein Auftrag gewählt werden.",inv:"Rechnung",invs:"Rechnungen",req:"Auftrag",provP:"Leistungszeitraum",provD:"Leistungsdatum",cP:"Position ändern",iRb:"Zeile darunter einfügen",dR:"Zeile löschen",sV:"USt festlegen",cD:"Löschen?",mR:"Zeile verschieben",svcPart:"Service-Anteil",vat:"Umsatzsteuer",combP:"Positionen zusammenfassen",iSum:"Zwischensumme",dtRel:"Freigegeben am: ",dtCr:"Erstellt am: ",rqV:"USt des Auftrags?",cthd:"wirklich aus-/einblenden ?",cst:{style:"currency",currency:"EUR"},sts:{IsWorkDone:"Arbeiten erledigt",Closed:"Auftrag geschlossen",SubcontractorPendingConfirmation:"Warten auf Bestätigung (Unterauftrag)",Scheduled:"Geplant",OfferIsRejected:"Angebot abgelehnt",OfferIsSend:"Offen (Angebot versandt)",CollaborationWaitingConfirmation:"Warten auf Bestätigung (Zusammenarbeit)",Released:"Freigegeben",OfferIsConfirmed:"Bestätigt",InProgress:"In Bearbeitung",ReadyForScheduling:"Zur Planung",Created:"Erstellt",Rejected:"Abgebrochen",Invoiced:"Rechnung gestellt","-":"-"},invHR:["Pos.","Menge","Artikelbezeichnung","VK","Summe"],frm:{invoiceaddress:"Adresse",loc:"Leistungsort / Lieferadresse",invoiceemail:"Email"}},$rcol={req:new fields_definition("Auftrag","Aufträge",[{name:"tags",label:"",type:"string",dfnc:function(e,t){""!==(e||"")&&($(this).aC("tags"),e.split(",").forEach((e=>{""!==e&&$(this).append($$.sc("tag "+e.replace(" ","_").replace("/","_").toLowerCase(),e))})))}},{name:"DateOfCreation",label:"Datum",type:"date",title:function(e){$(this).attr("title",$rct.dtCr+fdt(e.DateOfCreation).ne("-")+" \n"+$rct.dtRel+fdt(e.DateReleased).ne("-"))}},{name:"CustomerName",label:"Kunde (Firma)",type:"string"},{name:"Name",label:"Auftragsname",type:"string"},{name:"ExternalId",label:"Auftragsnummer",type:"string"},{name:"ParentExtenalId",label:"PAuftrag",type:"string"},{name:"InvoiceId",label:"RNummer",type:"string",dfnc:function(e,t){$(this).rwText(e," ").find("span").each((function(){$(this).aC("cla").click({id:$(this).text()},$inv.jdbn)}))}},{name:"State",label:"Status",type:"string"},{name:"WorkDoneAt",label:"Erledigt am",type:"date"},{name:"Description",label:"Beschreibung",type:"html"}]),itm:new fields_definition("Auftragsposition","Auftragspositionen",[{name:"NameOrNumber",label:"Bezeichnung",type:"string"},{name:"Type",label:"Typ",type:"select",required:!0,value:"Text",url:[{value:"Text",label:"Text"},{value:"Equipment",label:"Ausrüstung"},{value:"Material",label:"Material"},{value:"Service",label:"Arbeitsleistung"}],change:function(e){$req.quantChange.call(this,e)}},{name:"quantityhours",label:"Anzahl / Menge",type:"number",precision:"0.01",value:1,change:function(e){$inv.quantChange.call(this,e)}},{name:"UnitString",label:"Einheit",type:"select",url:["LFDM","Stck","Std.","QM","AW","Pauschal"],change:function(e){$inv.quantChange.call(this,e)}},{name:"net",label:"EinzelPreis netto",type:"number",precision:"0.01",value:0,change:function(e){$inv.quantChange.call(this,e)}},{name:"net_val",label:"GesamtPreis netto",type:"number",precision:"0.01",value:0},{name:"vat_val",label:"GesamtPreis USt",type:"number",precision:"0.01",value:0},{name:"svcnet_val",label:"Arbeitslohn netto",type:"number",precision:"0.01",value:0},{name:"svcvat_val",label:"Arbeitslohn USt",type:"number",precision:"0.01",value:0},{name:"net_pos",label:"Netto",type:"string"},{name:"bo_pos",label:"Brutto",type:"string"},{name:"vat",label:"USt",type:"string",value:"19,0%",change:function(e){$inv.quantChange.call(this,e)}},{name:"Note",label:"Details",type:"html",tinymce:!0}])},$ict={mdl:"Rechnungen",iov:{all:"Rechnungen (alle)","":"Rechnungen (nur fertige)","#d":"Rechnungen (nur Entwürfe)","#u":"Rechnungen (nur unbezahlt)","#r":"Rechnungen (nur angemahnt)","#a":"Rechnungen (nur Akonto)","#c":"Rechnungen (nur Storno)","#ru":"Rechnungen (nur angemahnt + unbez.)"},uba:", gesamter Zeitraum)",req:"Auftrag",inv:"Rechnung",rem:"Mahnung",in:"Rechnungsnummer",cc:"Kunde",wk:"Woche",nd:"Keine Daten gefunden.",dl:"Herunterladen",ed:"Bearbeiten",ced:"Bearbeitung fortsetzen",sItm:"Einzelheiten anzeigen",sPay:"Zahlungen anzeigen",cdI:"Entwurf der Rechnung löschen?",rel:"Neu Laden",relm:"Bitte laden Sie Liste manuell neu, um die Änderungen zu sehen.",dsp:"Rechnung anzeigen",storno:"Storno-Rechnung erstellen",credit:"Gutschrift erstellen",remd:"Mahnung erstellen",remdt:"Mahnung erstellen zur Rechnung {0}",remlst:"Mahnungen anzeigen",remdsp:"Mahnung anzeigen",remres:"Mahnung erneut senden",remresc:"Mahnung {0} wirklich erneut senden?",remresr:"Mahnung {0} wurde erfolgreich versandt.",setpyd:"Bezahlt markieren",cpyd:"Rechnung wirklich als bezahlt markieren?",setupd:"Bezahlt-Markierung aufheben",cupd:"Bezahlt-Markierung wirklich aufheben?",ivE:"Die Email-Adresse ist vermutlich nicht gültig.",ivEc:"\nMöchten Sie fortfahren?",pna:"Diese Seite ist in der Vorschau nicht verfügbar",tpe:"Die Anzahl von {0} Seiten wird aktuell nicht unterstützt",eis:"Der Rechnungsentwurf konnte nicht gespeichert werden.",iss:"Zwischenstand speichern.",p13b:"USt -> §13b",setm:"Set-Preisanzeige",setmo:{setprice:"Set mit Preis – Positionen ohne Preis",itemprices:"Positionen mit Preis – Set als Überschrift",setonly:"Nur Set mit Preis – Positionen ausgeblendet"},ctp:"Ansprechpartner festlegen",mfr:"Von MFR neu abrufen",rq1:"Auftragsdaten werden von MFR abgerufen.\nDer Vorgang kann bis zu 90Sek dauern.",rq2:"Auftragsdaten werden geladen",iq1:"Rechnungsdaten werden von MFR abgerufen.\nDer Vorgang kann bis zu 90Sek dauern.",iq2:"Rechnungsdaten werden geladen",sis:"Rechnung als versandt markieren",srs:"Mahnung als versandt markieren",sisc:"Rechnung wirklich als versandt markieren?",srsc:"Mahnung wirklich als versandt markieren?",iSt:{dft:"Entwurf",uns:"nicht versandt",pyd:"bezahlt",cc:"storniert",op:"offen",due:"fällig",ovd:"überfällig",rem:"angemahnt"},rSt:["","Überfällig","2. Mahnung","3. Stufe"],pSt:{a:"Vollst.",p:"Teilz."},ivT:{i:"AbschlagsR.",f:"SchlussR",r:"Rechnung",c:"StornoR."},rovlh:"Übersicht der bisherigen Mahnungen",rovl:["Betreff","Betrag","Betrag gezahlt","fertiggestellt am"],remHR:["Rechnung","vom","Rechnungsbetrag","bereits bezahlt","noch offen"],remt:{f:["Sehr geehrte Damen und Herren,","ein Mahnschreiben sollte kurz, freundlich und erfolgreich sein. Kurz ist es, freundlich sowieso; ob es auch erfolgreich ist, hängt von Ihnen ab."],m:["Sehr geehrte Damen und Herren,","nun müssen wir Sie noch einmal anschreiben.","Wahrscheinlich haben Sie triftige Gründe dafür, warum Sie die Zahlung unserer Forderung nicht vornehmen und auch nicht auf unsere Mahnung reagieren. Sollten wir darüber nicht einmal sprechen?","Bitte nehmen Sie umgehend in dieser Sache mit uns Kontakt auf."],l:["Sehr geehrte Damen und Herren,",'Eine DRITTE MAHNUNG zu erhalten bereitet Ihnen bestimmt ebenso wenig Freude wie uns, sie zu verschicken. Leider haben wir auf unsere zweite Mahnung noch keine Antwort von Ihnen erhalten.", "Wir bitten Sie, den offenen Betrag innerhalb der nächsten 7 Werktage nach Erhalt dieses Schreibens zu begleichen. Nach Ablauf dieser Frist erfolgt keine weitere Mahnung mehr.',"Sollte die Forderung bis dahin nicht beglichen sein, eröffnen wir das gerichtliche Mahnverfahren. Sollten Sie die Rechnung inzwischen beglichen haben, so betrachten Sie bitte dieses Schreiben als gegenstandslos."]},remt2:{f:["Wir bitten Sie, den noch offenen Rechnungsbetrag innerhalb einer Woche auf unser Konto zu überweisen.","Sollten Sie den Betrag bereits überwiesen haben, so bitten wir Sie, diese Zahlungserinnerung als gegenstandslos zu betrachten."],m:["Um Ihnen zusätzliche Kosten für weitere Mahnungen zu ersparen, bitten wir Sie nunmehr um die Überweisung des noch zu zahlenden Gesamtbetrages inklusive der ggf. bereits fälligen Mahnzinsen und Mahngebühren innerhalb von einer Woche."],l:[]},payi:{account:"Konto",name:"Zahler",text:"Verw.Zweck",InvoiceID:"Rechnung",amount:"Betrag",date:"Datum",manual:"Typ"}},$invcol={datev:new fields_definition("Rechnung","Rechnungen",[{name:"Umsatz (ohne Soll/Haben-Kz)",label:"Umsatz (ohne Soll/Haben-Kz)",type:"string"},{name:"vf",label:"vf",type:"string"},{name:"Soll/Haben-Kennzeichen",label:"Soll/Haben-Kennzeichen",type:"string"},{name:"Konto",label:"Konto",type:"string"},{name:"Gegenkonto",label:"Gegenkonto",type:"string"},{name:"BU-Schlüssel",label:"BU-Schlüssel",type:"string"},{name:"Belegdatum",label:"Belegdatum",type:"string"},{name:"Belegfeld 1",label:"Belegfeld 1",type:"string"},{name:"Belegfeld 2",label:"Belegfeld 2",type:"string"},{name:"Buchungstext",label:"Buchungstext",type:"string"}]),inv:new fields_definition("Rechnung","Rechnungen",[{name:"invstatus",label:"Status",type:"select",url:$ict.iSt},{name:"balance",label:"Umsatz",type:"string",dtype:"currency"},{name:"CustomerName",label:"Kunde",type:"string"},{name:"InvoiceId",label:"RNummer",type:"string"},{name:"InvoiceType",label:"Typ",type:"select",url:$ict.ivT},{name:"request",label:"Auftrag",type:"string",dtype:"num"},{name:"vat",label:"MwSt",type:"string",dtype:"num"},{name:"deb_cred",label:"Soll/Haben",type:"string"},{name:"customer",label:"Konto",type:"string",dtype:"num"},{name:"contra_account",label:"Gegenkonto",type:"string",dtype:"num"},{name:"Belegdatum",label:"Belegdatum",type:"date"},{name:"reminderstatus",label:"MahnStatus",type:"select",url:$ict.rSt},{name:"reminder",label:"# Mahnungen",type:"integer"},{name:"Buchungstext",label:"Buchungstext",type:"string"},{name:"Payment",label:"Zahlung",type:"string"}]),rem:new fields_definition("Zahlungserinnerung","Zahlungserinnerung",[{name:"amount",label:"Rechnungsbetrag",type:"number",precision:"0.01",value:1},{name:"amount_payed",label:"bereits bezahlt",type:"number",precision:"0.01",value:1}]),rem2:new fields_definition("Zahlungserinnerung","Zahlungserinnerung",[{name:"DocumentName",label:"Name",type:"string"},{name:"subject",label:"Betreff",type:"string"},{name:"DateSent",label:"Versanddatum",type:"date"},{name:"status",label:"Status",type:"string"},{name:"amount_open",label:"offener Betrag",type:"number",precision:"0.01"},{name:"InvoiceId",label:"RNummer",type:"string"}]),rid:new fields_definition("Zahlungserinnerung","Zahlungserinnerung",[{name:"type",label:"Typ",type:"select",url:[["f","einfache Zahlungserinnerung"],["m","Mahnung"],["l","letzte Mahnung"]],required:!0},{name:"level",label:"Stufe",type:"select",url:[["1","Stufe 1"],["2","Stufe 2"],["3","Stufe 3"],["4","Stufe 4"],["5","Stufe 5"],["6","Stufe 6"]],required:!0}]),ctp:new fields_definition("Ansprechpartner","Ansprechpartner",[{name:"name",label:"Name",type:"string"},{name:"email",label:"Email",type:"string"}])},gi=(e,t)=>$$.sc("glyphicon glyphicon-"+e).aC(t),$inv={init2:function(e,t){e=e||"inv",t=t||{},$ocms.getScript([],(function(){$inv.init3(e,t)}))},init3:async function(e,t){$fis.cf(!0);let n=$fis.lf(!0);$("#topbar").ocmsmenu([]),$("#activemodule").text($ict.mdl);let i=[(async()=>{await $fis.getAuth("fds_inv")>0&&($inv.prepLst(""),n.aC("fix"))})(),new Promise(((e,t)=>{$fis.prepAuth(["fds_reminder"])}))];await Promise.all(i)},prepLst:function(e){let t=new Date,n=$fis.lf(!0).ldng(1),i=new Date("2021-01-01");$fis.frm_list().IN((function(){}));let a=[];$.each($ict.iov,((e,t)=>{a.push({lbl:t,fnc:()=>{$inv.prepLst(e),n.aC("fix")}})})),$fis.lfm().ocmsmenu([{lbl:"Filter",itm:a}]);$$.i({placeholder:$ict.in}).appendTo($$.dc("mth ivn",n)).enterKey((function(e){let t=$(this),n=t.val()||"";e.stopPropagation(),t.parent().siblings().rC("selected"),n.length>3&&(t.parent().aC("selected"),$inv.renderinv("i:"+n,"s","all"),t.val(""))})),$$.i({placeholder:$ict.cc}).appendTo($$.dc("mth ivc",n)).enterKey((function(e){let t=$(this),n=t.val()||"";e.stopPropagation(),t.parent().siblings().rC("selected"),n.length>=3&&(t.parent().aC("selected"),$inv.renderinv("c:"+n,"s","all"),t.val(""))}));"#"===e.substr(0,1)&&$$.dc("mth extra",n).text($ict.iov[e].replace(")",$ict.uba)).click((function(t){let n=$(this);if(t.stopPropagation(),n.siblings().rC("selected"),!0===n.is(".selected")){n.toggleClass("selected");let t=fdt(new Date,"yy-MM-dd");$inv.renderinv(t,"a",e)}n.aC("selected")})),n.append("
");let r=$$.dc("mthl",n),l=t.getFullYear(),s=t.getMonth()+1;for(let t=i.getFullYear();t<=l;t++){let n=$$.dc("yr").prependTo(r).text($ict.iov[e]+" - "+t.toString()).toggleClass("selected",t===l);n.click({yr:t},(function(e){e.stopPropagation(),n.siblings().rC("selected"),n.aC("selected")}));let a=$$.dc("mfrm",n);for(let n=0;n<(t!==l?12:s);n++){i=new Date(t,n,1);let r=$$.dc("mth").prependTo(a).text($ict.iov[e]+" - "+fdt(i,"MMM yyyy"));if(r.click({yr:t,mt:n},(function(t){if(t.stopPropagation(),r.siblings().rC("selected"),!0===r.is(".selected")){r.toggleClass("selected");let n=fdt(new Date(t.data.yr,t.data.mt,1),"yy-MM-dd");$inv.renderinv(n,"m",e)}r.aC("selected")})),""===e){$$.dc("mthdl",r).append(gi("compressed","ico")).click({yr:t,mt:n},(function(e){e.stopPropagation();let t=fdt(new Date(e.data.yr,e.data.mt,1),"yy-MM-dd");$inv.downloadzip(t,"m")}))}let l=getMonday(i),s=new Date(i);s.setMonth(s.getMonth()+1),s.setDate(0),s=getMonday(s);let d=$$.dc("wfrm",r);for(;l<=s;){let t=$$.dc("wk",d).text(($ict.wk||"W")+" "+fdt(l,"dd.MM.yy"));t.click({rd:new Date(l)},(function(n){n.stopPropagation();let i=fdt(n.data.rd,"yy-MM-dd");$inv.renderinv(i,"w",e),r.siblings().rC("selected").find(".wk").rC("selected"),r.aC("selected").find(".wk").rC("selected"),t.aC("selected")})),$$.dc("wkdl",t).append(gi("compressed","ico")).click({rd:new Date(l)},(function(e){e.stopPropagation();let t=fdt(e.data.rd,"yy-MM-dd");$inv.downloadzip(t,"w")})),l.setDate(l.getDate()+7)}}}n.ldng(0)},rerenderinv:function(){let e=$("#contentframe .invfrm:first");if(e.length>0){let t=e.data("sets")||{};t.mode&&$inv.renderinv(t.tgt,t.mode,t.includes)}},renderinv:function(e,t,n){let i=$fis.frm_list(!0,!0).ldng(1),a=$$.dc("invfrm",i).aC("md"+t).data("sets",$.extend({},{tgt:e,mode:t,includes:n})),r=$fis.lf();$ocms.postXT({url:$ocms.url("inv/invl"),data:{mode:t,tgt:e,includes:n},success:i=>{r.rC("fix").aC("hd"),$$.dc("ovhd",a).text(i.admin.title);let l=$$.tblset({},a),s=$invcol.inv,d=$$.tr(l.hd);$$.th(d);$.each(s.fields||[],((e,t)=>{$$.th(d).text(t.label),"vat"===t.name&&$$.th(d)})),$.each(i.invoices||[],((d,c)=>{let o=$$.tr(l.bdy);o.click((function(){r.rC("fix").aC("hd"),o.toggleClass("selected").siblings().rC("selected").find("td.av").rC("av"),o.find("td.av").rC("av"),!0===o.is(".selected")?$inv.iMn(c):$inv.eM()}));let u=$$.td(o,{class:"raux"});c.hasFile?($$.dc("idl ilbtn",u,{title:$ict.dl+"\n"+c.DocumentName}).append(gi("save-file","ico")).click({id:c.Id},$inv.downloadinv),$$.dc("idl ilbtn",u,{title:$ict.dsp+"\n"+c.DocumentName}).append(gi("eye-open","ico")).click({id:c.Id,typ:"inv"},$inv.jdisp)):!1===c.isFinal&&!0===$fis.isAuth("fds_inv",2)&&$$.dc("idl ilbtn",u,{title:$ict.ed}).append(gi("edit","ico")).click({id:c.Id},$inv.doContInv),$$.dc("iitm ilbtn",u,{title:$ict.sItm}).append(gi("list","ico")).click({id:c.Id},$inv.showitm),$$.dc("iitm ilbtn",u,{title:$ict.sPay}).append(gi("euro","ico")).click({id:c.Id},$inv.showpay),$.each(s.fields||[],((r,l)=>{let s,d,u=$$.td(o).aC(l.dtype);switch("select"===(l.type||"")?u.text((l.url||{})[c[l.name]]||""):u.text(c[l.name]),l.name||""){case"vat":s=$$.sel().appendTo($$.td(o,{class:"vsel"})),d=(i.admin.ust_options||"19,0%;16,0%;0,0%").split(";"),$.each(d,((e,t)=>{$$.opt(t,t).appendTo(s)})),s.click((function(e){e.stopPropagation()})).val(c[l.name]).change().change({frm:a,tgt:e,mode:t,id:c.Id,td:u,includes:n},$inv.setvat),u.toggleClass("hl",c[l.name].substr(0,2)!==d[0].substr(0,2)).click((function(e){e.stopPropagation(),$(this).toggleClass("av")}));break;case"balance":u.aC("sh_"+(c.SollHaben||"").toLowerCase());break;case"invstatus":case"reminderstatus":u.aC(("invstatus"===l.name?"is_":"rs_")+c[l.name])}}))}))},complete:()=>{i.ldng(0)}})},setvat:function(e){let t=$(this),n=e.data||{};$ocms.postXT({url:$ocms.url("inv/setvat"),data:{id:n.id,val:t.val()},success:e=>{n.td.rC("av"),$inv.renderinv(n.tgt,n.mode,n.includes)}})},downloadzip:function(e,t){$(this).empty();window.open($ocms.url("inv/datevzip?mode="+t+"&tgt="+encodeURIComponent(e)),"_blank")},showitm:function(e){let t=$(this).closest("tr");e.stopPropagation(),!1!==t.is(".selected")&&$ocms.postXT({url:$ocms.url("inv/rqi"),data:{id:e.data.id},success:e=>{let t=$$.dc("rfrm");(e.requests||[]).length<1?t.text($ict.nd):$.each(e.requests||[],(function(e,n){let i=$$.dc("srq",t);$$.dc("nme",i).text(n.name);let a=$$.tblset({class:"if"},i);$.each(n.items||[],((e,t)=>{let n=$$.tr({id:"itm"+t.Id}).appendTo(a.bdy);$$.td(n).text(t.NameOrNumber),$$.td(n).text(t.Type),$$.td(n).aC("currency").text(t.net_pos),$$.td(n).aC("currency").text(t.bo_pos),$$.td(n).aC("num").text(t.vat)}))})),$ocms.dlg(t,{width:1e3})}})},showpay:function(e){let t=$(this).closest("tr");e.stopPropagation(),!1!==t.is(".selected")&&$ocms.postXT({url:$ocms.url("inv/pyi"),data:{id:e.data.id},success:e=>{let t=$$.dc("rfrm");if((e.payments||[]).length<1)t.text($ict.nd);else{let n=$$.tblset({class:"if"},t),i=$$.tr(n.hd);$.each(["date","account","name","text","InvoiceID","amount","manual"],((e,t)=>{$$.th(i,$ict.payi[t])})),$.each(e.payments,((e,t)=>{let i=$$.tr({id:"itm"+t.banking_uid}).appendTo(n.bdy);$$.td(i).aC("date").text(t.date),$$.td(i).text(t.account),$$.td(i).text(t.name),$$.td(i).text(t.text),$$.td(i).text(t.InvoiceID),$$.td(i).aC("currency").text(t.amount),$$.td(i).text(t.manual)}))}$ocms.dlg(t,{width:1e3,title:"Übersicht der Zahlungen"})}})},downloadinv:function(e){let t=$(this).closest("tr");e.stopPropagation(),!1!==t.is(".selected")&&window.open($ocms.url("inv/rdoc?id="+e.data.id),"_blank")},doContInv:function(e){let t=$(this).closest("tr");e.stopPropagation(),!1!==t.is(".selected")&&$inv.cntInv({id:e.data.id})}},$$inv={init2:$inv.init2,auth:{}};export default $$inv;$inv.cInv=function(e){let t=$(this).closest("tr");e.stopPropagation(),!1!==t.is(".selected")&&!1!==$fis.isAuth("fds_inv",2)&&$inv.cInv2({id:e.data.id})},$inv.rMn=e=>{let t=[{lbl:$ict.req,itm:[]}];return!0===bool(e,!1)&&!0===$fis.isAuth("fds_inv",2)&&Array.prototype.push.apply(t[0].itm,[{lbl:$rct.crI,fnc:$inv.ccInv,data:{typ:"r"}},{lbl:$rct.crII,fnc:$inv.ccInv,data:{typ:"i"}}]),t.push({lbl:$ict.rel,fnc:$inv.rReload}),$("#topbar").ocmsmenu(t)},$inv.iMnr=e=>{let t=booln(e.isFinal,!0),n=e.Id,i=booln(e.fds,!1),a=[{glyph:"glyphicon-menu-left",fnc:()=>{$fis.frm_edit().remove()}},{lbl:$ict.inv,itm:[]},{lbl:$ict.rem,itm:[]}];return!1===t&&!0===$fis.isAuth("fds_inv",2)?a[1].itm.push({lbl:$ict.ced,fnc:$inv.clCntInv}):!0===$fis.isAuth("fds_inv",1)&&a[1].itm.push({lbl:$ict.dsp,fnc:()=>$inv.disp(n,"inv")}),!0===i&&!0===t&&!0===$fis.isAuth("fds_inv",2)&&(a[1].itm.push({lbl:$ict.storno,fnc:()=>$inv.storno(n,i)}),a[1].itm.push({lbl:$ict.credit,fnc:()=>$inv.credit(n,i)})),!0===t&&!0===$fis.isAuth("fds_reminder",2)&&(a[2].itm.push({lbl:$ict.remd,fnc:()=>$inv.ccRem(n,e.InvoiceId)}),a[2].itm.push({lbl:$ict.remlst,fnc:()=>$inv.dspRem(n)})),!0===t&&!0===$fis.isAuth("fds_reminder",2)&&!1===booln(e.IsSent,!1)&&a[2].itm.push({lbl:$ict.srs,fnc:()=>$inv.srs(n)}),a.push({lbl:$ict.rel,fnc:$inv.rReload}),$("#topbar").ocmsmenu(a)},$inv.iMn=e=>{let t=booln(e.isFinal,!0),n=e.Id,i=booln(e.fds,!1),a=[{glyph:"glyphicon-menu-left",fnc:()=>{$fis.frm_edit().remove()}},{lbl:$ict.inv,itm:[]},{lbl:$ict.rem,itm:[]}];return!1===t&&!0===$fis.isAuth("fds_inv",2)?a[1].itm.push({lbl:$ict.ced,fnc:()=>{$inv.cntInv({id:n})}}):!0===$fis.isAuth("fds_inv",1)&&a[1].itm.push({lbl:$ict.dsp,fnc:()=>$inv.disp(n,"inv")}),!0===$fis.isAuth("fds_inv",2)&&(a[1].itm.push({lbl:$ict.storno,fnc:()=>$inv.storno(n,i)}),a[1].itm.push({lbl:$ict.credit,fnc:()=>$inv.credit(n,i)})),!0===t&&!1===booln(e.IsPayed,!1)?(!0===$fis.isAuth("fds_reminder",2)&&a[2].itm.push({lbl:$ict.remd,fnc:()=>$inv.ccRem(n,e.InvoiceId)}),!0===$fis.isAuth("fds_inv",2)&&a[1].itm.push({lbl:$ict.setpyd,fnc:()=>$inv.setPyd(n)})):!0===t&&!0===booln(e.IsPayed,!1)&&"m"===(e.PaymentStatus||"")&&!0===$fis.isAuth("fds_inv",2)&&a[1].itm.push({lbl:$ict.setupd,fnc:()=>$inv.setUpd(n)}),!0===$fis.isAuth("fds_reminder",2)&&a[2].itm.push({lbl:$ict.remlst,fnc:()=>$inv.dspRem(n)}),!0===t&&!0===$fis.isAuth("fds_inv",2)&&!1===booln(e.IsSent,!1)&&a[1].itm.push({lbl:$ict.sis,fnc:()=>$inv.sis(n)}),!1===i&&a[1].itm.push({lbl:$ict.mfr,fnc:()=>$inv.mfrrel(n)}),$("#topbar").ocmsmenu(a)},$inv.eM=(e,t,n)=>{let i=[];return!0!==booln(e,!1)&&!0!==booln(t,!1)||i.push({glyph:"glyphicon-menu-left",fnc:()=>{$fis.lf(!0),$fis.frm_edit().remove()}}),!0===(n||"").split(",").includes("iss")&&i.push({lbl:$ict.iss,fnc:$inv.ssave}),!0===(n||"").split(",").includes("ctp")&&i.push({lbl:$ict.ctp,fnc:$inv.sctp}),!0===(n||"").split(",").includes("p13b")&&i.push({lbl:$ict.p13b,fnc:$inv.sp13b}),!0===(n||"").split(",").includes("setm")&&i.push({lbl:$ict.setm,fnc:$inv.ssetmode}),!0===(n||"").split(",").includes("iss")&&(i.push({lbl:"Änderungshistorie",fnc:()=>$inv.d.history()}),i.push({lbl:"Änderungen verwerfen",fnc:()=>$inv.d.discard()})),!0===booln(e,!1)&&i.push({lbl:$ict.rel,fnc:$inv.rReload}),$("#topbar").ocmsmenu(i)},$inv.d={tbl:()=>$("div.invoice_layout table.invi"),layout:()=>$("div.invoice_layout"),token:function(){return $inv.d.tbl().data("dtoken")||""},hashes:function(){let e=$inv.d.tbl().data("bai")||[],t={};return $.each(e,((e,n)=>{t[(n.Id||"").toString()]=JSON.stringify(n)})),t},seed:function(e){let t=$inv.d.layout();t.aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dopen"),data:{payload:JSON.stringify(e)},success:e=>{$inv.d.tbl().data("dtoken",e.token).data("dver",e.version).data("dhashes",$inv.d.hashes()).data("dorder",$inv.d.order()),$fis.draft.bind(e.token,{onReady:()=>$inv.d.refresh(),onExpiring:e=>$inv.d.warnExpiry(e),onClosed:e=>$inv.d.closed(e)}),$inv.d.refresh()},error:()=>{t.rC("freeze")},complete:()=>{$inv.d.tbl().removeData("dseeding")}})},refresh:function(e){let t=$inv.d.token();""!==t&&$ocms.postXT({url:$ocms.url("inv/dstate"),data:{token:t},success:t=>{$inv.d.applyState(t),"function"==typeof e&&e(t)},error:e=>{e&&410===e.status&&$inv.d.closed("expired")},complete:()=>{$inv.d.layout().rC("freeze")}})},applyState:function(e){let t=$inv.d.tbl();t.length<1||(t.data("dver",e.version).data("serverSums",e.sums),$inv.d.footer(t,e.sums||{},e.admin||{}),$inv.d.validation(e.validation||[]),$inv.d.applyPositions(t,e.req||[]))},applyPositions:function(e,t){(t||[]).forEach((t=>(t&&t.itm||[]).forEach((t=>{if(!t||""===(t.id||""))return;let n=e.find("#itm"+t.id+" td.keep").first();n.length&&n.text(null!=t.p?t.p:"")}))))},sync:function(e){let t=$inv.d.token();""!==t&&($inv.d.layout().aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dpatch"),data:{token:t,delta:JSON.stringify(e)},success:()=>{$inv.d.refresh()},error:e=>{$inv.d.layout().rC("freeze"),e&&410===e.status&&$inv.d.closed("expired")}}))},order:function(){return($inv.d.tbl().data("bai")||[]).map((e=>(e.Id||"").toString()))},syncChanged:function(e){if(""===$inv.d.token())return;let t=e.data("bai")||[],n=e.data("dhashes")||{},i={},a=[],r=[];$.each(t,((e,t)=>{let r=(t.Id||"").toString(),l=JSON.stringify(t);i[r]=l,n[r]!==l&&a.push(t)})),$.each(n,(e=>{void 0===i[e]&&r.push(e)}));let l=$inv.d.order(),s=e.data("dorder")||[];e.data("dhashes",i).data("dorder",l),a.forEach((e=>$inv.d.sync({Target:"block.replace",Ref:(e.Id||"").toString(),Value:e}))),r.forEach((e=>$inv.d.sync({Target:"block.remove",Ref:e}))),s.length===l.length&&s.slice().sort().join(",")===l.slice().sort().join(",")&&s.join(",")!==l.join(",")&&$inv.d.sync({Target:"block.order",Value:l})},syncField:function(e,t){if(""===$inv.d.token())return;let n={invoicetitle:"title",invoiceaddress:"address",invoiceemail:"email",loc:"provisionlocation",provisionlocation:"provisionlocation",provisionperiod:"provisionperiod"}[e];n&&$inv.d.sync({Target:n,Value:t})},footer:function(e,t,n){let i=e.children("tfoot").empty();e.nextAll(".fnote").remove();let a=bool(n.p13b,!1),r=(e,t,n)=>$$.tdc("currency",$$.tr(i,{class:n||"tsum"}).append([$$.tdc("aux"),$$.td({colspan:4}).text(e)]),fnum(t,$rct.cst)),l=t=>$$.dc("fnote").insertAfter(e).rwText(t);r("Netto",t.total_net||0),!1===a&&$.each(t.vat||{},((e,t)=>r($rct.vat+" "+e+"%",t,"tvat"))),r("Summe",t.total_gross||0);let s=n.type||"";"i"===s?(l($rct.note2),l($rct.note4)):"c"===s?l($rct.note2):(l(string($rct.note3,[fnum(((t.service_net||0)+(t.service_vat||0))*(n.tax_servicerefund||0),$rct.cst)])).aC("ntax"),l($rct.note2),l(string($rct.note1,[fnum((t.service_net||0)+(t.service_vat||0),$rct.cst),fnum(t.service_net||0,$rct.cst),fnum(t.service_vat||0,$rct.cst)]))),!0===a&&l($rct.note13b)},validation:function(e){let t=$("div.invoice_layout");if(t.length<1)return;let n=t.children(".dvalidation");n.length<1&&(n=$$.dc("dvalidation"),t.prepend(n)),n.empty().tC("hidden",(e||[]).length<1),$.each(e||[],((e,t)=>$$.dc("dvmsg",n).aC(t.severity).text(t.message)))},preview:function(){let e=$inv.d.token();if(""===e)return;let t=$inv.d.layout(),n=($inv.d.tbl().data("new")||{}).invoiceemail||"";!1===$fis.ValidateEmail(n)&&!1===bool(confirm($ict.ivE+$ict.ivEc),!1)||(t.aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dpreview"),data:{token:e},success:n=>{t.rC("freeze");let i=$$.dc("imagecollection pdfpreview"),a=Math.round(.88*vh()),r=n.total;r>10&&$$.dc("note warn",i).text($ict.tpe),$.each(n.img||[],((e,t)=>{$$.dc("pdfp",i).append($$.img(t).css("max-height",(a-rpx(6)).toString()+"px"))}));for(let e=(n.img||[]).length+1;e<=r;e++)$$.dc("pdfp ph",i).append($$.dc("note",$ict.pna));$ocms.dlg(i,{size:[a,Math.round(.88*vw())],zindex:50,form:!1,button:$rct.crI,confirm:function(n){let i=$(this);t.aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dsave"),data:{token:e},success:e=>{$ocms.postXT({url:$ocms.url("req/sconf"),data:{id:e.invid},success:t=>{i.trigger("modal_close"),!0===t.hasFile&&window.open($ocms.url("req/idoc")+"?id="+e.invid,"_blank"),$inv.d.close(),$ocms.init("req"),$inv.rReload()},error:()=>{alert($t.f1),i.trigger("modal_close")},complete:()=>{t.rC("freeze")}})},error:()=>{t.rC("freeze"),alert($ict.eis)}})},cancel:function(e){confirm($ict.cdI)&&($inv.d.close(),$inv.rReload())}})},error:()=>{t.rC("freeze"),alert($ict.eis)}}))},save:function(){let e=$inv.d.token();if(""===e)return;let t=$inv.d.layout();t.aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dsave"),data:{token:e},success:e=>{$inv.d.tbl().data("invid",e.invid)},error:()=>{alert($ict.eis)},complete:()=>{t.rC("freeze")}})},history:function(){let e=$inv.d.token();""!==e&&$ocms.postXT({url:$ocms.url("inv/dhistory"),data:{token:e},success:e=>{let t=$$.dc("dhist");if((e.history||[]).length<1)$$.dc("note",t).text("Noch keine Änderungen erfasst.");else{let n=$$.tblset({class:"invtbl fullwidth"},t);$$.tr(n.hd).append([$$.th().text("Zeit"),$$.th().text("Feld"),$$.th().text("Alt"),$$.th().text("Neu")]),$.each(e.history,((e,t)=>$$.tr(n.bdy).append([$$.tdc("keep",fdt(t.timestamp)),$$.td().text(t.target),$$.td().text(t.oldValue),$$.td().text(t.newValue)])))}$ocms.dlg(t,{width:800,form:!1})}})},discard:function(){let e=$inv.d.tbl().data("invid")||"";""!==e?!1!==confirm("Alle Änderungen verwerfen und den zuletzt gespeicherten Stand neu laden?")&&($inv.d.close(),$inv.cntInv({id:e})):alert("Es wurde noch kein Zwischenstand gespeichert, der wiederhergestellt werden könnte.")},warnExpiry:function(e){let t=Math.max(1,Math.round((e||0)/60));$fis.notifications.push({severity:"info",title:"Entwurf läuft ab",message:"Der Rechnungsentwurf läuft in etwa "+t+" Minute(n) ab. Bitte zwischenspeichern, sonst gehen die Änderungen verloren."})},closed:function(e){let t=$inv.d.token();$inv.d.tbl().removeData("dtoken"),""!==t&&$fis.draft.release(t),$fis.frm_edit().remove(),$fis.lf(!0),$fis.notifications.push({severity:"error",title:"Entwurf geschlossen",message:"expired"===e?"Der Rechnungsentwurf ist wegen Inaktivität abgelaufen. Nicht gespeicherte Änderungen sind verloren.":"Der Rechnungsentwurf wurde geschlossen."});try{$inv.rReload()}catch(e){}},close:function(){let e=$inv.d.token();""!==e&&($ocms.postXT({url:$ocms.url("inv/dclose"),data:{token:e}}),$fis.draft.release(e)),$inv.d.tbl().removeData("dtoken")}},$inv.rd={tbl:()=>$("div.invoice_layout table.invi"),layout:()=>$("div.invoice_layout"),token:function(){return $inv.rd.tbl().data("rdtoken")||""},seed:function(e){let t=$inv.rd.layout();t.aC("freeze"),$ocms.postXT({url:$ocms.url("rem/dopen"),data:{payload:JSON.stringify(e)},success:e=>{$inv.rd.tbl().data("rdtoken",e.token).data("rdver",e.version),$fis.draft.bind(e.token,{onReady:()=>$inv.rd.refresh(),onExpiring:e=>$inv.rd.warnExpiry(e),onClosed:e=>$inv.rd.closed(e)}),$inv.rd.refresh()},error:()=>{t.rC("freeze")}})},refresh:function(e){let t=$inv.rd.token();""!==t&&$ocms.postXT({url:$ocms.url("rem/dstate"),data:{token:t},success:t=>{$inv.rd.applyState(t),"function"==typeof e&&e(t)},error:e=>{e&&410===e.status&&$inv.rd.closed("expired")},complete:()=>{$inv.rd.layout().rC("freeze")}})},applyState:function(e){let t=$inv.rd.tbl();t.length<1||(t.data("rdver",e.version).data("serverSums",e.sums).data("remid",e.remid||""),$inv.rd.footer(t,e.sums||{}),$inv.rd.validation(e.validation||[]))},sync:function(e){let t=$inv.rd.token();""!==t&&($inv.rd.layout().aC("freeze"),$ocms.postXT({url:$ocms.url("rem/dpatch"),data:{token:t,delta:JSON.stringify(e)},success:()=>{$inv.rd.refresh()},error:e=>{$inv.rd.layout().rC("freeze"),e&&410===e.status&&$inv.rd.closed("expired")}}))},syncField:function(e,t){if(""===$inv.rd.token())return;let n={subject:"subject",invoiceaddress:"address",invoiceemail:"email",text:"text"}[e];n&&$inv.rd.sync({Target:n,Value:t})},syncAmount:function(e,t){""!==$inv.rd.token()&&($inv.rd.sync({Target:"amount",Value:(null!=e?e:0).toString()}),$inv.rd.sync({Target:"amount_payed",Value:(null!=t?t:0).toString()}))},footer:function(e,t){let n=e.children("tfoot").empty(),i=$$.tr(n,{class:"tsum"}).append([$$.tdc("aux"),$$.td({colspan:3}).text("Offener Betrag")]);$$.tdc("currency",i,fnum(t.amount_open||0,$rct.cst))},validation:function(e){let t=$inv.rd.layout();if(t.length<1)return;let n=t.children(".dvalidation");n.length<1&&(n=$$.dc("dvalidation"),t.prepend(n)),n.empty().tC("hidden",(e||[]).length<1),$.each(e||[],((e,t)=>$$.dc("dvmsg",n).aC(t.severity).text(t.message)))},preview:function(){let e=$inv.rd.token();if(""===e)return;let t=$inv.rd.layout(),n=($inv.rd.tbl().data("new")||{}).invoiceemail||"";!1===$fis.ValidateEmail(n)&&!1===bool(confirm($ict.ivE+$ict.ivEc),!1)||(t.aC("freeze"),$ocms.postXT({url:$ocms.url("rem/dpreview"),data:{token:e},success:n=>{t.rC("freeze");let i=$$.dc("imagecollection pdfpreview"),a=Math.round(.88*vh());$.each(n.img||[],((e,t)=>{$$.dc("pdfp",i).append($$.img(t).css("max-height",(a-rpx(6)).toString()+"px"))})),$ocms.dlg(i,{size:[a,Math.round(.88*vw())],zindex:50,form:!1,button:$ict.remd,confirm:function(n){let i=$(this);t.aC("freeze"),$ocms.postXT({url:$ocms.url("rem/dsave"),data:{token:e},success:e=>{$ocms.postXT({url:$ocms.url("rem/conf"),data:{id:e.remid},success:()=>{i.trigger("modal_close"),window.open($ocms.url("rem/idoc")+"?id="+e.remid,"_blank"),$inv.rd.close(),$ocms.init("req"),$inv.rReload()},error:()=>{alert($t.f1),i.trigger("modal_close")},complete:()=>{t.rC("freeze")}})},error:()=>{t.rC("freeze"),alert($t.f1)}})},cancel:function(e){confirm($ict.cdI)&&($inv.rd.close(),$inv.rReload())}})},error:()=>{t.rC("freeze"),alert($t.f1)}}))},save:function(){let e=$inv.rd.token();if(""===e)return;let t=$inv.rd.layout();t.aC("freeze"),$ocms.postXT({url:$ocms.url("rem/dsave"),data:{token:e},success:e=>{$inv.rd.tbl().data("remid",e.remid)},error:()=>{alert($t.f1)},complete:()=>{t.rC("freeze")}})},history:function(){let e=$inv.rd.token();""!==e&&$ocms.postXT({url:$ocms.url("rem/dhistory"),data:{token:e},success:e=>{let t=$$.dc("dhist");if((e.history||[]).length<1)$$.dc("note",t).text("Noch keine Änderungen erfasst.");else{let n=$$.tblset({class:"invtbl fullwidth"},t);$$.tr(n.hd).append([$$.th().text("Zeit"),$$.th().text("Feld"),$$.th().text("Alt"),$$.th().text("Neu")]),$.each(e.history,((e,t)=>$$.tr(n.bdy).append([$$.tdc("keep",fdt(t.timestamp)),$$.td().text(t.target),$$.td().text(t.oldValue),$$.td().text(t.newValue)])))}$ocms.dlg(t,{width:800,form:!1})}})},warnExpiry:function(e){let t=Math.max(1,Math.round((e||0)/60));$fis.notifications.push({severity:"info",title:"Entwurf läuft ab",message:"Der Mahnentwurf läuft in etwa "+t+" Minute(n) ab. Bitte zwischenspeichern, sonst gehen die Änderungen verloren."})},closed:function(e){let t=$inv.rd.token();$inv.rd.tbl().removeData("rdtoken"),""!==t&&$fis.draft.release(t),$fis.frm_edit().remove(),$fis.lf(!0),$fis.notifications.push({severity:"error",title:"Entwurf geschlossen",message:"expired"===e?"Der Mahnentwurf ist wegen Inaktivität abgelaufen. Nicht gespeicherte Änderungen sind verloren.":"Der Mahnentwurf wurde geschlossen."});try{$inv.rReload()}catch(e){}},close:function(){let e=$inv.rd.token();""!==e&&($ocms.postXT({url:$ocms.url("rem/dclose"),data:{token:e}}),$fis.draft.release(e)),$inv.rd.tbl().removeData("rdtoken")}},$inv.cInv2=function(e){let t=$$.dc("rfrm").ldng(1),n=$ocms.dlg(t,{width:1e3});n&&n.ft.rwText($rct.rq1);let i=()=>{$ocms.postXT({url:$ocms.url("req/get"),timeout:60,data:{id:e.id,mode:"r"},success:t=>{t.admin=t.admin||{};let n=$fis.lf(!0).aC("fix").rC("hd");if($fis.frm_edit().IN(),$inv.eM(!0,!0),(t.requests||[]).length<1)n.aC("fix").text($rct.nd);else{$$.dc("lh",n,$rct.mdl);let i=$$.d(),a=$$.ul({class:"rql"}).data({search:e.id,parent:t.admin.parent}).appendTo(n),r={},l=$rcol.req.lbl();$.each(t.requests||[],(function(e,t){let n=$$.li({class:"cli rli"}).data($.extend({},t)).appendTo(a),s=$$.dc("lihd",n).addClass(t.state);!0===booln(t.open,!1)&&s.append($$.sc("cbox").click((()=>{n.tC("checked"),i.find("li").rC("checked"),!0===n.is(".checked")?$inv.rMn(t.open):$inv.eM(!0)}))),s.append([$$.sc("eid",t.ExternalId),$$.sc("nme",t.Name)]),$$.dc("lidt",n).append([$$.dc("rqs").append([$$.s(l.State+": "),$$.s($rct.sts[t.State||"-"])]),$$.dc("ivn").append([$$.s(l.InvoiceId+": "),$$.s(t.InvoiceId||"- -")]),$$.dc("wda").append([$$.s(l.WorkDoneAt+": "),$$.s(fdt(t.WorkDoneAt,"dd.MM.yyyy"))])]),r[t.Id]=n})),(t.inv||[]).length>0&&($$.dc("lh",n,$rct.invs),i=$$.ul({class:"ivl"}).appendTo(n),$.each(t.inv||[],((e,t)=>{let n=$$.li({class:"cli ili"}).data($.extend({},t)).appendTo(i),r=$$.dc("lihd",n).addClass(t.invstatus);!1===booln(t.isFinal,!0)?r.append($$.sc("cbox").click((()=>{""!==(t.Id||"")&&(n.tC("checked").siblings().rC("checked"),a.find("li").rC("checked"),!0===n.is(".checked")?$inv.iMnr(t):$inv.eM(!0))}))):["","dft"].indexOf(t.invstatus)<0&&r.append($$.sc("dli").click((function(){$inv.disp(t.Id,"inv")}))),r.append($$.sc("nme",t.DocumentName||t.Id)),$$.dc("lidt",n).append([$$.dc("wda").append([$$.s(fdt(t.DateCreated,"dd.MM.yyyy"))]),$$.d().text($ict.iSt[t.invstatus]||t.invstatus)])})))}},complete:()=>{n&&n.c.trigger("modal_close")}})};$ocms.postXT({url:$ocms.url("req/pget"),timeout:90,data:{id:e.id},success:e=>{n&&n.ft.rwText($rct.rq2),i()},error:()=>{confirm($rct.rq1f)?(n&&n.ft.rwText($rct.rq2),i()):n&&n.c.trigger("modal_close")}})},$inv.ccInv=function(e){let t=(e.data||{}).typ||"r",n=$fis.lf(),i=n.children("ul.rql"),a=i.data("parent"),r=[];if(i.find("li.rli.checked").each((function(){r.push($(this).data("Id"))})),r.length<1)return void alert($rct.dnS);if("i"===t&&r.length>1)return void alert($rct.dII);let l=$fis.frm_edit(),s=$$.dc("invoice_layout",l).append($$.dc("btn sprev").click($inv.sprev)),d=$fis.cf().width()>s.width()+n.width()+20;n.tC("fix",d).tC("hd",!d),$inv.eM(!1,!0);let c=$$.dc("rfrm").ldng(1),o=$ocms.dlg(c,{width:1e3});o.ft.rwText($rct.rq2),$ocms.postXT({url:$ocms.url("req/iget"),timeout:60,data:{id:a,mode:"ful",typ:t,sel:r.join(",")},success:e=>{let t=$$.dc("srq",s),n=$$.tblset({class:"invi"},t);n.bdy.remove(),n.ft=$$[0]("tfoot"),e.admin=e.admin||{},e.admin.p13b=bool(e.admin.p13b||"",!0===((e.inv||{}).InvoiceOptions||"").split(",").includes("§13b")),n.tbl.data($.extend({new:{},sms:{},itm:{}},{admin:e.admin,companies:e.companies,locations:e.locations}));let i=$$.tr(n.hd).aC("shd").append([$$.th().aC("aux")]);$rct.invHR.forEach((e=>$$.th(i,e))),n.tbl.on("fds.inv",$inv.invSumUpdate),$.each(e.requests||[],(function(t,i){if(0!==(i.Id||0)){let t=$inv.worknotes(i);i.text="i"===e.admin.type?$rct.req+jine([i.ExternalId,i.Name],": ").eine(" ",""):jine([jine([fdt(i.WorkDoneAt,"dd.MM.yy"),i.ExternalId]," - "+$rct.req+" "),t.ne(i.Name)],": \n");let a=$$.tbody(n.tbl).data($.extend({},i));$inv.rendersrq.call(a)}}));let a=$$.tr($$.tbody(n.tbl),{class:"placeholder"}).data({net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0});$inv.rrw.call(a),n.ft.appendTo(n.tbl);let r,l,d=e.admin||{},c=(e,t,i,a,r)=>{let l=$$.dc("inpfrm",s).aC(e).append("string"==typeof a?$$.dc("ahd",a):a>0?$$.dc("ahd",$rct.frm[i]):null),d=$$.dc("content",l).rwText(t);$$.dc("axf",l).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:d,nme:i,change:e=>{n.tbl.data("new")[i]=e}},r),$inv.eHtml)),n.tbl.data("new")[i]=t};c("tfrm",d.invoicetitle,"invoicetitle",0,null),c("adrfrm",d.invoiceaddress,"invoiceaddress",0,null),c("locfrm","","loc",1,{list:deepCopy(e.locations),lbl:"ref",property:"address"}),c("emailfrm",d.invoiceemail,"invoiceemail",0,null),$$.dc("sndfrm",s).append($$.dc("content").text(d.sender)),d.provisionend&&(l=d.provisionstart?$rct.provP:$rct.provD,r=d.provisionstart?fdt(d.provisionstart,"dd.MM.yyyy")+" - "+fdt(d.provisionend,"dd.MM.yyyy"):fdt(d.provisionend,"dd.MM.yyyy")),c("admfrm",r,"provisionperiod",l,1),n.tbl.data("new").CustomValues=d.CustomValues||"",$$.dc("inpfrm ctpfrm",s).text(jObj(d.CustomValues,"contactName")),n.tbl.children("tbody").each($inv.bdysort),n.tbl.trigger("fds.inv"),$inv.eM(!1,!0,"iss,p13b,setm,ctp")},complete:()=>{o.c.trigger("modal_close")}})},$inv.ccStInv=function(e){let t=e.data||{},n=$fis.lf(),i=t.id,a=$$.dc("invoice_layout",$fis.frm_edit()).append($$.dc("btn sprev").click($inv.sprev)),r=$fis.cf().width()>a.width()+n.width()+20;n.tC("fix",r).tC("hd",!r),$inv.eM(!1,!0);let l=$$.dc("rfrm").ldng(1),s=$ocms.dlg(l,{width:1e3});s.ft.rwText($ict.iq1),$ocms.postXT({url:$ocms.url("inv/pget"),timeout:90,data:{id:t.id},success:e=>{s&&s.ft.rwText($ict.iq2),$ocms.postXT({url:$ocms.url("inv/icget"),timeout:60,data:{id:i},success:e=>{let t=$$.dc("srq",a),n=$$.tblset({class:"invi"},t);n.bdy.remove(),n.ft=$$[0]("tfoot"),e.admin=e.admin||{},e.admin.p13b=bool(e.admin.p13b||"",!0===((e.inv||{}).InvoiceOptions||"").split(",").includes("§13b")),n.tbl.data($.extend({new:{},sms:{},itm:{}},{admin:e.admin,companies:e.companies,locations:e.locations}));let i=$$.tr(n.hd).aC("shd").append([$$.th().aC("aux")]);$rct.invHR.forEach((e=>$$.th(i,e))),n.tbl.on("fds.inv",$inv.invSumUpdate),$.each(e.requests||[],(function(t,i){if(0!==(i.Id||0)){let t=$inv.worknotes(i);i.text="i"===e.admin.type?$rct.req+jine([i.ExternalId,i.Name],": ").eine(" ",""):jine([fdt(i.WorkDoneAt,"dd.MM.yy")+t.ne(i.Name)],": ");let a=$$.tbody(n.tbl).data($.extend({},i));$inv.rendersrq.call(a)}}));let r=$$.tr($$.tbody(n.tbl),{class:"placeholder"}).data({net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0});$inv.rrw.call(r),n.ft.appendTo(n.tbl);let l,s,d=e.admin||{},c=(e,t,i,r,l)=>{let s=$$.dc("inpfrm",a).aC(e).append("string"==typeof r?$$.dc("ahd",r):r>0?$$.dc("ahd",$rct.frm[i]):null),d=$$.dc("content",s).rwText(t);$$.dc("axf",s).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:d,nme:i,change:e=>{n.tbl.data("new")[i]=e}},l),$inv.eHtml)),n.tbl.data("new")[i]=t};c("tfrm",d.invoicetitle,"invoicetitle",0,null),c("adrfrm",d.invoiceaddress,"invoiceaddress",0,null),c("locfrm",d.provisionlocation,"loc",1,{list:deepCopy(e.locations),lbl:"ref",property:"address"}),c("emailfrm",d.invoiceemail,"invoiceemail",0,null),$$.dc("sndfrm",a).append($$.dc("content").text(d.sender)),d.provisionend&&(s=d.provisionstart?$rct.provP:$rct.provD,l=d.provisionstart?fdt(d.provisionstart,"dd.MM.yyyy")+" - "+fdt(d.provisionend,"dd.MM.yyyy"):fdt(d.provisionend,"dd.MM.yyyy")),c("admfrm",l,"provisionperiod",s,1),n.tbl.data("new").CustomValues=d.CustomValues||"",$$.dc("inpfrm ctpfrm",a).text(jObj(d.CustomValues,"contactName")),n.tbl.children("tbody").each($inv.bdysort),n.tbl.trigger("fds.inv")},complete:()=>{s.c.trigger("modal_close")}})},error:()=>{s&&s.c.trigger("modal_close")}})},$inv.clCntInv=function(e){let t=$fis.lf(!1),n=[];t.find("li.ili.checked").each((function(){n.push($(this).data("Id"))})),1===n.length&&$inv.cntInv({id:n[0]})},$inv.cntInv=function(e){e=e||{};$fis.lf(!1).rC("fix").aC("hd");let t=$$.dc("invoice_layout",$fis.frm_edit()).append($$.dc("btn sprev").click($inv.sedit));$inv.eM(!1,!0);let n=$$.dc("rfrm").ldng(1),i=$ocms.dlg(n,{width:1e3});i.ft.rwText($rct.rq2),$ocms.postXT({url:$ocms.url("inv/get"),timeout:60,data:{id:e.id},success:e=>{e.admin=e.admin||{};let n=e.inv||{},i=$$.dc("srq",t),a=$$.tblset({class:"invi"},i);a.bdy.remove(),a.ft=$$[0]("tfoot"),a.tbl.data($.extend({invid:n.Id,new:{},sms:{},itm:{},bai:[]},e));let r=$$.tr(a.hd).aC("shd").append([$$.th().aC("aux")]);$rct.invHR.forEach((e=>$$.th(r,e))),a.tbl.on("fds.inv",$inv.invSumUpdate),$.each(e.req||[],(function(e,t){let n=$$.tbody(a.tbl).data($.extend({},t));$inv.rendersrq.call(n)}));let l=$$.tr($$.tbody(a.tbl),{class:"placeholder"}).data({net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0});$inv.rrw.call(l),a.ft.appendTo(a.tbl);let s=(e,n,i,r,l)=>{let s=$$.dc("inpfrm",t).aC(e).append("string"==typeof r?$$.dc("ahd",r):r>0?$$.dc("ahd",$rct.frm[i]):null),d=$$.dc("content",s).rwText(n);$$.dc("axf",s).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:d,nme:i,change:e=>{a.tbl.data("new")[i]=e}},l),$inv.eHtml)),a.tbl.data("new")[i]=n};s("tfrm",n.InvoiceTitle,"invoicetitle",0,null),s("adrfrm",n.SendToAddress,"invoiceaddress",0,null),s("locfrm",n.ProvisionLocation,"loc",1,null),s("emailfrm",n.SendToEmail,"invoiceemail",0,null),$$.dc("sndfrm",t).append($$.dc("content").text(e.admin.sender)),s("admfrm",n.ProvisionPeriod,"provisionperiod",!0===(n.ProvisionPeriod||"").includes("-")?$rct.provP:$rct.provD,1),a.tbl.data("new").CustomValues=n.CustomValues||"",$$.dc("inpfrm ctpfrm",t).text(jObj(n.CustomValues,"contactName")),a.tbl.children("tbody").each($inv.bdysort),a.tbl.trigger("fds.inv"),$inv.eM(!1,!0,"iss,p13b,setm,ctp")},complete:()=>{i.c.trigger("modal_close")}})},$inv.cSt=function(e){e=e||{};let t=$fis.lf(),n=$$.dc("invoice_layout",$fis.frm_edit()).append($$.dc("btn sprev").click($inv.sedit)),i=$fis.cf().width()>n.width()+t.width()+20;t.tC("fix",i).tC("hd",!i),$inv.eM(!1,!0);let a=$$.dc("rfrm").ldng(1),r=$ocms.dlg(a,{width:1e3});r.ft.rwText($ict.iq1),$ocms.postXT({url:$ocms.url("inv/pget"),data:{id:e.id},success:t=>{r&&r.ft.rwText($ict.iq2),$ocms.postXT({url:$ocms.url("inv/storno"),data:{id:e.id,mode:e.mode},success:e=>{e.admin=e.admin||{},e.admin.p13b=bool(e.admin.p13b||"",!0===((e.inv||{}).InvoiceOptions||"").split(",").includes("§13b"));let t=e.inv||{},i=$$.dc("srq",n),a=$$.tblset({class:"invi"},i);a.bdy.remove(),a.ft=$$[0]("tfoot"),a.tbl.data($.extend({invid:t.Id,new:{},sms:{},itm:{},bai:[]},e));let r=$$.tr(a.hd).aC("shd").append([$$.th().aC("aux")]);$rct.invHR.forEach((e=>$$.th(r,e))),a.tbl.on("fds.inv",$inv.invSumUpdate),$.each(e.req||[],(function(e,t){let n=$$.tbody(a.tbl).data($.extend({},t));$inv.rendersrq.call(n)}));let l=$$.tr($$.tbody(a.tbl),{class:"placeholder"}).data({net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0});$inv.rrw.call(l),a.ft.appendTo(a.tbl);let s=(e,t,i,r,l)=>{let s=$$.dc("inpfrm",n).aC(e).append("string"==typeof r?$$.dc("ahd",r):r>0?$$.dc("ahd",$rct.frm[i]):null),d=$$.dc("content",s).rwText(t);$$.dc("axf",s).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:d,nme:i,change:e=>{a.tbl.data("new")[i]=e}},l),$inv.eHtml)),a.tbl.data("new")[i]=t};s("tfrm",t.InvoiceTitle,"invoicetitle",0,null),s("adrfrm",t.SendToAddress,"invoiceaddress",0,null),s("locfrm",t.ProvisionLocation,"loc",1,null),s("emailfrm",t.SendToEmail,"invoiceemail",0,null),$$.dc("sndfrm",n).append($$.dc("content").text(e.admin.sender)),s("admfrm",t.ProvisionPeriod,"provisionperiod",!0===(t.ProvisionPeriod||"").includes("-")?$rct.provP:$rct.provD,1),a.tbl.data("new").CustomValues=t.CustomValues||"",$$.dc("inpfrm ctpfrm",n).text(jObj(t.CustomValues,"contactName")),a.tbl.children("tbody").each($inv.bdysort),a.tbl.trigger("fds.inv")},complete:()=>{r.c.trigger("modal_close")}})},error:()=>{r&&r.c.trigger("modal_close")}})},$inv.eHtml=function(e){let t=$(this),n=e.data instanceof jQuery?e.data:e.data.t,i=["invoiceemail","provisionperiod","invoicetitle"].includes(e.data.nme),a=i?[{name:"txt",label:"Text",type:"text",value:n.text()}]:[{name:"txt",label:"Text",type:"html",value:n.html(),tinymce:!0,attr:{style:"height: 300px"}}],r=e.data.change||null,l={title:t.data("dialog")||"",success:function(t){i?n.text(t.txt||""):n.html(t.txt),"function"==typeof r&&r(t.txt),$inv.d.syncField(e.data.nme,i?t.txt||"":t.txt),$inv.rd.syncField(e.data.nme,i?t.txt||"":t.txt)},tinymce:{valid_elements:"br",hidemenu:!0,hidetoolbar:!0}};if(Array.isArray(e.data.list)){let t=$$.dc("lstfrm");$.each(e.data.list,((n,i)=>{let a=$$.dc("li",t).append(""!==(e.data.lbl||"")?$$.dc("lbl").rwText(i[e.data.lbl]):null);$$.dc("adr",a).rwText(i[e.data.property]).data("val",i[e.data.property]).click((function(){let e=$(this),t=e.closest(".modal-body").find(':input[name="txt"]');t.is(".tinymce")?tinymce.get(t.attr("id")).setContent($$.s().rwText(e.data("val")).html()):"TEXTAREA"===t.prop("tagName")?t.val(e.data("val")).change():t.rwText(e.data("val"))}))})),l.addcontent=t}$ocms.dlgform(a,l)},$inv.setVat=function(e){$(this);let t=e.data,n=prompt($rct.rqV);n&&(n=parseFloat(n.replace("%","")),n>1&&(n*=.01),!1===isNaN(n)&&(t.siblings(".itm").each((function(){let e=$(this).data();e.vat=fnum(n,{style:"percent"}).replace(" ",""),(e.net_val||0)>0&&(e.vat_val=e.net_val*n),(e.svcnet_val||0)>0&&(e.svcvat_val=e.svcnet_val*n)})),$inv.t_fds_inv()))},$inv.inRow=function(e){let t=$(this),n=e.data,i={},a=$rcol.itm.clone(["SortOrder","NameOrNumber","Type","quantityhours","UnitString","net","svcnet_val","svcvat_val","net_val","vat_val","vat","Note"]),r="N"+(65536*(1+Math.random())||0).toString(16).substr(6),l=$$.tr({id:"itm_"+r.toString(),class:"itm"});$ocms.dlgform(a,{title:t.data("dialog")||"",success:function(e){l.data($.extend({Id:r},i,e)),$inv.rrw.call(l),l.insertAfter(n),$inv.t_fds_inv()},typedvalues:!0})},$inv.eRow=function(e){let t=$(this),n=e.data,i=n.data()||{},a=["SortOrder","NameOrNumber","Type","quantityhours","UnitString","net","svcnet_val","svcvat_val","net_val","vat_val","vat","Note"];i.id||""!==(i.Type||"")||a.unshift("Type");let r=$rcol.itm.clone(a).applyValues(i);r.set("Type","hidden","type"),$inv.eRw.call(t,n,i,r)},$inv.eRw=function(e,t,n){let i=$(this);$ocms.dlgform(n,{title:i.data("dialog")||"",success:function(n){let i={};""===(t.Id||"")&&(i.Id="N"+(65536*(1+Math.random())||0).toString(16).substr(6),e.attr("id","itm_"+i.Id.toString())),i.quantity=((n.quantityhours||"").toString()+" "+(n.UnitString||"").toString()).trimEnd(),e.data($.extend({},t,n,i)),console.debug("eRw success %o",e.data()),$inv.rrw.call(e),$inv.t_fds_inv()},typedvalues:!0})},$inv.bdysort=(e,t)=>{$(t).Sortable({dragItem:!1,dragHandleClass:"ico",parentident:"tr",onend:()=>{$inv.t_fds_inv()}})},$inv.rrw=function(){let e=$(this),t=e.data(),n={},i=e.is(".placeholder"),a=e.is(".hidenote"),r=e=>$$.d().append(e).html(),l=[$$.dc("ibtn insb",{title:$rct.iRb}).append(gi("indent-left")).click(e,$inv.inRow)];!1===i&&(l.unshift($$.dc("ibtn edit",{title:$rct.cP}).append(gi("pencil")).click(e,$inv.eRow)),l.push($$.dc("ibtn del",{title:$rct.dR}).append(gi("trash")).click((function(t){confirm($rct.cD)&&(e.remove(),$inv.t_fds_inv())}))));let s=$$.dc("axf").append(l);!0===i?n={id:"",typ:"placeholder"}:!0===e.is(".itm.osum")?n={invrqid:t.InvRqId,id:"osum"+e.index(),typ:"osum",p:"",q:null,t:r(t.tbl.tbl),tt:null,v:null,vt:t.net_val,vs:t.svcnet_val,vat:t.vat,vv:t.vat_val,vsv:t.svcvat_val,det:!1}:(n={invrqid:t.InvRqId,id:t.Id||"",typ:t.Type||"other",p:"",q:null,t:"",tt:null,v:null,vt:t.net_val,vs:t.svcnet_val,vat:t.vat,vv:t.vat_val,vsv:t.svcvat_val,det:""!==(t.Note||"")&&!1===a},$$.dc("ibtn ico move",s,{title:$rct.mR}),n.p=t.position||t.SortOrder||"",""===n.id?n.t="":["Text","Title"].includes(n.typ)&&0===(t.net_val||0)?n.t=t.htmltext||("#"!==(t.NameOrNumber||"").substr(0,1)?r($$[0]("p").text(t.NameOrNumber)):"")+(t.Note||""):(n.tt=n.det?"":$$.s(t.Note||"").text(),n.q=t.quantity||fnum(t.quantityhours)+" "+(t.UnitString||""),n.t=t.htmltext||(n.det?r($$.s(t.NameOrNumber||""))+r($$.dc("desc").html(t.Note)):r($$.s(t.NameOrNumber||""))),n.v=t.net,n.vt=t.net_val)),""!==(t.Note||"")&&$$.dc("ibtn add",s).append(gi("object-align-left")).click((function(t){$inv.rrw.call(e.tC("hidenote"))}));let d=[$$.tdc("aux").append(s),$$.tdc("keep").text(n.p)];""===n.id?d.push($$.td(e,{colspan:4}).append(n.t)):(Array.prototype.push.apply(d,n.q?[$$.tdc("keep").text(n.q)]:[]),Array.prototype.push.apply(d,[$$.tdc("txt",{colspan:n.q?1:2,title:n.tt}).append(n.t),$$.tdc("currency").text(fnum(n.v,$rct.cst)),$$.tdc("currency inetval").text(fnum(n.vt,$rct.cst)).attr("title",$rct.svcPart+": "+fnum(n.vs,$rct.cst))])),e.empty().attr("class",i?"placeholder":"itm").aC(n.Typ).tC("hidenote",a).append(d),t.co=n},$inv.invSumUpdate=function(){let e=$(this),t=e.children("tfoot").empty(),n=bool((e.data().admin||{}).p13b||"",!1);e.nextAll(".fnote").remove();let i={ttn:0,ttb:0,ttvat:0,tscn:0,tscvat:0,vat:{},itmnet:{}},a=[],r=(e,n,i)=>$$.tdc("currency",$$.tr(t,{class:i||"tsum"}).append([$$.tdc("aux"),$$.td({colspan:4}).text(e)]),fnum(n,$rct.cst)),l=t=>$$.dc("fnote").insertAfter(e).rwText(t),s=e.children("tbody");s.each(((e,t)=>{let n=$(t),r=n.data()||{},l=[],s=[],d=null,c=0,o=n.find("tr.itm"),u=0;n.tC("empty",o.length<1),o.each(((e,t)=>{let n=$(t).data()||{};!function(e,t,n){t.tscn+=e.svcnet_val||0,t.tscvat+=e.svcvat_val||0,t.ttn+=e.net_val||0,t.ttvat+=e.vat_val||0,t.ttb+=(e.net_val||0)+(e.vat_val||0),""!==(e.vat||"")&&(t.vat[e.vat]=(t.vat[e.vat]||0)+(e.vat_val||0))}(n,i,r.Id),c+=n.net_val||0,l.push(n.co);let a=$inv.itemToContract(n);"set"===a.type&&""!==a.id?d=a.id:null!==d&&""!==(a.id||"")&&(a.setId=d),s.push(a),(void 0===n.SortOrder||null===n.SortOrder?-1:n.SortOrder)>-1&&(!1===["text","title"].includes((n.Type||"other").toLowerCase())&&u++,n.SortOrder=0,n.position=u,$inv.rrw.call(t))})),n.find("tr.isum > td.isumval").text(fnum(c,$rct.cst)),a.push({Id:r.Id,nme:r.Name,text:r.text,itm:l,items:s,netval:c})}));let d=e.find("tbody:not(.empty)").length;s.find("tr.isum").tC("hidden",d<2),r("Netto",i.ttn),!1===n?$.each(i.vat,((e,t)=>{r($rct.vat+" "+e,t,"tvat")})):i.ttb=i.ttn,r("Summe",i.ttb);let c=e.data().admin.type;"i"===c?(l($rct.note2),l($rct.note4)):"c"===c?l($rct.note2):(l(string($rct.note3,[fnum((i.tscn+i.tscvat)*(e.data().admin.tax_servicerefund||0),$rct.cst)])).aC("ntax"),l($rct.note2),l(string($rct.note1,[fnum(i.tscn+i.tscvat,$rct.cst),fnum(i.tscn,$rct.cst),fnum(i.tscvat,$rct.cst)]))),!0===n&&l($rct.note13b),e.data("sms",i),e.data("bai",a),""===(e.data("dtoken")||"")&&!1===bool(e.data("dseeding"),!1)&&null!=(e.data("admin")||{}).type&&(e.data("dseeding",!0),$inv.d.seed($.extend($inv.invcPayload(e.data()),{invid:e.data("invid")||""})))},$inv.worknotes=function(e){let t="";return e.steps.forEach(((e,n)=>{let i;try{i=JSON.parse(e.Data||{}).fields||[]}catch(e){console.debug(e),i=[]}!0!==Array.isArray(i||"")&&(i="object"==typeof i&&!0===Array.isArray(i.field||"")?i.field:[]),i.forEach(((e,n)=>{"Ausgeführte Arbeiten"===e.name&&(t=e.result||"")}))})),t},$inv.rendersrq=function(){let e=$(this).empty(),t=e.is(".onesum"),n=e.data(),i=$$.tr(e,{id:"srq"+n.Id}).aC("title nosort"),a=($rcol.itm.lbl(),$$.dc("axf").appendTo($$.tdc("aux",i)));$$.dc("ibtn osum",a,{title:$rct.combP}).append(gi("euro")).click((function(t){e.tC("onesum"),$inv.rendersrq.call(e),$inv.t_fds_inv()})),$$.dc("ibtn setvat",a,{title:$rct.sV}).append(gi("gbp")).click(i,$inv.setVat),$$.dc("ibtn insb",a,{title:$rct.iRb}).append(gi("indent-left")).click(i,$inv.inRow);let r,l=$$.sc("text",n.text),s=($$.td(i,{colspan:t?4:5}).append(l),["net_val","vat_val","svcnet_val","svcvat_val","net"]);if($$.dc("ibtn edit",a).data("dialog",$rcol.req.lbl().Name).append(gi("pencil")).click({t:l,change:e=>{n.text=e,$inv.t_fds_inv()}},$inv.eHtml),t&&($$.tdc("currency isumval",i),r={Id:n.Id.toString()+"_osum",net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0},r.tbl=$$.tblset({class:"stbl"})),$.each(n.items||[],((n,i)=>{let a,l={Id:i.Id,net_val:i.net_val||0,vat_val:i.vat_val||0,svcnet_val:0,svcvat_val:0,net:i.net||0,Note:i.Note||""};if("service"===i.Type.toLowerCase())l.svcnet_val=i.net_val||0,l.svcvat_val=i.vat_val||0;t?(a=$$.tr(r.tbl.bdy,{id:"itm"+i.Id,class:"sitm"}).aC(i.Type),"Text"===i.Type||"Title"===i.Type?$$.td(a,{colspan:2}).html(i.htmltext||i.Note):($$.tdc("keep",a).text(i.quantity||((i.quantityhours||0)>0?fnum(i.quantityhours)+(i.UnitString||"").eine(" ",""):"")),i.htmltext?$$.tdc("txt",a).html(i.htmltext):$$.tdc("txt",a).text(i.NameOrNumber).attr("title",i.Note)),$.each(s,((e,t)=>{r[t]+=l[t]})),a.data(l)):($.extend(l,i),a=$$.tr(e,{id:"itm"+i.Id,class:"itm"}),a.data(l),$inv.rrw.call(a))})),t){let t=$$.tr(e,{id:"itmsq"+n.Id,class:"itm osum"}).data(r);$inv.rrw.call(t)}else{let t=$$.tr(e).aC("isum nosort");$$.tdc("aux",t),$$.td(t,{colspan:4}).text($rct.iSum),$$.tdc("currency isumval",t)}},$inv.t_fds_inv=()=>{let e=$("div.invoice_layout table.invi");e.trigger("fds.inv"),""!==(e.data("dtoken")||"")&&$inv.d.syncChanged(e)},$inv.sedit=()=>{$inv.sprev(!0)},$inv.jdisp=function(e){e.stopPropagation(),e.data.id&&$inv.disp(e.data.id,e.data.typ||"")},$inv.disp=(e,t)=>{let n="";switch(t){case"inv":n="inv/rdoc";break;case"rem":n="rem/rdoc"}""!==n&&$ocms.postXT({url:$ocms.url(n),data:{id:e||"",typ:"img"},success:e=>{let t=$$.dc("imagecollection pdfpreview"),n=Math.round(.88*vh());e.id;$.each(e.img||[],(function(e,i){$$.dc("pdfp",t).append($$.img(i).css("max-height",(n-rpx(6)).toString()+"px"))})),$ocms.dlg(t,{size:[n,Math.round(.88*vw())],zindex_min:50,form:!1,exclusive:!1})}})},$inv.jdbn=function(e){$ocms.postXT({url:$ocms.url("inv/rdocn"),data:{name:e.data.id||"",typ:"img"},success:e=>{let t=$$.dc("imagecollection pdfpreview"),n=Math.round(.88*vh());e.id;$.each(e.img||[],(function(e,i){$$.dc("pdfp",t).append($$.img(i).css("max-height",(n-rpx(6)).toString()+"px"))})),$ocms.dlg(t,{size:[n,Math.round(.88*vw())],zindex:50,form:!1})}})},$inv.sp13b=()=>{var e=$("div.invoice_layout").find("table.invi"),t=e.data();t.admin.p13b=!0,!1===(t.inv.InvoiceOptions||"").split(",").includes("§13b")&&(t.inv.InvoiceOptions+=",§13b"),e.trigger("fds.inv"),$inv.d.sync({Target:"p13b",Value:t.admin.p13b})},$inv.itemToContract=function(e){let t=((e=e||{}).Type||"").toString().toLowerCase(),n={id:(e.Id||"").toString(),type:t,title:"",desc:"",qty:"",price_net:"",total_net:e.net_val||0,vat:e.vat||""};var i;return e.co&&"osum"===e.co.typ?(n.desc=e.co.t||"",n.total_net=e.net_val||0):["text","title"].includes(t)&&0===(e.net_val||0)?(n.desc=e.htmltext||("#"!==(e.NameOrNumber||"").substr(0,1)?(i=$$[0]("p").text(e.NameOrNumber||""),$$.d().append(i).html()):"")+(e.Note||""),n.total_net=""):(e.htmltext?n.desc=e.htmltext:(n.title=e.NameOrNumber||"",n.desc=e.Note||""),n.qty=e.quantity||(0!==(e.quantityhours||0)?fnum(e.quantityhours)+(e.UnitString?" "+e.UnitString:""):""),n.price_net=e.net||0,n.total_net=e.net_val||0),n},$inv.ssetmode=()=>{let e=$("div.invoice_layout").find("table.invi").data();e.admin=e.admin||{};let t,n=e.admin.setmode||"setprice",i=e=>$$.dc("btn",$ict.setmo[e]).tC("selected",n===e).click((()=>{t.c.trigger("modal_close"),$inv.setSetmode(e)})),a=$$.dc("choicefrm").append([i("setprice"),i("itemprices"),i("setonly")]);t=$ocms.dlg(a,{width:800})},$inv.setSetmode=e=>{let t=$("div.invoice_layout").find("table.invi").data();t.admin=t.admin||{},t.admin.setmode=e,t.inv=t.inv||{};let n=(t.inv.InvoiceOptions||"").split(",").filter((e=>""!==e&&0!==e.indexOf("setmode:")));e&&"setprice"!==e&&n.push("setmode:"+e),t.inv.InvoiceOptions=n.join(","),$inv.d.sync({Target:"setmode",Value:e})},$inv.sctp=()=>{let e=$invcol.ctp;$ocms.dlgform(e,{title:$ict.ctp,success:function(e){var t=$("div.invoice_layout"),n=t.find("table.invi").data();let i={};void 0!==n.new&&"{"===(n.new.CustomValues||"").substr(0,1)&&(i=JSON.parse(n.inv.CustomValues)),i.contactName=e.name,i.contactEmail=e.email,n.new.CustomValues=JSON.stringify(i),t.find(".ctpfrm").text(ne(e.name,e.email)),$inv.d.sync({Target:"contact",Value:{name:e.name,email:e.email}})},typedvalues:!0})},$inv.invcPayload=function(e){let t=(e=e||{}).sms||{},n=$.extend({},e.new),i=$.extend({},e.admin);return n.total_net=t.ttn||0,n.total_gross=t.ttb||0,n.title=null!=n.invoicetitle?n.invoicetitle:n.title||"",n.provisionlocation=null!=n.loc?n.loc:n.provisionlocation||"",n.paymentterm=null!=i.paymentterms?i.paymentterms:n.paymentterm||"",i.customerid=null!=i.customerid?i.customerid:i.CustomerId,{admin:i,req:e.bai,sms:e.sms,new:n}},$inv.ssave=()=>{$inv.d.save()},$inv.sprev=e=>{$inv.d.preview()},$inv.rReload=()=>{try{let e=$("#listframe ul.rql:first").data();$inv.cInv2({id:e.search})}catch(e){}},$inv.quantChange=function(e){let t=$(this).closest("form"),n={},i=e=>parseFloat(e.toString().replace("%","").replace(",",".")),a=e=>e.toFixed(2);t.find(":input").each(((e,t)=>{n[$(t).attr("name")]=$(t)}));let r=parseInt(n.quantityhours.val()||"0"),l=i(n.net.val()||"0"),s=.01*i(n.vat.val());r>0&&l>0&&(n.net_val.val(a(r*l)),n.vat_val.val(a(r*l*s)),["Service"].includes(n.Type.val())&&(n.svcnet_val.val(a(r*l)),n.svcvat_val.val(a(r*l*s))))},$inv.storno=function(e,t){let n,i=$$.dc("choicefrm").append([$$.dc("btn","Storno ohne Details").click({id:e,mode:"simple"},(e=>{n.c.trigger("modal_close"),$inv.cSt(e.data)})),$$.dc("btn","Storno mit neuer Rechnung").click({id:e},(e=>{n.c.trigger("modal_close"),$inv.ccStInv(e)})),$$.dc("btn","Storno mit best. Rechnung").tC("inactive",!1===bool(t,!1)).click({id:e,mode:"copy"},(e=>{!0===bool(t,!1)&&(n.c.trigger("modal_close"),$inv.cSt(e.data))}))]);n=$ocms.dlg(i,{width:1e3})},$inv.credit=function(e,t){let n,i=$$.dc("choicefrm").append([$$.dc("btn","Gutschrift").click({id:e,mode:"credit"},(e=>{n.c.trigger("modal_close"),$inv.cSt(e.data)}))]);n=$ocms.dlg(i,{width:1e3})},$inv.setPyd=function(e){confirm($ict.cpyd)&&$ocms.postXT({url:$ocms.url("inv/setpyd"),timeout:60,data:{id:e},success:e=>{alert($ict.relm)},error:()=>{alert($t.f1)}})},$inv.setUpd=function(e){confirm($ict.cupd)&&$ocms.postXT({url:$ocms.url("inv/setupd"),timeout:60,data:{id:e},success:e=>{alert($ict.relm)},error:()=>{alert($t.f1)}})},$inv.resendRem=function(e){e.stopPropagation(),e.data.id&&confirm(string($ict.remresc,[e.data.name]))&&$ocms.postXT({url:$ocms.url("rem/resend"),timeout:60,data:{id:e.data.id},success:t=>{alert(string($ict.remresr,[e.data.name]))},error:()=>{alert($t.f1)}})},$inv.dspRem=function(e){let t=$$.dc("rfrm").ldng(1),n=$ocms.dlg(t,{width:1e3});n.ft.rwText($rct.rq2),$ocms.postXT({url:$ocms.url("inv/getrem"),timeout:60,data:{id:e,drafts:!1},success:e=>{n.ft.empty();let i=$$.tblset({class:"invtbl"},t.empty()),a=$invcol.rem2,r=$$.tr(i.hd);$$.th(r);$.each(a.fields||[],((e,t)=>{$$.th(r).text(t.label)}));let l=!1;$.each(e,((e,t)=>{l=!l;let n=$$.tr(i.bdy).tC("alt",l),r=$$.td(n);n.click((function(){n.tC("selected").siblings().rC("selected")})),!0===bool(t.hasFile,!1)&&($$.dc("idl ilbtn",r,{title:$ict.dl+"\n"+t.DocumentName}).append(gi("save-file","ico")).click({id:t.Id},$inv.downloadrem),$$.dc("idl ilbtn",r,{title:$ict.remdsp+"\n"+t.DocumentName}).append(gi("eye-open","ico")).click({id:t.Id,typ:"rem"},$inv.jdisp),$$.dc("idl ilbtn",r,{title:$ict.remres+"\n"+t.DocumentName}).append(gi("refresh","ico")).click({id:t.Id,typ:"rem",name:t.DocumentName},$inv.resendRem)),$.each(a.fields||[],((e,i)=>{let a=$$.td(n).aC(i.dtype),r=t[i.name];if("function"==typeof i.dfnc)i.dfnc.call(a,r,t);else switch(i.type||""){case"date":a.text(fdt(t[i.name],"dd.MM.yy"));break;case"datetime":a.text(fdt(t[i.name]));break;case"html":a.append($$.dc("ctw").html(r)),a.append($$.dc("ttip").html(r));break;default:a.text(t[i.name])}if("InvoiceId"===(i.name||""))a.aC("keep");switch(typeof i.title){case"function":i.title.call(a,t);break;case"string":a.attr("title",cs.title)}}))}))},error:()=>{t.empty(),n.ft.rwText($t.f1)},complete:()=>{t.ldng(0)}})},$inv.ccRem=function(e,t){$(this);$ocms.postXT({url:$ocms.url("rem/lrem"),timeout:60,data:{id:e},success:n=>{let i=$invcol.rid.clone();i.applyValues(n.ov);let a=$$.dc("ac"),r=$$.tblset({class:"fullgrid fullwidth"},a);if((n.lst||[]).length>0){$$.d({style:"margin: 1.5rem 0 1rem 0;font-size: 110%;text-decoration: underline;"}).prependTo(a).text($ict.rovlh);let e=$$.tr(r.hd);$ict.rovl.forEach(((t,n)=>$$.th(e,t))),$.each(n.lst,((e,t)=>{$$.tr(r.bdy).append([$$.tdc("keep",t.subject),$$.tdc("currency",fnum(t.amount,$rct.cst)),$$.tdc("currency",fnum(t.amount_payed,$rct.cst)),$$.tdc("keep",fdt(t.DateFinalized,"dd.MM.yy"))])}))}else $$.td($$.tr(r.bdy),$ict.nd);$ocms.dlgform(i,{addcontent:a,title:string($ict.remdt,[t||"?"]),success:function(t){$inv.ccRem_s2(e,t)},typedvalues:!0})}})},$inv.rRemRw=function(e){let t=$(this),n=e.rm||{};t.empty().data({invoiceid:n.invoiceid,invoicedate:n.invoicedate,amount:n.amount,amount_payed:n.amount_payed});let i=$$.dc("axf").append($$.dc("ibtn edit",{title:$rct.cP}).append(gi("pencil")).click(t,$inv.eRowR));t.append([$$.tdc("aux").append(i),$$.tdc("keep",n.invoiceid),$$.tdc("keep",fdt(n.invoicedate,"dd.MM.yy")),$$.tdc("currency",fnum(n.amount,$rct.cst)),$$.tdc("currency",fnum(n.amount_payed,$rct.cst)),$$.tdc("currency",fnum(n.amount-n.amount_payed,$rct.cst))])},$inv.eRowR=function(e){let t=$(this),n=e.data,i=n.data()||{},a=$invcol.rem.clone().applyValues(i);$ocms.dlgform(a,{title:t.data("dialog")||"",success:function(e){let i=t.closest("table"),a=i.data();$.extend(a.rm,e),i.data(a),$inv.rRemRw.call(n,a),$inv.rd.syncAmount(a.rm.amount,a.rm.amount_payed)},typedvalues:!0})},$inv.ccRem_s2=function(e,t){$fis.lf(!1).rC("fix").aC("hd");let n=$$.dc("invoice_layout",$fis.frm_edit()).append($$.dc("btn sprev").click($inv.rprev));$inv.eM(!1,!0);$$.dc("rfrm").ldng(1);$ocms.postXT({url:$ocms.url("rem/get"),timeout:60,data:$.extend({id:e},t),success:e=>{let t=e.rm||{},i=$$.dc("srq",n);$ict.remt[t.type].forEach((e=>$$[0]("p").rwText(e).appendTo(i)));let a=$$.tblset({class:"invi"},i);a.ft=$$[0]("tfoot"),a.tbl.data($.extend({invid:t.invid,new:{}},e));let r=$$.tr(a.hd).aC("shd").append([$$.th().aC("aux")]);$ict.remHR.forEach((e=>$$.th(r,e))),$inv.rRemRw.call($$.tr(a.bdy),a.tbl.data()),a.ft.appendTo(a.tbl),$ict.remt2[t.type].forEach((e=>$$[0]("p").rwText(e).appendTo(i)));let l=(e,t,i,r,l)=>{let s=$$.dc("inpfrm",n).aC(e).append("string"==typeof r?$$.dc("ahd",r):r>0?$$.dc("ahd",$rct.frm[i]):null),d=$$.dc("content",s).rwText(t);$$.dc("axf",s).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:d,nme:i,change:e=>{a.tbl.data("new")[i]=e}},l),$inv.eHtml)),a.tbl.data("new")[i]=t};l("tfrm",t.subject,"subject",0,null),l("adrfrm",t.invoiceaddress,"invoiceaddress",0,null),l("emailfrm",t.invoiceemail,"invoiceemail",0,null),$$.dc("sndfrm",n).append($$.dc("content").text(t.sender)),a.tbl.children("tbody").each($inv.bdysort),a.tbl.trigger("fds.inv");let s=a.tbl.data("new");s.amount=t.amount,s.amount_payed=t.amount_payed,$inv.rd.seed({rem:{invid:t.invid,type:t.type,invoiceid:t.invoiceid,invoicedate:t.invoicedate},new:s})},complete:()=>{}})},$inv.rprev=()=>{$inv.rd.preview()},$inv.sis=e=>{confirm($ict.sisc)&&$ocms.postXT({url:$ocms.url("inv/sis"),data:{id:e||""},success:e=>{}})},$inv.srs=e=>{confirm($ict.srsc)&&$ocms.postXT({url:$ocms.url("rem/srs"),data:{id:e||""},success:e=>{}})},$inv.mfrrel=e=>{$("#contentframe").ldng(),$ocms.postXT({url:$ocms.url("inv/mfrrel"),data:{id:e||""},success:e=>{$inv.rerenderinv()},complete:()=>{$("#contentframe").ldng(0)}})};
\ No newline at end of file
diff --git a/Fuchs/wwwroot/web/fis.req.de.js b/Fuchs/wwwroot/web/fis.req.de.js
index f3153c2..e553041 100644
--- a/Fuchs/wwwroot/web/fis.req.de.js
+++ b/Fuchs/wwwroot/web/fis.req.de.js
@@ -841,6 +841,161 @@ $inv.d = {
$inv.d.tbl().removeData('dtoken');
}
};
+/* ── Backend-authoritative reminder draft editing (ADR 0006/0007) ─────────────
+ The reminder mirror of $inv.d: the server holds the truth for a reminder draft in
+ an in-memory session; this object seeds it (rem/dopen), sends single edits as deltas
+ (rem/dpatch), and renders the open-amount footer + validation from the authoritative
+ server state (rem/dstate). Preview renders straight from the cache (rem/dpreview);
+ confirm flushes (rem/dsave) then finalises + emails (rem/conf). It coexists with $inv.d
+ on the same DOM: each keys off its own token (rdtoken vs dtoken), so the shared inline
+ editor safely no-ops for the mode that is not active. */
+$inv.rd = {
+ tbl: () => $('div.invoice_layout table.invi'),
+ layout: () => $('div.invoice_layout'),
+ token: function () { return $inv.rd.tbl().data('rdtoken') || ''; },
+ /* Seed the authoritative server session from the assembled reminder editor payload. */
+ seed: function (payload) {
+ let l = $inv.rd.layout(); l.aC('freeze');
+ $ocms.postXT({
+ url: $ocms.url('rem/dopen'), data: { payload: JSON.stringify(payload) }, success: (r) => {
+ $inv.rd.tbl().data('rdtoken', r.token).data('rdver', r.version);
+ $fis.draft.bind(r.token, {
+ onReady: () => $inv.rd.refresh(),
+ onExpiring: (s) => $inv.rd.warnExpiry(s),
+ onClosed: (reason) => $inv.rd.closed(reason)
+ });
+ $inv.rd.refresh();
+ }, error: () => { l.rC('freeze'); }
+ });
+ },
+ /* Re-fetch the authoritative state and render the open-amount footer + validation from it. */
+ refresh: function (cb) {
+ let t = $inv.rd.token(); if (t === '') { return; }
+ $ocms.postXT({
+ url: $ocms.url('rem/dstate'), data: { token: t }, success: (state) => {
+ $inv.rd.applyState(state); if (typeof cb === 'function') { cb(state); }
+ }, error: (xhr) => { if (xhr && xhr.status === 410) { $inv.rd.closed('expired'); } },
+ complete: () => { $inv.rd.layout().rC('freeze'); }
+ });
+ },
+ applyState: function (state) {
+ let tbl = $inv.rd.tbl(); if (tbl.length < 1) { return; }
+ tbl.data('rdver', state.version).data('serverSums', state.sums).data('remid', state.remid || '');
+ $inv.rd.footer(tbl, state.sums || {});
+ $inv.rd.validation(state.validation || []);
+ },
+ /* Send one change to the server; the draftReady signal and this success both refresh. */
+ sync: function (delta) {
+ let t = $inv.rd.token(); if (t === '') { return; }
+ $inv.rd.layout().aC('freeze');
+ $ocms.postXT({
+ url: $ocms.url('rem/dpatch'), data: { token: t, delta: JSON.stringify(delta) },
+ success: () => { $inv.rd.refresh(); },
+ error: (xhr) => { $inv.rd.layout().rC('freeze'); if (xhr && xhr.status === 410) { $inv.rd.closed('expired'); } }
+ });
+ },
+ /* Map an inline recipient field to its delta target and send it. */
+ syncField: function (nme, val) {
+ if ($inv.rd.token() === '') { return; }
+ let map = { subject: 'subject', invoiceaddress: 'address', invoiceemail: 'email', text: 'text' };
+ let target = map[nme]; if (!target) { return; }
+ $inv.rd.sync({ Target: target, Value: val });
+ },
+ /* Amount / amount-paid come from the item-row dialog; send both as their own deltas. */
+ syncAmount: function (amount, amount_payed) {
+ if ($inv.rd.token() === '') { return; }
+ $inv.rd.sync({ Target: 'amount', Value: (amount != null ? amount : 0).toString() });
+ $inv.rd.sync({ Target: 'amount_payed', Value: (amount_payed != null ? amount_payed : 0).toString() });
+ },
+ /* Render the open-amount footer from the server sums. */
+ footer: function (tbl, sums) {
+ let ft = tbl.children('tfoot').empty();
+ let tr = $$.tr(ft, { class: 'tsum' }).append([$$.tdc('aux'), $$.td({ colspan: 3 }).text('Offener Betrag')]);
+ $$.tdc('currency', tr, fnum(sums.amount_open || 0, $rct.cst));
+ },
+ validation: function (msgs) {
+ let frm = $inv.rd.layout(); if (frm.length < 1) { return; }
+ let box = frm.children('.dvalidation');
+ if (box.length < 1) { box = $$.dc('dvalidation'); frm.prepend(box); }
+ box.empty().tC('hidden', (msgs || []).length < 1);
+ $.each(msgs || [], (i, m) => $$.dc('dvmsg', box).aC(m.severity).text(m.message));
+ },
+ /* PDF preview straight from the cache; confirm = flush + finalise + email, cancel = discard. */
+ preview: function () {
+ let t = $inv.rd.token(); if (t === '') { return; }
+ let l = $inv.rd.layout();
+ let email = (($inv.rd.tbl().data('new') || {}).invoiceemail) || '';
+ if ($fis.ValidateEmail(email) === false) { if (bool(confirm($ict.ivE + $ict.ivEc), false) === false) { return; } }
+ l.aC('freeze');
+ $ocms.postXT({
+ url: $ocms.url('rem/dpreview'), data: { token: t }, success: (response) => {
+ l.rC('freeze');
+ let c = $$.dc('imagecollection pdfpreview'), vhr = Math.round(vh() * 0.88);
+ $.each(response.img || [], (ii, img) => { $$.dc('pdfp', c).append($$.img(img).css('max-height', (vhr - rpx(6)).toString() + 'px')); });
+ $ocms.dlg(c, {
+ size: [vhr, Math.round(vw() * 0.88)], zindex: 50, form: false, button: $ict.remd,
+ confirm: function (e) {
+ let ct = $(this); l.aC('freeze');
+ $ocms.postXT({
+ url: $ocms.url('rem/dsave'), data: { token: t }, success: (sv) => {
+ $ocms.postXT({
+ url: $ocms.url('rem/conf'), data: { id: sv.remid }, success: () => {
+ ct.trigger('modal_close');
+ window.open($ocms.url('rem/idoc') + '?id=' + sv.remid, '_blank');
+ $inv.rd.close();
+ $ocms.init('req'); $inv.rReload();
+ }, error: () => { alert($t.f1); ct.trigger('modal_close'); }, complete: () => { l.rC('freeze'); }
+ });
+ }, error: () => { l.rC('freeze'); alert($t.f1); }
+ });
+ },
+ cancel: function (e) { if (confirm($ict.cdI)) { $inv.rd.close(); $inv.rReload(); } }
+ });
+ }, error: () => { l.rC('freeze'); alert($t.f1); }
+ });
+ },
+ /* Zwischenspeichern: flush the cache to the DB (no re-upload); stay in the editor. */
+ save: function () {
+ let t = $inv.rd.token(); if (t === '') { return; }
+ let l = $inv.rd.layout(); l.aC('freeze');
+ $ocms.postXT({
+ url: $ocms.url('rem/dsave'), data: { token: t }, success: (r) => { $inv.rd.tbl().data('remid', r.remid); },
+ error: () => { alert($t.f1); }, complete: () => { l.rC('freeze'); }
+ });
+ },
+ history: function () {
+ let t = $inv.rd.token(); if (t === '') { return; }
+ $ocms.postXT({
+ url: $ocms.url('rem/dhistory'), data: { token: t }, success: (r) => {
+ let c = $$.dc('dhist');
+ if ((r.history || []).length < 1) { $$.dc('note', c).text('Noch keine Änderungen erfasst.'); }
+ else {
+ let ts = $$.tblset({ class: 'invtbl fullwidth' }, c);
+ $$.tr(ts.hd).append([$$.th().text('Zeit'), $$.th().text('Feld'), $$.th().text('Alt'), $$.th().text('Neu')]);
+ $.each(r.history, (i, h) => $$.tr(ts.bdy).append([$$.tdc('keep', fdt(h.timestamp)), $$.td().text(h.target), $$.td().text(h.oldValue), $$.td().text(h.newValue)]));
+ }
+ $ocms.dlg(c, { width: 800, form: false });
+ }
+ });
+ },
+ warnExpiry: function (secondsLeft) {
+ let mins = Math.max(1, Math.round((secondsLeft || 0) / 60));
+ $fis.notifications.push({ severity: 'info', title: 'Entwurf läuft ab', message: 'Der Mahnentwurf läuft in etwa ' + mins + ' Minute(n) ab. Bitte zwischenspeichern, sonst gehen die Änderungen verloren.' });
+ },
+ closed: function (reason) {
+ let t = $inv.rd.token();
+ $inv.rd.tbl().removeData('rdtoken');
+ if (t !== '') { $fis.draft.release(t); }
+ $fis.frm_edit().remove(); $fis.lf(true);
+ $fis.notifications.push({ severity: 'error', title: 'Entwurf geschlossen', message: reason === 'expired' ? 'Der Mahnentwurf ist wegen Inaktivität abgelaufen. Nicht gespeicherte Änderungen sind verloren.' : 'Der Mahnentwurf wurde geschlossen.' });
+ try { $inv.rReload(); } catch (e) { }
+ },
+ close: function () {
+ let t = $inv.rd.token();
+ if (t !== '') { $ocms.postXT({ url: $ocms.url('rem/dclose'), data: { token: t } }); $fis.draft.release(t); }
+ $inv.rd.tbl().removeData('rdtoken');
+ }
+};
$inv.cInv2 = function (data) {
let fr = $$.dc('rfrm').ldng(1);
let o = $ocms.dlg(fr, { width: 1000 });
@@ -1239,8 +1394,11 @@ $inv.eHtml = function (ev) {
if (typeof change === 'function') {
change(response.txt);
}
- /* backend-authoritative: mirror the inline recipient-field edit to the server session */
+ /* backend-authoritative: mirror the inline recipient-field edit to the server session.
+ Invoice and reminder editors share this DOM; each syncField no-ops unless its own
+ draft token is present, so only the active mode's session receives the delta. */
$inv.d.syncField(ev.data.nme, isPlainText ? (response.txt || '') : response.txt);
+ $inv.rd.syncField(ev.data.nme, isPlainText ? (response.txt || '') : response.txt);
},
tinymce: { valid_elements: 'br', hidemenu: true, hidetoolbar: true }
}
@@ -1895,6 +2053,8 @@ $inv.eRowR = function (ev) {
$.extend(tdta.rm, res);
tbl.data(tdta);
$inv.rRemRw.call(row, tdta);
+ /* backend-authoritative: mirror the edited amount / amount-paid to the server session */
+ $inv.rd.syncAmount(tdta.rm.amount, tdta.rm.amount_payed);
}, typedvalues: true
});
};
@@ -1935,57 +2095,26 @@ $inv.ccRem_s2 = function (id, sets) { //reminder creation
rif.tbl.children('tbody').each($inv.bdysort);
rif.tbl.trigger('fds.inv'); /* trigger calculations */
+ /* Seed the authoritative server session (ADR 0006). Amounts join the recipient
+ fields in the 'new' block; the reference invoice data goes into 'rem'. From here
+ the backend owns the open-amount computation and validation; inline edits and the
+ item-row dialog post single deltas (see $inv.rd). */
+ let nw = rif.tbl.data('new');
+ nw.amount = rem.amount; nw.amount_payed = rem.amount_payed;
+ $inv.rd.seed({
+ rem: { invid: rem.invid, type: rem.type, invoiceid: rem.invoiceid, invoicedate: rem.invoicedate },
+ new: nw
+ });
}, complete: () => {
//o.c.trigger('modal_close');
}
});
};
$inv.rprev = () => {
- var l = $('div.invoice_layout'), tbl = l.find('table.invi'), d = tbl.data();
- $.extend(d.new, tbl.find('tbody > tr:first').data());
- l.aC('freeze');
- //console.debug({ rem: d.rm, new: d.new });
- if ($fis.ValidateEmail(d.new.invoiceemail || '') === false) {
- if (bool(confirm($ict.ivE + $ict.ivEc), false) === false) {
- l.rC('freeze');
- return;
- }
- }
- $ocms.postXT({
- url: $ocms.url('rem/prep'), data: { remc: JSON.stringify({ rem: d.rm, new: d.new }), id: d.invid || '' }, success: (response) => {
- l.rC('freeze');
- let c = $$.dc('imagecollection pdfpreview'), vhr = Math.round(vh() * 0.88), remid = response.id;
- $.each(response.img || [], function (ii, img) {
- $$.dc('pdfp', c).append($$.img(img).css('max-height', (vhr - rpx(6)).toString() + 'px'));
- });
- $ocms.dlg(c, {
- size: [vhr, Math.round(vw() * 0.88)], zindex: 50, form: false, button: $ict.remd, confirm: function (e) {
- let ct = $(this);
- $ocms.postXT({
- url: $ocms.url('rem/conf'), data: { id: remid }, success: () => {
- ct.trigger('modal_close');
- window.open($ocms.url('rem/idoc') + '?id=' + remid, '_blank'); /* open pdf in new tab */
- $ocms.init('req'); /* go back to request list */
- $inv.rReload();
- }, error: () => {
- alert($t.f1);
- ct.trigger('modal_close');
- }
- });
- }, cancel: function (e) {
- let ct = $(this);
- if (confirm($ict.cdI)) {
- $ocms.postXT({
- url: $ocms.url('rem/del'), data: {
- id: remid
- }
- });
- }
- $inv.rReload();
- }
- });
- }
- });
+ /* Preview + finalise now run through the backend-authoritative session ($inv.rd):
+ the PDF renders straight from the server cache (no rem/prep DB write), and confirm
+ flushes (rem/dsave) then finalises + emails (rem/conf). */
+ $inv.rd.preview();
};
$inv.sis = (id) => {
if (confirm($ict.sisc)) {
diff --git a/Fuchs/wwwroot/web/fis.req.de.min.js b/Fuchs/wwwroot/web/fis.req.de.min.js
index 094ecb1..3ec39d1 100644
--- a/Fuchs/wwwroot/web/fis.req.de.min.js
+++ b/Fuchs/wwwroot/web/fis.req.de.min.js
@@ -1 +1 @@
-let $rct={mdl:"Aufträge",or:"offene Aufträge",orr:"offene Aufträge (4 W)",rn:"Auftragsnummer",iov:{all:"Auftragsübersicht (alle)","":"Auftragsübersicht"},wk:"Woche",nd:"Keine Daten gefunden.",h:"Uhr",rq1:"Auftragsdaten werden von MFR abgerufen.\nDer Vorgang kann bis zu 90Sek dauern.",rq2:"Auftragsdaten werden geladen",rq1f:"Die Auftragsdaten von MFR konnten nicht oder nicht schnell genug abgerufen werde.\nMöchten Sie mit den bestehenden Daten trotzdem weitermachen?",note1:"Im Bruttobetrag sind {0} Lohnkosten enthalten (netto {1}). Die darin enthaltene Umsatzsteuer beträgt {2}.",note2:"Bitte beachten Sie, nach §14 Abs. 1 Umsatzsteuergesetz ist diese Rechnung ein Zahlungsbeleg oder eine andere beweiskräftige Unterlage für 2 Jahre nach Ablauf des Kalenderjahres der Ausstellung dieser Rechnung aufzubewahren, soweit nicht aufgrund anderer gesetzlicher Regelungen andere ggf.längere Aufbewahrungsfristen gelten.",note3:"Privathaushalten erstattet das Finanzamt bis zu {0} des Arbeitslohns mit der nächsten Steuererklärung.",note4:"Für bereits erbrachte Arbeiten, Dienstleistungen, Materiallieferungen und getätigte Bestellvorgänge zum oben genannten Bauvorhaben, die sich aus dem mit Ihnen geschlossenen Vertrag ergeben, stellen wir Ihnen vertragsgemäß unsere Akontozahlung in Rechnung. Eine Endabrechnung erhalten Sie als Schlussrechnung nach Abschluss des gesamten Bauvorhabens. Das Ausführungsdatum entnehmen Sie bitte dem Schlusstext dieser Rechnung. Wir danken Ihnen herzlich für das entgegengebrachte Vertrauen und bitten Sie um kurzfristigen Ausgleich der Akontorechnung.",note13b:"Gem. §13b Umsatzsteuergesetz unterliegen Sie der Steuerschuldnerschaft des Leistungsempfängers zur Umsatzsteuer aus dieser Rechnung mit einem Steuersatz von 19%.",crI:"Rechnung erstellen",crII:"Abschlagsrechnung erstellen",dII:"Für eine Abschlagsrechnung darf nur ein Auftrag gewählt werden.",dnS:"Für eine Rechnung muss mindestens ein Auftrag gewählt werden.",inv:"Rechnung",invs:"Rechnungen",req:"Auftrag",provP:"Leistungszeitraum",provD:"Leistungsdatum",cP:"Position ändern",iRb:"Zeile darunter einfügen",dR:"Zeile löschen",sV:"USt festlegen",cD:"Löschen?",mR:"Zeile verschieben",svcPart:"Service-Anteil",vat:"Umsatzsteuer",combP:"Positionen zusammenfassen",iSum:"Zwischensumme",dtRel:"Freigegeben am: ",dtCr:"Erstellt am: ",rqV:"USt des Auftrags?",cthd:"wirklich aus-/einblenden ?",cst:{style:"currency",currency:"EUR"},sts:{IsWorkDone:"Arbeiten erledigt",Closed:"Auftrag geschlossen",SubcontractorPendingConfirmation:"Warten auf Bestätigung (Unterauftrag)",Scheduled:"Geplant",OfferIsRejected:"Angebot abgelehnt",OfferIsSend:"Offen (Angebot versandt)",CollaborationWaitingConfirmation:"Warten auf Bestätigung (Zusammenarbeit)",Released:"Freigegeben",OfferIsConfirmed:"Bestätigt",InProgress:"In Bearbeitung",ReadyForScheduling:"Zur Planung",Created:"Erstellt",Rejected:"Abgebrochen",Invoiced:"Rechnung gestellt","-":"-"},invHR:["Pos.","Menge","Artikelbezeichnung","VK","Summe"],frm:{invoiceaddress:"Adresse",loc:"Leistungsort / Lieferadresse",invoiceemail:"Email"}},$rcol={req:new fields_definition("Auftrag","Aufträge",[{name:"tags",label:"",type:"string",dfnc:function(e,t){""!==(e||"")&&($(this).aC("tags"),e.split(",").forEach((e=>{""!==e&&$(this).append($$.sc("tag "+e.replace(" ","_").replace("/","_").toLowerCase(),e))})))}},{name:"DateOfCreation",label:"Datum",type:"date",title:function(e){$(this).attr("title",$rct.dtCr+fdt(e.DateOfCreation).ne("-")+" \n"+$rct.dtRel+fdt(e.DateReleased).ne("-"))}},{name:"CustomerName",label:"Kunde (Firma)",type:"string"},{name:"Name",label:"Auftragsname",type:"string"},{name:"ExternalId",label:"Auftragsnummer",type:"string"},{name:"ParentExtenalId",label:"PAuftrag",type:"string"},{name:"InvoiceId",label:"RNummer",type:"string",dfnc:function(e,t){$(this).rwText(e," ").find("span").each((function(){$(this).aC("cla").click({id:$(this).text()},$inv.jdbn)}))}},{name:"State",label:"Status",type:"string"},{name:"WorkDoneAt",label:"Erledigt am",type:"date"},{name:"Description",label:"Beschreibung",type:"html"}]),itm:new fields_definition("Auftragsposition","Auftragspositionen",[{name:"NameOrNumber",label:"Bezeichnung",type:"string"},{name:"Type",label:"Typ",type:"select",required:!0,value:"Text",url:[{value:"Text",label:"Text"},{value:"Equipment",label:"Ausrüstung"},{value:"Material",label:"Material"},{value:"Service",label:"Arbeitsleistung"}],change:function(e){$req.quantChange.call(this,e)}},{name:"quantityhours",label:"Anzahl / Menge",type:"number",precision:"0.01",value:1,change:function(e){$inv.quantChange.call(this,e)}},{name:"UnitString",label:"Einheit",type:"select",url:["LFDM","Stck","Std.","QM","AW","Pauschal"],change:function(e){$inv.quantChange.call(this,e)}},{name:"net",label:"EinzelPreis netto",type:"number",precision:"0.01",value:0,change:function(e){$inv.quantChange.call(this,e)}},{name:"net_val",label:"GesamtPreis netto",type:"number",precision:"0.01",value:0},{name:"vat_val",label:"GesamtPreis USt",type:"number",precision:"0.01",value:0},{name:"svcnet_val",label:"Arbeitslohn netto",type:"number",precision:"0.01",value:0},{name:"svcvat_val",label:"Arbeitslohn USt",type:"number",precision:"0.01",value:0},{name:"net_pos",label:"Netto",type:"string"},{name:"bo_pos",label:"Brutto",type:"string"},{name:"vat",label:"USt",type:"string",value:"19,0%",change:function(e){$inv.quantChange.call(this,e)}},{name:"Note",label:"Details",type:"html",tinymce:!0}])},$ict={mdl:"Rechnungen",iov:{all:"Rechnungen (alle)","":"Rechnungen (nur fertige)","#d":"Rechnungen (nur Entwürfe)","#u":"Rechnungen (nur unbezahlt)","#r":"Rechnungen (nur angemahnt)","#a":"Rechnungen (nur Akonto)","#c":"Rechnungen (nur Storno)","#ru":"Rechnungen (nur angemahnt + unbez.)"},uba:", gesamter Zeitraum)",req:"Auftrag",inv:"Rechnung",rem:"Mahnung",in:"Rechnungsnummer",cc:"Kunde",wk:"Woche",nd:"Keine Daten gefunden.",dl:"Herunterladen",ed:"Bearbeiten",ced:"Bearbeitung fortsetzen",sItm:"Einzelheiten anzeigen",sPay:"Zahlungen anzeigen",cdI:"Entwurf der Rechnung löschen?",rel:"Neu Laden",relm:"Bitte laden Sie Liste manuell neu, um die Änderungen zu sehen.",dsp:"Rechnung anzeigen",storno:"Storno-Rechnung erstellen",credit:"Gutschrift erstellen",remd:"Mahnung erstellen",remdt:"Mahnung erstellen zur Rechnung {0}",remlst:"Mahnungen anzeigen",remdsp:"Mahnung anzeigen",remres:"Mahnung erneut senden",remresc:"Mahnung {0} wirklich erneut senden?",remresr:"Mahnung {0} wurde erfolgreich versandt.",setpyd:"Bezahlt markieren",cpyd:"Rechnung wirklich als bezahlt markieren?",setupd:"Bezahlt-Markierung aufheben",cupd:"Bezahlt-Markierung wirklich aufheben?",ivE:"Die Email-Adresse ist vermutlich nicht gültig.",ivEc:"\nMöchten Sie fortfahren?",pna:"Diese Seite ist in der Vorschau nicht verfügbar",tpe:"Die Anzahl von {0} Seiten wird aktuell nicht unterstützt",eis:"Der Rechnungsentwurf konnte nicht gespeichert werden.",iss:"Zwischenstand speichern.",p13b:"USt -> §13b",setm:"Set-Preisanzeige",setmo:{setprice:"Set mit Preis – Positionen ohne Preis",itemprices:"Positionen mit Preis – Set als Überschrift",setonly:"Nur Set mit Preis – Positionen ausgeblendet"},ctp:"Ansprechpartner festlegen",mfr:"Von MFR neu abrufen",rq1:"Auftragsdaten werden von MFR abgerufen.\nDer Vorgang kann bis zu 90Sek dauern.",rq2:"Auftragsdaten werden geladen",iq1:"Rechnungsdaten werden von MFR abgerufen.\nDer Vorgang kann bis zu 90Sek dauern.",iq2:"Rechnungsdaten werden geladen",sis:"Rechnung als versandt markieren",srs:"Mahnung als versandt markieren",sisc:"Rechnung wirklich als versandt markieren?",srsc:"Mahnung wirklich als versandt markieren?",iSt:{dft:"Entwurf",uns:"nicht versandt",pyd:"bezahlt",cc:"storniert",op:"offen",due:"fällig",ovd:"überfällig",rem:"angemahnt"},rSt:["","Überfällig","2. Mahnung","3. Stufe"],pSt:{a:"Vollst.",p:"Teilz."},ivT:{i:"AbschlagsR.",f:"SchlussR",r:"Rechnung",c:"StornoR."},rovlh:"Übersicht der bisherigen Mahnungen",rovl:["Betreff","Betrag","Betrag gezahlt","fertiggestellt am"],remHR:["Rechnung","vom","Rechnungsbetrag","bereits bezahlt","noch offen"],remt:{f:["Sehr geehrte Damen und Herren,","ein Mahnschreiben sollte kurz, freundlich und erfolgreich sein. Kurz ist es, freundlich sowieso; ob es auch erfolgreich ist, hängt von Ihnen ab."],m:["Sehr geehrte Damen und Herren,","nun müssen wir Sie noch einmal anschreiben.","Wahrscheinlich haben Sie triftige Gründe dafür, warum Sie die Zahlung unserer Forderung nicht vornehmen und auch nicht auf unsere Mahnung reagieren. Sollten wir darüber nicht einmal sprechen?","Bitte nehmen Sie umgehend in dieser Sache mit uns Kontakt auf."],l:["Sehr geehrte Damen und Herren,",'Eine DRITTE MAHNUNG zu erhalten bereitet Ihnen bestimmt ebenso wenig Freude wie uns, sie zu verschicken. Leider haben wir auf unsere zweite Mahnung noch keine Antwort von Ihnen erhalten.", "Wir bitten Sie, den offenen Betrag innerhalb der nächsten 7 Werktage nach Erhalt dieses Schreibens zu begleichen. Nach Ablauf dieser Frist erfolgt keine weitere Mahnung mehr.',"Sollte die Forderung bis dahin nicht beglichen sein, eröffnen wir das gerichtliche Mahnverfahren. Sollten Sie die Rechnung inzwischen beglichen haben, so betrachten Sie bitte dieses Schreiben als gegenstandslos."]},remt2:{f:["Wir bitten Sie, den noch offenen Rechnungsbetrag innerhalb einer Woche auf unser Konto zu überweisen.","Sollten Sie den Betrag bereits überwiesen haben, so bitten wir Sie, diese Zahlungserinnerung als gegenstandslos zu betrachten."],m:["Um Ihnen zusätzliche Kosten für weitere Mahnungen zu ersparen, bitten wir Sie nunmehr um die Überweisung des noch zu zahlenden Gesamtbetrages inklusive der ggf. bereits fälligen Mahnzinsen und Mahngebühren innerhalb von einer Woche."],l:[]},payi:{account:"Konto",name:"Zahler",text:"Verw.Zweck",InvoiceID:"Rechnung",amount:"Betrag",date:"Datum",manual:"Typ"}},$invcol={datev:new fields_definition("Rechnung","Rechnungen",[{name:"Umsatz (ohne Soll/Haben-Kz)",label:"Umsatz (ohne Soll/Haben-Kz)",type:"string"},{name:"vf",label:"vf",type:"string"},{name:"Soll/Haben-Kennzeichen",label:"Soll/Haben-Kennzeichen",type:"string"},{name:"Konto",label:"Konto",type:"string"},{name:"Gegenkonto",label:"Gegenkonto",type:"string"},{name:"BU-Schlüssel",label:"BU-Schlüssel",type:"string"},{name:"Belegdatum",label:"Belegdatum",type:"string"},{name:"Belegfeld 1",label:"Belegfeld 1",type:"string"},{name:"Belegfeld 2",label:"Belegfeld 2",type:"string"},{name:"Buchungstext",label:"Buchungstext",type:"string"}]),inv:new fields_definition("Rechnung","Rechnungen",[{name:"invstatus",label:"Status",type:"select",url:$ict.iSt},{name:"balance",label:"Umsatz",type:"string",dtype:"currency"},{name:"CustomerName",label:"Kunde",type:"string"},{name:"InvoiceId",label:"RNummer",type:"string"},{name:"InvoiceType",label:"Typ",type:"select",url:$ict.ivT},{name:"request",label:"Auftrag",type:"string",dtype:"num"},{name:"vat",label:"MwSt",type:"string",dtype:"num"},{name:"deb_cred",label:"Soll/Haben",type:"string"},{name:"customer",label:"Konto",type:"string",dtype:"num"},{name:"contra_account",label:"Gegenkonto",type:"string",dtype:"num"},{name:"Belegdatum",label:"Belegdatum",type:"date"},{name:"reminderstatus",label:"MahnStatus",type:"select",url:$ict.rSt},{name:"reminder",label:"# Mahnungen",type:"integer"},{name:"Buchungstext",label:"Buchungstext",type:"string"},{name:"Payment",label:"Zahlung",type:"string"}]),rem:new fields_definition("Zahlungserinnerung","Zahlungserinnerung",[{name:"amount",label:"Rechnungsbetrag",type:"number",precision:"0.01",value:1},{name:"amount_payed",label:"bereits bezahlt",type:"number",precision:"0.01",value:1}]),rem2:new fields_definition("Zahlungserinnerung","Zahlungserinnerung",[{name:"DocumentName",label:"Name",type:"string"},{name:"subject",label:"Betreff",type:"string"},{name:"DateSent",label:"Versanddatum",type:"date"},{name:"status",label:"Status",type:"string"},{name:"amount_open",label:"offener Betrag",type:"number",precision:"0.01"},{name:"InvoiceId",label:"RNummer",type:"string"}]),rid:new fields_definition("Zahlungserinnerung","Zahlungserinnerung",[{name:"type",label:"Typ",type:"select",url:[["f","einfache Zahlungserinnerung"],["m","Mahnung"],["l","letzte Mahnung"]],required:!0},{name:"level",label:"Stufe",type:"select",url:[["1","Stufe 1"],["2","Stufe 2"],["3","Stufe 3"],["4","Stufe 4"],["5","Stufe 5"],["6","Stufe 6"]],required:!0}]),ctp:new fields_definition("Ansprechpartner","Ansprechpartner",[{name:"name",label:"Name",type:"string"},{name:"email",label:"Email",type:"string"}])},gi=(e,t)=>$$.sc("glyphicon glyphicon-"+e).aC(t),$inv={},$req={init2:function(e,t){e=e||"inv",t=t||{},$ocms.getScript([],(function(){$req.init3(e,t)}))},init3:async function(e,t){$fis.cf(!0);let n=$fis.lf(!0);$("#topbar").ocmsmenu([]),$("#activemodule").text($rct.mdl),await $fis.prepAuth("fds_req,fds_inv,fds_reminder");let i=[(async()=>{!0===$fis.isAuth("fds_req",1)&&($req.prepLst(""),n.aC("fix"))})(),new Promise(((e,t)=>{n.find("div.oreq2").aC("selected"),$req.renderreq(fdt(new Date,"yy-MM-dd"),"r"),e()}))];await Promise.all(i)},prepLst:function(e){let t=new Date,n=$fis.lf(!0).ldng(1),i=new Date("2021-01-01");$fis.frm_list().IN((function(){}));$$.dc("mth oreq",n).text($rct.or).click((function(e){let t=$(this);e.stopPropagation(),t.siblings().rC("selected"),!0===t.is(".selected")&&(t.tC("selected"),$req.renderreq(fdt(new Date,"yy-MM-dd"),"o")),t.aC("selected")})),$$.dc("mth oreq2",n).text($rct.orr).click((function(e){let t=$(this);e.stopPropagation(),t.siblings().rC("selected"),!0===t.is(".selected")&&(t.tC("selected"),$req.renderreq(fdt(new Date,"yy-MM-dd"),"r")),t.aC("selected")})),$$.i({placeholder:$rct.rn}).appendTo($$.dc("mth oreqn",n)).enterKey((function(e){let t=$(this),n=t.val()||"";e.stopPropagation(),t.parent().siblings().rC("selected"),n.length>3&&(t.parent().aC("selected"),$req.renderreq("n:"+n,"s"),t.val(""))}));n.append("
");let a=$$.dc("mthl",n),r=t.getFullYear(),l=t.getMonth()+1;for(let t=i.getFullYear();t<=r;t++){let n=$$.dc("yr").prependTo(a).text($rct.iov[e]+" - "+t.toString()).toggleClass("selected",t===r);n.click({yr:t},(function(e){e.stopPropagation(),n.siblings().rC("selected"),n.aC("selected")}));let s=$$.dc("mfrm",n);for(let n=0;n<(t!==r?12:l);n++){i=new Date(t,n,1);let a=$$.dc("mth").prependTo(s).text($rct.iov[e]+" - "+fdt(i,"MMM yyyy"));a.click({yr:t,mt:n},(function(e){if(e.stopPropagation(),a.siblings().rC("selected"),!0===a.is(".selected")){a.tC("selected");let t=fdt(new Date(e.data.yr,e.data.mt,1),"yy-MM-dd");$req.renderreq(t,"m")}a.aC("selected")}));let r=getMonday(i),l=new Date(i);l.setMonth(l.getMonth()+1),l.setDate(0),l=getMonday(l);let d=$$.dc("wfrm",a);for(;r<=l;){let e=$$.dc("wk",d).text(($rct.wk||"W")+" "+fdt(r,"dd.MM.yy"));e.click({rd:new Date(r)},(function(t){t.stopPropagation();let n=fdt(t.data.rd,"yy-MM-dd");$req.renderreq(n,"w"),a.siblings().rC("selected").find(".wk").rC("selected"),a.aC("selected").find(".wk").rC("selected"),e.aC("selected")}));let t=$$.dc("wkdl",e).append($$.sc("ico glyphicon glyphicon-compressed"));!0===$fis.isAuth("fds_inv",2)&&t.click({rd:new Date(r)},(function(e){e.stopPropagation();let t=fdt(e.data.rd,"yy-MM-dd");$req.downloadzip.call(t,"w")})),r.setDate(r.getDate()+7)}}}n.ldng(0)},renderreq:function(e,t){let n=$fis.frm_list().ldng(1),i=$$.dc("invfrm",n).aC("md"+t),a=$fis.lf();$ocms.postXT({url:$ocms.url("req/reql"),data:{mode:t,tgt:e},success:n=>{a.rC("fix").aC("hd"),$$.dc("ovhd",i).append($$.s(n.admin.title)).appendIf($$.sc("note",n.admin.note),""!==ne(n.admin.note,""));let r=$$.tblset({},i),l=$rcol.req,s=$$.tr(r.hd);$$.th(s);$.each(l.fields||[],((e,t)=>{$$.th(s).text(t.label),"vat"===t.name&&$$.th(s)}));let d=0,c=!1;$.each(n.requests||[],((n,s)=>{d>0&&d!==s.ParentServiceRequestId&&(c=!c);let o=$$.tr(r.bdy).tC("alt",c);d=s.ParentServiceRequestId,o.click((function(){a.rC("fix").aC("hd"),o.tC("selected").siblings().rC("selected").find("td.av").rC("av"),o.find("td.av").rC("av")})),o.tC("child",s.isChild);let u=$$.td(o,{class:"raux"});!0===bool(s.open,!1)&&$$.dc("ihd ilbtn",u).append(gi("eye-close","ico")).click({id:s.Id},$req.tHd),$$.dc("iitm ilbtn",u).append(gi("list","ico")).click({id:s.Id},$req.showitm),!0===$fis.isAuth("fds_inv",2)&&$$.dc("invc ilbtn",u).append(gi("edit","ico")).click({id:s.Id},$inv.cInv),$.each(l.fields||[],((n,a)=>{let r=$$.td(o).aC(a.dtype),l=s[a.name];if("function"==typeof a.dfnc)a.dfnc.call(r,l,s);else switch(a.type||""){case"date":r.text(fdt(s[a.name],"dd.MM.yy"));break;case"datetime":r.text(fdt(s[a.name]));break;case"html":r.append($$.dc("ctw").html(l)),r.append($$.dc("ttip").html(l));break;default:r.text(s[a.name])}switch(a.name||""){case"State":r.text($rct.sts[l||"-"]);break;case"Name":r.aC(a.name.toLowerCase());break;case"vat":$$.sel().appendTo($$.td(o,{class:"vsel"})).click((function(e){e.stopPropagation()})).append([$$.opt("19,0 %","19,0 %"),$$.opt("16,0 %","16,0 %"),$$.opt("0,0 %","0,0 %")]).val(s[a.name]).change().change({frm:i,tgt:e,mode:t,id:s.Id,td:r},$req.setvat),r.tC("hl","19"!==s[a.name].substr(0,2)).click((function(e){e.stopPropagation(),$(this).tC("av")}));break;case"balance":r.aC("sh_"+(s.SollHaben||"").toLowerCase());break;case"InvoiceId":r.aC("keep")}switch(typeof a.title){case"function":a.title.call(r,s);break;case"string":r.attr("title",cs.title)}}))}))},complete:()=>{n.ldng(0)}})},tHd:function(e){let t=$(this).closest("tr");e.stopPropagation(),!1!==t.is(".selected")&&confirm($rct.cthd)&&$ocms.postXT({url:$ocms.url("req/rthd"),data:{id:e.data.id},success:n=>{n.id===e.data.id&&!1===bool(n.visible,!0)?(!1===t.is(".tbhd")&&setTimeout((()=>{t.filter(".tbhd").remove()}),15e3),t.aC("tbhd")):n.id===e.data.id&&t.rC("tbhd")}})},showitm:function(e){let t=$(this).closest("tr");if(e.stopPropagation(),!1===t.is(".selected"))return;let n=$$.dc("rfrm").ldng(1);$ocms.postXT({url:$ocms.url("req/pget"),data:{id:e.data.id},success:t=>{$ocms.postXT({url:$ocms.url("req/get"),data:{id:e.data.id,mode:"ful"},success:e=>{if((e.requests||[]).length<1)n.text($rct.nd);else{let t=$$.dc("srq",n),i=$$.tblset({class:"if"},t);$.each(e.requests||[],(function(e,t){e>0&&$$.tr(i.bdy).aC("sep").append($$.td({colspan:6}));let n=$$.tr(i.bdy).aC("title"),a=$rcol.itm.lbl(),r=$inv.worknotes(t);$$.td(n,{colspan:6}).append([$$.s($rcol.req.label_sng),$$.sc("eid",t.ExternalId),$$.sc("nme",fdt(t.WorkDoneAt,"dd.MM.yy")+": "+r.ne(t.Name))]);$$.tr(i.bdy).aC("shd").append([$$.td(),$$.td(a.NameOrNumber),$$.td(a.Type),$$.td(a.net_pos),$$.td(a.bo_pos),$$.td(a.vat)]);$.each(t.items||[],((e,t)=>{t.ServiceRequestId;let n=$$.tr(i.bdy,{id:"itm"+t.Id}).aC(t.Type);$$.td(n).aC("ico"),$$.td(n).text(t.NameOrNumber),$$.td(n).text(t.Type),$$.td(n).aC("currency").text(t.net_pos),$$.td(n).aC("currency").text(t.bo_pos),$$.td(n).aC("num").text(t.vat)}))}))}},error:()=>{n.text($t.t12)},complete:()=>{n.ldng(0)}})},error:()=>{n.text($t.t12),n.ldng(0)}}),$ocms.dlg(n,{width:1e3})}},$$req={init2:$req.init2,auth:{}};export default $$req;$inv.cInv=function(e){let t=$(this).closest("tr");e.stopPropagation(),!1!==t.is(".selected")&&!1!==$fis.isAuth("fds_inv",2)&&$inv.cInv2({id:e.data.id})},$inv.rMn=e=>{let t=[{lbl:$ict.req,itm:[]}];return!0===bool(e,!1)&&!0===$fis.isAuth("fds_inv",2)&&Array.prototype.push.apply(t[0].itm,[{lbl:$rct.crI,fnc:$inv.ccInv,data:{typ:"r"}},{lbl:$rct.crII,fnc:$inv.ccInv,data:{typ:"i"}}]),t.push({lbl:$ict.rel,fnc:$inv.rReload}),$("#topbar").ocmsmenu(t)},$inv.iMnr=e=>{let t=booln(e.isFinal,!0),n=e.Id,i=booln(e.fds,!1),a=[{glyph:"glyphicon-menu-left",fnc:()=>{$fis.frm_edit().remove()}},{lbl:$ict.inv,itm:[]},{lbl:$ict.rem,itm:[]}];return!1===t&&!0===$fis.isAuth("fds_inv",2)?a[1].itm.push({lbl:$ict.ced,fnc:$inv.clCntInv}):!0===$fis.isAuth("fds_inv",1)&&a[1].itm.push({lbl:$ict.dsp,fnc:()=>$inv.disp(n,"inv")}),!0===i&&!0===t&&!0===$fis.isAuth("fds_inv",2)&&(a[1].itm.push({lbl:$ict.storno,fnc:()=>$inv.storno(n,i)}),a[1].itm.push({lbl:$ict.credit,fnc:()=>$inv.credit(n,i)})),!0===t&&!0===$fis.isAuth("fds_reminder",2)&&(a[2].itm.push({lbl:$ict.remd,fnc:()=>$inv.ccRem(n,e.InvoiceId)}),a[2].itm.push({lbl:$ict.remlst,fnc:()=>$inv.dspRem(n)})),!0===t&&!0===$fis.isAuth("fds_reminder",2)&&!1===booln(e.IsSent,!1)&&a[2].itm.push({lbl:$ict.srs,fnc:()=>$inv.srs(n)}),a.push({lbl:$ict.rel,fnc:$inv.rReload}),$("#topbar").ocmsmenu(a)},$inv.iMn=e=>{let t=booln(e.isFinal,!0),n=e.Id,i=booln(e.fds,!1),a=[{glyph:"glyphicon-menu-left",fnc:()=>{$fis.frm_edit().remove()}},{lbl:$ict.inv,itm:[]},{lbl:$ict.rem,itm:[]}];return!1===t&&!0===$fis.isAuth("fds_inv",2)?a[1].itm.push({lbl:$ict.ced,fnc:()=>{$inv.cntInv({id:n})}}):!0===$fis.isAuth("fds_inv",1)&&a[1].itm.push({lbl:$ict.dsp,fnc:()=>$inv.disp(n,"inv")}),!0===$fis.isAuth("fds_inv",2)&&(a[1].itm.push({lbl:$ict.storno,fnc:()=>$inv.storno(n,i)}),a[1].itm.push({lbl:$ict.credit,fnc:()=>$inv.credit(n,i)})),!0===t&&!1===booln(e.IsPayed,!1)?(!0===$fis.isAuth("fds_reminder",2)&&a[2].itm.push({lbl:$ict.remd,fnc:()=>$inv.ccRem(n,e.InvoiceId)}),!0===$fis.isAuth("fds_inv",2)&&a[1].itm.push({lbl:$ict.setpyd,fnc:()=>$inv.setPyd(n)})):!0===t&&!0===booln(e.IsPayed,!1)&&"m"===(e.PaymentStatus||"")&&!0===$fis.isAuth("fds_inv",2)&&a[1].itm.push({lbl:$ict.setupd,fnc:()=>$inv.setUpd(n)}),!0===$fis.isAuth("fds_reminder",2)&&a[2].itm.push({lbl:$ict.remlst,fnc:()=>$inv.dspRem(n)}),!0===t&&!0===$fis.isAuth("fds_inv",2)&&!1===booln(e.IsSent,!1)&&a[1].itm.push({lbl:$ict.sis,fnc:()=>$inv.sis(n)}),!1===i&&a[1].itm.push({lbl:$ict.mfr,fnc:()=>$inv.mfrrel(n)}),$("#topbar").ocmsmenu(a)},$inv.eM=(e,t,n)=>{let i=[];return!0!==booln(e,!1)&&!0!==booln(t,!1)||i.push({glyph:"glyphicon-menu-left",fnc:()=>{$fis.lf(!0),$fis.frm_edit().remove()}}),!0===(n||"").split(",").includes("iss")&&i.push({lbl:$ict.iss,fnc:$inv.ssave}),!0===(n||"").split(",").includes("ctp")&&i.push({lbl:$ict.ctp,fnc:$inv.sctp}),!0===(n||"").split(",").includes("p13b")&&i.push({lbl:$ict.p13b,fnc:$inv.sp13b}),!0===(n||"").split(",").includes("setm")&&i.push({lbl:$ict.setm,fnc:$inv.ssetmode}),!0===(n||"").split(",").includes("iss")&&(i.push({lbl:"Änderungshistorie",fnc:()=>$inv.d.history()}),i.push({lbl:"Änderungen verwerfen",fnc:()=>$inv.d.discard()})),!0===booln(e,!1)&&i.push({lbl:$ict.rel,fnc:$inv.rReload}),$("#topbar").ocmsmenu(i)},$inv.d={tbl:()=>$("div.invoice_layout table.invi"),layout:()=>$("div.invoice_layout"),token:function(){return $inv.d.tbl().data("dtoken")||""},hashes:function(){let e=$inv.d.tbl().data("bai")||[],t={};return $.each(e,((e,n)=>{t[(n.Id||"").toString()]=JSON.stringify(n)})),t},seed:function(e){let t=$inv.d.layout();t.aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dopen"),data:{payload:JSON.stringify(e)},success:e=>{$inv.d.tbl().data("dtoken",e.token).data("dver",e.version).data("dhashes",$inv.d.hashes()).data("dorder",$inv.d.order()),$fis.draft.bind(e.token,{onReady:()=>$inv.d.refresh(),onExpiring:e=>$inv.d.warnExpiry(e),onClosed:e=>$inv.d.closed(e)}),$inv.d.refresh()},error:()=>{t.rC("freeze")},complete:()=>{$inv.d.tbl().removeData("dseeding")}})},refresh:function(e){let t=$inv.d.token();""!==t&&$ocms.postXT({url:$ocms.url("inv/dstate"),data:{token:t},success:t=>{$inv.d.applyState(t),"function"==typeof e&&e(t)},error:e=>{e&&410===e.status&&$inv.d.closed("expired")},complete:()=>{$inv.d.layout().rC("freeze")}})},applyState:function(e){let t=$inv.d.tbl();t.length<1||(t.data("dver",e.version).data("serverSums",e.sums),$inv.d.footer(t,e.sums||{},e.admin||{}),$inv.d.validation(e.validation||[]),$inv.d.applyPositions(t,e.req||[]))},applyPositions:function(e,t){(t||[]).forEach((t=>(t&&t.itm||[]).forEach((t=>{if(!t||""===(t.id||""))return;let n=e.find("#itm"+t.id+" td.keep").first();n.length&&n.text(null!=t.p?t.p:"")}))))},sync:function(e){let t=$inv.d.token();""!==t&&($inv.d.layout().aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dpatch"),data:{token:t,delta:JSON.stringify(e)},success:()=>{$inv.d.refresh()},error:e=>{$inv.d.layout().rC("freeze"),e&&410===e.status&&$inv.d.closed("expired")}}))},order:function(){return($inv.d.tbl().data("bai")||[]).map((e=>(e.Id||"").toString()))},syncChanged:function(e){if(""===$inv.d.token())return;let t=e.data("bai")||[],n=e.data("dhashes")||{},i={},a=[],r=[];$.each(t,((e,t)=>{let r=(t.Id||"").toString(),l=JSON.stringify(t);i[r]=l,n[r]!==l&&a.push(t)})),$.each(n,(e=>{void 0===i[e]&&r.push(e)}));let l=$inv.d.order(),s=e.data("dorder")||[];e.data("dhashes",i).data("dorder",l),a.forEach((e=>$inv.d.sync({Target:"block.replace",Ref:(e.Id||"").toString(),Value:e}))),r.forEach((e=>$inv.d.sync({Target:"block.remove",Ref:e}))),s.length===l.length&&s.slice().sort().join(",")===l.slice().sort().join(",")&&s.join(",")!==l.join(",")&&$inv.d.sync({Target:"block.order",Value:l})},syncField:function(e,t){if(""===$inv.d.token())return;let n={invoicetitle:"title",invoiceaddress:"address",invoiceemail:"email",loc:"provisionlocation",provisionlocation:"provisionlocation",provisionperiod:"provisionperiod"}[e];n&&$inv.d.sync({Target:n,Value:t})},footer:function(e,t,n){let i=e.children("tfoot").empty();e.nextAll(".fnote").remove();let a=bool(n.p13b,!1),r=(e,t,n)=>$$.tdc("currency",$$.tr(i,{class:n||"tsum"}).append([$$.tdc("aux"),$$.td({colspan:4}).text(e)]),fnum(t,$rct.cst)),l=t=>$$.dc("fnote").insertAfter(e).rwText(t);r("Netto",t.total_net||0),!1===a&&$.each(t.vat||{},((e,t)=>r($rct.vat+" "+e+"%",t,"tvat"))),r("Summe",t.total_gross||0);let s=n.type||"";"i"===s?(l($rct.note2),l($rct.note4)):"c"===s?l($rct.note2):(l(string($rct.note3,[fnum(((t.service_net||0)+(t.service_vat||0))*(n.tax_servicerefund||0),$rct.cst)])).aC("ntax"),l($rct.note2),l(string($rct.note1,[fnum((t.service_net||0)+(t.service_vat||0),$rct.cst),fnum(t.service_net||0,$rct.cst),fnum(t.service_vat||0,$rct.cst)]))),!0===a&&l($rct.note13b)},validation:function(e){let t=$("div.invoice_layout");if(t.length<1)return;let n=t.children(".dvalidation");n.length<1&&(n=$$.dc("dvalidation"),t.prepend(n)),n.empty().tC("hidden",(e||[]).length<1),$.each(e||[],((e,t)=>$$.dc("dvmsg",n).aC(t.severity).text(t.message)))},preview:function(){let e=$inv.d.token();if(""===e)return;let t=$inv.d.layout(),n=($inv.d.tbl().data("new")||{}).invoiceemail||"";!1===$fis.ValidateEmail(n)&&!1===bool(confirm($ict.ivE+$ict.ivEc),!1)||(t.aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dpreview"),data:{token:e},success:n=>{t.rC("freeze");let i=$$.dc("imagecollection pdfpreview"),a=Math.round(.88*vh()),r=n.total;r>10&&$$.dc("note warn",i).text($ict.tpe),$.each(n.img||[],((e,t)=>{$$.dc("pdfp",i).append($$.img(t).css("max-height",(a-rpx(6)).toString()+"px"))}));for(let e=(n.img||[]).length+1;e<=r;e++)$$.dc("pdfp ph",i).append($$.dc("note",$ict.pna));$ocms.dlg(i,{size:[a,Math.round(.88*vw())],zindex:50,form:!1,button:$rct.crI,confirm:function(n){let i=$(this);t.aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dsave"),data:{token:e},success:e=>{$ocms.postXT({url:$ocms.url("req/sconf"),data:{id:e.invid},success:t=>{i.trigger("modal_close"),!0===t.hasFile&&window.open($ocms.url("req/idoc")+"?id="+e.invid,"_blank"),$inv.d.close(),$ocms.init("req"),$inv.rReload()},error:()=>{alert($t.f1),i.trigger("modal_close")},complete:()=>{t.rC("freeze")}})},error:()=>{t.rC("freeze"),alert($ict.eis)}})},cancel:function(e){confirm($ict.cdI)&&($inv.d.close(),$inv.rReload())}})},error:()=>{t.rC("freeze"),alert($ict.eis)}}))},save:function(){let e=$inv.d.token();if(""===e)return;let t=$inv.d.layout();t.aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dsave"),data:{token:e},success:e=>{$inv.d.tbl().data("invid",e.invid)},error:()=>{alert($ict.eis)},complete:()=>{t.rC("freeze")}})},history:function(){let e=$inv.d.token();""!==e&&$ocms.postXT({url:$ocms.url("inv/dhistory"),data:{token:e},success:e=>{let t=$$.dc("dhist");if((e.history||[]).length<1)$$.dc("note",t).text("Noch keine Änderungen erfasst.");else{let n=$$.tblset({class:"invtbl fullwidth"},t);$$.tr(n.hd).append([$$.th().text("Zeit"),$$.th().text("Feld"),$$.th().text("Alt"),$$.th().text("Neu")]),$.each(e.history,((e,t)=>$$.tr(n.bdy).append([$$.tdc("keep",fdt(t.timestamp)),$$.td().text(t.target),$$.td().text(t.oldValue),$$.td().text(t.newValue)])))}$ocms.dlg(t,{width:800,form:!1})}})},discard:function(){let e=$inv.d.tbl().data("invid")||"";""!==e?!1!==confirm("Alle Änderungen verwerfen und den zuletzt gespeicherten Stand neu laden?")&&($inv.d.close(),$inv.cntInv({id:e})):alert("Es wurde noch kein Zwischenstand gespeichert, der wiederhergestellt werden könnte.")},warnExpiry:function(e){let t=Math.max(1,Math.round((e||0)/60));$fis.notifications.push({severity:"info",title:"Entwurf läuft ab",message:"Der Rechnungsentwurf läuft in etwa "+t+" Minute(n) ab. Bitte zwischenspeichern, sonst gehen die Änderungen verloren."})},closed:function(e){let t=$inv.d.token();$inv.d.tbl().removeData("dtoken"),""!==t&&$fis.draft.release(t),$fis.frm_edit().remove(),$fis.lf(!0),$fis.notifications.push({severity:"error",title:"Entwurf geschlossen",message:"expired"===e?"Der Rechnungsentwurf ist wegen Inaktivität abgelaufen. Nicht gespeicherte Änderungen sind verloren.":"Der Rechnungsentwurf wurde geschlossen."});try{$inv.rReload()}catch(e){}},close:function(){let e=$inv.d.token();""!==e&&($ocms.postXT({url:$ocms.url("inv/dclose"),data:{token:e}}),$fis.draft.release(e)),$inv.d.tbl().removeData("dtoken")}},$inv.cInv2=function(e){let t=$$.dc("rfrm").ldng(1),n=$ocms.dlg(t,{width:1e3});n&&n.ft.rwText($rct.rq1);let i=()=>{$ocms.postXT({url:$ocms.url("req/get"),timeout:60,data:{id:e.id,mode:"r"},success:t=>{t.admin=t.admin||{};let n=$fis.lf(!0).aC("fix").rC("hd");if($fis.frm_edit().IN(),$inv.eM(!0,!0),(t.requests||[]).length<1)n.aC("fix").text($rct.nd);else{$$.dc("lh",n,$rct.mdl);let i=$$.d(),a=$$.ul({class:"rql"}).data({search:e.id,parent:t.admin.parent}).appendTo(n),r={},l=$rcol.req.lbl();$.each(t.requests||[],(function(e,t){let n=$$.li({class:"cli rli"}).data($.extend({},t)).appendTo(a),s=$$.dc("lihd",n).addClass(t.state);!0===booln(t.open,!1)&&s.append($$.sc("cbox").click((()=>{n.tC("checked"),i.find("li").rC("checked"),!0===n.is(".checked")?$inv.rMn(t.open):$inv.eM(!0)}))),s.append([$$.sc("eid",t.ExternalId),$$.sc("nme",t.Name)]),$$.dc("lidt",n).append([$$.dc("rqs").append([$$.s(l.State+": "),$$.s($rct.sts[t.State||"-"])]),$$.dc("ivn").append([$$.s(l.InvoiceId+": "),$$.s(t.InvoiceId||"- -")]),$$.dc("wda").append([$$.s(l.WorkDoneAt+": "),$$.s(fdt(t.WorkDoneAt,"dd.MM.yyyy"))])]),r[t.Id]=n})),(t.inv||[]).length>0&&($$.dc("lh",n,$rct.invs),i=$$.ul({class:"ivl"}).appendTo(n),$.each(t.inv||[],((e,t)=>{let n=$$.li({class:"cli ili"}).data($.extend({},t)).appendTo(i),r=$$.dc("lihd",n).addClass(t.invstatus);!1===booln(t.isFinal,!0)?r.append($$.sc("cbox").click((()=>{""!==(t.Id||"")&&(n.tC("checked").siblings().rC("checked"),a.find("li").rC("checked"),!0===n.is(".checked")?$inv.iMnr(t):$inv.eM(!0))}))):["","dft"].indexOf(t.invstatus)<0&&r.append($$.sc("dli").click((function(){$inv.disp(t.Id,"inv")}))),r.append($$.sc("nme",t.DocumentName||t.Id)),$$.dc("lidt",n).append([$$.dc("wda").append([$$.s(fdt(t.DateCreated,"dd.MM.yyyy"))]),$$.d().text($ict.iSt[t.invstatus]||t.invstatus)])})))}},complete:()=>{n&&n.c.trigger("modal_close")}})};$ocms.postXT({url:$ocms.url("req/pget"),timeout:90,data:{id:e.id},success:e=>{n&&n.ft.rwText($rct.rq2),i()},error:()=>{confirm($rct.rq1f)?(n&&n.ft.rwText($rct.rq2),i()):n&&n.c.trigger("modal_close")}})},$inv.ccInv=function(e){let t=(e.data||{}).typ||"r",n=$fis.lf(),i=n.children("ul.rql"),a=i.data("parent"),r=[];if(i.find("li.rli.checked").each((function(){r.push($(this).data("Id"))})),r.length<1)return void alert($rct.dnS);if("i"===t&&r.length>1)return void alert($rct.dII);let l=$fis.frm_edit(),s=$$.dc("invoice_layout",l).append($$.dc("btn sprev").click($inv.sprev)),d=$fis.cf().width()>s.width()+n.width()+20;n.tC("fix",d).tC("hd",!d),$inv.eM(!1,!0);let c=$$.dc("rfrm").ldng(1),o=$ocms.dlg(c,{width:1e3});o.ft.rwText($rct.rq2),$ocms.postXT({url:$ocms.url("req/iget"),timeout:60,data:{id:a,mode:"ful",typ:t,sel:r.join(",")},success:e=>{let t=$$.dc("srq",s),n=$$.tblset({class:"invi"},t);n.bdy.remove(),n.ft=$$[0]("tfoot"),e.admin=e.admin||{},e.admin.p13b=bool(e.admin.p13b||"",!0===((e.inv||{}).InvoiceOptions||"").split(",").includes("§13b")),n.tbl.data($.extend({new:{},sms:{},itm:{}},{admin:e.admin,companies:e.companies,locations:e.locations}));let i=$$.tr(n.hd).aC("shd").append([$$.th().aC("aux")]);$rct.invHR.forEach((e=>$$.th(i,e))),n.tbl.on("fds.inv",$inv.invSumUpdate),$.each(e.requests||[],(function(t,i){if(0!==(i.Id||0)){let t=$inv.worknotes(i);i.text="i"===e.admin.type?$rct.req+jine([i.ExternalId,i.Name],": ").eine(" ",""):jine([jine([fdt(i.WorkDoneAt,"dd.MM.yy"),i.ExternalId]," - "+$rct.req+" "),t.ne(i.Name)],": \n");let a=$$.tbody(n.tbl).data($.extend({},i));$inv.rendersrq.call(a)}}));let a=$$.tr($$.tbody(n.tbl),{class:"placeholder"}).data({net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0});$inv.rrw.call(a),n.ft.appendTo(n.tbl);let r,l,d=e.admin||{},c=(e,t,i,a,r)=>{let l=$$.dc("inpfrm",s).aC(e).append("string"==typeof a?$$.dc("ahd",a):a>0?$$.dc("ahd",$rct.frm[i]):null),d=$$.dc("content",l).rwText(t);$$.dc("axf",l).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:d,nme:i,change:e=>{n.tbl.data("new")[i]=e}},r),$inv.eHtml)),n.tbl.data("new")[i]=t};c("tfrm",d.invoicetitle,"invoicetitle",0,null),c("adrfrm",d.invoiceaddress,"invoiceaddress",0,null),c("locfrm","","loc",1,{list:deepCopy(e.locations),lbl:"ref",property:"address"}),c("emailfrm",d.invoiceemail,"invoiceemail",0,null),$$.dc("sndfrm",s).append($$.dc("content").text(d.sender)),d.provisionend&&(l=d.provisionstart?$rct.provP:$rct.provD,r=d.provisionstart?fdt(d.provisionstart,"dd.MM.yyyy")+" - "+fdt(d.provisionend,"dd.MM.yyyy"):fdt(d.provisionend,"dd.MM.yyyy")),c("admfrm",r,"provisionperiod",l,1),n.tbl.data("new").CustomValues=d.CustomValues||"",$$.dc("inpfrm ctpfrm",s).text(jObj(d.CustomValues,"contactName")),n.tbl.children("tbody").each($inv.bdysort),n.tbl.trigger("fds.inv"),$inv.eM(!1,!0,"iss,p13b,setm,ctp")},complete:()=>{o.c.trigger("modal_close")}})},$inv.ccStInv=function(e){let t=e.data||{},n=$fis.lf(),i=t.id,a=$$.dc("invoice_layout",$fis.frm_edit()).append($$.dc("btn sprev").click($inv.sprev)),r=$fis.cf().width()>a.width()+n.width()+20;n.tC("fix",r).tC("hd",!r),$inv.eM(!1,!0);let l=$$.dc("rfrm").ldng(1),s=$ocms.dlg(l,{width:1e3});s.ft.rwText($ict.iq1),$ocms.postXT({url:$ocms.url("inv/pget"),timeout:90,data:{id:t.id},success:e=>{s&&s.ft.rwText($ict.iq2),$ocms.postXT({url:$ocms.url("inv/icget"),timeout:60,data:{id:i},success:e=>{let t=$$.dc("srq",a),n=$$.tblset({class:"invi"},t);n.bdy.remove(),n.ft=$$[0]("tfoot"),e.admin=e.admin||{},e.admin.p13b=bool(e.admin.p13b||"",!0===((e.inv||{}).InvoiceOptions||"").split(",").includes("§13b")),n.tbl.data($.extend({new:{},sms:{},itm:{}},{admin:e.admin,companies:e.companies,locations:e.locations}));let i=$$.tr(n.hd).aC("shd").append([$$.th().aC("aux")]);$rct.invHR.forEach((e=>$$.th(i,e))),n.tbl.on("fds.inv",$inv.invSumUpdate),$.each(e.requests||[],(function(t,i){if(0!==(i.Id||0)){let t=$inv.worknotes(i);i.text="i"===e.admin.type?$rct.req+jine([i.ExternalId,i.Name],": ").eine(" ",""):jine([fdt(i.WorkDoneAt,"dd.MM.yy")+t.ne(i.Name)],": ");let a=$$.tbody(n.tbl).data($.extend({},i));$inv.rendersrq.call(a)}}));let r=$$.tr($$.tbody(n.tbl),{class:"placeholder"}).data({net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0});$inv.rrw.call(r),n.ft.appendTo(n.tbl);let l,s,d=e.admin||{},c=(e,t,i,r,l)=>{let s=$$.dc("inpfrm",a).aC(e).append("string"==typeof r?$$.dc("ahd",r):r>0?$$.dc("ahd",$rct.frm[i]):null),d=$$.dc("content",s).rwText(t);$$.dc("axf",s).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:d,nme:i,change:e=>{n.tbl.data("new")[i]=e}},l),$inv.eHtml)),n.tbl.data("new")[i]=t};c("tfrm",d.invoicetitle,"invoicetitle",0,null),c("adrfrm",d.invoiceaddress,"invoiceaddress",0,null),c("locfrm",d.provisionlocation,"loc",1,{list:deepCopy(e.locations),lbl:"ref",property:"address"}),c("emailfrm",d.invoiceemail,"invoiceemail",0,null),$$.dc("sndfrm",a).append($$.dc("content").text(d.sender)),d.provisionend&&(s=d.provisionstart?$rct.provP:$rct.provD,l=d.provisionstart?fdt(d.provisionstart,"dd.MM.yyyy")+" - "+fdt(d.provisionend,"dd.MM.yyyy"):fdt(d.provisionend,"dd.MM.yyyy")),c("admfrm",l,"provisionperiod",s,1),n.tbl.data("new").CustomValues=d.CustomValues||"",$$.dc("inpfrm ctpfrm",a).text(jObj(d.CustomValues,"contactName")),n.tbl.children("tbody").each($inv.bdysort),n.tbl.trigger("fds.inv")},complete:()=>{s.c.trigger("modal_close")}})},error:()=>{s&&s.c.trigger("modal_close")}})},$inv.clCntInv=function(e){let t=$fis.lf(!1),n=[];t.find("li.ili.checked").each((function(){n.push($(this).data("Id"))})),1===n.length&&$inv.cntInv({id:n[0]})},$inv.cntInv=function(e){e=e||{};$fis.lf(!1).rC("fix").aC("hd");let t=$$.dc("invoice_layout",$fis.frm_edit()).append($$.dc("btn sprev").click($inv.sedit));$inv.eM(!1,!0);let n=$$.dc("rfrm").ldng(1),i=$ocms.dlg(n,{width:1e3});i.ft.rwText($rct.rq2),$ocms.postXT({url:$ocms.url("inv/get"),timeout:60,data:{id:e.id},success:e=>{e.admin=e.admin||{};let n=e.inv||{},i=$$.dc("srq",t),a=$$.tblset({class:"invi"},i);a.bdy.remove(),a.ft=$$[0]("tfoot"),a.tbl.data($.extend({invid:n.Id,new:{},sms:{},itm:{},bai:[]},e));let r=$$.tr(a.hd).aC("shd").append([$$.th().aC("aux")]);$rct.invHR.forEach((e=>$$.th(r,e))),a.tbl.on("fds.inv",$inv.invSumUpdate),$.each(e.req||[],(function(e,t){let n=$$.tbody(a.tbl).data($.extend({},t));$inv.rendersrq.call(n)}));let l=$$.tr($$.tbody(a.tbl),{class:"placeholder"}).data({net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0});$inv.rrw.call(l),a.ft.appendTo(a.tbl);let s=(e,n,i,r,l)=>{let s=$$.dc("inpfrm",t).aC(e).append("string"==typeof r?$$.dc("ahd",r):r>0?$$.dc("ahd",$rct.frm[i]):null),d=$$.dc("content",s).rwText(n);$$.dc("axf",s).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:d,nme:i,change:e=>{a.tbl.data("new")[i]=e}},l),$inv.eHtml)),a.tbl.data("new")[i]=n};s("tfrm",n.InvoiceTitle,"invoicetitle",0,null),s("adrfrm",n.SendToAddress,"invoiceaddress",0,null),s("locfrm",n.ProvisionLocation,"loc",1,null),s("emailfrm",n.SendToEmail,"invoiceemail",0,null),$$.dc("sndfrm",t).append($$.dc("content").text(e.admin.sender)),s("admfrm",n.ProvisionPeriod,"provisionperiod",!0===(n.ProvisionPeriod||"").includes("-")?$rct.provP:$rct.provD,1),a.tbl.data("new").CustomValues=n.CustomValues||"",$$.dc("inpfrm ctpfrm",t).text(jObj(n.CustomValues,"contactName")),a.tbl.children("tbody").each($inv.bdysort),a.tbl.trigger("fds.inv"),$inv.eM(!1,!0,"iss,p13b,setm,ctp")},complete:()=>{i.c.trigger("modal_close")}})},$inv.cSt=function(e){e=e||{};let t=$fis.lf(),n=$$.dc("invoice_layout",$fis.frm_edit()).append($$.dc("btn sprev").click($inv.sedit)),i=$fis.cf().width()>n.width()+t.width()+20;t.tC("fix",i).tC("hd",!i),$inv.eM(!1,!0);let a=$$.dc("rfrm").ldng(1),r=$ocms.dlg(a,{width:1e3});r.ft.rwText($ict.iq1),$ocms.postXT({url:$ocms.url("inv/pget"),data:{id:e.id},success:t=>{r&&r.ft.rwText($ict.iq2),$ocms.postXT({url:$ocms.url("inv/storno"),data:{id:e.id,mode:e.mode},success:e=>{e.admin=e.admin||{},e.admin.p13b=bool(e.admin.p13b||"",!0===((e.inv||{}).InvoiceOptions||"").split(",").includes("§13b"));let t=e.inv||{},i=$$.dc("srq",n),a=$$.tblset({class:"invi"},i);a.bdy.remove(),a.ft=$$[0]("tfoot"),a.tbl.data($.extend({invid:t.Id,new:{},sms:{},itm:{},bai:[]},e));let r=$$.tr(a.hd).aC("shd").append([$$.th().aC("aux")]);$rct.invHR.forEach((e=>$$.th(r,e))),a.tbl.on("fds.inv",$inv.invSumUpdate),$.each(e.req||[],(function(e,t){let n=$$.tbody(a.tbl).data($.extend({},t));$inv.rendersrq.call(n)}));let l=$$.tr($$.tbody(a.tbl),{class:"placeholder"}).data({net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0});$inv.rrw.call(l),a.ft.appendTo(a.tbl);let s=(e,t,i,r,l)=>{let s=$$.dc("inpfrm",n).aC(e).append("string"==typeof r?$$.dc("ahd",r):r>0?$$.dc("ahd",$rct.frm[i]):null),d=$$.dc("content",s).rwText(t);$$.dc("axf",s).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:d,nme:i,change:e=>{a.tbl.data("new")[i]=e}},l),$inv.eHtml)),a.tbl.data("new")[i]=t};s("tfrm",t.InvoiceTitle,"invoicetitle",0,null),s("adrfrm",t.SendToAddress,"invoiceaddress",0,null),s("locfrm",t.ProvisionLocation,"loc",1,null),s("emailfrm",t.SendToEmail,"invoiceemail",0,null),$$.dc("sndfrm",n).append($$.dc("content").text(e.admin.sender)),s("admfrm",t.ProvisionPeriod,"provisionperiod",!0===(t.ProvisionPeriod||"").includes("-")?$rct.provP:$rct.provD,1),a.tbl.data("new").CustomValues=t.CustomValues||"",$$.dc("inpfrm ctpfrm",n).text(jObj(t.CustomValues,"contactName")),a.tbl.children("tbody").each($inv.bdysort),a.tbl.trigger("fds.inv")},complete:()=>{r.c.trigger("modal_close")}})},error:()=>{r&&r.c.trigger("modal_close")}})},$inv.eHtml=function(e){let t=$(this),n=e.data instanceof jQuery?e.data:e.data.t,i=["invoiceemail","provisionperiod","invoicetitle"].includes(e.data.nme),a=i?[{name:"txt",label:"Text",type:"text",value:n.text()}]:[{name:"txt",label:"Text",type:"html",value:n.html(),tinymce:!0,attr:{style:"height: 300px"}}],r=e.data.change||null,l={title:t.data("dialog")||"",success:function(t){i?n.text(t.txt||""):n.html(t.txt),"function"==typeof r&&r(t.txt),$inv.d.syncField(e.data.nme,i?t.txt||"":t.txt)},tinymce:{valid_elements:"br",hidemenu:!0,hidetoolbar:!0}};if(Array.isArray(e.data.list)){let t=$$.dc("lstfrm");$.each(e.data.list,((n,i)=>{let a=$$.dc("li",t).append(""!==(e.data.lbl||"")?$$.dc("lbl").rwText(i[e.data.lbl]):null);$$.dc("adr",a).rwText(i[e.data.property]).data("val",i[e.data.property]).click((function(){let e=$(this),t=e.closest(".modal-body").find(':input[name="txt"]');t.is(".tinymce")?tinymce.get(t.attr("id")).setContent($$.s().rwText(e.data("val")).html()):"TEXTAREA"===t.prop("tagName")?t.val(e.data("val")).change():t.rwText(e.data("val"))}))})),l.addcontent=t}$ocms.dlgform(a,l)},$inv.setVat=function(e){$(this);let t=e.data,n=prompt($rct.rqV);n&&(n=parseFloat(n.replace("%","")),n>1&&(n*=.01),!1===isNaN(n)&&(t.siblings(".itm").each((function(){let e=$(this).data();e.vat=fnum(n,{style:"percent"}).replace(" ",""),(e.net_val||0)>0&&(e.vat_val=e.net_val*n),(e.svcnet_val||0)>0&&(e.svcvat_val=e.svcnet_val*n)})),$inv.t_fds_inv()))},$inv.inRow=function(e){let t=$(this),n=e.data,i={},a=$rcol.itm.clone(["SortOrder","NameOrNumber","Type","quantityhours","UnitString","net","svcnet_val","svcvat_val","net_val","vat_val","vat","Note"]),r="N"+(65536*(1+Math.random())||0).toString(16).substr(6),l=$$.tr({id:"itm_"+r.toString(),class:"itm"});$ocms.dlgform(a,{title:t.data("dialog")||"",success:function(e){l.data($.extend({Id:r},i,e)),$inv.rrw.call(l),l.insertAfter(n),$inv.t_fds_inv()},typedvalues:!0})},$inv.eRow=function(e){let t=$(this),n=e.data,i=n.data()||{},a=["SortOrder","NameOrNumber","Type","quantityhours","UnitString","net","svcnet_val","svcvat_val","net_val","vat_val","vat","Note"];i.id||""!==(i.Type||"")||a.unshift("Type");let r=$rcol.itm.clone(a).applyValues(i);r.set("Type","hidden","type"),$inv.eRw.call(t,n,i,r)},$inv.eRw=function(e,t,n){let i=$(this);$ocms.dlgform(n,{title:i.data("dialog")||"",success:function(n){let i={};""===(t.Id||"")&&(i.Id="N"+(65536*(1+Math.random())||0).toString(16).substr(6),e.attr("id","itm_"+i.Id.toString())),i.quantity=((n.quantityhours||"").toString()+" "+(n.UnitString||"").toString()).trimEnd(),e.data($.extend({},t,n,i)),console.debug("eRw success %o",e.data()),$inv.rrw.call(e),$inv.t_fds_inv()},typedvalues:!0})},$inv.bdysort=(e,t)=>{$(t).Sortable({dragItem:!1,dragHandleClass:"ico",parentident:"tr",onend:()=>{$inv.t_fds_inv()}})},$inv.rrw=function(){let e=$(this),t=e.data(),n={},i=e.is(".placeholder"),a=e.is(".hidenote"),r=e=>$$.d().append(e).html(),l=[$$.dc("ibtn insb",{title:$rct.iRb}).append(gi("indent-left")).click(e,$inv.inRow)];!1===i&&(l.unshift($$.dc("ibtn edit",{title:$rct.cP}).append(gi("pencil")).click(e,$inv.eRow)),l.push($$.dc("ibtn del",{title:$rct.dR}).append(gi("trash")).click((function(t){confirm($rct.cD)&&(e.remove(),$inv.t_fds_inv())}))));let s=$$.dc("axf").append(l);!0===i?n={id:"",typ:"placeholder"}:!0===e.is(".itm.osum")?n={invrqid:t.InvRqId,id:"osum"+e.index(),typ:"osum",p:"",q:null,t:r(t.tbl.tbl),tt:null,v:null,vt:t.net_val,vs:t.svcnet_val,vat:t.vat,vv:t.vat_val,vsv:t.svcvat_val,det:!1}:(n={invrqid:t.InvRqId,id:t.Id||"",typ:t.Type||"other",p:"",q:null,t:"",tt:null,v:null,vt:t.net_val,vs:t.svcnet_val,vat:t.vat,vv:t.vat_val,vsv:t.svcvat_val,det:""!==(t.Note||"")&&!1===a},$$.dc("ibtn ico move",s,{title:$rct.mR}),n.p=t.position||t.SortOrder||"",""===n.id?n.t="":["Text","Title"].includes(n.typ)&&0===(t.net_val||0)?n.t=t.htmltext||("#"!==(t.NameOrNumber||"").substr(0,1)?r($$[0]("p").text(t.NameOrNumber)):"")+(t.Note||""):(n.tt=n.det?"":$$.s(t.Note||"").text(),n.q=t.quantity||fnum(t.quantityhours)+" "+(t.UnitString||""),n.t=t.htmltext||(n.det?r($$.s(t.NameOrNumber||""))+r($$.dc("desc").html(t.Note)):r($$.s(t.NameOrNumber||""))),n.v=t.net,n.vt=t.net_val)),""!==(t.Note||"")&&$$.dc("ibtn add",s).append(gi("object-align-left")).click((function(t){$inv.rrw.call(e.tC("hidenote"))}));let d=[$$.tdc("aux").append(s),$$.tdc("keep").text(n.p)];""===n.id?d.push($$.td(e,{colspan:4}).append(n.t)):(Array.prototype.push.apply(d,n.q?[$$.tdc("keep").text(n.q)]:[]),Array.prototype.push.apply(d,[$$.tdc("txt",{colspan:n.q?1:2,title:n.tt}).append(n.t),$$.tdc("currency").text(fnum(n.v,$rct.cst)),$$.tdc("currency inetval").text(fnum(n.vt,$rct.cst)).attr("title",$rct.svcPart+": "+fnum(n.vs,$rct.cst))])),e.empty().attr("class",i?"placeholder":"itm").aC(n.Typ).tC("hidenote",a).append(d),t.co=n},$inv.invSumUpdate=function(){let e=$(this),t=e.children("tfoot").empty(),n=bool((e.data().admin||{}).p13b||"",!1);e.nextAll(".fnote").remove();let i={ttn:0,ttb:0,ttvat:0,tscn:0,tscvat:0,vat:{},itmnet:{}},a=[],r=(e,n,i)=>$$.tdc("currency",$$.tr(t,{class:i||"tsum"}).append([$$.tdc("aux"),$$.td({colspan:4}).text(e)]),fnum(n,$rct.cst)),l=t=>$$.dc("fnote").insertAfter(e).rwText(t),s=e.children("tbody");s.each(((e,t)=>{let n=$(t),r=n.data()||{},l=[],s=[],d=null,c=0,o=n.find("tr.itm"),u=0;n.tC("empty",o.length<1),o.each(((e,t)=>{let n=$(t).data()||{};!function(e,t,n){t.tscn+=e.svcnet_val||0,t.tscvat+=e.svcvat_val||0,t.ttn+=e.net_val||0,t.ttvat+=e.vat_val||0,t.ttb+=(e.net_val||0)+(e.vat_val||0),""!==(e.vat||"")&&(t.vat[e.vat]=(t.vat[e.vat]||0)+(e.vat_val||0))}(n,i,r.Id),c+=n.net_val||0,l.push(n.co);let a=$inv.itemToContract(n);"set"===a.type&&""!==a.id?d=a.id:null!==d&&""!==(a.id||"")&&(a.setId=d),s.push(a),(void 0===n.SortOrder||null===n.SortOrder?-1:n.SortOrder)>-1&&(!1===["text","title"].includes((n.Type||"other").toLowerCase())&&u++,n.SortOrder=0,n.position=u,$inv.rrw.call(t))})),n.find("tr.isum > td.isumval").text(fnum(c,$rct.cst)),a.push({Id:r.Id,nme:r.Name,text:r.text,itm:l,items:s,netval:c})}));let d=e.find("tbody:not(.empty)").length;s.find("tr.isum").tC("hidden",d<2),r("Netto",i.ttn),!1===n?$.each(i.vat,((e,t)=>{r($rct.vat+" "+e,t,"tvat")})):i.ttb=i.ttn,r("Summe",i.ttb);let c=e.data().admin.type;"i"===c?(l($rct.note2),l($rct.note4)):"c"===c?l($rct.note2):(l(string($rct.note3,[fnum((i.tscn+i.tscvat)*(e.data().admin.tax_servicerefund||0),$rct.cst)])).aC("ntax"),l($rct.note2),l(string($rct.note1,[fnum(i.tscn+i.tscvat,$rct.cst),fnum(i.tscn,$rct.cst),fnum(i.tscvat,$rct.cst)]))),!0===n&&l($rct.note13b),e.data("sms",i),e.data("bai",a),""===(e.data("dtoken")||"")&&!1===bool(e.data("dseeding"),!1)&&null!=(e.data("admin")||{}).type&&(e.data("dseeding",!0),$inv.d.seed($.extend($inv.invcPayload(e.data()),{invid:e.data("invid")||""})))},$inv.worknotes=function(e){let t="";return e.steps.forEach(((e,n)=>{let i;try{i=JSON.parse(e.Data||{}).fields||[]}catch(e){console.debug(e),i=[]}!0!==Array.isArray(i||"")&&(i="object"==typeof i&&!0===Array.isArray(i.field||"")?i.field:[]),i.forEach(((e,n)=>{"Ausgeführte Arbeiten"===e.name&&(t=e.result||"")}))})),t},$inv.rendersrq=function(){let e=$(this).empty(),t=e.is(".onesum"),n=e.data(),i=$$.tr(e,{id:"srq"+n.Id}).aC("title nosort"),a=($rcol.itm.lbl(),$$.dc("axf").appendTo($$.tdc("aux",i)));$$.dc("ibtn osum",a,{title:$rct.combP}).append(gi("euro")).click((function(t){e.tC("onesum"),$inv.rendersrq.call(e),$inv.t_fds_inv()})),$$.dc("ibtn setvat",a,{title:$rct.sV}).append(gi("gbp")).click(i,$inv.setVat),$$.dc("ibtn insb",a,{title:$rct.iRb}).append(gi("indent-left")).click(i,$inv.inRow);let r,l=$$.sc("text",n.text),s=($$.td(i,{colspan:t?4:5}).append(l),["net_val","vat_val","svcnet_val","svcvat_val","net"]);if($$.dc("ibtn edit",a).data("dialog",$rcol.req.lbl().Name).append(gi("pencil")).click({t:l,change:e=>{n.text=e,$inv.t_fds_inv()}},$inv.eHtml),t&&($$.tdc("currency isumval",i),r={Id:n.Id.toString()+"_osum",net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0},r.tbl=$$.tblset({class:"stbl"})),$.each(n.items||[],((n,i)=>{let a,l={Id:i.Id,net_val:i.net_val||0,vat_val:i.vat_val||0,svcnet_val:0,svcvat_val:0,net:i.net||0,Note:i.Note||""};if("service"===i.Type.toLowerCase())l.svcnet_val=i.net_val||0,l.svcvat_val=i.vat_val||0;t?(a=$$.tr(r.tbl.bdy,{id:"itm"+i.Id,class:"sitm"}).aC(i.Type),"Text"===i.Type||"Title"===i.Type?$$.td(a,{colspan:2}).html(i.htmltext||i.Note):($$.tdc("keep",a).text(i.quantity||((i.quantityhours||0)>0?fnum(i.quantityhours)+(i.UnitString||"").eine(" ",""):"")),i.htmltext?$$.tdc("txt",a).html(i.htmltext):$$.tdc("txt",a).text(i.NameOrNumber).attr("title",i.Note)),$.each(s,((e,t)=>{r[t]+=l[t]})),a.data(l)):($.extend(l,i),a=$$.tr(e,{id:"itm"+i.Id,class:"itm"}),a.data(l),$inv.rrw.call(a))})),t){let t=$$.tr(e,{id:"itmsq"+n.Id,class:"itm osum"}).data(r);$inv.rrw.call(t)}else{let t=$$.tr(e).aC("isum nosort");$$.tdc("aux",t),$$.td(t,{colspan:4}).text($rct.iSum),$$.tdc("currency isumval",t)}},$inv.t_fds_inv=()=>{let e=$("div.invoice_layout table.invi");e.trigger("fds.inv"),""!==(e.data("dtoken")||"")&&$inv.d.syncChanged(e)},$inv.sedit=()=>{$inv.sprev(!0)},$inv.jdisp=function(e){e.stopPropagation(),e.data.id&&$inv.disp(e.data.id,e.data.typ||"")},$inv.disp=(e,t)=>{let n="";switch(t){case"inv":n="inv/rdoc";break;case"rem":n="rem/rdoc"}""!==n&&$ocms.postXT({url:$ocms.url(n),data:{id:e||"",typ:"img"},success:e=>{let t=$$.dc("imagecollection pdfpreview"),n=Math.round(.88*vh());e.id;$.each(e.img||[],(function(e,i){$$.dc("pdfp",t).append($$.img(i).css("max-height",(n-rpx(6)).toString()+"px"))})),$ocms.dlg(t,{size:[n,Math.round(.88*vw())],zindex_min:50,form:!1,exclusive:!1})}})},$inv.jdbn=function(e){$ocms.postXT({url:$ocms.url("inv/rdocn"),data:{name:e.data.id||"",typ:"img"},success:e=>{let t=$$.dc("imagecollection pdfpreview"),n=Math.round(.88*vh());e.id;$.each(e.img||[],(function(e,i){$$.dc("pdfp",t).append($$.img(i).css("max-height",(n-rpx(6)).toString()+"px"))})),$ocms.dlg(t,{size:[n,Math.round(.88*vw())],zindex:50,form:!1})}})},$inv.sp13b=()=>{var e=$("div.invoice_layout").find("table.invi"),t=e.data();t.admin.p13b=!0,!1===(t.inv.InvoiceOptions||"").split(",").includes("§13b")&&(t.inv.InvoiceOptions+=",§13b"),e.trigger("fds.inv"),$inv.d.sync({Target:"p13b",Value:t.admin.p13b})},$inv.itemToContract=function(e){let t=((e=e||{}).Type||"").toString().toLowerCase(),n={id:(e.Id||"").toString(),type:t,title:"",desc:"",qty:"",price_net:"",total_net:e.net_val||0,vat:e.vat||""};var i;return e.co&&"osum"===e.co.typ?(n.desc=e.co.t||"",n.total_net=e.net_val||0):["text","title"].includes(t)&&0===(e.net_val||0)?(n.desc=e.htmltext||("#"!==(e.NameOrNumber||"").substr(0,1)?(i=$$[0]("p").text(e.NameOrNumber||""),$$.d().append(i).html()):"")+(e.Note||""),n.total_net=""):(e.htmltext?n.desc=e.htmltext:(n.title=e.NameOrNumber||"",n.desc=e.Note||""),n.qty=e.quantity||(0!==(e.quantityhours||0)?fnum(e.quantityhours)+(e.UnitString?" "+e.UnitString:""):""),n.price_net=e.net||0,n.total_net=e.net_val||0),n},$inv.ssetmode=()=>{let e=$("div.invoice_layout").find("table.invi").data();e.admin=e.admin||{};let t,n=e.admin.setmode||"setprice",i=e=>$$.dc("btn",$ict.setmo[e]).tC("selected",n===e).click((()=>{t.c.trigger("modal_close"),$inv.setSetmode(e)})),a=$$.dc("choicefrm").append([i("setprice"),i("itemprices"),i("setonly")]);t=$ocms.dlg(a,{width:800})},$inv.setSetmode=e=>{let t=$("div.invoice_layout").find("table.invi").data();t.admin=t.admin||{},t.admin.setmode=e,t.inv=t.inv||{};let n=(t.inv.InvoiceOptions||"").split(",").filter((e=>""!==e&&0!==e.indexOf("setmode:")));e&&"setprice"!==e&&n.push("setmode:"+e),t.inv.InvoiceOptions=n.join(","),$inv.d.sync({Target:"setmode",Value:e})},$inv.sctp=()=>{let e=$invcol.ctp;$ocms.dlgform(e,{title:$ict.ctp,success:function(e){var t=$("div.invoice_layout"),n=t.find("table.invi").data();let i={};void 0!==n.new&&"{"===(n.new.CustomValues||"").substr(0,1)&&(i=JSON.parse(n.inv.CustomValues)),i.contactName=e.name,i.contactEmail=e.email,n.new.CustomValues=JSON.stringify(i),t.find(".ctpfrm").text(ne(e.name,e.email)),$inv.d.sync({Target:"contact",Value:{name:e.name,email:e.email}})},typedvalues:!0})},$inv.invcPayload=function(e){let t=(e=e||{}).sms||{},n=$.extend({},e.new),i=$.extend({},e.admin);return n.total_net=t.ttn||0,n.total_gross=t.ttb||0,n.title=null!=n.invoicetitle?n.invoicetitle:n.title||"",n.provisionlocation=null!=n.loc?n.loc:n.provisionlocation||"",n.paymentterm=null!=i.paymentterms?i.paymentterms:n.paymentterm||"",i.customerid=null!=i.customerid?i.customerid:i.CustomerId,{admin:i,req:e.bai,sms:e.sms,new:n}},$inv.ssave=()=>{$inv.d.save()},$inv.sprev=e=>{$inv.d.preview()},$inv.rReload=()=>{try{let e=$("#listframe ul.rql:first").data();$inv.cInv2({id:e.search})}catch(e){}},$inv.quantChange=function(e){let t=$(this).closest("form"),n={},i=e=>parseFloat(e.toString().replace("%","").replace(",",".")),a=e=>e.toFixed(2);t.find(":input").each(((e,t)=>{n[$(t).attr("name")]=$(t)}));let r=parseInt(n.quantityhours.val()||"0"),l=i(n.net.val()||"0"),s=.01*i(n.vat.val());r>0&&l>0&&(n.net_val.val(a(r*l)),n.vat_val.val(a(r*l*s)),["Service"].includes(n.Type.val())&&(n.svcnet_val.val(a(r*l)),n.svcvat_val.val(a(r*l*s))))},$inv.storno=function(e,t){let n,i=$$.dc("choicefrm").append([$$.dc("btn","Storno ohne Details").click({id:e,mode:"simple"},(e=>{n.c.trigger("modal_close"),$inv.cSt(e.data)})),$$.dc("btn","Storno mit neuer Rechnung").click({id:e},(e=>{n.c.trigger("modal_close"),$inv.ccStInv(e)})),$$.dc("btn","Storno mit best. Rechnung").tC("inactive",!1===bool(t,!1)).click({id:e,mode:"copy"},(e=>{!0===bool(t,!1)&&(n.c.trigger("modal_close"),$inv.cSt(e.data))}))]);n=$ocms.dlg(i,{width:1e3})},$inv.credit=function(e,t){let n,i=$$.dc("choicefrm").append([$$.dc("btn","Gutschrift").click({id:e,mode:"credit"},(e=>{n.c.trigger("modal_close"),$inv.cSt(e.data)}))]);n=$ocms.dlg(i,{width:1e3})},$inv.setPyd=function(e){confirm($ict.cpyd)&&$ocms.postXT({url:$ocms.url("inv/setpyd"),timeout:60,data:{id:e},success:e=>{alert($ict.relm)},error:()=>{alert($t.f1)}})},$inv.setUpd=function(e){confirm($ict.cupd)&&$ocms.postXT({url:$ocms.url("inv/setupd"),timeout:60,data:{id:e},success:e=>{alert($ict.relm)},error:()=>{alert($t.f1)}})},$inv.resendRem=function(e){e.stopPropagation(),e.data.id&&confirm(string($ict.remresc,[e.data.name]))&&$ocms.postXT({url:$ocms.url("rem/resend"),timeout:60,data:{id:e.data.id},success:t=>{alert(string($ict.remresr,[e.data.name]))},error:()=>{alert($t.f1)}})},$inv.dspRem=function(e){let t=$$.dc("rfrm").ldng(1),n=$ocms.dlg(t,{width:1e3});n.ft.rwText($rct.rq2),$ocms.postXT({url:$ocms.url("inv/getrem"),timeout:60,data:{id:e,drafts:!1},success:e=>{n.ft.empty();let i=$$.tblset({class:"invtbl"},t.empty()),a=$invcol.rem2,r=$$.tr(i.hd);$$.th(r);$.each(a.fields||[],((e,t)=>{$$.th(r).text(t.label)}));let l=!1;$.each(e,((e,t)=>{l=!l;let n=$$.tr(i.bdy).tC("alt",l),r=$$.td(n);n.click((function(){n.tC("selected").siblings().rC("selected")})),!0===bool(t.hasFile,!1)&&($$.dc("idl ilbtn",r,{title:$ict.dl+"\n"+t.DocumentName}).append(gi("save-file","ico")).click({id:t.Id},$inv.downloadrem),$$.dc("idl ilbtn",r,{title:$ict.remdsp+"\n"+t.DocumentName}).append(gi("eye-open","ico")).click({id:t.Id,typ:"rem"},$inv.jdisp),$$.dc("idl ilbtn",r,{title:$ict.remres+"\n"+t.DocumentName}).append(gi("refresh","ico")).click({id:t.Id,typ:"rem",name:t.DocumentName},$inv.resendRem)),$.each(a.fields||[],((e,i)=>{let a=$$.td(n).aC(i.dtype),r=t[i.name];if("function"==typeof i.dfnc)i.dfnc.call(a,r,t);else switch(i.type||""){case"date":a.text(fdt(t[i.name],"dd.MM.yy"));break;case"datetime":a.text(fdt(t[i.name]));break;case"html":a.append($$.dc("ctw").html(r)),a.append($$.dc("ttip").html(r));break;default:a.text(t[i.name])}if("InvoiceId"===(i.name||""))a.aC("keep");switch(typeof i.title){case"function":i.title.call(a,t);break;case"string":a.attr("title",cs.title)}}))}))},error:()=>{t.empty(),n.ft.rwText($t.f1)},complete:()=>{t.ldng(0)}})},$inv.ccRem=function(e,t){$(this);$ocms.postXT({url:$ocms.url("rem/lrem"),timeout:60,data:{id:e},success:n=>{let i=$invcol.rid.clone();i.applyValues(n.ov);let a=$$.dc("ac"),r=$$.tblset({class:"fullgrid fullwidth"},a);if((n.lst||[]).length>0){$$.d({style:"margin: 1.5rem 0 1rem 0;font-size: 110%;text-decoration: underline;"}).prependTo(a).text($ict.rovlh);let e=$$.tr(r.hd);$ict.rovl.forEach(((t,n)=>$$.th(e,t))),$.each(n.lst,((e,t)=>{$$.tr(r.bdy).append([$$.tdc("keep",t.subject),$$.tdc("currency",fnum(t.amount,$rct.cst)),$$.tdc("currency",fnum(t.amount_payed,$rct.cst)),$$.tdc("keep",fdt(t.DateFinalized,"dd.MM.yy"))])}))}else $$.td($$.tr(r.bdy),$ict.nd);$ocms.dlgform(i,{addcontent:a,title:string($ict.remdt,[t||"?"]),success:function(t){$inv.ccRem_s2(e,t)},typedvalues:!0})}})},$inv.rRemRw=function(e){let t=$(this),n=e.rm||{};t.empty().data({invoiceid:n.invoiceid,invoicedate:n.invoicedate,amount:n.amount,amount_payed:n.amount_payed});let i=$$.dc("axf").append($$.dc("ibtn edit",{title:$rct.cP}).append(gi("pencil")).click(t,$inv.eRowR));t.append([$$.tdc("aux").append(i),$$.tdc("keep",n.invoiceid),$$.tdc("keep",fdt(n.invoicedate,"dd.MM.yy")),$$.tdc("currency",fnum(n.amount,$rct.cst)),$$.tdc("currency",fnum(n.amount_payed,$rct.cst)),$$.tdc("currency",fnum(n.amount-n.amount_payed,$rct.cst))])},$inv.eRowR=function(e){let t=$(this),n=e.data,i=n.data()||{},a=$invcol.rem.clone().applyValues(i);$ocms.dlgform(a,{title:t.data("dialog")||"",success:function(e){let i=t.closest("table"),a=i.data();$.extend(a.rm,e),i.data(a),$inv.rRemRw.call(n,a)},typedvalues:!0})},$inv.ccRem_s2=function(e,t){$fis.lf(!1).rC("fix").aC("hd");let n=$$.dc("invoice_layout",$fis.frm_edit()).append($$.dc("btn sprev").click($inv.rprev));$inv.eM(!1,!0);$$.dc("rfrm").ldng(1);$ocms.postXT({url:$ocms.url("rem/get"),timeout:60,data:$.extend({id:e},t),success:e=>{let t=e.rm||{},i=$$.dc("srq",n);$ict.remt[t.type].forEach((e=>$$[0]("p").rwText(e).appendTo(i)));let a=$$.tblset({class:"invi"},i);a.ft=$$[0]("tfoot"),a.tbl.data($.extend({invid:t.invid,new:{}},e));let r=$$.tr(a.hd).aC("shd").append([$$.th().aC("aux")]);$ict.remHR.forEach((e=>$$.th(r,e))),$inv.rRemRw.call($$.tr(a.bdy),a.tbl.data()),a.ft.appendTo(a.tbl),$ict.remt2[t.type].forEach((e=>$$[0]("p").rwText(e).appendTo(i)));let l=(e,t,i,r,l)=>{let s=$$.dc("inpfrm",n).aC(e).append("string"==typeof r?$$.dc("ahd",r):r>0?$$.dc("ahd",$rct.frm[i]):null),d=$$.dc("content",s).rwText(t);$$.dc("axf",s).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:d,nme:i,change:e=>{a.tbl.data("new")[i]=e}},l),$inv.eHtml)),a.tbl.data("new")[i]=t};l("tfrm",t.subject,"subject",0,null),l("adrfrm",t.invoiceaddress,"invoiceaddress",0,null),l("emailfrm",t.invoiceemail,"invoiceemail",0,null),$$.dc("sndfrm",n).append($$.dc("content").text(t.sender)),a.tbl.children("tbody").each($inv.bdysort),a.tbl.trigger("fds.inv")},complete:()=>{}})},$inv.rprev=()=>{var e=$("div.invoice_layout"),t=e.find("table.invi"),n=t.data();$.extend(n.new,t.find("tbody > tr:first").data()),e.aC("freeze"),!1!==$fis.ValidateEmail(n.new.invoiceemail||"")||!1!==bool(confirm($ict.ivE+$ict.ivEc),!1)?$ocms.postXT({url:$ocms.url("rem/prep"),data:{remc:JSON.stringify({rem:n.rm,new:n.new}),id:n.invid||""},success:t=>{e.rC("freeze");let n=$$.dc("imagecollection pdfpreview"),i=Math.round(.88*vh()),a=t.id;$.each(t.img||[],(function(e,t){$$.dc("pdfp",n).append($$.img(t).css("max-height",(i-rpx(6)).toString()+"px"))})),$ocms.dlg(n,{size:[i,Math.round(.88*vw())],zindex:50,form:!1,button:$ict.remd,confirm:function(e){let t=$(this);$ocms.postXT({url:$ocms.url("rem/conf"),data:{id:a},success:()=>{t.trigger("modal_close"),window.open($ocms.url("rem/idoc")+"?id="+a,"_blank"),$ocms.init("req"),$inv.rReload()},error:()=>{alert($t.f1),t.trigger("modal_close")}})},cancel:function(e){$(this);confirm($ict.cdI)&&$ocms.postXT({url:$ocms.url("rem/del"),data:{id:a}}),$inv.rReload()}})}}):e.rC("freeze")},$inv.sis=e=>{confirm($ict.sisc)&&$ocms.postXT({url:$ocms.url("inv/sis"),data:{id:e||""},success:e=>{}})},$inv.srs=e=>{confirm($ict.srsc)&&$ocms.postXT({url:$ocms.url("rem/srs"),data:{id:e||""},success:e=>{}})},$inv.mfrrel=e=>{$("#contentframe").ldng(),$ocms.postXT({url:$ocms.url("inv/mfrrel"),data:{id:e||""},success:e=>{$inv.rerenderinv()},complete:()=>{$("#contentframe").ldng(0)}})};
\ No newline at end of file
+let $rct={mdl:"Aufträge",or:"offene Aufträge",orr:"offene Aufträge (4 W)",rn:"Auftragsnummer",iov:{all:"Auftragsübersicht (alle)","":"Auftragsübersicht"},wk:"Woche",nd:"Keine Daten gefunden.",h:"Uhr",rq1:"Auftragsdaten werden von MFR abgerufen.\nDer Vorgang kann bis zu 90Sek dauern.",rq2:"Auftragsdaten werden geladen",rq1f:"Die Auftragsdaten von MFR konnten nicht oder nicht schnell genug abgerufen werde.\nMöchten Sie mit den bestehenden Daten trotzdem weitermachen?",note1:"Im Bruttobetrag sind {0} Lohnkosten enthalten (netto {1}). Die darin enthaltene Umsatzsteuer beträgt {2}.",note2:"Bitte beachten Sie, nach §14 Abs. 1 Umsatzsteuergesetz ist diese Rechnung ein Zahlungsbeleg oder eine andere beweiskräftige Unterlage für 2 Jahre nach Ablauf des Kalenderjahres der Ausstellung dieser Rechnung aufzubewahren, soweit nicht aufgrund anderer gesetzlicher Regelungen andere ggf.längere Aufbewahrungsfristen gelten.",note3:"Privathaushalten erstattet das Finanzamt bis zu {0} des Arbeitslohns mit der nächsten Steuererklärung.",note4:"Für bereits erbrachte Arbeiten, Dienstleistungen, Materiallieferungen und getätigte Bestellvorgänge zum oben genannten Bauvorhaben, die sich aus dem mit Ihnen geschlossenen Vertrag ergeben, stellen wir Ihnen vertragsgemäß unsere Akontozahlung in Rechnung. Eine Endabrechnung erhalten Sie als Schlussrechnung nach Abschluss des gesamten Bauvorhabens. Das Ausführungsdatum entnehmen Sie bitte dem Schlusstext dieser Rechnung. Wir danken Ihnen herzlich für das entgegengebrachte Vertrauen und bitten Sie um kurzfristigen Ausgleich der Akontorechnung.",note13b:"Gem. §13b Umsatzsteuergesetz unterliegen Sie der Steuerschuldnerschaft des Leistungsempfängers zur Umsatzsteuer aus dieser Rechnung mit einem Steuersatz von 19%.",crI:"Rechnung erstellen",crII:"Abschlagsrechnung erstellen",dII:"Für eine Abschlagsrechnung darf nur ein Auftrag gewählt werden.",dnS:"Für eine Rechnung muss mindestens ein Auftrag gewählt werden.",inv:"Rechnung",invs:"Rechnungen",req:"Auftrag",provP:"Leistungszeitraum",provD:"Leistungsdatum",cP:"Position ändern",iRb:"Zeile darunter einfügen",dR:"Zeile löschen",sV:"USt festlegen",cD:"Löschen?",mR:"Zeile verschieben",svcPart:"Service-Anteil",vat:"Umsatzsteuer",combP:"Positionen zusammenfassen",iSum:"Zwischensumme",dtRel:"Freigegeben am: ",dtCr:"Erstellt am: ",rqV:"USt des Auftrags?",cthd:"wirklich aus-/einblenden ?",cst:{style:"currency",currency:"EUR"},sts:{IsWorkDone:"Arbeiten erledigt",Closed:"Auftrag geschlossen",SubcontractorPendingConfirmation:"Warten auf Bestätigung (Unterauftrag)",Scheduled:"Geplant",OfferIsRejected:"Angebot abgelehnt",OfferIsSend:"Offen (Angebot versandt)",CollaborationWaitingConfirmation:"Warten auf Bestätigung (Zusammenarbeit)",Released:"Freigegeben",OfferIsConfirmed:"Bestätigt",InProgress:"In Bearbeitung",ReadyForScheduling:"Zur Planung",Created:"Erstellt",Rejected:"Abgebrochen",Invoiced:"Rechnung gestellt","-":"-"},invHR:["Pos.","Menge","Artikelbezeichnung","VK","Summe"],frm:{invoiceaddress:"Adresse",loc:"Leistungsort / Lieferadresse",invoiceemail:"Email"}},$rcol={req:new fields_definition("Auftrag","Aufträge",[{name:"tags",label:"",type:"string",dfnc:function(e,t){""!==(e||"")&&($(this).aC("tags"),e.split(",").forEach((e=>{""!==e&&$(this).append($$.sc("tag "+e.replace(" ","_").replace("/","_").toLowerCase(),e))})))}},{name:"DateOfCreation",label:"Datum",type:"date",title:function(e){$(this).attr("title",$rct.dtCr+fdt(e.DateOfCreation).ne("-")+" \n"+$rct.dtRel+fdt(e.DateReleased).ne("-"))}},{name:"CustomerName",label:"Kunde (Firma)",type:"string"},{name:"Name",label:"Auftragsname",type:"string"},{name:"ExternalId",label:"Auftragsnummer",type:"string"},{name:"ParentExtenalId",label:"PAuftrag",type:"string"},{name:"InvoiceId",label:"RNummer",type:"string",dfnc:function(e,t){$(this).rwText(e," ").find("span").each((function(){$(this).aC("cla").click({id:$(this).text()},$inv.jdbn)}))}},{name:"State",label:"Status",type:"string"},{name:"WorkDoneAt",label:"Erledigt am",type:"date"},{name:"Description",label:"Beschreibung",type:"html"}]),itm:new fields_definition("Auftragsposition","Auftragspositionen",[{name:"NameOrNumber",label:"Bezeichnung",type:"string"},{name:"Type",label:"Typ",type:"select",required:!0,value:"Text",url:[{value:"Text",label:"Text"},{value:"Equipment",label:"Ausrüstung"},{value:"Material",label:"Material"},{value:"Service",label:"Arbeitsleistung"}],change:function(e){$req.quantChange.call(this,e)}},{name:"quantityhours",label:"Anzahl / Menge",type:"number",precision:"0.01",value:1,change:function(e){$inv.quantChange.call(this,e)}},{name:"UnitString",label:"Einheit",type:"select",url:["LFDM","Stck","Std.","QM","AW","Pauschal"],change:function(e){$inv.quantChange.call(this,e)}},{name:"net",label:"EinzelPreis netto",type:"number",precision:"0.01",value:0,change:function(e){$inv.quantChange.call(this,e)}},{name:"net_val",label:"GesamtPreis netto",type:"number",precision:"0.01",value:0},{name:"vat_val",label:"GesamtPreis USt",type:"number",precision:"0.01",value:0},{name:"svcnet_val",label:"Arbeitslohn netto",type:"number",precision:"0.01",value:0},{name:"svcvat_val",label:"Arbeitslohn USt",type:"number",precision:"0.01",value:0},{name:"net_pos",label:"Netto",type:"string"},{name:"bo_pos",label:"Brutto",type:"string"},{name:"vat",label:"USt",type:"string",value:"19,0%",change:function(e){$inv.quantChange.call(this,e)}},{name:"Note",label:"Details",type:"html",tinymce:!0}])},$ict={mdl:"Rechnungen",iov:{all:"Rechnungen (alle)","":"Rechnungen (nur fertige)","#d":"Rechnungen (nur Entwürfe)","#u":"Rechnungen (nur unbezahlt)","#r":"Rechnungen (nur angemahnt)","#a":"Rechnungen (nur Akonto)","#c":"Rechnungen (nur Storno)","#ru":"Rechnungen (nur angemahnt + unbez.)"},uba:", gesamter Zeitraum)",req:"Auftrag",inv:"Rechnung",rem:"Mahnung",in:"Rechnungsnummer",cc:"Kunde",wk:"Woche",nd:"Keine Daten gefunden.",dl:"Herunterladen",ed:"Bearbeiten",ced:"Bearbeitung fortsetzen",sItm:"Einzelheiten anzeigen",sPay:"Zahlungen anzeigen",cdI:"Entwurf der Rechnung löschen?",rel:"Neu Laden",relm:"Bitte laden Sie Liste manuell neu, um die Änderungen zu sehen.",dsp:"Rechnung anzeigen",storno:"Storno-Rechnung erstellen",credit:"Gutschrift erstellen",remd:"Mahnung erstellen",remdt:"Mahnung erstellen zur Rechnung {0}",remlst:"Mahnungen anzeigen",remdsp:"Mahnung anzeigen",remres:"Mahnung erneut senden",remresc:"Mahnung {0} wirklich erneut senden?",remresr:"Mahnung {0} wurde erfolgreich versandt.",setpyd:"Bezahlt markieren",cpyd:"Rechnung wirklich als bezahlt markieren?",setupd:"Bezahlt-Markierung aufheben",cupd:"Bezahlt-Markierung wirklich aufheben?",ivE:"Die Email-Adresse ist vermutlich nicht gültig.",ivEc:"\nMöchten Sie fortfahren?",pna:"Diese Seite ist in der Vorschau nicht verfügbar",tpe:"Die Anzahl von {0} Seiten wird aktuell nicht unterstützt",eis:"Der Rechnungsentwurf konnte nicht gespeichert werden.",iss:"Zwischenstand speichern.",p13b:"USt -> §13b",setm:"Set-Preisanzeige",setmo:{setprice:"Set mit Preis – Positionen ohne Preis",itemprices:"Positionen mit Preis – Set als Überschrift",setonly:"Nur Set mit Preis – Positionen ausgeblendet"},ctp:"Ansprechpartner festlegen",mfr:"Von MFR neu abrufen",rq1:"Auftragsdaten werden von MFR abgerufen.\nDer Vorgang kann bis zu 90Sek dauern.",rq2:"Auftragsdaten werden geladen",iq1:"Rechnungsdaten werden von MFR abgerufen.\nDer Vorgang kann bis zu 90Sek dauern.",iq2:"Rechnungsdaten werden geladen",sis:"Rechnung als versandt markieren",srs:"Mahnung als versandt markieren",sisc:"Rechnung wirklich als versandt markieren?",srsc:"Mahnung wirklich als versandt markieren?",iSt:{dft:"Entwurf",uns:"nicht versandt",pyd:"bezahlt",cc:"storniert",op:"offen",due:"fällig",ovd:"überfällig",rem:"angemahnt"},rSt:["","Überfällig","2. Mahnung","3. Stufe"],pSt:{a:"Vollst.",p:"Teilz."},ivT:{i:"AbschlagsR.",f:"SchlussR",r:"Rechnung",c:"StornoR."},rovlh:"Übersicht der bisherigen Mahnungen",rovl:["Betreff","Betrag","Betrag gezahlt","fertiggestellt am"],remHR:["Rechnung","vom","Rechnungsbetrag","bereits bezahlt","noch offen"],remt:{f:["Sehr geehrte Damen und Herren,","ein Mahnschreiben sollte kurz, freundlich und erfolgreich sein. Kurz ist es, freundlich sowieso; ob es auch erfolgreich ist, hängt von Ihnen ab."],m:["Sehr geehrte Damen und Herren,","nun müssen wir Sie noch einmal anschreiben.","Wahrscheinlich haben Sie triftige Gründe dafür, warum Sie die Zahlung unserer Forderung nicht vornehmen und auch nicht auf unsere Mahnung reagieren. Sollten wir darüber nicht einmal sprechen?","Bitte nehmen Sie umgehend in dieser Sache mit uns Kontakt auf."],l:["Sehr geehrte Damen und Herren,",'Eine DRITTE MAHNUNG zu erhalten bereitet Ihnen bestimmt ebenso wenig Freude wie uns, sie zu verschicken. Leider haben wir auf unsere zweite Mahnung noch keine Antwort von Ihnen erhalten.", "Wir bitten Sie, den offenen Betrag innerhalb der nächsten 7 Werktage nach Erhalt dieses Schreibens zu begleichen. Nach Ablauf dieser Frist erfolgt keine weitere Mahnung mehr.',"Sollte die Forderung bis dahin nicht beglichen sein, eröffnen wir das gerichtliche Mahnverfahren. Sollten Sie die Rechnung inzwischen beglichen haben, so betrachten Sie bitte dieses Schreiben als gegenstandslos."]},remt2:{f:["Wir bitten Sie, den noch offenen Rechnungsbetrag innerhalb einer Woche auf unser Konto zu überweisen.","Sollten Sie den Betrag bereits überwiesen haben, so bitten wir Sie, diese Zahlungserinnerung als gegenstandslos zu betrachten."],m:["Um Ihnen zusätzliche Kosten für weitere Mahnungen zu ersparen, bitten wir Sie nunmehr um die Überweisung des noch zu zahlenden Gesamtbetrages inklusive der ggf. bereits fälligen Mahnzinsen und Mahngebühren innerhalb von einer Woche."],l:[]},payi:{account:"Konto",name:"Zahler",text:"Verw.Zweck",InvoiceID:"Rechnung",amount:"Betrag",date:"Datum",manual:"Typ"}},$invcol={datev:new fields_definition("Rechnung","Rechnungen",[{name:"Umsatz (ohne Soll/Haben-Kz)",label:"Umsatz (ohne Soll/Haben-Kz)",type:"string"},{name:"vf",label:"vf",type:"string"},{name:"Soll/Haben-Kennzeichen",label:"Soll/Haben-Kennzeichen",type:"string"},{name:"Konto",label:"Konto",type:"string"},{name:"Gegenkonto",label:"Gegenkonto",type:"string"},{name:"BU-Schlüssel",label:"BU-Schlüssel",type:"string"},{name:"Belegdatum",label:"Belegdatum",type:"string"},{name:"Belegfeld 1",label:"Belegfeld 1",type:"string"},{name:"Belegfeld 2",label:"Belegfeld 2",type:"string"},{name:"Buchungstext",label:"Buchungstext",type:"string"}]),inv:new fields_definition("Rechnung","Rechnungen",[{name:"invstatus",label:"Status",type:"select",url:$ict.iSt},{name:"balance",label:"Umsatz",type:"string",dtype:"currency"},{name:"CustomerName",label:"Kunde",type:"string"},{name:"InvoiceId",label:"RNummer",type:"string"},{name:"InvoiceType",label:"Typ",type:"select",url:$ict.ivT},{name:"request",label:"Auftrag",type:"string",dtype:"num"},{name:"vat",label:"MwSt",type:"string",dtype:"num"},{name:"deb_cred",label:"Soll/Haben",type:"string"},{name:"customer",label:"Konto",type:"string",dtype:"num"},{name:"contra_account",label:"Gegenkonto",type:"string",dtype:"num"},{name:"Belegdatum",label:"Belegdatum",type:"date"},{name:"reminderstatus",label:"MahnStatus",type:"select",url:$ict.rSt},{name:"reminder",label:"# Mahnungen",type:"integer"},{name:"Buchungstext",label:"Buchungstext",type:"string"},{name:"Payment",label:"Zahlung",type:"string"}]),rem:new fields_definition("Zahlungserinnerung","Zahlungserinnerung",[{name:"amount",label:"Rechnungsbetrag",type:"number",precision:"0.01",value:1},{name:"amount_payed",label:"bereits bezahlt",type:"number",precision:"0.01",value:1}]),rem2:new fields_definition("Zahlungserinnerung","Zahlungserinnerung",[{name:"DocumentName",label:"Name",type:"string"},{name:"subject",label:"Betreff",type:"string"},{name:"DateSent",label:"Versanddatum",type:"date"},{name:"status",label:"Status",type:"string"},{name:"amount_open",label:"offener Betrag",type:"number",precision:"0.01"},{name:"InvoiceId",label:"RNummer",type:"string"}]),rid:new fields_definition("Zahlungserinnerung","Zahlungserinnerung",[{name:"type",label:"Typ",type:"select",url:[["f","einfache Zahlungserinnerung"],["m","Mahnung"],["l","letzte Mahnung"]],required:!0},{name:"level",label:"Stufe",type:"select",url:[["1","Stufe 1"],["2","Stufe 2"],["3","Stufe 3"],["4","Stufe 4"],["5","Stufe 5"],["6","Stufe 6"]],required:!0}]),ctp:new fields_definition("Ansprechpartner","Ansprechpartner",[{name:"name",label:"Name",type:"string"},{name:"email",label:"Email",type:"string"}])},gi=(e,t)=>$$.sc("glyphicon glyphicon-"+e).aC(t),$inv={},$req={init2:function(e,t){e=e||"inv",t=t||{},$ocms.getScript([],(function(){$req.init3(e,t)}))},init3:async function(e,t){$fis.cf(!0);let n=$fis.lf(!0);$("#topbar").ocmsmenu([]),$("#activemodule").text($rct.mdl),await $fis.prepAuth("fds_req,fds_inv,fds_reminder");let i=[(async()=>{!0===$fis.isAuth("fds_req",1)&&($req.prepLst(""),n.aC("fix"))})(),new Promise(((e,t)=>{n.find("div.oreq2").aC("selected"),$req.renderreq(fdt(new Date,"yy-MM-dd"),"r"),e()}))];await Promise.all(i)},prepLst:function(e){let t=new Date,n=$fis.lf(!0).ldng(1),i=new Date("2021-01-01");$fis.frm_list().IN((function(){}));$$.dc("mth oreq",n).text($rct.or).click((function(e){let t=$(this);e.stopPropagation(),t.siblings().rC("selected"),!0===t.is(".selected")&&(t.tC("selected"),$req.renderreq(fdt(new Date,"yy-MM-dd"),"o")),t.aC("selected")})),$$.dc("mth oreq2",n).text($rct.orr).click((function(e){let t=$(this);e.stopPropagation(),t.siblings().rC("selected"),!0===t.is(".selected")&&(t.tC("selected"),$req.renderreq(fdt(new Date,"yy-MM-dd"),"r")),t.aC("selected")})),$$.i({placeholder:$rct.rn}).appendTo($$.dc("mth oreqn",n)).enterKey((function(e){let t=$(this),n=t.val()||"";e.stopPropagation(),t.parent().siblings().rC("selected"),n.length>3&&(t.parent().aC("selected"),$req.renderreq("n:"+n,"s"),t.val(""))}));n.append("
");let a=$$.dc("mthl",n),r=t.getFullYear(),l=t.getMonth()+1;for(let t=i.getFullYear();t<=r;t++){let n=$$.dc("yr").prependTo(a).text($rct.iov[e]+" - "+t.toString()).toggleClass("selected",t===r);n.click({yr:t},(function(e){e.stopPropagation(),n.siblings().rC("selected"),n.aC("selected")}));let d=$$.dc("mfrm",n);for(let n=0;n<(t!==r?12:l);n++){i=new Date(t,n,1);let a=$$.dc("mth").prependTo(d).text($rct.iov[e]+" - "+fdt(i,"MMM yyyy"));a.click({yr:t,mt:n},(function(e){if(e.stopPropagation(),a.siblings().rC("selected"),!0===a.is(".selected")){a.tC("selected");let t=fdt(new Date(e.data.yr,e.data.mt,1),"yy-MM-dd");$req.renderreq(t,"m")}a.aC("selected")}));let r=getMonday(i),l=new Date(i);l.setMonth(l.getMonth()+1),l.setDate(0),l=getMonday(l);let s=$$.dc("wfrm",a);for(;r<=l;){let e=$$.dc("wk",s).text(($rct.wk||"W")+" "+fdt(r,"dd.MM.yy"));e.click({rd:new Date(r)},(function(t){t.stopPropagation();let n=fdt(t.data.rd,"yy-MM-dd");$req.renderreq(n,"w"),a.siblings().rC("selected").find(".wk").rC("selected"),a.aC("selected").find(".wk").rC("selected"),e.aC("selected")}));let t=$$.dc("wkdl",e).append($$.sc("ico glyphicon glyphicon-compressed"));!0===$fis.isAuth("fds_inv",2)&&t.click({rd:new Date(r)},(function(e){e.stopPropagation();let t=fdt(e.data.rd,"yy-MM-dd");$req.downloadzip.call(t,"w")})),r.setDate(r.getDate()+7)}}}n.ldng(0)},renderreq:function(e,t){let n=$fis.frm_list().ldng(1),i=$$.dc("invfrm",n).aC("md"+t),a=$fis.lf();$ocms.postXT({url:$ocms.url("req/reql"),data:{mode:t,tgt:e},success:n=>{a.rC("fix").aC("hd"),$$.dc("ovhd",i).append($$.s(n.admin.title)).appendIf($$.sc("note",n.admin.note),""!==ne(n.admin.note,""));let r=$$.tblset({},i),l=$rcol.req,d=$$.tr(r.hd);$$.th(d);$.each(l.fields||[],((e,t)=>{$$.th(d).text(t.label),"vat"===t.name&&$$.th(d)}));let s=0,c=!1;$.each(n.requests||[],((n,d)=>{s>0&&s!==d.ParentServiceRequestId&&(c=!c);let o=$$.tr(r.bdy).tC("alt",c);s=d.ParentServiceRequestId,o.click((function(){a.rC("fix").aC("hd"),o.tC("selected").siblings().rC("selected").find("td.av").rC("av"),o.find("td.av").rC("av")})),o.tC("child",d.isChild);let u=$$.td(o,{class:"raux"});!0===bool(d.open,!1)&&$$.dc("ihd ilbtn",u).append(gi("eye-close","ico")).click({id:d.Id},$req.tHd),$$.dc("iitm ilbtn",u).append(gi("list","ico")).click({id:d.Id},$req.showitm),!0===$fis.isAuth("fds_inv",2)&&$$.dc("invc ilbtn",u).append(gi("edit","ico")).click({id:d.Id},$inv.cInv),$.each(l.fields||[],((n,a)=>{let r=$$.td(o).aC(a.dtype),l=d[a.name];if("function"==typeof a.dfnc)a.dfnc.call(r,l,d);else switch(a.type||""){case"date":r.text(fdt(d[a.name],"dd.MM.yy"));break;case"datetime":r.text(fdt(d[a.name]));break;case"html":r.append($$.dc("ctw").html(l)),r.append($$.dc("ttip").html(l));break;default:r.text(d[a.name])}switch(a.name||""){case"State":r.text($rct.sts[l||"-"]);break;case"Name":r.aC(a.name.toLowerCase());break;case"vat":$$.sel().appendTo($$.td(o,{class:"vsel"})).click((function(e){e.stopPropagation()})).append([$$.opt("19,0 %","19,0 %"),$$.opt("16,0 %","16,0 %"),$$.opt("0,0 %","0,0 %")]).val(d[a.name]).change().change({frm:i,tgt:e,mode:t,id:d.Id,td:r},$req.setvat),r.tC("hl","19"!==d[a.name].substr(0,2)).click((function(e){e.stopPropagation(),$(this).tC("av")}));break;case"balance":r.aC("sh_"+(d.SollHaben||"").toLowerCase());break;case"InvoiceId":r.aC("keep")}switch(typeof a.title){case"function":a.title.call(r,d);break;case"string":r.attr("title",cs.title)}}))}))},complete:()=>{n.ldng(0)}})},tHd:function(e){let t=$(this).closest("tr");e.stopPropagation(),!1!==t.is(".selected")&&confirm($rct.cthd)&&$ocms.postXT({url:$ocms.url("req/rthd"),data:{id:e.data.id},success:n=>{n.id===e.data.id&&!1===bool(n.visible,!0)?(!1===t.is(".tbhd")&&setTimeout((()=>{t.filter(".tbhd").remove()}),15e3),t.aC("tbhd")):n.id===e.data.id&&t.rC("tbhd")}})},showitm:function(e){let t=$(this).closest("tr");if(e.stopPropagation(),!1===t.is(".selected"))return;let n=$$.dc("rfrm").ldng(1);$ocms.postXT({url:$ocms.url("req/pget"),data:{id:e.data.id},success:t=>{$ocms.postXT({url:$ocms.url("req/get"),data:{id:e.data.id,mode:"ful"},success:e=>{if((e.requests||[]).length<1)n.text($rct.nd);else{let t=$$.dc("srq",n),i=$$.tblset({class:"if"},t);$.each(e.requests||[],(function(e,t){e>0&&$$.tr(i.bdy).aC("sep").append($$.td({colspan:6}));let n=$$.tr(i.bdy).aC("title"),a=$rcol.itm.lbl(),r=$inv.worknotes(t);$$.td(n,{colspan:6}).append([$$.s($rcol.req.label_sng),$$.sc("eid",t.ExternalId),$$.sc("nme",fdt(t.WorkDoneAt,"dd.MM.yy")+": "+r.ne(t.Name))]);$$.tr(i.bdy).aC("shd").append([$$.td(),$$.td(a.NameOrNumber),$$.td(a.Type),$$.td(a.net_pos),$$.td(a.bo_pos),$$.td(a.vat)]);$.each(t.items||[],((e,t)=>{t.ServiceRequestId;let n=$$.tr(i.bdy,{id:"itm"+t.Id}).aC(t.Type);$$.td(n).aC("ico"),$$.td(n).text(t.NameOrNumber),$$.td(n).text(t.Type),$$.td(n).aC("currency").text(t.net_pos),$$.td(n).aC("currency").text(t.bo_pos),$$.td(n).aC("num").text(t.vat)}))}))}},error:()=>{n.text($t.t12)},complete:()=>{n.ldng(0)}})},error:()=>{n.text($t.t12),n.ldng(0)}}),$ocms.dlg(n,{width:1e3})}},$$req={init2:$req.init2,auth:{}};export default $$req;$inv.cInv=function(e){let t=$(this).closest("tr");e.stopPropagation(),!1!==t.is(".selected")&&!1!==$fis.isAuth("fds_inv",2)&&$inv.cInv2({id:e.data.id})},$inv.rMn=e=>{let t=[{lbl:$ict.req,itm:[]}];return!0===bool(e,!1)&&!0===$fis.isAuth("fds_inv",2)&&Array.prototype.push.apply(t[0].itm,[{lbl:$rct.crI,fnc:$inv.ccInv,data:{typ:"r"}},{lbl:$rct.crII,fnc:$inv.ccInv,data:{typ:"i"}}]),t.push({lbl:$ict.rel,fnc:$inv.rReload}),$("#topbar").ocmsmenu(t)},$inv.iMnr=e=>{let t=booln(e.isFinal,!0),n=e.Id,i=booln(e.fds,!1),a=[{glyph:"glyphicon-menu-left",fnc:()=>{$fis.frm_edit().remove()}},{lbl:$ict.inv,itm:[]},{lbl:$ict.rem,itm:[]}];return!1===t&&!0===$fis.isAuth("fds_inv",2)?a[1].itm.push({lbl:$ict.ced,fnc:$inv.clCntInv}):!0===$fis.isAuth("fds_inv",1)&&a[1].itm.push({lbl:$ict.dsp,fnc:()=>$inv.disp(n,"inv")}),!0===i&&!0===t&&!0===$fis.isAuth("fds_inv",2)&&(a[1].itm.push({lbl:$ict.storno,fnc:()=>$inv.storno(n,i)}),a[1].itm.push({lbl:$ict.credit,fnc:()=>$inv.credit(n,i)})),!0===t&&!0===$fis.isAuth("fds_reminder",2)&&(a[2].itm.push({lbl:$ict.remd,fnc:()=>$inv.ccRem(n,e.InvoiceId)}),a[2].itm.push({lbl:$ict.remlst,fnc:()=>$inv.dspRem(n)})),!0===t&&!0===$fis.isAuth("fds_reminder",2)&&!1===booln(e.IsSent,!1)&&a[2].itm.push({lbl:$ict.srs,fnc:()=>$inv.srs(n)}),a.push({lbl:$ict.rel,fnc:$inv.rReload}),$("#topbar").ocmsmenu(a)},$inv.iMn=e=>{let t=booln(e.isFinal,!0),n=e.Id,i=booln(e.fds,!1),a=[{glyph:"glyphicon-menu-left",fnc:()=>{$fis.frm_edit().remove()}},{lbl:$ict.inv,itm:[]},{lbl:$ict.rem,itm:[]}];return!1===t&&!0===$fis.isAuth("fds_inv",2)?a[1].itm.push({lbl:$ict.ced,fnc:()=>{$inv.cntInv({id:n})}}):!0===$fis.isAuth("fds_inv",1)&&a[1].itm.push({lbl:$ict.dsp,fnc:()=>$inv.disp(n,"inv")}),!0===$fis.isAuth("fds_inv",2)&&(a[1].itm.push({lbl:$ict.storno,fnc:()=>$inv.storno(n,i)}),a[1].itm.push({lbl:$ict.credit,fnc:()=>$inv.credit(n,i)})),!0===t&&!1===booln(e.IsPayed,!1)?(!0===$fis.isAuth("fds_reminder",2)&&a[2].itm.push({lbl:$ict.remd,fnc:()=>$inv.ccRem(n,e.InvoiceId)}),!0===$fis.isAuth("fds_inv",2)&&a[1].itm.push({lbl:$ict.setpyd,fnc:()=>$inv.setPyd(n)})):!0===t&&!0===booln(e.IsPayed,!1)&&"m"===(e.PaymentStatus||"")&&!0===$fis.isAuth("fds_inv",2)&&a[1].itm.push({lbl:$ict.setupd,fnc:()=>$inv.setUpd(n)}),!0===$fis.isAuth("fds_reminder",2)&&a[2].itm.push({lbl:$ict.remlst,fnc:()=>$inv.dspRem(n)}),!0===t&&!0===$fis.isAuth("fds_inv",2)&&!1===booln(e.IsSent,!1)&&a[1].itm.push({lbl:$ict.sis,fnc:()=>$inv.sis(n)}),!1===i&&a[1].itm.push({lbl:$ict.mfr,fnc:()=>$inv.mfrrel(n)}),$("#topbar").ocmsmenu(a)},$inv.eM=(e,t,n)=>{let i=[];return!0!==booln(e,!1)&&!0!==booln(t,!1)||i.push({glyph:"glyphicon-menu-left",fnc:()=>{$fis.lf(!0),$fis.frm_edit().remove()}}),!0===(n||"").split(",").includes("iss")&&i.push({lbl:$ict.iss,fnc:$inv.ssave}),!0===(n||"").split(",").includes("ctp")&&i.push({lbl:$ict.ctp,fnc:$inv.sctp}),!0===(n||"").split(",").includes("p13b")&&i.push({lbl:$ict.p13b,fnc:$inv.sp13b}),!0===(n||"").split(",").includes("setm")&&i.push({lbl:$ict.setm,fnc:$inv.ssetmode}),!0===(n||"").split(",").includes("iss")&&(i.push({lbl:"Änderungshistorie",fnc:()=>$inv.d.history()}),i.push({lbl:"Änderungen verwerfen",fnc:()=>$inv.d.discard()})),!0===booln(e,!1)&&i.push({lbl:$ict.rel,fnc:$inv.rReload}),$("#topbar").ocmsmenu(i)},$inv.d={tbl:()=>$("div.invoice_layout table.invi"),layout:()=>$("div.invoice_layout"),token:function(){return $inv.d.tbl().data("dtoken")||""},hashes:function(){let e=$inv.d.tbl().data("bai")||[],t={};return $.each(e,((e,n)=>{t[(n.Id||"").toString()]=JSON.stringify(n)})),t},seed:function(e){let t=$inv.d.layout();t.aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dopen"),data:{payload:JSON.stringify(e)},success:e=>{$inv.d.tbl().data("dtoken",e.token).data("dver",e.version).data("dhashes",$inv.d.hashes()).data("dorder",$inv.d.order()),$fis.draft.bind(e.token,{onReady:()=>$inv.d.refresh(),onExpiring:e=>$inv.d.warnExpiry(e),onClosed:e=>$inv.d.closed(e)}),$inv.d.refresh()},error:()=>{t.rC("freeze")},complete:()=>{$inv.d.tbl().removeData("dseeding")}})},refresh:function(e){let t=$inv.d.token();""!==t&&$ocms.postXT({url:$ocms.url("inv/dstate"),data:{token:t},success:t=>{$inv.d.applyState(t),"function"==typeof e&&e(t)},error:e=>{e&&410===e.status&&$inv.d.closed("expired")},complete:()=>{$inv.d.layout().rC("freeze")}})},applyState:function(e){let t=$inv.d.tbl();t.length<1||(t.data("dver",e.version).data("serverSums",e.sums),$inv.d.footer(t,e.sums||{},e.admin||{}),$inv.d.validation(e.validation||[]),$inv.d.applyPositions(t,e.req||[]))},applyPositions:function(e,t){(t||[]).forEach((t=>(t&&t.itm||[]).forEach((t=>{if(!t||""===(t.id||""))return;let n=e.find("#itm"+t.id+" td.keep").first();n.length&&n.text(null!=t.p?t.p:"")}))))},sync:function(e){let t=$inv.d.token();""!==t&&($inv.d.layout().aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dpatch"),data:{token:t,delta:JSON.stringify(e)},success:()=>{$inv.d.refresh()},error:e=>{$inv.d.layout().rC("freeze"),e&&410===e.status&&$inv.d.closed("expired")}}))},order:function(){return($inv.d.tbl().data("bai")||[]).map((e=>(e.Id||"").toString()))},syncChanged:function(e){if(""===$inv.d.token())return;let t=e.data("bai")||[],n=e.data("dhashes")||{},i={},a=[],r=[];$.each(t,((e,t)=>{let r=(t.Id||"").toString(),l=JSON.stringify(t);i[r]=l,n[r]!==l&&a.push(t)})),$.each(n,(e=>{void 0===i[e]&&r.push(e)}));let l=$inv.d.order(),d=e.data("dorder")||[];e.data("dhashes",i).data("dorder",l),a.forEach((e=>$inv.d.sync({Target:"block.replace",Ref:(e.Id||"").toString(),Value:e}))),r.forEach((e=>$inv.d.sync({Target:"block.remove",Ref:e}))),d.length===l.length&&d.slice().sort().join(",")===l.slice().sort().join(",")&&d.join(",")!==l.join(",")&&$inv.d.sync({Target:"block.order",Value:l})},syncField:function(e,t){if(""===$inv.d.token())return;let n={invoicetitle:"title",invoiceaddress:"address",invoiceemail:"email",loc:"provisionlocation",provisionlocation:"provisionlocation",provisionperiod:"provisionperiod"}[e];n&&$inv.d.sync({Target:n,Value:t})},footer:function(e,t,n){let i=e.children("tfoot").empty();e.nextAll(".fnote").remove();let a=bool(n.p13b,!1),r=(e,t,n)=>$$.tdc("currency",$$.tr(i,{class:n||"tsum"}).append([$$.tdc("aux"),$$.td({colspan:4}).text(e)]),fnum(t,$rct.cst)),l=t=>$$.dc("fnote").insertAfter(e).rwText(t);r("Netto",t.total_net||0),!1===a&&$.each(t.vat||{},((e,t)=>r($rct.vat+" "+e+"%",t,"tvat"))),r("Summe",t.total_gross||0);let d=n.type||"";"i"===d?(l($rct.note2),l($rct.note4)):"c"===d?l($rct.note2):(l(string($rct.note3,[fnum(((t.service_net||0)+(t.service_vat||0))*(n.tax_servicerefund||0),$rct.cst)])).aC("ntax"),l($rct.note2),l(string($rct.note1,[fnum((t.service_net||0)+(t.service_vat||0),$rct.cst),fnum(t.service_net||0,$rct.cst),fnum(t.service_vat||0,$rct.cst)]))),!0===a&&l($rct.note13b)},validation:function(e){let t=$("div.invoice_layout");if(t.length<1)return;let n=t.children(".dvalidation");n.length<1&&(n=$$.dc("dvalidation"),t.prepend(n)),n.empty().tC("hidden",(e||[]).length<1),$.each(e||[],((e,t)=>$$.dc("dvmsg",n).aC(t.severity).text(t.message)))},preview:function(){let e=$inv.d.token();if(""===e)return;let t=$inv.d.layout(),n=($inv.d.tbl().data("new")||{}).invoiceemail||"";!1===$fis.ValidateEmail(n)&&!1===bool(confirm($ict.ivE+$ict.ivEc),!1)||(t.aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dpreview"),data:{token:e},success:n=>{t.rC("freeze");let i=$$.dc("imagecollection pdfpreview"),a=Math.round(.88*vh()),r=n.total;r>10&&$$.dc("note warn",i).text($ict.tpe),$.each(n.img||[],((e,t)=>{$$.dc("pdfp",i).append($$.img(t).css("max-height",(a-rpx(6)).toString()+"px"))}));for(let e=(n.img||[]).length+1;e<=r;e++)$$.dc("pdfp ph",i).append($$.dc("note",$ict.pna));$ocms.dlg(i,{size:[a,Math.round(.88*vw())],zindex:50,form:!1,button:$rct.crI,confirm:function(n){let i=$(this);t.aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dsave"),data:{token:e},success:e=>{$ocms.postXT({url:$ocms.url("req/sconf"),data:{id:e.invid},success:t=>{i.trigger("modal_close"),!0===t.hasFile&&window.open($ocms.url("req/idoc")+"?id="+e.invid,"_blank"),$inv.d.close(),$ocms.init("req"),$inv.rReload()},error:()=>{alert($t.f1),i.trigger("modal_close")},complete:()=>{t.rC("freeze")}})},error:()=>{t.rC("freeze"),alert($ict.eis)}})},cancel:function(e){confirm($ict.cdI)&&($inv.d.close(),$inv.rReload())}})},error:()=>{t.rC("freeze"),alert($ict.eis)}}))},save:function(){let e=$inv.d.token();if(""===e)return;let t=$inv.d.layout();t.aC("freeze"),$ocms.postXT({url:$ocms.url("inv/dsave"),data:{token:e},success:e=>{$inv.d.tbl().data("invid",e.invid)},error:()=>{alert($ict.eis)},complete:()=>{t.rC("freeze")}})},history:function(){let e=$inv.d.token();""!==e&&$ocms.postXT({url:$ocms.url("inv/dhistory"),data:{token:e},success:e=>{let t=$$.dc("dhist");if((e.history||[]).length<1)$$.dc("note",t).text("Noch keine Änderungen erfasst.");else{let n=$$.tblset({class:"invtbl fullwidth"},t);$$.tr(n.hd).append([$$.th().text("Zeit"),$$.th().text("Feld"),$$.th().text("Alt"),$$.th().text("Neu")]),$.each(e.history,((e,t)=>$$.tr(n.bdy).append([$$.tdc("keep",fdt(t.timestamp)),$$.td().text(t.target),$$.td().text(t.oldValue),$$.td().text(t.newValue)])))}$ocms.dlg(t,{width:800,form:!1})}})},discard:function(){let e=$inv.d.tbl().data("invid")||"";""!==e?!1!==confirm("Alle Änderungen verwerfen und den zuletzt gespeicherten Stand neu laden?")&&($inv.d.close(),$inv.cntInv({id:e})):alert("Es wurde noch kein Zwischenstand gespeichert, der wiederhergestellt werden könnte.")},warnExpiry:function(e){let t=Math.max(1,Math.round((e||0)/60));$fis.notifications.push({severity:"info",title:"Entwurf läuft ab",message:"Der Rechnungsentwurf läuft in etwa "+t+" Minute(n) ab. Bitte zwischenspeichern, sonst gehen die Änderungen verloren."})},closed:function(e){let t=$inv.d.token();$inv.d.tbl().removeData("dtoken"),""!==t&&$fis.draft.release(t),$fis.frm_edit().remove(),$fis.lf(!0),$fis.notifications.push({severity:"error",title:"Entwurf geschlossen",message:"expired"===e?"Der Rechnungsentwurf ist wegen Inaktivität abgelaufen. Nicht gespeicherte Änderungen sind verloren.":"Der Rechnungsentwurf wurde geschlossen."});try{$inv.rReload()}catch(e){}},close:function(){let e=$inv.d.token();""!==e&&($ocms.postXT({url:$ocms.url("inv/dclose"),data:{token:e}}),$fis.draft.release(e)),$inv.d.tbl().removeData("dtoken")}},$inv.rd={tbl:()=>$("div.invoice_layout table.invi"),layout:()=>$("div.invoice_layout"),token:function(){return $inv.rd.tbl().data("rdtoken")||""},seed:function(e){let t=$inv.rd.layout();t.aC("freeze"),$ocms.postXT({url:$ocms.url("rem/dopen"),data:{payload:JSON.stringify(e)},success:e=>{$inv.rd.tbl().data("rdtoken",e.token).data("rdver",e.version),$fis.draft.bind(e.token,{onReady:()=>$inv.rd.refresh(),onExpiring:e=>$inv.rd.warnExpiry(e),onClosed:e=>$inv.rd.closed(e)}),$inv.rd.refresh()},error:()=>{t.rC("freeze")}})},refresh:function(e){let t=$inv.rd.token();""!==t&&$ocms.postXT({url:$ocms.url("rem/dstate"),data:{token:t},success:t=>{$inv.rd.applyState(t),"function"==typeof e&&e(t)},error:e=>{e&&410===e.status&&$inv.rd.closed("expired")},complete:()=>{$inv.rd.layout().rC("freeze")}})},applyState:function(e){let t=$inv.rd.tbl();t.length<1||(t.data("rdver",e.version).data("serverSums",e.sums).data("remid",e.remid||""),$inv.rd.footer(t,e.sums||{}),$inv.rd.validation(e.validation||[]))},sync:function(e){let t=$inv.rd.token();""!==t&&($inv.rd.layout().aC("freeze"),$ocms.postXT({url:$ocms.url("rem/dpatch"),data:{token:t,delta:JSON.stringify(e)},success:()=>{$inv.rd.refresh()},error:e=>{$inv.rd.layout().rC("freeze"),e&&410===e.status&&$inv.rd.closed("expired")}}))},syncField:function(e,t){if(""===$inv.rd.token())return;let n={subject:"subject",invoiceaddress:"address",invoiceemail:"email",text:"text"}[e];n&&$inv.rd.sync({Target:n,Value:t})},syncAmount:function(e,t){""!==$inv.rd.token()&&($inv.rd.sync({Target:"amount",Value:(null!=e?e:0).toString()}),$inv.rd.sync({Target:"amount_payed",Value:(null!=t?t:0).toString()}))},footer:function(e,t){let n=e.children("tfoot").empty(),i=$$.tr(n,{class:"tsum"}).append([$$.tdc("aux"),$$.td({colspan:3}).text("Offener Betrag")]);$$.tdc("currency",i,fnum(t.amount_open||0,$rct.cst))},validation:function(e){let t=$inv.rd.layout();if(t.length<1)return;let n=t.children(".dvalidation");n.length<1&&(n=$$.dc("dvalidation"),t.prepend(n)),n.empty().tC("hidden",(e||[]).length<1),$.each(e||[],((e,t)=>$$.dc("dvmsg",n).aC(t.severity).text(t.message)))},preview:function(){let e=$inv.rd.token();if(""===e)return;let t=$inv.rd.layout(),n=($inv.rd.tbl().data("new")||{}).invoiceemail||"";!1===$fis.ValidateEmail(n)&&!1===bool(confirm($ict.ivE+$ict.ivEc),!1)||(t.aC("freeze"),$ocms.postXT({url:$ocms.url("rem/dpreview"),data:{token:e},success:n=>{t.rC("freeze");let i=$$.dc("imagecollection pdfpreview"),a=Math.round(.88*vh());$.each(n.img||[],((e,t)=>{$$.dc("pdfp",i).append($$.img(t).css("max-height",(a-rpx(6)).toString()+"px"))})),$ocms.dlg(i,{size:[a,Math.round(.88*vw())],zindex:50,form:!1,button:$ict.remd,confirm:function(n){let i=$(this);t.aC("freeze"),$ocms.postXT({url:$ocms.url("rem/dsave"),data:{token:e},success:e=>{$ocms.postXT({url:$ocms.url("rem/conf"),data:{id:e.remid},success:()=>{i.trigger("modal_close"),window.open($ocms.url("rem/idoc")+"?id="+e.remid,"_blank"),$inv.rd.close(),$ocms.init("req"),$inv.rReload()},error:()=>{alert($t.f1),i.trigger("modal_close")},complete:()=>{t.rC("freeze")}})},error:()=>{t.rC("freeze"),alert($t.f1)}})},cancel:function(e){confirm($ict.cdI)&&($inv.rd.close(),$inv.rReload())}})},error:()=>{t.rC("freeze"),alert($t.f1)}}))},save:function(){let e=$inv.rd.token();if(""===e)return;let t=$inv.rd.layout();t.aC("freeze"),$ocms.postXT({url:$ocms.url("rem/dsave"),data:{token:e},success:e=>{$inv.rd.tbl().data("remid",e.remid)},error:()=>{alert($t.f1)},complete:()=>{t.rC("freeze")}})},history:function(){let e=$inv.rd.token();""!==e&&$ocms.postXT({url:$ocms.url("rem/dhistory"),data:{token:e},success:e=>{let t=$$.dc("dhist");if((e.history||[]).length<1)$$.dc("note",t).text("Noch keine Änderungen erfasst.");else{let n=$$.tblset({class:"invtbl fullwidth"},t);$$.tr(n.hd).append([$$.th().text("Zeit"),$$.th().text("Feld"),$$.th().text("Alt"),$$.th().text("Neu")]),$.each(e.history,((e,t)=>$$.tr(n.bdy).append([$$.tdc("keep",fdt(t.timestamp)),$$.td().text(t.target),$$.td().text(t.oldValue),$$.td().text(t.newValue)])))}$ocms.dlg(t,{width:800,form:!1})}})},warnExpiry:function(e){let t=Math.max(1,Math.round((e||0)/60));$fis.notifications.push({severity:"info",title:"Entwurf läuft ab",message:"Der Mahnentwurf läuft in etwa "+t+" Minute(n) ab. Bitte zwischenspeichern, sonst gehen die Änderungen verloren."})},closed:function(e){let t=$inv.rd.token();$inv.rd.tbl().removeData("rdtoken"),""!==t&&$fis.draft.release(t),$fis.frm_edit().remove(),$fis.lf(!0),$fis.notifications.push({severity:"error",title:"Entwurf geschlossen",message:"expired"===e?"Der Mahnentwurf ist wegen Inaktivität abgelaufen. Nicht gespeicherte Änderungen sind verloren.":"Der Mahnentwurf wurde geschlossen."});try{$inv.rReload()}catch(e){}},close:function(){let e=$inv.rd.token();""!==e&&($ocms.postXT({url:$ocms.url("rem/dclose"),data:{token:e}}),$fis.draft.release(e)),$inv.rd.tbl().removeData("rdtoken")}},$inv.cInv2=function(e){let t=$$.dc("rfrm").ldng(1),n=$ocms.dlg(t,{width:1e3});n&&n.ft.rwText($rct.rq1);let i=()=>{$ocms.postXT({url:$ocms.url("req/get"),timeout:60,data:{id:e.id,mode:"r"},success:t=>{t.admin=t.admin||{};let n=$fis.lf(!0).aC("fix").rC("hd");if($fis.frm_edit().IN(),$inv.eM(!0,!0),(t.requests||[]).length<1)n.aC("fix").text($rct.nd);else{$$.dc("lh",n,$rct.mdl);let i=$$.d(),a=$$.ul({class:"rql"}).data({search:e.id,parent:t.admin.parent}).appendTo(n),r={},l=$rcol.req.lbl();$.each(t.requests||[],(function(e,t){let n=$$.li({class:"cli rli"}).data($.extend({},t)).appendTo(a),d=$$.dc("lihd",n).addClass(t.state);!0===booln(t.open,!1)&&d.append($$.sc("cbox").click((()=>{n.tC("checked"),i.find("li").rC("checked"),!0===n.is(".checked")?$inv.rMn(t.open):$inv.eM(!0)}))),d.append([$$.sc("eid",t.ExternalId),$$.sc("nme",t.Name)]),$$.dc("lidt",n).append([$$.dc("rqs").append([$$.s(l.State+": "),$$.s($rct.sts[t.State||"-"])]),$$.dc("ivn").append([$$.s(l.InvoiceId+": "),$$.s(t.InvoiceId||"- -")]),$$.dc("wda").append([$$.s(l.WorkDoneAt+": "),$$.s(fdt(t.WorkDoneAt,"dd.MM.yyyy"))])]),r[t.Id]=n})),(t.inv||[]).length>0&&($$.dc("lh",n,$rct.invs),i=$$.ul({class:"ivl"}).appendTo(n),$.each(t.inv||[],((e,t)=>{let n=$$.li({class:"cli ili"}).data($.extend({},t)).appendTo(i),r=$$.dc("lihd",n).addClass(t.invstatus);!1===booln(t.isFinal,!0)?r.append($$.sc("cbox").click((()=>{""!==(t.Id||"")&&(n.tC("checked").siblings().rC("checked"),a.find("li").rC("checked"),!0===n.is(".checked")?$inv.iMnr(t):$inv.eM(!0))}))):["","dft"].indexOf(t.invstatus)<0&&r.append($$.sc("dli").click((function(){$inv.disp(t.Id,"inv")}))),r.append($$.sc("nme",t.DocumentName||t.Id)),$$.dc("lidt",n).append([$$.dc("wda").append([$$.s(fdt(t.DateCreated,"dd.MM.yyyy"))]),$$.d().text($ict.iSt[t.invstatus]||t.invstatus)])})))}},complete:()=>{n&&n.c.trigger("modal_close")}})};$ocms.postXT({url:$ocms.url("req/pget"),timeout:90,data:{id:e.id},success:e=>{n&&n.ft.rwText($rct.rq2),i()},error:()=>{confirm($rct.rq1f)?(n&&n.ft.rwText($rct.rq2),i()):n&&n.c.trigger("modal_close")}})},$inv.ccInv=function(e){let t=(e.data||{}).typ||"r",n=$fis.lf(),i=n.children("ul.rql"),a=i.data("parent"),r=[];if(i.find("li.rli.checked").each((function(){r.push($(this).data("Id"))})),r.length<1)return void alert($rct.dnS);if("i"===t&&r.length>1)return void alert($rct.dII);let l=$fis.frm_edit(),d=$$.dc("invoice_layout",l).append($$.dc("btn sprev").click($inv.sprev)),s=$fis.cf().width()>d.width()+n.width()+20;n.tC("fix",s).tC("hd",!s),$inv.eM(!1,!0);let c=$$.dc("rfrm").ldng(1),o=$ocms.dlg(c,{width:1e3});o.ft.rwText($rct.rq2),$ocms.postXT({url:$ocms.url("req/iget"),timeout:60,data:{id:a,mode:"ful",typ:t,sel:r.join(",")},success:e=>{let t=$$.dc("srq",d),n=$$.tblset({class:"invi"},t);n.bdy.remove(),n.ft=$$[0]("tfoot"),e.admin=e.admin||{},e.admin.p13b=bool(e.admin.p13b||"",!0===((e.inv||{}).InvoiceOptions||"").split(",").includes("§13b")),n.tbl.data($.extend({new:{},sms:{},itm:{}},{admin:e.admin,companies:e.companies,locations:e.locations}));let i=$$.tr(n.hd).aC("shd").append([$$.th().aC("aux")]);$rct.invHR.forEach((e=>$$.th(i,e))),n.tbl.on("fds.inv",$inv.invSumUpdate),$.each(e.requests||[],(function(t,i){if(0!==(i.Id||0)){let t=$inv.worknotes(i);i.text="i"===e.admin.type?$rct.req+jine([i.ExternalId,i.Name],": ").eine(" ",""):jine([jine([fdt(i.WorkDoneAt,"dd.MM.yy"),i.ExternalId]," - "+$rct.req+" "),t.ne(i.Name)],": \n");let a=$$.tbody(n.tbl).data($.extend({},i));$inv.rendersrq.call(a)}}));let a=$$.tr($$.tbody(n.tbl),{class:"placeholder"}).data({net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0});$inv.rrw.call(a),n.ft.appendTo(n.tbl);let r,l,s=e.admin||{},c=(e,t,i,a,r)=>{let l=$$.dc("inpfrm",d).aC(e).append("string"==typeof a?$$.dc("ahd",a):a>0?$$.dc("ahd",$rct.frm[i]):null),s=$$.dc("content",l).rwText(t);$$.dc("axf",l).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:s,nme:i,change:e=>{n.tbl.data("new")[i]=e}},r),$inv.eHtml)),n.tbl.data("new")[i]=t};c("tfrm",s.invoicetitle,"invoicetitle",0,null),c("adrfrm",s.invoiceaddress,"invoiceaddress",0,null),c("locfrm","","loc",1,{list:deepCopy(e.locations),lbl:"ref",property:"address"}),c("emailfrm",s.invoiceemail,"invoiceemail",0,null),$$.dc("sndfrm",d).append($$.dc("content").text(s.sender)),s.provisionend&&(l=s.provisionstart?$rct.provP:$rct.provD,r=s.provisionstart?fdt(s.provisionstart,"dd.MM.yyyy")+" - "+fdt(s.provisionend,"dd.MM.yyyy"):fdt(s.provisionend,"dd.MM.yyyy")),c("admfrm",r,"provisionperiod",l,1),n.tbl.data("new").CustomValues=s.CustomValues||"",$$.dc("inpfrm ctpfrm",d).text(jObj(s.CustomValues,"contactName")),n.tbl.children("tbody").each($inv.bdysort),n.tbl.trigger("fds.inv"),$inv.eM(!1,!0,"iss,p13b,setm,ctp")},complete:()=>{o.c.trigger("modal_close")}})},$inv.ccStInv=function(e){let t=e.data||{},n=$fis.lf(),i=t.id,a=$$.dc("invoice_layout",$fis.frm_edit()).append($$.dc("btn sprev").click($inv.sprev)),r=$fis.cf().width()>a.width()+n.width()+20;n.tC("fix",r).tC("hd",!r),$inv.eM(!1,!0);let l=$$.dc("rfrm").ldng(1),d=$ocms.dlg(l,{width:1e3});d.ft.rwText($ict.iq1),$ocms.postXT({url:$ocms.url("inv/pget"),timeout:90,data:{id:t.id},success:e=>{d&&d.ft.rwText($ict.iq2),$ocms.postXT({url:$ocms.url("inv/icget"),timeout:60,data:{id:i},success:e=>{let t=$$.dc("srq",a),n=$$.tblset({class:"invi"},t);n.bdy.remove(),n.ft=$$[0]("tfoot"),e.admin=e.admin||{},e.admin.p13b=bool(e.admin.p13b||"",!0===((e.inv||{}).InvoiceOptions||"").split(",").includes("§13b")),n.tbl.data($.extend({new:{},sms:{},itm:{}},{admin:e.admin,companies:e.companies,locations:e.locations}));let i=$$.tr(n.hd).aC("shd").append([$$.th().aC("aux")]);$rct.invHR.forEach((e=>$$.th(i,e))),n.tbl.on("fds.inv",$inv.invSumUpdate),$.each(e.requests||[],(function(t,i){if(0!==(i.Id||0)){let t=$inv.worknotes(i);i.text="i"===e.admin.type?$rct.req+jine([i.ExternalId,i.Name],": ").eine(" ",""):jine([fdt(i.WorkDoneAt,"dd.MM.yy")+t.ne(i.Name)],": ");let a=$$.tbody(n.tbl).data($.extend({},i));$inv.rendersrq.call(a)}}));let r=$$.tr($$.tbody(n.tbl),{class:"placeholder"}).data({net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0});$inv.rrw.call(r),n.ft.appendTo(n.tbl);let l,d,s=e.admin||{},c=(e,t,i,r,l)=>{let d=$$.dc("inpfrm",a).aC(e).append("string"==typeof r?$$.dc("ahd",r):r>0?$$.dc("ahd",$rct.frm[i]):null),s=$$.dc("content",d).rwText(t);$$.dc("axf",d).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:s,nme:i,change:e=>{n.tbl.data("new")[i]=e}},l),$inv.eHtml)),n.tbl.data("new")[i]=t};c("tfrm",s.invoicetitle,"invoicetitle",0,null),c("adrfrm",s.invoiceaddress,"invoiceaddress",0,null),c("locfrm",s.provisionlocation,"loc",1,{list:deepCopy(e.locations),lbl:"ref",property:"address"}),c("emailfrm",s.invoiceemail,"invoiceemail",0,null),$$.dc("sndfrm",a).append($$.dc("content").text(s.sender)),s.provisionend&&(d=s.provisionstart?$rct.provP:$rct.provD,l=s.provisionstart?fdt(s.provisionstart,"dd.MM.yyyy")+" - "+fdt(s.provisionend,"dd.MM.yyyy"):fdt(s.provisionend,"dd.MM.yyyy")),c("admfrm",l,"provisionperiod",d,1),n.tbl.data("new").CustomValues=s.CustomValues||"",$$.dc("inpfrm ctpfrm",a).text(jObj(s.CustomValues,"contactName")),n.tbl.children("tbody").each($inv.bdysort),n.tbl.trigger("fds.inv")},complete:()=>{d.c.trigger("modal_close")}})},error:()=>{d&&d.c.trigger("modal_close")}})},$inv.clCntInv=function(e){let t=$fis.lf(!1),n=[];t.find("li.ili.checked").each((function(){n.push($(this).data("Id"))})),1===n.length&&$inv.cntInv({id:n[0]})},$inv.cntInv=function(e){e=e||{};$fis.lf(!1).rC("fix").aC("hd");let t=$$.dc("invoice_layout",$fis.frm_edit()).append($$.dc("btn sprev").click($inv.sedit));$inv.eM(!1,!0);let n=$$.dc("rfrm").ldng(1),i=$ocms.dlg(n,{width:1e3});i.ft.rwText($rct.rq2),$ocms.postXT({url:$ocms.url("inv/get"),timeout:60,data:{id:e.id},success:e=>{e.admin=e.admin||{};let n=e.inv||{},i=$$.dc("srq",t),a=$$.tblset({class:"invi"},i);a.bdy.remove(),a.ft=$$[0]("tfoot"),a.tbl.data($.extend({invid:n.Id,new:{},sms:{},itm:{},bai:[]},e));let r=$$.tr(a.hd).aC("shd").append([$$.th().aC("aux")]);$rct.invHR.forEach((e=>$$.th(r,e))),a.tbl.on("fds.inv",$inv.invSumUpdate),$.each(e.req||[],(function(e,t){let n=$$.tbody(a.tbl).data($.extend({},t));$inv.rendersrq.call(n)}));let l=$$.tr($$.tbody(a.tbl),{class:"placeholder"}).data({net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0});$inv.rrw.call(l),a.ft.appendTo(a.tbl);let d=(e,n,i,r,l)=>{let d=$$.dc("inpfrm",t).aC(e).append("string"==typeof r?$$.dc("ahd",r):r>0?$$.dc("ahd",$rct.frm[i]):null),s=$$.dc("content",d).rwText(n);$$.dc("axf",d).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:s,nme:i,change:e=>{a.tbl.data("new")[i]=e}},l),$inv.eHtml)),a.tbl.data("new")[i]=n};d("tfrm",n.InvoiceTitle,"invoicetitle",0,null),d("adrfrm",n.SendToAddress,"invoiceaddress",0,null),d("locfrm",n.ProvisionLocation,"loc",1,null),d("emailfrm",n.SendToEmail,"invoiceemail",0,null),$$.dc("sndfrm",t).append($$.dc("content").text(e.admin.sender)),d("admfrm",n.ProvisionPeriod,"provisionperiod",!0===(n.ProvisionPeriod||"").includes("-")?$rct.provP:$rct.provD,1),a.tbl.data("new").CustomValues=n.CustomValues||"",$$.dc("inpfrm ctpfrm",t).text(jObj(n.CustomValues,"contactName")),a.tbl.children("tbody").each($inv.bdysort),a.tbl.trigger("fds.inv"),$inv.eM(!1,!0,"iss,p13b,setm,ctp")},complete:()=>{i.c.trigger("modal_close")}})},$inv.cSt=function(e){e=e||{};let t=$fis.lf(),n=$$.dc("invoice_layout",$fis.frm_edit()).append($$.dc("btn sprev").click($inv.sedit)),i=$fis.cf().width()>n.width()+t.width()+20;t.tC("fix",i).tC("hd",!i),$inv.eM(!1,!0);let a=$$.dc("rfrm").ldng(1),r=$ocms.dlg(a,{width:1e3});r.ft.rwText($ict.iq1),$ocms.postXT({url:$ocms.url("inv/pget"),data:{id:e.id},success:t=>{r&&r.ft.rwText($ict.iq2),$ocms.postXT({url:$ocms.url("inv/storno"),data:{id:e.id,mode:e.mode},success:e=>{e.admin=e.admin||{},e.admin.p13b=bool(e.admin.p13b||"",!0===((e.inv||{}).InvoiceOptions||"").split(",").includes("§13b"));let t=e.inv||{},i=$$.dc("srq",n),a=$$.tblset({class:"invi"},i);a.bdy.remove(),a.ft=$$[0]("tfoot"),a.tbl.data($.extend({invid:t.Id,new:{},sms:{},itm:{},bai:[]},e));let r=$$.tr(a.hd).aC("shd").append([$$.th().aC("aux")]);$rct.invHR.forEach((e=>$$.th(r,e))),a.tbl.on("fds.inv",$inv.invSumUpdate),$.each(e.req||[],(function(e,t){let n=$$.tbody(a.tbl).data($.extend({},t));$inv.rendersrq.call(n)}));let l=$$.tr($$.tbody(a.tbl),{class:"placeholder"}).data({net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0});$inv.rrw.call(l),a.ft.appendTo(a.tbl);let d=(e,t,i,r,l)=>{let d=$$.dc("inpfrm",n).aC(e).append("string"==typeof r?$$.dc("ahd",r):r>0?$$.dc("ahd",$rct.frm[i]):null),s=$$.dc("content",d).rwText(t);$$.dc("axf",d).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:s,nme:i,change:e=>{a.tbl.data("new")[i]=e}},l),$inv.eHtml)),a.tbl.data("new")[i]=t};d("tfrm",t.InvoiceTitle,"invoicetitle",0,null),d("adrfrm",t.SendToAddress,"invoiceaddress",0,null),d("locfrm",t.ProvisionLocation,"loc",1,null),d("emailfrm",t.SendToEmail,"invoiceemail",0,null),$$.dc("sndfrm",n).append($$.dc("content").text(e.admin.sender)),d("admfrm",t.ProvisionPeriod,"provisionperiod",!0===(t.ProvisionPeriod||"").includes("-")?$rct.provP:$rct.provD,1),a.tbl.data("new").CustomValues=t.CustomValues||"",$$.dc("inpfrm ctpfrm",n).text(jObj(t.CustomValues,"contactName")),a.tbl.children("tbody").each($inv.bdysort),a.tbl.trigger("fds.inv")},complete:()=>{r.c.trigger("modal_close")}})},error:()=>{r&&r.c.trigger("modal_close")}})},$inv.eHtml=function(e){let t=$(this),n=e.data instanceof jQuery?e.data:e.data.t,i=["invoiceemail","provisionperiod","invoicetitle"].includes(e.data.nme),a=i?[{name:"txt",label:"Text",type:"text",value:n.text()}]:[{name:"txt",label:"Text",type:"html",value:n.html(),tinymce:!0,attr:{style:"height: 300px"}}],r=e.data.change||null,l={title:t.data("dialog")||"",success:function(t){i?n.text(t.txt||""):n.html(t.txt),"function"==typeof r&&r(t.txt),$inv.d.syncField(e.data.nme,i?t.txt||"":t.txt),$inv.rd.syncField(e.data.nme,i?t.txt||"":t.txt)},tinymce:{valid_elements:"br",hidemenu:!0,hidetoolbar:!0}};if(Array.isArray(e.data.list)){let t=$$.dc("lstfrm");$.each(e.data.list,((n,i)=>{let a=$$.dc("li",t).append(""!==(e.data.lbl||"")?$$.dc("lbl").rwText(i[e.data.lbl]):null);$$.dc("adr",a).rwText(i[e.data.property]).data("val",i[e.data.property]).click((function(){let e=$(this),t=e.closest(".modal-body").find(':input[name="txt"]');t.is(".tinymce")?tinymce.get(t.attr("id")).setContent($$.s().rwText(e.data("val")).html()):"TEXTAREA"===t.prop("tagName")?t.val(e.data("val")).change():t.rwText(e.data("val"))}))})),l.addcontent=t}$ocms.dlgform(a,l)},$inv.setVat=function(e){$(this);let t=e.data,n=prompt($rct.rqV);n&&(n=parseFloat(n.replace("%","")),n>1&&(n*=.01),!1===isNaN(n)&&(t.siblings(".itm").each((function(){let e=$(this).data();e.vat=fnum(n,{style:"percent"}).replace(" ",""),(e.net_val||0)>0&&(e.vat_val=e.net_val*n),(e.svcnet_val||0)>0&&(e.svcvat_val=e.svcnet_val*n)})),$inv.t_fds_inv()))},$inv.inRow=function(e){let t=$(this),n=e.data,i={},a=$rcol.itm.clone(["SortOrder","NameOrNumber","Type","quantityhours","UnitString","net","svcnet_val","svcvat_val","net_val","vat_val","vat","Note"]),r="N"+(65536*(1+Math.random())||0).toString(16).substr(6),l=$$.tr({id:"itm_"+r.toString(),class:"itm"});$ocms.dlgform(a,{title:t.data("dialog")||"",success:function(e){l.data($.extend({Id:r},i,e)),$inv.rrw.call(l),l.insertAfter(n),$inv.t_fds_inv()},typedvalues:!0})},$inv.eRow=function(e){let t=$(this),n=e.data,i=n.data()||{},a=["SortOrder","NameOrNumber","Type","quantityhours","UnitString","net","svcnet_val","svcvat_val","net_val","vat_val","vat","Note"];i.id||""!==(i.Type||"")||a.unshift("Type");let r=$rcol.itm.clone(a).applyValues(i);r.set("Type","hidden","type"),$inv.eRw.call(t,n,i,r)},$inv.eRw=function(e,t,n){let i=$(this);$ocms.dlgform(n,{title:i.data("dialog")||"",success:function(n){let i={};""===(t.Id||"")&&(i.Id="N"+(65536*(1+Math.random())||0).toString(16).substr(6),e.attr("id","itm_"+i.Id.toString())),i.quantity=((n.quantityhours||"").toString()+" "+(n.UnitString||"").toString()).trimEnd(),e.data($.extend({},t,n,i)),console.debug("eRw success %o",e.data()),$inv.rrw.call(e),$inv.t_fds_inv()},typedvalues:!0})},$inv.bdysort=(e,t)=>{$(t).Sortable({dragItem:!1,dragHandleClass:"ico",parentident:"tr",onend:()=>{$inv.t_fds_inv()}})},$inv.rrw=function(){let e=$(this),t=e.data(),n={},i=e.is(".placeholder"),a=e.is(".hidenote"),r=e=>$$.d().append(e).html(),l=[$$.dc("ibtn insb",{title:$rct.iRb}).append(gi("indent-left")).click(e,$inv.inRow)];!1===i&&(l.unshift($$.dc("ibtn edit",{title:$rct.cP}).append(gi("pencil")).click(e,$inv.eRow)),l.push($$.dc("ibtn del",{title:$rct.dR}).append(gi("trash")).click((function(t){confirm($rct.cD)&&(e.remove(),$inv.t_fds_inv())}))));let d=$$.dc("axf").append(l);!0===i?n={id:"",typ:"placeholder"}:!0===e.is(".itm.osum")?n={invrqid:t.InvRqId,id:"osum"+e.index(),typ:"osum",p:"",q:null,t:r(t.tbl.tbl),tt:null,v:null,vt:t.net_val,vs:t.svcnet_val,vat:t.vat,vv:t.vat_val,vsv:t.svcvat_val,det:!1}:(n={invrqid:t.InvRqId,id:t.Id||"",typ:t.Type||"other",p:"",q:null,t:"",tt:null,v:null,vt:t.net_val,vs:t.svcnet_val,vat:t.vat,vv:t.vat_val,vsv:t.svcvat_val,det:""!==(t.Note||"")&&!1===a},$$.dc("ibtn ico move",d,{title:$rct.mR}),n.p=t.position||t.SortOrder||"",""===n.id?n.t="":["Text","Title"].includes(n.typ)&&0===(t.net_val||0)?n.t=t.htmltext||("#"!==(t.NameOrNumber||"").substr(0,1)?r($$[0]("p").text(t.NameOrNumber)):"")+(t.Note||""):(n.tt=n.det?"":$$.s(t.Note||"").text(),n.q=t.quantity||fnum(t.quantityhours)+" "+(t.UnitString||""),n.t=t.htmltext||(n.det?r($$.s(t.NameOrNumber||""))+r($$.dc("desc").html(t.Note)):r($$.s(t.NameOrNumber||""))),n.v=t.net,n.vt=t.net_val)),""!==(t.Note||"")&&$$.dc("ibtn add",d).append(gi("object-align-left")).click((function(t){$inv.rrw.call(e.tC("hidenote"))}));let s=[$$.tdc("aux").append(d),$$.tdc("keep").text(n.p)];""===n.id?s.push($$.td(e,{colspan:4}).append(n.t)):(Array.prototype.push.apply(s,n.q?[$$.tdc("keep").text(n.q)]:[]),Array.prototype.push.apply(s,[$$.tdc("txt",{colspan:n.q?1:2,title:n.tt}).append(n.t),$$.tdc("currency").text(fnum(n.v,$rct.cst)),$$.tdc("currency inetval").text(fnum(n.vt,$rct.cst)).attr("title",$rct.svcPart+": "+fnum(n.vs,$rct.cst))])),e.empty().attr("class",i?"placeholder":"itm").aC(n.Typ).tC("hidenote",a).append(s),t.co=n},$inv.invSumUpdate=function(){let e=$(this),t=e.children("tfoot").empty(),n=bool((e.data().admin||{}).p13b||"",!1);e.nextAll(".fnote").remove();let i={ttn:0,ttb:0,ttvat:0,tscn:0,tscvat:0,vat:{},itmnet:{}},a=[],r=(e,n,i)=>$$.tdc("currency",$$.tr(t,{class:i||"tsum"}).append([$$.tdc("aux"),$$.td({colspan:4}).text(e)]),fnum(n,$rct.cst)),l=t=>$$.dc("fnote").insertAfter(e).rwText(t),d=e.children("tbody");d.each(((e,t)=>{let n=$(t),r=n.data()||{},l=[],d=[],s=null,c=0,o=n.find("tr.itm"),u=0;n.tC("empty",o.length<1),o.each(((e,t)=>{let n=$(t).data()||{};!function(e,t,n){t.tscn+=e.svcnet_val||0,t.tscvat+=e.svcvat_val||0,t.ttn+=e.net_val||0,t.ttvat+=e.vat_val||0,t.ttb+=(e.net_val||0)+(e.vat_val||0),""!==(e.vat||"")&&(t.vat[e.vat]=(t.vat[e.vat]||0)+(e.vat_val||0))}(n,i,r.Id),c+=n.net_val||0,l.push(n.co);let a=$inv.itemToContract(n);"set"===a.type&&""!==a.id?s=a.id:null!==s&&""!==(a.id||"")&&(a.setId=s),d.push(a),(void 0===n.SortOrder||null===n.SortOrder?-1:n.SortOrder)>-1&&(!1===["text","title"].includes((n.Type||"other").toLowerCase())&&u++,n.SortOrder=0,n.position=u,$inv.rrw.call(t))})),n.find("tr.isum > td.isumval").text(fnum(c,$rct.cst)),a.push({Id:r.Id,nme:r.Name,text:r.text,itm:l,items:d,netval:c})}));let s=e.find("tbody:not(.empty)").length;d.find("tr.isum").tC("hidden",s<2),r("Netto",i.ttn),!1===n?$.each(i.vat,((e,t)=>{r($rct.vat+" "+e,t,"tvat")})):i.ttb=i.ttn,r("Summe",i.ttb);let c=e.data().admin.type;"i"===c?(l($rct.note2),l($rct.note4)):"c"===c?l($rct.note2):(l(string($rct.note3,[fnum((i.tscn+i.tscvat)*(e.data().admin.tax_servicerefund||0),$rct.cst)])).aC("ntax"),l($rct.note2),l(string($rct.note1,[fnum(i.tscn+i.tscvat,$rct.cst),fnum(i.tscn,$rct.cst),fnum(i.tscvat,$rct.cst)]))),!0===n&&l($rct.note13b),e.data("sms",i),e.data("bai",a),""===(e.data("dtoken")||"")&&!1===bool(e.data("dseeding"),!1)&&null!=(e.data("admin")||{}).type&&(e.data("dseeding",!0),$inv.d.seed($.extend($inv.invcPayload(e.data()),{invid:e.data("invid")||""})))},$inv.worknotes=function(e){let t="";return e.steps.forEach(((e,n)=>{let i;try{i=JSON.parse(e.Data||{}).fields||[]}catch(e){console.debug(e),i=[]}!0!==Array.isArray(i||"")&&(i="object"==typeof i&&!0===Array.isArray(i.field||"")?i.field:[]),i.forEach(((e,n)=>{"Ausgeführte Arbeiten"===e.name&&(t=e.result||"")}))})),t},$inv.rendersrq=function(){let e=$(this).empty(),t=e.is(".onesum"),n=e.data(),i=$$.tr(e,{id:"srq"+n.Id}).aC("title nosort"),a=($rcol.itm.lbl(),$$.dc("axf").appendTo($$.tdc("aux",i)));$$.dc("ibtn osum",a,{title:$rct.combP}).append(gi("euro")).click((function(t){e.tC("onesum"),$inv.rendersrq.call(e),$inv.t_fds_inv()})),$$.dc("ibtn setvat",a,{title:$rct.sV}).append(gi("gbp")).click(i,$inv.setVat),$$.dc("ibtn insb",a,{title:$rct.iRb}).append(gi("indent-left")).click(i,$inv.inRow);let r,l=$$.sc("text",n.text),d=($$.td(i,{colspan:t?4:5}).append(l),["net_val","vat_val","svcnet_val","svcvat_val","net"]);if($$.dc("ibtn edit",a).data("dialog",$rcol.req.lbl().Name).append(gi("pencil")).click({t:l,change:e=>{n.text=e,$inv.t_fds_inv()}},$inv.eHtml),t&&($$.tdc("currency isumval",i),r={Id:n.Id.toString()+"_osum",net_val:0,vat_val:0,svcnet_val:0,svcvat_val:0,net:0},r.tbl=$$.tblset({class:"stbl"})),$.each(n.items||[],((n,i)=>{let a,l={Id:i.Id,net_val:i.net_val||0,vat_val:i.vat_val||0,svcnet_val:0,svcvat_val:0,net:i.net||0,Note:i.Note||""};if("service"===i.Type.toLowerCase())l.svcnet_val=i.net_val||0,l.svcvat_val=i.vat_val||0;t?(a=$$.tr(r.tbl.bdy,{id:"itm"+i.Id,class:"sitm"}).aC(i.Type),"Text"===i.Type||"Title"===i.Type?$$.td(a,{colspan:2}).html(i.htmltext||i.Note):($$.tdc("keep",a).text(i.quantity||((i.quantityhours||0)>0?fnum(i.quantityhours)+(i.UnitString||"").eine(" ",""):"")),i.htmltext?$$.tdc("txt",a).html(i.htmltext):$$.tdc("txt",a).text(i.NameOrNumber).attr("title",i.Note)),$.each(d,((e,t)=>{r[t]+=l[t]})),a.data(l)):($.extend(l,i),a=$$.tr(e,{id:"itm"+i.Id,class:"itm"}),a.data(l),$inv.rrw.call(a))})),t){let t=$$.tr(e,{id:"itmsq"+n.Id,class:"itm osum"}).data(r);$inv.rrw.call(t)}else{let t=$$.tr(e).aC("isum nosort");$$.tdc("aux",t),$$.td(t,{colspan:4}).text($rct.iSum),$$.tdc("currency isumval",t)}},$inv.t_fds_inv=()=>{let e=$("div.invoice_layout table.invi");e.trigger("fds.inv"),""!==(e.data("dtoken")||"")&&$inv.d.syncChanged(e)},$inv.sedit=()=>{$inv.sprev(!0)},$inv.jdisp=function(e){e.stopPropagation(),e.data.id&&$inv.disp(e.data.id,e.data.typ||"")},$inv.disp=(e,t)=>{let n="";switch(t){case"inv":n="inv/rdoc";break;case"rem":n="rem/rdoc"}""!==n&&$ocms.postXT({url:$ocms.url(n),data:{id:e||"",typ:"img"},success:e=>{let t=$$.dc("imagecollection pdfpreview"),n=Math.round(.88*vh());e.id;$.each(e.img||[],(function(e,i){$$.dc("pdfp",t).append($$.img(i).css("max-height",(n-rpx(6)).toString()+"px"))})),$ocms.dlg(t,{size:[n,Math.round(.88*vw())],zindex_min:50,form:!1,exclusive:!1})}})},$inv.jdbn=function(e){$ocms.postXT({url:$ocms.url("inv/rdocn"),data:{name:e.data.id||"",typ:"img"},success:e=>{let t=$$.dc("imagecollection pdfpreview"),n=Math.round(.88*vh());e.id;$.each(e.img||[],(function(e,i){$$.dc("pdfp",t).append($$.img(i).css("max-height",(n-rpx(6)).toString()+"px"))})),$ocms.dlg(t,{size:[n,Math.round(.88*vw())],zindex:50,form:!1})}})},$inv.sp13b=()=>{var e=$("div.invoice_layout").find("table.invi"),t=e.data();t.admin.p13b=!0,!1===(t.inv.InvoiceOptions||"").split(",").includes("§13b")&&(t.inv.InvoiceOptions+=",§13b"),e.trigger("fds.inv"),$inv.d.sync({Target:"p13b",Value:t.admin.p13b})},$inv.itemToContract=function(e){let t=((e=e||{}).Type||"").toString().toLowerCase(),n={id:(e.Id||"").toString(),type:t,title:"",desc:"",qty:"",price_net:"",total_net:e.net_val||0,vat:e.vat||""};var i;return e.co&&"osum"===e.co.typ?(n.desc=e.co.t||"",n.total_net=e.net_val||0):["text","title"].includes(t)&&0===(e.net_val||0)?(n.desc=e.htmltext||("#"!==(e.NameOrNumber||"").substr(0,1)?(i=$$[0]("p").text(e.NameOrNumber||""),$$.d().append(i).html()):"")+(e.Note||""),n.total_net=""):(e.htmltext?n.desc=e.htmltext:(n.title=e.NameOrNumber||"",n.desc=e.Note||""),n.qty=e.quantity||(0!==(e.quantityhours||0)?fnum(e.quantityhours)+(e.UnitString?" "+e.UnitString:""):""),n.price_net=e.net||0,n.total_net=e.net_val||0),n},$inv.ssetmode=()=>{let e=$("div.invoice_layout").find("table.invi").data();e.admin=e.admin||{};let t,n=e.admin.setmode||"setprice",i=e=>$$.dc("btn",$ict.setmo[e]).tC("selected",n===e).click((()=>{t.c.trigger("modal_close"),$inv.setSetmode(e)})),a=$$.dc("choicefrm").append([i("setprice"),i("itemprices"),i("setonly")]);t=$ocms.dlg(a,{width:800})},$inv.setSetmode=e=>{let t=$("div.invoice_layout").find("table.invi").data();t.admin=t.admin||{},t.admin.setmode=e,t.inv=t.inv||{};let n=(t.inv.InvoiceOptions||"").split(",").filter((e=>""!==e&&0!==e.indexOf("setmode:")));e&&"setprice"!==e&&n.push("setmode:"+e),t.inv.InvoiceOptions=n.join(","),$inv.d.sync({Target:"setmode",Value:e})},$inv.sctp=()=>{let e=$invcol.ctp;$ocms.dlgform(e,{title:$ict.ctp,success:function(e){var t=$("div.invoice_layout"),n=t.find("table.invi").data();let i={};void 0!==n.new&&"{"===(n.new.CustomValues||"").substr(0,1)&&(i=JSON.parse(n.inv.CustomValues)),i.contactName=e.name,i.contactEmail=e.email,n.new.CustomValues=JSON.stringify(i),t.find(".ctpfrm").text(ne(e.name,e.email)),$inv.d.sync({Target:"contact",Value:{name:e.name,email:e.email}})},typedvalues:!0})},$inv.invcPayload=function(e){let t=(e=e||{}).sms||{},n=$.extend({},e.new),i=$.extend({},e.admin);return n.total_net=t.ttn||0,n.total_gross=t.ttb||0,n.title=null!=n.invoicetitle?n.invoicetitle:n.title||"",n.provisionlocation=null!=n.loc?n.loc:n.provisionlocation||"",n.paymentterm=null!=i.paymentterms?i.paymentterms:n.paymentterm||"",i.customerid=null!=i.customerid?i.customerid:i.CustomerId,{admin:i,req:e.bai,sms:e.sms,new:n}},$inv.ssave=()=>{$inv.d.save()},$inv.sprev=e=>{$inv.d.preview()},$inv.rReload=()=>{try{let e=$("#listframe ul.rql:first").data();$inv.cInv2({id:e.search})}catch(e){}},$inv.quantChange=function(e){let t=$(this).closest("form"),n={},i=e=>parseFloat(e.toString().replace("%","").replace(",",".")),a=e=>e.toFixed(2);t.find(":input").each(((e,t)=>{n[$(t).attr("name")]=$(t)}));let r=parseInt(n.quantityhours.val()||"0"),l=i(n.net.val()||"0"),d=.01*i(n.vat.val());r>0&&l>0&&(n.net_val.val(a(r*l)),n.vat_val.val(a(r*l*d)),["Service"].includes(n.Type.val())&&(n.svcnet_val.val(a(r*l)),n.svcvat_val.val(a(r*l*d))))},$inv.storno=function(e,t){let n,i=$$.dc("choicefrm").append([$$.dc("btn","Storno ohne Details").click({id:e,mode:"simple"},(e=>{n.c.trigger("modal_close"),$inv.cSt(e.data)})),$$.dc("btn","Storno mit neuer Rechnung").click({id:e},(e=>{n.c.trigger("modal_close"),$inv.ccStInv(e)})),$$.dc("btn","Storno mit best. Rechnung").tC("inactive",!1===bool(t,!1)).click({id:e,mode:"copy"},(e=>{!0===bool(t,!1)&&(n.c.trigger("modal_close"),$inv.cSt(e.data))}))]);n=$ocms.dlg(i,{width:1e3})},$inv.credit=function(e,t){let n,i=$$.dc("choicefrm").append([$$.dc("btn","Gutschrift").click({id:e,mode:"credit"},(e=>{n.c.trigger("modal_close"),$inv.cSt(e.data)}))]);n=$ocms.dlg(i,{width:1e3})},$inv.setPyd=function(e){confirm($ict.cpyd)&&$ocms.postXT({url:$ocms.url("inv/setpyd"),timeout:60,data:{id:e},success:e=>{alert($ict.relm)},error:()=>{alert($t.f1)}})},$inv.setUpd=function(e){confirm($ict.cupd)&&$ocms.postXT({url:$ocms.url("inv/setupd"),timeout:60,data:{id:e},success:e=>{alert($ict.relm)},error:()=>{alert($t.f1)}})},$inv.resendRem=function(e){e.stopPropagation(),e.data.id&&confirm(string($ict.remresc,[e.data.name]))&&$ocms.postXT({url:$ocms.url("rem/resend"),timeout:60,data:{id:e.data.id},success:t=>{alert(string($ict.remresr,[e.data.name]))},error:()=>{alert($t.f1)}})},$inv.dspRem=function(e){let t=$$.dc("rfrm").ldng(1),n=$ocms.dlg(t,{width:1e3});n.ft.rwText($rct.rq2),$ocms.postXT({url:$ocms.url("inv/getrem"),timeout:60,data:{id:e,drafts:!1},success:e=>{n.ft.empty();let i=$$.tblset({class:"invtbl"},t.empty()),a=$invcol.rem2,r=$$.tr(i.hd);$$.th(r);$.each(a.fields||[],((e,t)=>{$$.th(r).text(t.label)}));let l=!1;$.each(e,((e,t)=>{l=!l;let n=$$.tr(i.bdy).tC("alt",l),r=$$.td(n);n.click((function(){n.tC("selected").siblings().rC("selected")})),!0===bool(t.hasFile,!1)&&($$.dc("idl ilbtn",r,{title:$ict.dl+"\n"+t.DocumentName}).append(gi("save-file","ico")).click({id:t.Id},$inv.downloadrem),$$.dc("idl ilbtn",r,{title:$ict.remdsp+"\n"+t.DocumentName}).append(gi("eye-open","ico")).click({id:t.Id,typ:"rem"},$inv.jdisp),$$.dc("idl ilbtn",r,{title:$ict.remres+"\n"+t.DocumentName}).append(gi("refresh","ico")).click({id:t.Id,typ:"rem",name:t.DocumentName},$inv.resendRem)),$.each(a.fields||[],((e,i)=>{let a=$$.td(n).aC(i.dtype),r=t[i.name];if("function"==typeof i.dfnc)i.dfnc.call(a,r,t);else switch(i.type||""){case"date":a.text(fdt(t[i.name],"dd.MM.yy"));break;case"datetime":a.text(fdt(t[i.name]));break;case"html":a.append($$.dc("ctw").html(r)),a.append($$.dc("ttip").html(r));break;default:a.text(t[i.name])}if("InvoiceId"===(i.name||""))a.aC("keep");switch(typeof i.title){case"function":i.title.call(a,t);break;case"string":a.attr("title",cs.title)}}))}))},error:()=>{t.empty(),n.ft.rwText($t.f1)},complete:()=>{t.ldng(0)}})},$inv.ccRem=function(e,t){$(this);$ocms.postXT({url:$ocms.url("rem/lrem"),timeout:60,data:{id:e},success:n=>{let i=$invcol.rid.clone();i.applyValues(n.ov);let a=$$.dc("ac"),r=$$.tblset({class:"fullgrid fullwidth"},a);if((n.lst||[]).length>0){$$.d({style:"margin: 1.5rem 0 1rem 0;font-size: 110%;text-decoration: underline;"}).prependTo(a).text($ict.rovlh);let e=$$.tr(r.hd);$ict.rovl.forEach(((t,n)=>$$.th(e,t))),$.each(n.lst,((e,t)=>{$$.tr(r.bdy).append([$$.tdc("keep",t.subject),$$.tdc("currency",fnum(t.amount,$rct.cst)),$$.tdc("currency",fnum(t.amount_payed,$rct.cst)),$$.tdc("keep",fdt(t.DateFinalized,"dd.MM.yy"))])}))}else $$.td($$.tr(r.bdy),$ict.nd);$ocms.dlgform(i,{addcontent:a,title:string($ict.remdt,[t||"?"]),success:function(t){$inv.ccRem_s2(e,t)},typedvalues:!0})}})},$inv.rRemRw=function(e){let t=$(this),n=e.rm||{};t.empty().data({invoiceid:n.invoiceid,invoicedate:n.invoicedate,amount:n.amount,amount_payed:n.amount_payed});let i=$$.dc("axf").append($$.dc("ibtn edit",{title:$rct.cP}).append(gi("pencil")).click(t,$inv.eRowR));t.append([$$.tdc("aux").append(i),$$.tdc("keep",n.invoiceid),$$.tdc("keep",fdt(n.invoicedate,"dd.MM.yy")),$$.tdc("currency",fnum(n.amount,$rct.cst)),$$.tdc("currency",fnum(n.amount_payed,$rct.cst)),$$.tdc("currency",fnum(n.amount-n.amount_payed,$rct.cst))])},$inv.eRowR=function(e){let t=$(this),n=e.data,i=n.data()||{},a=$invcol.rem.clone().applyValues(i);$ocms.dlgform(a,{title:t.data("dialog")||"",success:function(e){let i=t.closest("table"),a=i.data();$.extend(a.rm,e),i.data(a),$inv.rRemRw.call(n,a),$inv.rd.syncAmount(a.rm.amount,a.rm.amount_payed)},typedvalues:!0})},$inv.ccRem_s2=function(e,t){$fis.lf(!1).rC("fix").aC("hd");let n=$$.dc("invoice_layout",$fis.frm_edit()).append($$.dc("btn sprev").click($inv.rprev));$inv.eM(!1,!0);$$.dc("rfrm").ldng(1);$ocms.postXT({url:$ocms.url("rem/get"),timeout:60,data:$.extend({id:e},t),success:e=>{let t=e.rm||{},i=$$.dc("srq",n);$ict.remt[t.type].forEach((e=>$$[0]("p").rwText(e).appendTo(i)));let a=$$.tblset({class:"invi"},i);a.ft=$$[0]("tfoot"),a.tbl.data($.extend({invid:t.invid,new:{}},e));let r=$$.tr(a.hd).aC("shd").append([$$.th().aC("aux")]);$ict.remHR.forEach((e=>$$.th(r,e))),$inv.rRemRw.call($$.tr(a.bdy),a.tbl.data()),a.ft.appendTo(a.tbl),$ict.remt2[t.type].forEach((e=>$$[0]("p").rwText(e).appendTo(i)));let l=(e,t,i,r,l)=>{let d=$$.dc("inpfrm",n).aC(e).append("string"==typeof r?$$.dc("ahd",r):r>0?$$.dc("ahd",$rct.frm[i]):null),s=$$.dc("content",d).rwText(t);$$.dc("axf",d).append($$.dc("ibtn edit").data("dialog",$rct.frm[i]).append(gi("pencil")).click($.extend({t:s,nme:i,change:e=>{a.tbl.data("new")[i]=e}},l),$inv.eHtml)),a.tbl.data("new")[i]=t};l("tfrm",t.subject,"subject",0,null),l("adrfrm",t.invoiceaddress,"invoiceaddress",0,null),l("emailfrm",t.invoiceemail,"invoiceemail",0,null),$$.dc("sndfrm",n).append($$.dc("content").text(t.sender)),a.tbl.children("tbody").each($inv.bdysort),a.tbl.trigger("fds.inv");let d=a.tbl.data("new");d.amount=t.amount,d.amount_payed=t.amount_payed,$inv.rd.seed({rem:{invid:t.invid,type:t.type,invoiceid:t.invoiceid,invoicedate:t.invoicedate},new:d})},complete:()=>{}})},$inv.rprev=()=>{$inv.rd.preview()},$inv.sis=e=>{confirm($ict.sisc)&&$ocms.postXT({url:$ocms.url("inv/sis"),data:{id:e||""},success:e=>{}})},$inv.srs=e=>{confirm($ict.srsc)&&$ocms.postXT({url:$ocms.url("rem/srs"),data:{id:e||""},success:e=>{}})},$inv.mfrrel=e=>{$("#contentframe").ldng(),$ocms.postXT({url:$ocms.url("inv/mfrrel"),data:{id:e||""},success:e=>{$inv.rerenderinv()},complete:()=>{$("#contentframe").ldng(0)}})};
\ No newline at end of file
diff --git a/Fuchs/wwwroot/web/tools.js b/Fuchs/wwwroot/web/tools.js
index f36c9c0..ceb47a5 100644
--- a/Fuchs/wwwroot/web/tools.js
+++ b/Fuchs/wwwroot/web/tools.js
@@ -1,5 +1,4 @@
+/*! js-cookie v3.0.1 | MIT */
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self,function(){var n=e.Cookies,o=e.Cookies=t();o.noConflict=function(){return e.Cookies=n,o}}())}(this,(function(){"use strict";function e(e){for(var t=1;t+~]|"+ge+")"+ge+"*"),x=new RegExp(ge+"|>"),j=new RegExp(g),A=new RegExp("^"+t+"$"),D={ID:new RegExp("^#("+t+")"),CLASS:new RegExp("^\\.("+t+")"),TAG:new RegExp("^("+t+"|[*])"),ATTR:new RegExp("^"+p),PSEUDO:new RegExp("^"+g),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ge+"*(even|odd|(([+-]|)(\\d*)n|)"+ge+"*(?:([+-]|)"+ge+"*(\\d+)|))"+ge+"*\\)|)","i"),bool:new RegExp("^(?:"+f+")$","i"),needsContext:new RegExp("^"+ge+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ge+"*((?:-\\d)?\\d*)"+ge+"*\\)|)(?=[^-]|$)","i")},N=/^(?:input|select|textarea|button)$/i,q=/^h\d$/i,L=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,H=/[+~]/,O=new RegExp("\\\\[\\da-fA-F]{1,6}"+ge+"?|\\\\([^\\r\\n\\f])","g"),P=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},M=function(){V()},R=J(function(e){return!0===e.disabled&&fe(e,"fieldset")},{dir:"parentNode",next:"legend"});try{k.apply(oe=ae.call(ye.childNodes),ye.childNodes),oe[ye.childNodes.length].nodeType}catch(e){k={apply:function(e,t){me.apply(e,ae.call(t))},call:function(e){me.apply(e,ae.call(arguments,1))}}}function I(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(V(e),e=e||T,C)){if(11!==p&&(u=L.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return k.call(n,a),n}else if(f&&(a=f.getElementById(i))&&I.contains(e,a)&&a.id===i)return k.call(n,a),n}else{if(u[2])return k.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&e.getElementsByClassName)return k.apply(n,e.getElementsByClassName(i)),n}if(!(h[t+" "]||d&&d.test(t))){if(c=t,f=e,1===p&&(x.test(t)||m.test(t))){(f=H.test(t)&&U(e.parentNode)||e)==e&&le.scope||((s=e.getAttribute("id"))?s=ce.escapeSelector(s):e.setAttribute("id",s=S)),o=(l=Y(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+Q(l[o]);c=l.join(",")}try{return k.apply(n,f.querySelectorAll(c)),n}catch(e){h(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return re(t.replace(ve,"$1"),e,n,r)}function W(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function F(e){return e[S]=!0,e}function $(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function B(t){return function(e){return fe(e,"input")&&e.type===t}}function _(t){return function(e){return(fe(e,"input")||fe(e,"button"))&&e.type===t}}function z(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&R(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function X(a){return F(function(o){return o=+o,F(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function U(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function V(e){var t,n=e?e.ownerDocument||e:ye;return n!=T&&9===n.nodeType&&n.documentElement&&(r=(T=n).documentElement,C=!ce.isXMLDoc(T),i=r.matches||r.webkitMatchesSelector||r.msMatchesSelector,r.msMatchesSelector&&ye!=T&&(t=T.defaultView)&&t.top!==t&&t.addEventListener("unload",M),le.getById=$(function(e){return r.appendChild(e).id=ce.expando,!T.getElementsByName||!T.getElementsByName(ce.expando).length}),le.disconnectedMatch=$(function(e){return i.call(e,"*")}),le.scope=$(function(){return T.querySelectorAll(":scope")}),le.cssHas=$(function(){try{return T.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),le.getById?(b.filter.ID=function(e){var t=e.replace(O,P);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(O,P);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},b.find.CLASS=function(e,t){if("undefined"!=typeof t.getElementsByClassName&&C)return t.getElementsByClassName(e)},d=[],$(function(e){var t;r.appendChild(e).innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+ge+"*(?:value|"+f+")"),e.querySelectorAll("[id~="+S+"-]").length||d.push("~="),e.querySelectorAll("a#"+S+"+*").length||d.push(".#.+[+~]"),e.querySelectorAll(":checked").length||d.push(":checked"),(t=T.createElement("input")).setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),r.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&d.push(":enabled",":disabled"),(t=T.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||d.push("\\["+ge+"*name"+ge+"*="+ge+"*(?:''|\"\")")}),le.cssHas||d.push(":has"),d=d.length&&new RegExp(d.join("|")),l=function(e,t){if(e===t)return a=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!le.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument==ye&&I.contains(ye,e)?-1:t===T||t.ownerDocument==ye&&I.contains(ye,t)?1:o?se.call(o,e)-se.call(o,t):0:4&n?-1:1)}),T}for(e in I.matches=function(e,t){return I(e,null,null,t)},I.matchesSelector=function(e,t){if(V(e),C&&!h[t+" "]&&(!d||!d.test(t)))try{var n=i.call(e,t);if(n||le.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){h(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(O,P),e[3]=(e[3]||e[4]||e[5]||"").replace(O,P),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||I.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&I.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return D.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&j.test(n)&&(t=Y(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(O,P).toLowerCase();return"*"===e?function(){return!0}:function(e){return fe(e,t)}},CLASS:function(e){var t=s[e+" "];return t||(t=new RegExp("(^|"+ge+")"+e+"("+ge+"|$)"))&&s(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=I.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function T(e,n,r){return v(n)?ce.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?ce.grep(e,function(e){return e===n!==r}):"string"!=typeof n?ce.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(ce.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||k,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:S.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof ce?t[0]:t,ce.merge(this,ce.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),w.test(r[1])&&ce.isPlainObject(t))for(r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=C.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(ce):ce.makeArray(e,this)}).prototype=ce.fn,k=ce(C);var E=/^(?:parents|prev(?:Until|All))/,j={children:!0,contents:!0,next:!0,prev:!0};function A(e,t){while((e=e[t])&&1!==e.nodeType);return e}ce.fn.extend({has:function(e){var t=ce(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,Ce=/^$|^module$|\/(?:java|ecma)script/i;xe=C.createDocumentFragment().appendChild(C.createElement("div")),(be=C.createElement("input")).setAttribute("type","radio"),be.setAttribute("checked","checked"),be.setAttribute("name","t"),xe.appendChild(be),le.checkClone=xe.cloneNode(!0).cloneNode(!0).lastChild.checked,xe.innerHTML="",le.noCloneChecked=!!xe.cloneNode(!0).lastChild.defaultValue,xe.innerHTML="",le.option=!!xe.lastChild;var ke={thead:[1,""],col:[2,""],tr:[2,""],td:[3,""],_default:[0,"",""]};function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&fe(e,t)?ce.merge([e],n):n}function Ee(e,t){for(var n=0,r=e.length;n",""]);var je=/<|?\w+;/;function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function Re(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild,"tr")&&ce(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=_.get(e).events))for(i in _.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){i&&i()}}});var Jt,Kt=[],Zt=/(=)\?(?=&|$)|\?\?/;ce.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Kt.pop()||ce.expando+"_"+jt.guid++;return this[e]=!0,e}}),ce.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Zt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Zt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Zt,"$1"+r):!1!==e.jsonp&&(e.url+=(At.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||ce.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=ie[r],ie[r]=function(){o=arguments},n.always(function(){void 0===i?ce(ie).removeProp(r):ie[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Kt.push(r)),o&&v(i)&&i(o[0]),o=i=void 0}),"script"}),le.createHTMLDocument=((Jt=C.implementation.createHTMLDocument("").body).innerHTML="",2===Jt.childNodes.length),ce.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(le.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument("")).createElement("base")).href=C.location.href,t.head.appendChild(r)):t=C),o=!n&&[],(i=w.exec(e))?[t.createElement(i[1])]:(i=Ae([e],t,o),o&&o.length&&ce(o).remove(),ce.merge([],i.childNodes)));var r,i,o},ce.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(ce.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ce.expr.pseudos.animated=function(t){return ce.grep(ce.timers,function(e){return t===e.elem}).length},ce.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=ce.css(e,"position"),c=ce(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=ce.css(e,"top"),u=ce.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),v(t)&&(t=t.call(e,n,ce.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},ce.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){ce.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ce.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===ce.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=ce(e).offset()).top+=ce.css(e,"borderTopWidth",!0),i.left+=ce.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ce.css(r,"marginTop",!0),left:t.left-i.left-ce.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===ce.css(e,"position"))e=e.offsetParent;return e||J})}}),ce.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;ce.fn[t]=function(e){return M(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),ce.each(["top","left"],function(e,n){ce.cssHooks[n]=Ye(le.pixelPosition,function(e,t){if(t)return t=Ge(e,n),_e.test(t)?ce(e).position()[n]+"px":t})}),ce.each({Height:"height",Width:"width"},function(a,s){ce.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){ce.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return M(this,function(e,t,n){var r;return y(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?ce.css(e,t,i):ce.style(e,t,n,i)},s,n?e:void 0,n)}})}),ce.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ce.fn[t]=function(e){return this.on(t,e)}}),ce.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.on("mouseenter",e).on("mouseleave",t||e)}}),ce.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){ce.fn[n]=function(e,t){return 0