@lambda-development/erp-core 0.6.2 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bootstrap.d.ts +1 -1
- package/dist/index.js +285 -252
- package/dist/index.js.map +1 -1
- package/dist/lib/chat-doctype-redirects.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { jsx as e, jsxs as r, Fragment as we } from "react/jsx-runtime";
|
|
2
2
|
import { useState as S, useEffect as se, useCallback as Pe, useContext as Kn, createContext as jn, useRef as te, useMemo as Ce, useLayoutEffect as un, StrictMode as ka } from "react";
|
|
3
3
|
import { createRoot as Sa } from "react-dom/client";
|
|
4
|
-
import { useQueryClient as We, useQuery as ie, useMutation as oe, QueryClientProvider as Ca, QueryClient as
|
|
5
|
-
import { NavLink as Ot, useLocation as Ct, useNavigate as Le, Outlet as
|
|
4
|
+
import { useQueryClient as We, useQuery as ie, useMutation as oe, QueryClientProvider as Ca, QueryClient as Da } from "@tanstack/react-query";
|
|
5
|
+
import { NavLink as Ot, useLocation as Ct, useNavigate as Le, Outlet as Aa, Navigate as Pa, Link as be, useSearchParams as qt, useParams as ut, createBrowserRouter as _a, RouterProvider as Ta } from "react-router-dom";
|
|
6
6
|
import { useTranslation as Z, initReactI18next as Ra } from "react-i18next";
|
|
7
7
|
import { BookOpen as Ia, ShoppingCart as Gn, CreditCard as Ba, FileText as nn, Package as Wn, BarChart3 as Ea, Database as La, Settings as Oa, MessageCircle as qa, ChevronDown as zt, ChevronRight as Mt, Plus as Hn, Trash2 as Qn, LineChart as za, ArrowLeft as Ma, TrendingUp as Fa, ArrowDownRight as $a, ArrowUpRight as Ua, Wallet as Va, Receipt as mn, Info as Ka } from "lucide-react";
|
|
8
8
|
import { createColumnHelper as Yn, useReactTable as Jn, getCoreRowModel as Zn, flexRender as It } from "@tanstack/react-table";
|
|
9
9
|
import { createPortal as Xn } from "react-dom";
|
|
10
10
|
import { ResponsiveContainer as ja, LineChart as Ga, CartesianGrid as pn, XAxis as hn, YAxis as gn, Tooltip as Vt, Line as Wa, PieChart as Ha, Pie as Qa, Cell as Ya, BarChart as Ja, Bar as Za } from "recharts";
|
|
11
11
|
import ea from "i18next";
|
|
12
|
-
import { default as
|
|
12
|
+
import { default as Vo } from "i18next";
|
|
13
13
|
let ct = "/api";
|
|
14
|
-
function
|
|
14
|
+
function Bo(t) {
|
|
15
15
|
ct = t.replace(/\/+$/, "");
|
|
16
16
|
}
|
|
17
17
|
function Xa(t) {
|
|
@@ -349,8 +349,8 @@ function tt(t) {
|
|
|
349
349
|
return Number.isNaN(a) ? 0 : a;
|
|
350
350
|
}
|
|
351
351
|
function rr({ children: t }) {
|
|
352
|
-
const n = We(), [a, s] = S([]), [o, i] = S({}), [l, c] = S({}), [g, m] = S({}), [p, u] = S({}), [N, v] = S({}), [x, f] = S({}), [R, P] = S({}), [b, d] = S(null), [h, _] = S("connecting"), [y, B] = S(0),
|
|
353
|
-
function
|
|
352
|
+
const n = We(), [a, s] = S([]), [o, i] = S({}), [l, c] = S({}), [g, m] = S({}), [p, u] = S({}), [N, v] = S({}), [x, f] = S({}), [R, P] = S({}), [b, d] = S(null), [h, _] = S("connecting"), [y, B] = S(0), D = te(null), O = te(null), G = te(/* @__PURE__ */ new Map()), ee = te(null), C = te({}), w = te({}), q = te(null);
|
|
353
|
+
function A(I) {
|
|
354
354
|
for (const V of G.current.values())
|
|
355
355
|
V.reject(new Error(I));
|
|
356
356
|
G.current.clear();
|
|
@@ -398,23 +398,23 @@ function rr({ children: t }) {
|
|
|
398
398
|
C.current = V;
|
|
399
399
|
}
|
|
400
400
|
function E(I) {
|
|
401
|
-
const V =
|
|
401
|
+
const V = D.current;
|
|
402
402
|
if (!V || V.readyState !== WebSocket.OPEN)
|
|
403
403
|
throw new Error("Chat is disconnected.");
|
|
404
404
|
V.send(JSON.stringify(I));
|
|
405
405
|
}
|
|
406
406
|
function ne(I, V, W) {
|
|
407
407
|
return new Promise((ve, xe) => {
|
|
408
|
-
const
|
|
409
|
-
G.current.set(
|
|
408
|
+
const Ae = ar();
|
|
409
|
+
G.current.set(Ae, {
|
|
410
410
|
expectedType: W,
|
|
411
411
|
resolve: ve,
|
|
412
412
|
reject: xe
|
|
413
413
|
});
|
|
414
414
|
try {
|
|
415
|
-
E({ type: I, request_id:
|
|
415
|
+
E({ type: I, request_id: Ae, ...V });
|
|
416
416
|
} catch (ot) {
|
|
417
|
-
G.current.delete(
|
|
417
|
+
G.current.delete(Ae), xe(ot instanceof Error ? ot : new Error("Chat request failed."));
|
|
418
418
|
}
|
|
419
419
|
});
|
|
420
420
|
}
|
|
@@ -424,16 +424,16 @@ function rr({ children: t }) {
|
|
|
424
424
|
if (I) return;
|
|
425
425
|
_("connecting");
|
|
426
426
|
const ve = `${window.location.protocol === "https:" ? "wss:" : "ws:"}//${window.location.host}/ws/chat`, xe = new WebSocket(ve);
|
|
427
|
-
|
|
427
|
+
D.current = xe, xe.onopen = () => {
|
|
428
428
|
if (I) {
|
|
429
429
|
xe.close();
|
|
430
430
|
return;
|
|
431
431
|
}
|
|
432
|
-
_("connected"), B((
|
|
433
|
-
}, xe.onmessage = (
|
|
432
|
+
_("connected"), B((Ae) => Ae + 1);
|
|
433
|
+
}, xe.onmessage = (Ae) => {
|
|
434
434
|
var ot;
|
|
435
435
|
try {
|
|
436
|
-
const K = JSON.parse(
|
|
436
|
+
const K = JSON.parse(Ae.data), Ze = typeof K.request_id == "string" ? K.request_id : null, me = typeof K.type == "string" ? K.type : null, M = typeof K.session_id == "string" ? K.session_id : null;
|
|
437
437
|
if (Ze) {
|
|
438
438
|
const F = G.current.get(Ze);
|
|
439
439
|
F && (me === "error" ? (G.current.delete(Ze), F.reject(new Error(String(K.content || "Request failed.")))) : me === F.expectedType && (G.current.delete(Ze), F.resolve(K)));
|
|
@@ -458,7 +458,7 @@ function rr({ children: t }) {
|
|
|
458
458
|
).then((Ne) => {
|
|
459
459
|
const le = Ne.filter((ue) => !!ue);
|
|
460
460
|
le.length && (Ue(le), pe((ue) => [
|
|
461
|
-
...le.filter((
|
|
461
|
+
...le.filter((ft) => !ue.some((xt) => xt.id === ft.id)),
|
|
462
462
|
...ue
|
|
463
463
|
]));
|
|
464
464
|
});
|
|
@@ -501,10 +501,10 @@ function rr({ children: t }) {
|
|
|
501
501
|
const F = Array.isArray(K.messages) ? K.messages.map(bn) : [], j = K.before_id != null, Q = !!K.has_more, ze = typeof K.oldest_id == "number" ? K.oldest_id : null;
|
|
502
502
|
i((le) => {
|
|
503
503
|
if (j) {
|
|
504
|
-
const ue = le[M] ?? [],
|
|
504
|
+
const ue = le[M] ?? [], ft = new Set(
|
|
505
505
|
ue.map((Xe) => Xe.id).filter((Xe) => typeof Xe == "number")
|
|
506
506
|
), xt = F.filter(
|
|
507
|
-
(Xe) => Xe.id === void 0 || !
|
|
507
|
+
(Xe) => Xe.id === void 0 || !ft.has(Xe.id)
|
|
508
508
|
);
|
|
509
509
|
return { ...le, [M]: [...xt, ...ue] };
|
|
510
510
|
}
|
|
@@ -651,9 +651,9 @@ function rr({ children: t }) {
|
|
|
651
651
|
}
|
|
652
652
|
}, xe.onerror = () => {
|
|
653
653
|
xe.close();
|
|
654
|
-
}, xe.onclose = (
|
|
655
|
-
if (
|
|
656
|
-
if (
|
|
654
|
+
}, xe.onclose = (Ae) => {
|
|
655
|
+
if (D.current === xe && (D.current = null), A("Chat disconnected."), _("disconnected"), !I) {
|
|
656
|
+
if (Ae.code === 4001 || Ae.code === 4003) {
|
|
657
657
|
window.location.href = "/login";
|
|
658
658
|
return;
|
|
659
659
|
}
|
|
@@ -662,9 +662,9 @@ function rr({ children: t }) {
|
|
|
662
662
|
};
|
|
663
663
|
}
|
|
664
664
|
return V(), () => {
|
|
665
|
-
if (I = !0, O.current !== null && window.clearTimeout(O.current), q.current !== null && window.clearTimeout(q.current),
|
|
666
|
-
const W =
|
|
667
|
-
|
|
665
|
+
if (I = !0, O.current !== null && window.clearTimeout(O.current), q.current !== null && window.clearTimeout(q.current), A("Chat disconnected."), D.current) {
|
|
666
|
+
const W = D.current;
|
|
667
|
+
D.current = null, W.close();
|
|
668
668
|
}
|
|
669
669
|
};
|
|
670
670
|
}, []);
|
|
@@ -676,7 +676,7 @@ function rr({ children: t }) {
|
|
|
676
676
|
});
|
|
677
677
|
return ee.current = I, I;
|
|
678
678
|
}
|
|
679
|
-
async function
|
|
679
|
+
async function De(I) {
|
|
680
680
|
re(I, "running"), ce(I, null);
|
|
681
681
|
try {
|
|
682
682
|
await ne("start_demo", { session_id: I }, "demo_started");
|
|
@@ -696,7 +696,7 @@ function rr({ children: t }) {
|
|
|
696
696
|
async function vt(I) {
|
|
697
697
|
await ne("load_history", { session_id: I }, "history_loaded");
|
|
698
698
|
}
|
|
699
|
-
async function
|
|
699
|
+
async function pt(I) {
|
|
700
700
|
if (p[I]) return;
|
|
701
701
|
const V = g[I];
|
|
702
702
|
if (V != null && l[I]) {
|
|
@@ -720,12 +720,12 @@ function rr({ children: t }) {
|
|
|
720
720
|
if (!ve && !xe) return !1;
|
|
721
721
|
try {
|
|
722
722
|
Y(I, !0);
|
|
723
|
-
const
|
|
723
|
+
const Ae = {
|
|
724
724
|
type: "send_message",
|
|
725
725
|
session_id: I,
|
|
726
726
|
content: ve
|
|
727
727
|
};
|
|
728
|
-
return xe && (
|
|
728
|
+
return xe && (Ae.attachment_ids = W), E(Ae), !0;
|
|
729
729
|
} catch {
|
|
730
730
|
return Y(I, !1), !1;
|
|
731
731
|
}
|
|
@@ -749,13 +749,13 @@ function rr({ children: t }) {
|
|
|
749
749
|
function Ie(I) {
|
|
750
750
|
return I ? !!l[I] : !1;
|
|
751
751
|
}
|
|
752
|
-
function
|
|
752
|
+
function ht(I) {
|
|
753
753
|
return I ? !!p[I] : !1;
|
|
754
754
|
}
|
|
755
755
|
function it(I) {
|
|
756
756
|
return I ? x[I] ?? "idle" : "idle";
|
|
757
757
|
}
|
|
758
|
-
function
|
|
758
|
+
function gt(I) {
|
|
759
759
|
return I ? R[I] ?? null : null;
|
|
760
760
|
}
|
|
761
761
|
return /* @__PURE__ */ e(
|
|
@@ -767,26 +767,26 @@ function rr({ children: t }) {
|
|
|
767
767
|
connectionVersion: y,
|
|
768
768
|
navigationFlash: b,
|
|
769
769
|
createSession: Re,
|
|
770
|
-
startDemo:
|
|
770
|
+
startDemo: De,
|
|
771
771
|
completeDemoTyping: Ve,
|
|
772
772
|
deleteSession: Me,
|
|
773
773
|
loadHistory: vt,
|
|
774
|
-
loadMoreHistory:
|
|
774
|
+
loadMoreHistory: pt,
|
|
775
775
|
clearHistory: Je,
|
|
776
776
|
sendMessage: ke,
|
|
777
777
|
transcribeAudio: Te,
|
|
778
778
|
getMessages: Ke,
|
|
779
779
|
hasMoreHistory: Ie,
|
|
780
|
-
isLoadingOlder:
|
|
780
|
+
isLoadingOlder: ht,
|
|
781
781
|
isThinking: Qe,
|
|
782
782
|
getDemoStatus: it,
|
|
783
|
-
getDemoTypingCue:
|
|
783
|
+
getDemoTypingCue: gt
|
|
784
784
|
},
|
|
785
785
|
children: t
|
|
786
786
|
}
|
|
787
787
|
);
|
|
788
788
|
}
|
|
789
|
-
function
|
|
789
|
+
function mt() {
|
|
790
790
|
const t = Kn(na);
|
|
791
791
|
if (!t)
|
|
792
792
|
throw new Error("useChat must be used within ChatProvider.");
|
|
@@ -880,7 +880,7 @@ const dt = [
|
|
|
880
880
|
function sr() {
|
|
881
881
|
return dt;
|
|
882
882
|
}
|
|
883
|
-
function
|
|
883
|
+
function Eo(t, n) {
|
|
884
884
|
const a = dt.findIndex((s) => s.label === t.label);
|
|
885
885
|
if (a >= 0) {
|
|
886
886
|
dt[a] = t;
|
|
@@ -888,12 +888,12 @@ function Ro(t, n) {
|
|
|
888
888
|
}
|
|
889
889
|
(n == null ? void 0 : n.index) != null ? dt.splice(n.index, 0, t) : dt.push(t);
|
|
890
890
|
}
|
|
891
|
-
function
|
|
891
|
+
function Lo(t, n) {
|
|
892
892
|
const a = dt.find((s) => s.label === t);
|
|
893
893
|
a ? a.items.push(n) : dt.push({ label: t, icon: null, items: [n] });
|
|
894
894
|
}
|
|
895
895
|
let Jt = { appName: "Lambda ERP" };
|
|
896
|
-
function
|
|
896
|
+
function Oo(t) {
|
|
897
897
|
if (Jt = { ...Jt, ...t }, !(typeof document > "u") && (t.appName && (document.title = t.appName), t.tokens)) {
|
|
898
898
|
const n = document.documentElement;
|
|
899
899
|
for (const [a, s] of Object.entries(t.tokens))
|
|
@@ -969,7 +969,7 @@ const sn = {
|
|
|
969
969
|
"Custom Analytics": "bg-indigo-300 text-indigo-950 ring-2 ring-inset ring-indigo-100"
|
|
970
970
|
};
|
|
971
971
|
function or() {
|
|
972
|
-
const [t, n] = rn("chats"), a = Ct(), s = Le(), { t: o } = Z(), { sessions: i, createSession: l, deleteSession: c } =
|
|
972
|
+
const [t, n] = rn("chats"), a = Ct(), s = Le(), { t: o } = Z(), { sessions: i, createSession: l, deleteSession: c } = mt(), g = async () => {
|
|
973
973
|
try {
|
|
974
974
|
const p = await l();
|
|
975
975
|
s(`/chat/${p.id}`);
|
|
@@ -1047,7 +1047,7 @@ function on() {
|
|
|
1047
1047
|
);
|
|
1048
1048
|
}
|
|
1049
1049
|
function lr() {
|
|
1050
|
-
const [t, n, a] = rn("custom-analytics"), s = Ct(), o = Le(), i = We(), { t: l } = Z(), { navigationFlash: c, sessions: g, createSession: m } =
|
|
1050
|
+
const [t, n, a] = rn("custom-analytics"), s = Ct(), o = Le(), i = We(), { t: l } = Z(), { navigationFlash: c, sessions: g, createSession: m } = mt(), p = (c == null ? void 0 : c.group) === "Custom Analytics", u = sn["Custom Analytics"], { data: N } = ie({
|
|
1051
1051
|
queryKey: ["runtime-drafts"],
|
|
1052
1052
|
queryFn: () => T.listRuntimeDrafts(),
|
|
1053
1053
|
staleTime: 3e4
|
|
@@ -1137,7 +1137,7 @@ function lr() {
|
|
|
1137
1137
|
] });
|
|
1138
1138
|
}
|
|
1139
1139
|
function cr({ group: t }) {
|
|
1140
|
-
const [n, a] = rn(t.label), { t: s } = Z(), { navigationFlash: o } =
|
|
1140
|
+
const [n, a] = rn(t.label), { t: s } = Z(), { navigationFlash: o } = mt(), i = (o == null ? void 0 : o.group) === t.label, l = sn[t.label] ?? "bg-blue-300 text-blue-950 ring-2 ring-inset ring-blue-100";
|
|
1141
1141
|
return /* @__PURE__ */ r("div", { children: [
|
|
1142
1142
|
/* @__PURE__ */ r(
|
|
1143
1143
|
"button",
|
|
@@ -1279,7 +1279,7 @@ function hr() {
|
|
|
1279
1279
|
return /* @__PURE__ */ e(rr, { children: /* @__PURE__ */ e(gr, {}) });
|
|
1280
1280
|
}
|
|
1281
1281
|
function gr() {
|
|
1282
|
-
const { pathname: t } = Ct(), n = Le(), { user: a, logout: s } = st(), { navigationFlash: o } =
|
|
1282
|
+
const { pathname: t } = Ct(), n = Le(), { user: a, logout: s } = st(), { navigationFlash: o } = mt(), { t: i } = Z(), l = mr(t, i), c = pr(t), g = () => {
|
|
1283
1283
|
var N;
|
|
1284
1284
|
c && (((N = window.history.state) == null ? void 0 : N.idx) > 0 ? n(-1) : n(c));
|
|
1285
1285
|
}, [m, p] = S(!1);
|
|
@@ -1338,7 +1338,7 @@ function gr() {
|
|
|
1338
1338
|
)
|
|
1339
1339
|
] })
|
|
1340
1340
|
] }),
|
|
1341
|
-
/* @__PURE__ */ e("main", { className: "flex-1 overflow-auto p-4 md:p-6", children: /* @__PURE__ */ e(
|
|
1341
|
+
/* @__PURE__ */ e("main", { className: "flex-1 overflow-auto p-4 md:p-6", children: /* @__PURE__ */ e(Aa, {}) })
|
|
1342
1342
|
] })
|
|
1343
1343
|
] });
|
|
1344
1344
|
}
|
|
@@ -1423,7 +1423,7 @@ function qe(t) {
|
|
|
1423
1423
|
}
|
|
1424
1424
|
return ((s = a[0]) == null ? void 0 : s.default_currency) || "USD";
|
|
1425
1425
|
}
|
|
1426
|
-
function
|
|
1426
|
+
function At({ title: t, value: n, icon: a, tone: s }) {
|
|
1427
1427
|
const o = s ?? "text-brand bg-brand/10", i = qe();
|
|
1428
1428
|
return /* @__PURE__ */ e($, { children: /* @__PURE__ */ r("div", { className: "flex items-start justify-between gap-4", children: [
|
|
1429
1429
|
/* @__PURE__ */ r("div", { className: "min-w-0", children: [
|
|
@@ -1492,7 +1492,7 @@ function Nr() {
|
|
|
1492
1492
|
/* @__PURE__ */ e(Pt, {})
|
|
1493
1493
|
] }) : /* @__PURE__ */ r(we, { children: [
|
|
1494
1494
|
/* @__PURE__ */ e(
|
|
1495
|
-
|
|
1495
|
+
At,
|
|
1496
1496
|
{
|
|
1497
1497
|
title: t("dashboard.totalRevenue"),
|
|
1498
1498
|
value: n == null ? void 0 : n.total_revenue,
|
|
@@ -1501,7 +1501,7 @@ function Nr() {
|
|
|
1501
1501
|
}
|
|
1502
1502
|
),
|
|
1503
1503
|
/* @__PURE__ */ e(
|
|
1504
|
-
|
|
1504
|
+
At,
|
|
1505
1505
|
{
|
|
1506
1506
|
title: t("dashboard.outstandingReceivable"),
|
|
1507
1507
|
value: n == null ? void 0 : n.outstanding_receivable,
|
|
@@ -1510,7 +1510,7 @@ function Nr() {
|
|
|
1510
1510
|
}
|
|
1511
1511
|
),
|
|
1512
1512
|
/* @__PURE__ */ e(
|
|
1513
|
-
|
|
1513
|
+
At,
|
|
1514
1514
|
{
|
|
1515
1515
|
title: t("dashboard.outstandingPayable"),
|
|
1516
1516
|
value: n == null ? void 0 : n.outstanding_payable,
|
|
@@ -1519,7 +1519,7 @@ function Nr() {
|
|
|
1519
1519
|
}
|
|
1520
1520
|
),
|
|
1521
1521
|
/* @__PURE__ */ e(
|
|
1522
|
-
|
|
1522
|
+
At,
|
|
1523
1523
|
{
|
|
1524
1524
|
title: t("dashboard.totalStockValue"),
|
|
1525
1525
|
value: n == null ? void 0 : n.total_stock_value,
|
|
@@ -2233,10 +2233,10 @@ const rt = [
|
|
|
2233
2233
|
function oa(t) {
|
|
2234
2234
|
return cn[t];
|
|
2235
2235
|
}
|
|
2236
|
-
function
|
|
2236
|
+
function qo(t) {
|
|
2237
2237
|
cn[t.slug] = t;
|
|
2238
2238
|
}
|
|
2239
|
-
function
|
|
2239
|
+
function zo() {
|
|
2240
2240
|
return Object.values(cn);
|
|
2241
2241
|
}
|
|
2242
2242
|
const Sr = {
|
|
@@ -2329,7 +2329,7 @@ function J({ label: t, hint: n, error: a, className: s, id: o, ...i }) {
|
|
|
2329
2329
|
)
|
|
2330
2330
|
] });
|
|
2331
2331
|
}
|
|
2332
|
-
function
|
|
2332
|
+
function Dr(t) {
|
|
2333
2333
|
return typeof t == "string" ? { value: t, label: t } : t;
|
|
2334
2334
|
}
|
|
2335
2335
|
function He({ label: t, options: n, value: a, onChange: s, className: o, required: i, disabled: l }) {
|
|
@@ -2363,7 +2363,7 @@ function He({ label: t, options: n, value: a, onChange: s, className: o, require
|
|
|
2363
2363
|
children: [
|
|
2364
2364
|
/* @__PURE__ */ e("option", { value: "", children: "Select..." }),
|
|
2365
2365
|
n.map((g) => {
|
|
2366
|
-
const { value: m, label: p } =
|
|
2366
|
+
const { value: m, label: p } = Dr(g);
|
|
2367
2367
|
return /* @__PURE__ */ e("option", { value: m, children: p }, m);
|
|
2368
2368
|
})
|
|
2369
2369
|
]
|
|
@@ -2371,7 +2371,7 @@ function He({ label: t, options: n, value: a, onChange: s, className: o, require
|
|
|
2371
2371
|
)
|
|
2372
2372
|
] });
|
|
2373
2373
|
}
|
|
2374
|
-
function
|
|
2374
|
+
function Ar({ text: t }) {
|
|
2375
2375
|
const [n, a] = S(!1);
|
|
2376
2376
|
return /* @__PURE__ */ r("span", { className: "relative ml-1 inline-flex", children: [
|
|
2377
2377
|
/* @__PURE__ */ e(
|
|
@@ -2455,7 +2455,7 @@ function Xt(t, n) {
|
|
|
2455
2455
|
function wn({ label: t, hint: n, extra: a }) {
|
|
2456
2456
|
return /* @__PURE__ */ r("label", { className: "mb-1.5 block text-sm font-medium text-fg", children: [
|
|
2457
2457
|
t,
|
|
2458
|
-
n && /* @__PURE__ */ e(
|
|
2458
|
+
n && /* @__PURE__ */ e(Ar, { text: n }),
|
|
2459
2459
|
a
|
|
2460
2460
|
] });
|
|
2461
2461
|
}
|
|
@@ -2773,7 +2773,7 @@ function kn(t, n) {
|
|
|
2773
2773
|
}
|
|
2774
2774
|
function Sn() {
|
|
2775
2775
|
var Ue;
|
|
2776
|
-
const { doctype: t, name: n } =
|
|
2776
|
+
const { doctype: t, name: n } = ut(), a = Le(), s = We(), { t: o } = Z(), i = oa(t ?? ""), l = !n, [c, g] = S({}), [m, p] = S(!1), { data: u, isLoading: N } = ie({
|
|
2777
2777
|
queryKey: ["document", t, n],
|
|
2778
2778
|
queryFn: () => T.getDocument(t, n),
|
|
2779
2779
|
enabled: !!t && !!n && !l
|
|
@@ -2844,19 +2844,19 @@ function Sn() {
|
|
|
2844
2844
|
const Re = ne.toLowerCase().replace(/\s+/g, "-");
|
|
2845
2845
|
a(`/app/${Re}/${E.name}`);
|
|
2846
2846
|
}
|
|
2847
|
-
}),
|
|
2847
|
+
}), D = Pe(
|
|
2848
2848
|
(E, ne) => {
|
|
2849
2849
|
E === "currency" && p(!0), g((Re) => {
|
|
2850
|
-
const
|
|
2851
|
-
return E === "currency" && (
|
|
2850
|
+
const De = { ...Re, [E]: ne };
|
|
2851
|
+
return E === "currency" && (De.conversion_rate = 0), kn(De, i);
|
|
2852
2852
|
});
|
|
2853
2853
|
},
|
|
2854
2854
|
[i]
|
|
2855
2855
|
), O = Pe(
|
|
2856
2856
|
(E, ne) => {
|
|
2857
2857
|
g((Re) => {
|
|
2858
|
-
const
|
|
2859
|
-
return kn(
|
|
2858
|
+
const De = { ...Re, [E]: ne };
|
|
2859
|
+
return kn(De, i);
|
|
2860
2860
|
});
|
|
2861
2861
|
},
|
|
2862
2862
|
[i]
|
|
@@ -2878,7 +2878,7 @@ function Sn() {
|
|
|
2878
2878
|
] });
|
|
2879
2879
|
if (!l && N)
|
|
2880
2880
|
return /* @__PURE__ */ e("p", { className: "text-fg-muted", children: o("common.loading") });
|
|
2881
|
-
const
|
|
2881
|
+
const A = c.docstatus ?? 0, z = !!c.discarded, Y = A >= 1 || z, re = c.currency || R, ce = Fe(c.conversion_rate ?? 1), ge = i.fields.filter((E) => !E.readOnly), _e = ge.filter((E) => E.type !== "textarea"), pe = ge.filter((E) => E.type === "textarea"), fe = i.fields.filter((E) => E.readOnly);
|
|
2882
2882
|
return /* @__PURE__ */ r("div", { className: "space-y-6", children: [
|
|
2883
2883
|
/* @__PURE__ */ r("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
2884
2884
|
/* @__PURE__ */ r("div", { className: "flex items-center gap-3", children: [
|
|
@@ -2904,7 +2904,7 @@ function Sn() {
|
|
|
2904
2904
|
isNew: l,
|
|
2905
2905
|
doctype: t,
|
|
2906
2906
|
name: n,
|
|
2907
|
-
docstatus:
|
|
2907
|
+
docstatus: A,
|
|
2908
2908
|
saving: b.isPending || d.isPending,
|
|
2909
2909
|
config: i,
|
|
2910
2910
|
discarded: z,
|
|
@@ -2923,7 +2923,7 @@ function Sn() {
|
|
|
2923
2923
|
{
|
|
2924
2924
|
field: E,
|
|
2925
2925
|
value: c[E.name],
|
|
2926
|
-
onChange: (ne) =>
|
|
2926
|
+
onChange: (ne) => D(E.name, ne),
|
|
2927
2927
|
readOnly: Y,
|
|
2928
2928
|
rowData: c,
|
|
2929
2929
|
currency: re
|
|
@@ -2935,7 +2935,7 @@ function Sn() {
|
|
|
2935
2935
|
{
|
|
2936
2936
|
field: E,
|
|
2937
2937
|
value: c[E.name],
|
|
2938
|
-
onChange: (ne) =>
|
|
2938
|
+
onChange: (ne) => D(E.name, ne),
|
|
2939
2939
|
readOnly: Y,
|
|
2940
2940
|
rowData: c,
|
|
2941
2941
|
currency: re
|
|
@@ -2993,7 +2993,7 @@ function tn(t) {
|
|
|
2993
2993
|
const n = en(t);
|
|
2994
2994
|
return new Date(n.getFullYear(), n.getMonth() + 3, 0);
|
|
2995
2995
|
}
|
|
2996
|
-
function
|
|
2996
|
+
function Dn(t) {
|
|
2997
2997
|
return new Date(t.getFullYear(), 0, 1);
|
|
2998
2998
|
}
|
|
2999
2999
|
function Et(t) {
|
|
@@ -3021,7 +3021,7 @@ const Lr = [
|
|
|
3021
3021
|
},
|
|
3022
3022
|
{
|
|
3023
3023
|
label: "This Year",
|
|
3024
|
-
range: () => [ye(
|
|
3024
|
+
range: () => [ye(Dn(/* @__PURE__ */ new Date())), ye(Et(/* @__PURE__ */ new Date()))]
|
|
3025
3025
|
},
|
|
3026
3026
|
{
|
|
3027
3027
|
label: "Last Month",
|
|
@@ -3041,7 +3041,7 @@ const Lr = [
|
|
|
3041
3041
|
label: "Last Year",
|
|
3042
3042
|
range: () => {
|
|
3043
3043
|
const t = new Date((/* @__PURE__ */ new Date()).getFullYear() - 1, 6, 1);
|
|
3044
|
-
return [ye(
|
|
3044
|
+
return [ye(Dn(t)), ye(Et(t))];
|
|
3045
3045
|
}
|
|
3046
3046
|
}
|
|
3047
3047
|
];
|
|
@@ -3096,7 +3096,7 @@ const Or = ["All", "Draft", "Submitted", "Cancelled"], qr = /* @__PURE__ */ new
|
|
|
3096
3096
|
"delivery_date",
|
|
3097
3097
|
"valid_till",
|
|
3098
3098
|
"date"
|
|
3099
|
-
]),
|
|
3099
|
+
]), An = {
|
|
3100
3100
|
customer: "customer",
|
|
3101
3101
|
supplier: "supplier",
|
|
3102
3102
|
item_code: "item",
|
|
@@ -3113,48 +3113,48 @@ function Mr(t) {
|
|
|
3113
3113
|
}
|
|
3114
3114
|
const Fr = ["25", "50", "100", "200"];
|
|
3115
3115
|
function $r() {
|
|
3116
|
-
const { t } = Z(), n = qe(), { doctype: a } =
|
|
3116
|
+
const { t } = Z(), n = qe(), { doctype: a } = ut(), s = oa(a ?? ""), [o] = ae("status", "All"), [i] = ae("from", ""), [l] = ae("to", ""), [c] = ae("discarded", ""), [g] = ae("per_page", 50), [m] = ae("page", 1), p = m - 1, u = Ye(), N = (C) => u({ page: C === 0 ? null : C + 1 }), v = (C) => u({ status: C === "All" ? null : C, page: null }), x = (C) => u({ from: C || null, page: null }), f = (C) => u({ to: C || null, page: null }), R = (C) => u({ discarded: C ? "1" : null, page: null }), P = (C) => u({ per_page: C, page: null }), b = Ce(() => {
|
|
3117
3117
|
const C = {};
|
|
3118
3118
|
return o !== "All" && (C.status = o), i && (C.from_date = i), l && (C.to_date = l), c && (C.include_discarded = "true"), C.limit = g, C.offset = p * g, C;
|
|
3119
|
-
}, [o, i, l, c, g, p]), { data: d, isLoading: h } = wr(a ?? "", b), _ = (d == null ? void 0 : d.rows) ?? [], y = (d == null ? void 0 : d.total) ?? 0, B = Math.max(1, Math.ceil(y / g)),
|
|
3119
|
+
}, [o, i, l, c, g, p]), { data: d, isLoading: h } = wr(a ?? "", b), _ = (d == null ? void 0 : d.rows) ?? [], y = (d == null ? void 0 : d.total) ?? 0, B = Math.max(1, Math.ceil(y / g)), D = y === 0 ? 0 : p * g + 1, O = Math.min(y, (p + 1) * g), G = Ce(() => {
|
|
3120
3120
|
if (!s) return [];
|
|
3121
3121
|
const C = Yn(), w = (q) => {
|
|
3122
|
-
const
|
|
3123
|
-
return t(`fields.${
|
|
3122
|
+
const A = q.split("_").map((z) => z.charAt(0).toUpperCase() + z.slice(1)).join(" ");
|
|
3123
|
+
return t(`fields.${A}`, { defaultValue: A });
|
|
3124
3124
|
};
|
|
3125
3125
|
return s.listColumns.map((q) => {
|
|
3126
3126
|
if (q === "name")
|
|
3127
3127
|
return C.accessor("name", {
|
|
3128
3128
|
header: t("fields.Name", { defaultValue: "Name" }),
|
|
3129
|
-
cell: (
|
|
3129
|
+
cell: (A) => /* @__PURE__ */ e(
|
|
3130
3130
|
be,
|
|
3131
3131
|
{
|
|
3132
|
-
to: `/app/${s.slug}/${
|
|
3132
|
+
to: `/app/${s.slug}/${A.getValue()}`,
|
|
3133
3133
|
className: "font-medium text-brand transition-colors hover:text-brand/80",
|
|
3134
|
-
children:
|
|
3134
|
+
children: A.getValue()
|
|
3135
3135
|
}
|
|
3136
3136
|
)
|
|
3137
3137
|
});
|
|
3138
3138
|
if (q === "status")
|
|
3139
3139
|
return C.accessor("status", {
|
|
3140
3140
|
header: t("fields.Status", { defaultValue: "Status" }),
|
|
3141
|
-
cell: (
|
|
3141
|
+
cell: (A) => /* @__PURE__ */ e(ln, { status: A.getValue() })
|
|
3142
3142
|
});
|
|
3143
3143
|
if (qr.has(q))
|
|
3144
3144
|
return C.accessor(q, {
|
|
3145
3145
|
header: w(q),
|
|
3146
|
-
cell: (
|
|
3146
|
+
cell: (A) => {
|
|
3147
3147
|
var z;
|
|
3148
|
-
return Oe(
|
|
3148
|
+
return Oe(A.getValue(), ((z = A.row.original) == null ? void 0 : z.currency) || n);
|
|
3149
3149
|
}
|
|
3150
3150
|
});
|
|
3151
3151
|
if (q === "party")
|
|
3152
3152
|
return C.accessor("party", {
|
|
3153
3153
|
header: t("fields.Party", { defaultValue: "Party" }),
|
|
3154
|
-
cell: (
|
|
3155
|
-
const z =
|
|
3154
|
+
cell: (A) => {
|
|
3155
|
+
const z = A.getValue();
|
|
3156
3156
|
if (!z) return "-";
|
|
3157
|
-
const Y = Mr(
|
|
3157
|
+
const Y = Mr(A.row.original.party_type), re = Y ? Xt(Y, String(z)) : null;
|
|
3158
3158
|
return re ? /* @__PURE__ */ e(
|
|
3159
3159
|
be,
|
|
3160
3160
|
{
|
|
@@ -3166,14 +3166,14 @@ function $r() {
|
|
|
3166
3166
|
) : String(z);
|
|
3167
3167
|
}
|
|
3168
3168
|
});
|
|
3169
|
-
if (
|
|
3170
|
-
const
|
|
3169
|
+
if (An[q]) {
|
|
3170
|
+
const A = An[q];
|
|
3171
3171
|
return C.accessor(q, {
|
|
3172
3172
|
header: w(q),
|
|
3173
3173
|
cell: (z) => {
|
|
3174
3174
|
const Y = z.getValue();
|
|
3175
3175
|
if (!Y) return "-";
|
|
3176
|
-
const re = Xt(
|
|
3176
|
+
const re = Xt(A, String(Y));
|
|
3177
3177
|
return re ? /* @__PURE__ */ e(
|
|
3178
3178
|
be,
|
|
3179
3179
|
{
|
|
@@ -3188,7 +3188,7 @@ function $r() {
|
|
|
3188
3188
|
}
|
|
3189
3189
|
return zr.has(q) ? C.accessor(q, {
|
|
3190
3190
|
header: w(q),
|
|
3191
|
-
cell: (
|
|
3191
|
+
cell: (A) => Ft(A.getValue())
|
|
3192
3192
|
}) : C.accessor(q, {
|
|
3193
3193
|
header: w(q)
|
|
3194
3194
|
});
|
|
@@ -3268,7 +3268,7 @@ function $r() {
|
|
|
3268
3268
|
t("common.showing"),
|
|
3269
3269
|
" ",
|
|
3270
3270
|
/* @__PURE__ */ r("span", { className: "font-medium text-fg", children: [
|
|
3271
|
-
|
|
3271
|
+
D,
|
|
3272
3272
|
"–",
|
|
3273
3273
|
O
|
|
3274
3274
|
] }),
|
|
@@ -3368,7 +3368,7 @@ function Se({
|
|
|
3368
3368
|
}, B = (O) => {
|
|
3369
3369
|
const G = O.name ?? O.id ?? String(O);
|
|
3370
3370
|
l(G), a(G), p(!1), g([]);
|
|
3371
|
-
},
|
|
3371
|
+
}, D = () => {
|
|
3372
3372
|
setTimeout(() => {
|
|
3373
3373
|
if (d.current) {
|
|
3374
3374
|
d.current = !1;
|
|
@@ -3399,7 +3399,7 @@ function Se({
|
|
|
3399
3399
|
onFocus: () => {
|
|
3400
3400
|
h(), _(i);
|
|
3401
3401
|
},
|
|
3402
|
-
onBlur:
|
|
3402
|
+
onBlur: D,
|
|
3403
3403
|
placeholder: `Search ${s}...`,
|
|
3404
3404
|
className: Ee(
|
|
3405
3405
|
"block h-9 w-full rounded-lg bg-surface px-3 text-sm text-fg ring-1 ring-line transition-all placeholder:text-fg-muted/70 focus:outline-none focus:ring-2 focus:ring-brand/30",
|
|
@@ -3435,7 +3435,7 @@ const _t = () => ({
|
|
|
3435
3435
|
is_recommended: 0
|
|
3436
3436
|
}), Ur = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
3437
3437
|
function Pn() {
|
|
3438
|
-
const { name: t } =
|
|
3438
|
+
const { name: t } = ut(), n = !t, a = Le(), s = We(), { t: o } = Z(), i = (w, q) => o(w, { defaultValue: q }), [l, c] = S({
|
|
3439
3439
|
title: "Offerte",
|
|
3440
3440
|
customer: "",
|
|
3441
3441
|
company: "",
|
|
@@ -3443,7 +3443,7 @@ function Pn() {
|
|
|
3443
3443
|
partner_name: "",
|
|
3444
3444
|
partner_email: "",
|
|
3445
3445
|
cover_letter: ""
|
|
3446
|
-
}), [g, m] = S([_t()]), [p, u] = S(null), [N, v] = S(!1), [x, f] = S(null), R = te(null), P = (w, q) => c((
|
|
3446
|
+
}), [g, m] = S([_t()]), [p, u] = S(null), [N, v] = S(!1), [x, f] = S(null), R = te(null), P = (w, q) => c((A) => ({ ...A, [w]: q })), { data: b } = ie({
|
|
3447
3447
|
queryKey: ["document", "proposal", t],
|
|
3448
3448
|
queryFn: () => T.getDocument("proposal", t),
|
|
3449
3449
|
enabled: !n
|
|
@@ -3487,14 +3487,14 @@ function Pn() {
|
|
|
3487
3487
|
s.invalidateQueries({ queryKey: ["documents", "proposal"] }), a("/app/proposal");
|
|
3488
3488
|
},
|
|
3489
3489
|
onError: (w) => f((w == null ? void 0 : w.message) ?? "Discard failed")
|
|
3490
|
-
}), B = (w, q) => m((
|
|
3490
|
+
}), B = (w, q) => m((A) => A.map((z, Y) => Y === w ? { ...z, ...q } : z)), D = () => m((w) => [...w, _t()]), O = (w) => m((q) => q.length > 1 ? q.filter((A, z) => z !== w) : q), G = (w, q) => m((A) => {
|
|
3491
3491
|
const z = w + q;
|
|
3492
|
-
if (z < 0 || z >=
|
|
3493
|
-
const Y = [...
|
|
3492
|
+
if (z < 0 || z >= A.length) return A;
|
|
3493
|
+
const Y = [...A];
|
|
3494
3494
|
return [Y[w], Y[z]] = [Y[z], Y[w]], Y;
|
|
3495
3495
|
}), ee = async (w) => {
|
|
3496
|
-
var
|
|
3497
|
-
const q = (
|
|
3496
|
+
var A;
|
|
3497
|
+
const q = (A = w.target.files) == null ? void 0 : A[0];
|
|
3498
3498
|
if (w.target.value = "", !(!q || n)) {
|
|
3499
3499
|
v(!0), f(null);
|
|
3500
3500
|
try {
|
|
@@ -3569,23 +3569,23 @@ function Pn() {
|
|
|
3569
3569
|
/* @__PURE__ */ r($, { className: "space-y-4 p-5", children: [
|
|
3570
3570
|
/* @__PURE__ */ r("div", { className: "flex items-center justify-between", children: [
|
|
3571
3571
|
/* @__PURE__ */ e("h2", { className: "font-semibold text-fg", children: i("proposal.offers", "Offers") }),
|
|
3572
|
-
/* @__PURE__ */ e(H, { size: "sm", variant: "secondary", onClick:
|
|
3572
|
+
/* @__PURE__ */ e(H, { size: "sm", variant: "secondary", onClick: D, children: i("proposal.addOffer", "Add offer") })
|
|
3573
3573
|
] }),
|
|
3574
3574
|
g.map((w, q) => /* @__PURE__ */ r("div", { className: "rounded-lg p-3 ring-1 ring-line", children: [
|
|
3575
3575
|
/* @__PURE__ */ r("div", { className: "mb-2 flex items-center gap-2", children: [
|
|
3576
3576
|
/* @__PURE__ */ e("span", { className: "flex h-6 w-6 items-center justify-center rounded-full bg-brand/10 text-sm font-bold text-brand", children: Ur[q] ?? q + 1 }),
|
|
3577
|
-
/* @__PURE__ */ e("div", { className: "flex-1", children: /* @__PURE__ */ e(Se, { label: "", value: w.quotation, onChange: (
|
|
3577
|
+
/* @__PURE__ */ e("div", { className: "flex-1", children: /* @__PURE__ */ e(Se, { label: "", value: w.quotation, onChange: (A) => B(q, { quotation: A }), linkDoctype: "quotation", readOnly: !1 }) }),
|
|
3578
3578
|
/* @__PURE__ */ e("button", { type: "button", onClick: () => G(q, -1), disabled: q === 0, className: "px-1 text-fg-muted disabled:opacity-30", children: "↑" }),
|
|
3579
3579
|
/* @__PURE__ */ e("button", { type: "button", onClick: () => G(q, 1), disabled: q === g.length - 1, className: "px-1 text-fg-muted disabled:opacity-30", children: "↓" }),
|
|
3580
3580
|
/* @__PURE__ */ e("button", { type: "button", onClick: () => O(q), className: "px-1 text-red-500 hover:text-red-700", children: "✕" })
|
|
3581
3581
|
] }),
|
|
3582
3582
|
/* @__PURE__ */ r("div", { className: "grid grid-cols-1 gap-2 pl-8 sm:grid-cols-2", children: [
|
|
3583
|
-
/* @__PURE__ */ e(J, { label: i("proposal.positionTitle", "Position title"), value: w.position_title, onChange: (
|
|
3583
|
+
/* @__PURE__ */ e(J, { label: i("proposal.positionTitle", "Position title"), value: w.position_title, onChange: (A) => B(q, { position_title: A.target.value }), placeholder: i("proposal.positionTitleHint", "defaults to the offer's first item") }),
|
|
3584
3584
|
/* @__PURE__ */ r("label", { className: "flex items-center gap-2 self-end pb-2 text-sm text-fg", children: [
|
|
3585
|
-
/* @__PURE__ */ e("input", { type: "checkbox", checked: !!w.is_recommended, onChange: (
|
|
3585
|
+
/* @__PURE__ */ e("input", { type: "checkbox", checked: !!w.is_recommended, onChange: (A) => B(q, { is_recommended: A.target.checked ? 1 : 0 }) }),
|
|
3586
3586
|
i("proposal.recommended", "Mark as recommendation")
|
|
3587
3587
|
] }),
|
|
3588
|
-
/* @__PURE__ */ e("div", { className: "sm:col-span-2", children: /* @__PURE__ */ e(J, { label: i("proposal.blurb", "Description"), value: w.position_blurb, onChange: (
|
|
3588
|
+
/* @__PURE__ */ e("div", { className: "sm:col-span-2", children: /* @__PURE__ */ e(J, { label: i("proposal.blurb", "Description"), value: w.position_blurb, onChange: (A) => B(q, { position_blurb: A.target.value }), placeholder: i("proposal.blurbHint", "defaults to the offer's notes") }) })
|
|
3589
3589
|
] })
|
|
3590
3590
|
] }, q))
|
|
3591
3591
|
] }),
|
|
@@ -3611,7 +3611,7 @@ function Pn() {
|
|
|
3611
3611
|
const Vr = ["25", "50", "100", "200"];
|
|
3612
3612
|
function Kr() {
|
|
3613
3613
|
var d;
|
|
3614
|
-
const { type: t } =
|
|
3614
|
+
const { type: t } = ut(), n = Le(), s = (d = Ct().state) == null ? void 0 : d.notice, [o] = ae("per_page", 50), [i] = ae("page", 1), l = i - 1, c = Ye(), g = (h) => c({ page: h === 0 ? null : h + 1 }), m = (h) => c({ per_page: h, page: null }), { data: p, isLoading: u } = ie({
|
|
3615
3615
|
queryKey: ["masters", t, l, o],
|
|
3616
3616
|
queryFn: () => T.listMasters(t, {
|
|
3617
3617
|
include_disabled: 1,
|
|
@@ -3626,19 +3626,19 @@ function Kr() {
|
|
|
3626
3626
|
(y) => h.accessor(y, {
|
|
3627
3627
|
header: y.split("_").map((B) => B.charAt(0).toUpperCase() + B.slice(1)).join(" "),
|
|
3628
3628
|
cell: (B) => {
|
|
3629
|
-
const
|
|
3629
|
+
const D = B.getValue();
|
|
3630
3630
|
if (y === "name") {
|
|
3631
3631
|
const O = B.row.original.disabled === 1;
|
|
3632
3632
|
return /* @__PURE__ */ e(
|
|
3633
3633
|
be,
|
|
3634
3634
|
{
|
|
3635
|
-
to: `/masters/${t}/${
|
|
3635
|
+
to: `/masters/${t}/${D}`,
|
|
3636
3636
|
className: O ? "font-medium text-fg-muted" : "font-medium text-brand transition-colors hover:text-brand/80",
|
|
3637
|
-
children:
|
|
3637
|
+
children: D
|
|
3638
3638
|
}
|
|
3639
3639
|
);
|
|
3640
3640
|
}
|
|
3641
|
-
return y === "disabled" ?
|
|
3641
|
+
return y === "disabled" ? D === 1 ? "Disabled" : "Active" : D ?? "-";
|
|
3642
3642
|
}
|
|
3643
3643
|
})
|
|
3644
3644
|
);
|
|
@@ -3803,47 +3803,47 @@ const jr = {
|
|
|
3803
3803
|
}, _n = /* @__PURE__ */ new Set(["customer", "supplier", "item", "warehouse"]);
|
|
3804
3804
|
function Tn() {
|
|
3805
3805
|
var B;
|
|
3806
|
-
const { type: t, name: n } =
|
|
3806
|
+
const { type: t, name: n } = ut(), a = Le(), s = We(), { t: o } = Z(), i = !n || n === "new", l = Gr[t ?? ""] ?? t ?? "", c = o(`masters.${t}.one`, { defaultValue: l }), g = jr[t ?? ""] ?? [], m = (D) => o(`fields.${D.label}`, { defaultValue: D.label }), [p, u] = S({}), { data: N, isLoading: v } = ie({
|
|
3807
3807
|
queryKey: ["master", t, n],
|
|
3808
3808
|
queryFn: () => T.getMaster(t, n),
|
|
3809
3809
|
enabled: !!t && !!n && !i
|
|
3810
3810
|
});
|
|
3811
3811
|
se(() => {
|
|
3812
3812
|
if (i) {
|
|
3813
|
-
const
|
|
3813
|
+
const D = {};
|
|
3814
3814
|
g.forEach((O) => {
|
|
3815
|
-
|
|
3816
|
-
}), u(
|
|
3815
|
+
D[O.name] = O.default ?? "";
|
|
3816
|
+
}), u(D);
|
|
3817
3817
|
} else N && u(N);
|
|
3818
3818
|
}, [i, N, g]);
|
|
3819
3819
|
const x = qe();
|
|
3820
3820
|
se(() => {
|
|
3821
|
-
!i || !x || g.some((
|
|
3822
|
-
const O =
|
|
3823
|
-
return O && O !== "USD" || O === x ?
|
|
3821
|
+
!i || !x || g.some((D) => D.name === "default_currency") && u((D) => {
|
|
3822
|
+
const O = D.default_currency;
|
|
3823
|
+
return O && O !== "USD" || O === x ? D : { ...D, default_currency: x };
|
|
3824
3824
|
});
|
|
3825
3825
|
}, [i, g, x]);
|
|
3826
3826
|
const f = oe({
|
|
3827
|
-
mutationFn: (
|
|
3828
|
-
onSuccess: (
|
|
3829
|
-
s.invalidateQueries({ queryKey: ["masters", t] }), a(`/masters/${t}/${
|
|
3827
|
+
mutationFn: (D) => T.createMaster(t, D),
|
|
3828
|
+
onSuccess: (D) => {
|
|
3829
|
+
s.invalidateQueries({ queryKey: ["masters", t] }), a(`/masters/${t}/${D.name}`, { replace: !0 });
|
|
3830
3830
|
}
|
|
3831
3831
|
}), R = oe({
|
|
3832
|
-
mutationFn: (
|
|
3832
|
+
mutationFn: (D) => T.updateMaster(t, n, D),
|
|
3833
3833
|
onSuccess: () => {
|
|
3834
3834
|
s.invalidateQueries({ queryKey: ["master", t, n] }), s.invalidateQueries({ queryKey: ["masters", t] });
|
|
3835
3835
|
}
|
|
3836
3836
|
}), P = oe({
|
|
3837
3837
|
mutationFn: () => T.deleteMaster(t, n),
|
|
3838
|
-
onSuccess: (
|
|
3839
|
-
if (s.invalidateQueries({ queryKey: ["masters", t] }), (
|
|
3838
|
+
onSuccess: (D) => {
|
|
3839
|
+
if (s.invalidateQueries({ queryKey: ["masters", t] }), (D == null ? void 0 : D.status) === "disabled") {
|
|
3840
3840
|
a(`/masters/${t}`, {
|
|
3841
3841
|
replace: !0,
|
|
3842
3842
|
state: {
|
|
3843
3843
|
notice: o("masterForm.disabledOnDelete", {
|
|
3844
3844
|
label: c,
|
|
3845
3845
|
name: n,
|
|
3846
|
-
reason:
|
|
3846
|
+
reason: D.reason ?? "other records"
|
|
3847
3847
|
})
|
|
3848
3848
|
}
|
|
3849
3849
|
});
|
|
@@ -3853,18 +3853,18 @@ function Tn() {
|
|
|
3853
3853
|
}
|
|
3854
3854
|
}), b = () => {
|
|
3855
3855
|
if (y.length > 0) return;
|
|
3856
|
-
const
|
|
3857
|
-
i ? f.mutate(
|
|
3856
|
+
const D = t === "company" && !p.name ? { ...p, name: p.company_name } : p;
|
|
3857
|
+
i ? f.mutate(D) : R.mutate(D);
|
|
3858
3858
|
}, d = () => {
|
|
3859
3859
|
window.confirm(o("masterForm.deleteConfirm", { label: c })) && P.mutate();
|
|
3860
|
-
}, h = (
|
|
3861
|
-
u((G) => ({ ...G, [
|
|
3860
|
+
}, h = (D, O) => {
|
|
3861
|
+
u((G) => ({ ...G, [D]: O }));
|
|
3862
3862
|
};
|
|
3863
3863
|
if (!i && v)
|
|
3864
3864
|
return /* @__PURE__ */ e("p", { className: "text-fg-muted", children: o("common.loading") });
|
|
3865
|
-
const _ = f.isPending || R.isPending, y = g.filter((
|
|
3866
|
-
if (!
|
|
3867
|
-
const O = p[
|
|
3865
|
+
const _ = f.isPending || R.isPending, y = g.filter((D) => {
|
|
3866
|
+
if (!D.required || D.readOnly || i && D.name === "name" && _n.has(t ?? "")) return !1;
|
|
3867
|
+
const O = p[D.name];
|
|
3868
3868
|
return O == null || String(O).trim() === "";
|
|
3869
3869
|
});
|
|
3870
3870
|
return /* @__PURE__ */ r("div", { className: "space-y-6", children: [
|
|
@@ -3883,55 +3883,55 @@ function Tn() {
|
|
|
3883
3883
|
(f.error || R.error || P.error) && /* @__PURE__ */ e("div", { className: "rounded-lg bg-rose-50 p-4 text-sm text-rose-700 ring-1 ring-rose-200", children: ((B = f.error ?? R.error ?? P.error) == null ? void 0 : B.message) ?? o("common.errorOccurred") }),
|
|
3884
3884
|
y.length > 0 && /* @__PURE__ */ e("div", { className: "rounded-lg bg-amber-50 p-4 text-sm text-amber-800 ring-1 ring-amber-200", children: o("masterForm.required", { fields: y.map(m).join(", ") }) }),
|
|
3885
3885
|
p.disabled === 1 && /* @__PURE__ */ e("div", { className: "rounded-lg bg-amber-50 p-4 text-sm text-amber-800 ring-1 ring-amber-200", children: o("masterForm.disabledNotice", { label: c }) }),
|
|
3886
|
-
/* @__PURE__ */ e($, { children: /* @__PURE__ */ e("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: g.map((
|
|
3887
|
-
const G =
|
|
3888
|
-
if (
|
|
3889
|
-
const w = p[
|
|
3886
|
+
/* @__PURE__ */ e($, { children: /* @__PURE__ */ e("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: g.map((D) => {
|
|
3887
|
+
const G = D.name === "name" && !i || D.readOnly, ee = D.required && !(i && D.name === "name" && _n.has(t ?? ""));
|
|
3888
|
+
if (D.type === "select" && D.options) {
|
|
3889
|
+
const w = p[D.name], q = typeof w == "string" && w !== "" && !D.options.includes(w) ? [...D.options, w] : D.options;
|
|
3890
3890
|
return /* @__PURE__ */ e("div", { children: /* @__PURE__ */ e(
|
|
3891
3891
|
He,
|
|
3892
3892
|
{
|
|
3893
|
-
label: m(
|
|
3893
|
+
label: m(D),
|
|
3894
3894
|
options: q,
|
|
3895
|
-
value: p[
|
|
3895
|
+
value: p[D.name] ?? "",
|
|
3896
3896
|
required: ee,
|
|
3897
3897
|
disabled: G,
|
|
3898
|
-
onChange: (
|
|
3898
|
+
onChange: (A) => h(D.name, A.target.value)
|
|
3899
3899
|
}
|
|
3900
|
-
) },
|
|
3900
|
+
) }, D.name);
|
|
3901
3901
|
}
|
|
3902
|
-
if (
|
|
3902
|
+
if (D.type === "textarea")
|
|
3903
3903
|
return /* @__PURE__ */ r("div", { className: "sm:col-span-2", children: [
|
|
3904
|
-
/* @__PURE__ */ e("label", { className: "mb-1.5 block text-sm font-medium text-fg", children: m(
|
|
3904
|
+
/* @__PURE__ */ e("label", { className: "mb-1.5 block text-sm font-medium text-fg", children: m(D) }),
|
|
3905
3905
|
/* @__PURE__ */ e(
|
|
3906
3906
|
"textarea",
|
|
3907
3907
|
{
|
|
3908
3908
|
className: "block w-full rounded-lg bg-surface px-3 py-2 text-sm text-fg ring-1 ring-line transition-all placeholder:text-fg-muted/70 focus:outline-none focus:ring-2 focus:ring-brand/30 disabled:bg-surface-subtle disabled:text-fg-muted",
|
|
3909
3909
|
rows: 3,
|
|
3910
|
-
value: p[
|
|
3910
|
+
value: p[D.name] ?? "",
|
|
3911
3911
|
required: ee,
|
|
3912
3912
|
readOnly: G,
|
|
3913
3913
|
disabled: G,
|
|
3914
|
-
onChange: (w) => h(
|
|
3914
|
+
onChange: (w) => h(D.name, w.target.value)
|
|
3915
3915
|
}
|
|
3916
3916
|
)
|
|
3917
|
-
] },
|
|
3918
|
-
const C =
|
|
3917
|
+
] }, D.name);
|
|
3918
|
+
const C = D.type === "number" || D.type === "currency" ? "number" : D.type === "date" ? "date" : "text";
|
|
3919
3919
|
return /* @__PURE__ */ e(
|
|
3920
3920
|
J,
|
|
3921
3921
|
{
|
|
3922
|
-
label: m(
|
|
3922
|
+
label: m(D),
|
|
3923
3923
|
type: C,
|
|
3924
|
-
step:
|
|
3924
|
+
step: D.type === "currency" ? "0.01" : void 0,
|
|
3925
3925
|
required: ee,
|
|
3926
3926
|
readOnly: G,
|
|
3927
3927
|
disabled: G,
|
|
3928
|
-
value: p[
|
|
3928
|
+
value: p[D.name] ?? "",
|
|
3929
3929
|
onChange: (w) => h(
|
|
3930
|
-
|
|
3930
|
+
D.name,
|
|
3931
3931
|
C === "number" ? parseFloat(w.target.value) || 0 : w.target.value
|
|
3932
3932
|
)
|
|
3933
3933
|
},
|
|
3934
|
-
|
|
3934
|
+
D.name
|
|
3935
3935
|
);
|
|
3936
3936
|
}) }) })
|
|
3937
3937
|
] });
|
|
@@ -4160,17 +4160,17 @@ function rs(t) {
|
|
|
4160
4160
|
}
|
|
4161
4161
|
const ss = ["25", "50", "100", "200"];
|
|
4162
4162
|
function is() {
|
|
4163
|
-
const { t } = Z(), [n] = ae("account", ""), [a] = ae("party", ""), [s] = ae("from", ""), [o] = ae("to", ""), [i] = ae("per_page", 50), [l] = ae("page", 1), c = l - 1, g = Ye(), m = (
|
|
4164
|
-
const
|
|
4165
|
-
return n && (
|
|
4166
|
-
}, [n, a, s, o, i, c]), { data: y, isLoading: B, refetch:
|
|
4163
|
+
const { t } = Z(), [n] = ae("account", ""), [a] = ae("party", ""), [s] = ae("from", ""), [o] = ae("to", ""), [i] = ae("per_page", 50), [l] = ae("page", 1), c = l - 1, g = Ye(), m = (A) => g({ page: A === 0 ? null : A + 1 }), p = (A) => g({ per_page: A, page: null }), [u, N] = S(n), [v, x] = S(a), [f, R] = S(s), [P, b] = S(o), d = qe(), h = (A) => Oe(A, d), _ = Ce(() => {
|
|
4164
|
+
const A = {};
|
|
4165
|
+
return n && (A.account = n), a && (A.party = a), s && (A.from_date = s), o && (A.to_date = o), A.limit = String(i), A.offset = String(c * i), A;
|
|
4166
|
+
}, [n, a, s, o, i, c]), { data: y, isLoading: B, refetch: D } = Qr(_), O = (y == null ? void 0 : y.rows) ?? [], G = (y == null ? void 0 : y.total) ?? 0, ee = Math.max(1, Math.ceil(G / i)), C = G === 0 ? 0 : c * i + 1, w = Math.min(G, (c + 1) * i), q = () => {
|
|
4167
4167
|
g({
|
|
4168
4168
|
account: u || null,
|
|
4169
4169
|
party: v || null,
|
|
4170
4170
|
from: f || null,
|
|
4171
4171
|
to: P || null,
|
|
4172
4172
|
page: null
|
|
4173
|
-
}),
|
|
4173
|
+
}), D();
|
|
4174
4174
|
};
|
|
4175
4175
|
return /* @__PURE__ */ r("div", { className: "space-y-4", children: [
|
|
4176
4176
|
/* @__PURE__ */ r("div", { className: "flex flex-wrap items-end gap-4", children: [
|
|
@@ -4200,7 +4200,7 @@ function is() {
|
|
|
4200
4200
|
label: t("fields.From Date", { defaultValue: "From Date" }),
|
|
4201
4201
|
type: "date",
|
|
4202
4202
|
value: f,
|
|
4203
|
-
onChange: (
|
|
4203
|
+
onChange: (A) => R(A.target.value)
|
|
4204
4204
|
}
|
|
4205
4205
|
),
|
|
4206
4206
|
/* @__PURE__ */ e(
|
|
@@ -4209,13 +4209,13 @@ function is() {
|
|
|
4209
4209
|
label: t("fields.To Date", { defaultValue: "To Date" }),
|
|
4210
4210
|
type: "date",
|
|
4211
4211
|
value: P,
|
|
4212
|
-
onChange: (
|
|
4212
|
+
onChange: (A) => b(A.target.value)
|
|
4213
4213
|
}
|
|
4214
4214
|
),
|
|
4215
4215
|
/* @__PURE__ */ e(H, { onClick: q, children: t("common.apply") })
|
|
4216
4216
|
] }),
|
|
4217
|
-
/* @__PURE__ */ e($t, { onSelect: (
|
|
4218
|
-
R(
|
|
4217
|
+
/* @__PURE__ */ e($t, { onSelect: (A, z) => {
|
|
4218
|
+
R(A), b(z), g({ from: A, to: z, page: null });
|
|
4219
4219
|
} }),
|
|
4220
4220
|
B ? /* @__PURE__ */ e("p", { className: "text-gray-500", children: t("common.loading") }) : O.length === 0 ? /* @__PURE__ */ e("p", { className: "py-8 text-center text-gray-400", children: t("reports.noEntries") }) : /* @__PURE__ */ r(we, { children: [
|
|
4221
4221
|
/* @__PURE__ */ e($, { children: /* @__PURE__ */ e("div", { className: "overflow-x-auto", children: /* @__PURE__ */ r("table", { className: "min-w-full divide-y divide-gray-200 text-sm", children: [
|
|
@@ -4229,22 +4229,22 @@ function is() {
|
|
|
4229
4229
|
/* @__PURE__ */ e("th", { className: "px-4 py-3 text-left font-medium text-gray-500", children: t("fields.Voucher Type", { defaultValue: "Voucher Type" }) }),
|
|
4230
4230
|
/* @__PURE__ */ e("th", { className: "px-4 py-3 text-left font-medium text-gray-500", children: t("fields.Voucher No", { defaultValue: "Voucher No" }) })
|
|
4231
4231
|
] }) }),
|
|
4232
|
-
/* @__PURE__ */ e("tbody", { className: "divide-y divide-gray-100", children: O.map((
|
|
4233
|
-
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-gray-500", children: Ft(
|
|
4234
|
-
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-gray-900", children:
|
|
4235
|
-
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-gray-700", children:
|
|
4236
|
-
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-right", children: h(
|
|
4237
|
-
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-right", children: h(
|
|
4238
|
-
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-right font-medium", children: h(
|
|
4239
|
-
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-gray-700", children:
|
|
4240
|
-
/* @__PURE__ */ e("td", { className: "px-4 py-2", children:
|
|
4232
|
+
/* @__PURE__ */ e("tbody", { className: "divide-y divide-gray-100", children: O.map((A, z) => /* @__PURE__ */ r("tr", { className: "hover:bg-gray-50", children: [
|
|
4233
|
+
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-gray-500", children: Ft(A.posting_date ?? A.date) }),
|
|
4234
|
+
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-gray-900", children: A.account }),
|
|
4235
|
+
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-gray-700", children: A.party ?? "-" }),
|
|
4236
|
+
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-right", children: h(A.debit) }),
|
|
4237
|
+
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-right", children: h(A.credit) }),
|
|
4238
|
+
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-right font-medium", children: h(A.balance) }),
|
|
4239
|
+
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-gray-700", children: A.voucher_type ?? "-" }),
|
|
4240
|
+
/* @__PURE__ */ e("td", { className: "px-4 py-2", children: A.voucher_type && A.voucher_no ? /* @__PURE__ */ e(
|
|
4241
4241
|
be,
|
|
4242
4242
|
{
|
|
4243
|
-
to: `/app/${rs(
|
|
4243
|
+
to: `/app/${rs(A.voucher_type)}/${A.voucher_no}`,
|
|
4244
4244
|
className: "font-medium text-blue-600 hover:text-blue-800",
|
|
4245
|
-
children:
|
|
4245
|
+
children: A.voucher_no
|
|
4246
4246
|
}
|
|
4247
|
-
) :
|
|
4247
|
+
) : A.voucher_no ?? "-" })
|
|
4248
4248
|
] }, z)) })
|
|
4249
4249
|
] }) }) }),
|
|
4250
4250
|
/* @__PURE__ */ r("div", { className: "flex flex-wrap items-center justify-between gap-3 text-sm text-gray-600", children: [
|
|
@@ -4268,9 +4268,9 @@ function is() {
|
|
|
4268
4268
|
"select",
|
|
4269
4269
|
{
|
|
4270
4270
|
value: i,
|
|
4271
|
-
onChange: (
|
|
4271
|
+
onChange: (A) => p(Number(A.target.value)),
|
|
4272
4272
|
className: "rounded border border-gray-300 bg-white px-2 py-1 text-sm",
|
|
4273
|
-
children: ss.map((
|
|
4273
|
+
children: ss.map((A) => /* @__PURE__ */ e("option", { value: A, children: A }, A))
|
|
4274
4274
|
}
|
|
4275
4275
|
)
|
|
4276
4276
|
] }),
|
|
@@ -4694,7 +4694,7 @@ return {
|
|
|
4694
4694
|
}
|
|
4695
4695
|
const da = ps();
|
|
4696
4696
|
function hs() {
|
|
4697
|
-
const t = Le(), { sessions: n, createSession: a } =
|
|
4697
|
+
const t = Le(), { sessions: n, createSession: a } = mt(), [s] = ae("report_id", ""), [o] = ae("metric", ""), [i] = ae("group_by", ""), [l] = ae("from", ""), [c] = ae("to", ""), [g] = ae("company", ""), [m, p] = S(da), [u, N] = S([]), [v, x] = S(null), [f, R] = S(""), [P, b] = S(!1), [d, h] = S(!1), [_, y] = S(""), B = te(null), D = te(""), O = te(""), G = te(0), ee = Ce(() => !o || !i ? "" : JSON.stringify(bs({
|
|
4698
4698
|
metric: o,
|
|
4699
4699
|
groupBy: i,
|
|
4700
4700
|
fromDate: l || void 0,
|
|
@@ -4714,9 +4714,9 @@ function hs() {
|
|
|
4714
4714
|
const Re = window.setTimeout(() => {
|
|
4715
4715
|
fe.terminate(), ne(new Error("Report runtime exceeded 4 seconds"));
|
|
4716
4716
|
}, 4e3);
|
|
4717
|
-
fe.onmessage = (
|
|
4717
|
+
fe.onmessage = (De) => {
|
|
4718
4718
|
var Ve, Me;
|
|
4719
|
-
window.clearTimeout(Re), fe.terminate(), B.current === fe && (B.current = null), (Ve =
|
|
4719
|
+
window.clearTimeout(Re), fe.terminate(), B.current === fe && (B.current = null), (Ve = De.data) != null && Ve.ok ? E(De.data.output) : ne(new Error(((Me = De.data) == null ? void 0 : Me.error) || "Runtime failed"));
|
|
4720
4720
|
}, fe.postMessage({
|
|
4721
4721
|
datasets: pe.datasets,
|
|
4722
4722
|
params: {},
|
|
@@ -4734,21 +4734,21 @@ function hs() {
|
|
|
4734
4734
|
};
|
|
4735
4735
|
se(() => {
|
|
4736
4736
|
let z = !1;
|
|
4737
|
-
return s ?
|
|
4737
|
+
return s ? D.current === s ? void 0 : (h(!0), R(""), T.getRuntimeDraft(s).then((Y) => {
|
|
4738
4738
|
if (z) return;
|
|
4739
4739
|
const re = JSON.stringify(Y.definition, null, 2);
|
|
4740
|
-
return
|
|
4740
|
+
return D.current = s, O.current = re, y(Y.source_chat_session_id || ""), p(re), C(re);
|
|
4741
4741
|
}).catch((Y) => {
|
|
4742
4742
|
z || (x(null), R(Y instanceof Error ? Y.message : String(Y)));
|
|
4743
4743
|
}).finally(() => {
|
|
4744
4744
|
z || h(!1);
|
|
4745
4745
|
}), () => {
|
|
4746
4746
|
z = !0;
|
|
4747
|
-
}) : (
|
|
4747
|
+
}) : (D.current = "", O.current = "", y(""), ee && (O.current = ee, p(ee), C(ee)), () => {
|
|
4748
4748
|
z = !0;
|
|
4749
4749
|
});
|
|
4750
4750
|
}, [s, ee]);
|
|
4751
|
-
const w = !!(!s && ee), q = Ce(() => ys(v), [v]),
|
|
4751
|
+
const w = !!(!s && ee), q = Ce(() => ys(v), [v]), A = async () => {
|
|
4752
4752
|
var pe;
|
|
4753
4753
|
const z = m.trim() !== O.current.trim(), Y = s || "unsaved-runtime-report", re = u.map((fe) => ({
|
|
4754
4754
|
name: fe.name,
|
|
@@ -4796,7 +4796,7 @@ function hs() {
|
|
|
4796
4796
|
"Loaded draft: ",
|
|
4797
4797
|
s
|
|
4798
4798
|
] }) : w ? /* @__PURE__ */ e("div", { className: "text-xs text-gray-500", children: "Loaded runtime report from legacy URL filters." }) : null,
|
|
4799
|
-
s ? /* @__PURE__ */ e(H, { variant: "secondary", onClick: () => void
|
|
4799
|
+
s ? /* @__PURE__ */ e(H, { variant: "secondary", onClick: () => void A(), children: "Fix In Chat" }) : null,
|
|
4800
4800
|
/* @__PURE__ */ e(H, { onClick: () => void C(), disabled: P, children: P ? "Running..." : "Run Report" })
|
|
4801
4801
|
] })
|
|
4802
4802
|
] }) }),
|
|
@@ -4925,7 +4925,7 @@ function ys(t) {
|
|
|
4925
4925
|
function bs(t) {
|
|
4926
4926
|
const n = `${vs(t.metric)} by ${fs(t.groupBy)}`, a = t.groupBy === "month" ? "helpers.monthKey" : t.groupBy === "quarter" ? "helpers.quarterKey" : "helpers.yearKey";
|
|
4927
4927
|
if (t.metric === "sales_revenue")
|
|
4928
|
-
return
|
|
4928
|
+
return bt({
|
|
4929
4929
|
title: n,
|
|
4930
4930
|
dataset: t.groupBy === "item" ? "sales_invoice_lines" : "sales_invoices",
|
|
4931
4931
|
requestName: "rows",
|
|
@@ -4942,7 +4942,7 @@ function bs(t) {
|
|
|
4942
4942
|
chartType: t.groupBy === "customer" || t.groupBy === "item" ? "bar" : "line"
|
|
4943
4943
|
});
|
|
4944
4944
|
if (t.metric === "sales_returns")
|
|
4945
|
-
return
|
|
4945
|
+
return bt({
|
|
4946
4946
|
title: n,
|
|
4947
4947
|
dataset: "sales_invoices",
|
|
4948
4948
|
requestName: "rows",
|
|
@@ -4959,7 +4959,7 @@ function bs(t) {
|
|
|
4959
4959
|
chartType: t.groupBy === "customer" ? "bar" : "line"
|
|
4960
4960
|
});
|
|
4961
4961
|
if (t.metric === "purchases")
|
|
4962
|
-
return
|
|
4962
|
+
return bt({
|
|
4963
4963
|
title: n,
|
|
4964
4964
|
dataset: t.groupBy === "item" ? "purchase_invoice_lines" : "purchase_invoices",
|
|
4965
4965
|
requestName: "rows",
|
|
@@ -4977,7 +4977,7 @@ function bs(t) {
|
|
|
4977
4977
|
});
|
|
4978
4978
|
if (t.metric === "payments_received" || t.metric === "payments_made") {
|
|
4979
4979
|
const s = t.metric === "payments_received";
|
|
4980
|
-
return
|
|
4980
|
+
return bt({
|
|
4981
4981
|
title: n,
|
|
4982
4982
|
dataset: "payments",
|
|
4983
4983
|
requestName: "rows",
|
|
@@ -4997,7 +4997,7 @@ function bs(t) {
|
|
|
4997
4997
|
}
|
|
4998
4998
|
if (t.metric === "outstanding_ar" || t.metric === "outstanding_ap") {
|
|
4999
4999
|
const s = t.metric === "outstanding_ar", o = s ? "ar_open_items" : "ap_open_items", i = s ? "customer" : "supplier", l = "outstanding_amount";
|
|
5000
|
-
return
|
|
5000
|
+
return bt({
|
|
5001
5001
|
title: n,
|
|
5002
5002
|
dataset: o,
|
|
5003
5003
|
requestName: "rows",
|
|
@@ -5013,7 +5013,7 @@ function bs(t) {
|
|
|
5013
5013
|
chartType: "bar"
|
|
5014
5014
|
});
|
|
5015
5015
|
}
|
|
5016
|
-
return t.metric === "stock_value" ?
|
|
5016
|
+
return t.metric === "stock_value" ? bt({
|
|
5017
5017
|
title: n,
|
|
5018
5018
|
dataset: "stock_balances",
|
|
5019
5019
|
requestName: "rows",
|
|
@@ -5028,7 +5028,7 @@ function bs(t) {
|
|
|
5028
5028
|
chartType: "bar"
|
|
5029
5029
|
}) : JSON.parse(da);
|
|
5030
5030
|
}
|
|
5031
|
-
function
|
|
5031
|
+
function bt(t) {
|
|
5032
5032
|
const n = Object.fromEntries(Object.entries(t.filters).filter(([, s]) => s !== void 0)), a = ["month", "quarter", "year"].includes(t.groupBy) ? `${t.timeBucket}(row.${t.keyField})` : `row.${t.keyField} || "—"`;
|
|
5033
5033
|
return {
|
|
5034
5034
|
title: t.title,
|
|
@@ -5134,7 +5134,7 @@ function Ss() {
|
|
|
5134
5134
|
email: "",
|
|
5135
5135
|
phone: "",
|
|
5136
5136
|
tax_id: ""
|
|
5137
|
-
}), m = (y) => (B) => g((
|
|
5137
|
+
}), m = (y) => (B) => g((D) => ({ ...D, [y]: B.target.value })), [p, u] = S("quick"), [N, v] = S(!1), [x, f] = S(null), R = oe({
|
|
5138
5138
|
mutationFn: () => T.createCompany({ name: s, currency: i, ...c })
|
|
5139
5139
|
}), P = oe({
|
|
5140
5140
|
mutationFn: () => T.seedDemo()
|
|
@@ -5326,7 +5326,7 @@ function Cs({ company: t }) {
|
|
|
5326
5326
|
t.default_currency && /* @__PURE__ */ e("span", { className: "shrink-0 rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-600", children: t.default_currency })
|
|
5327
5327
|
] });
|
|
5328
5328
|
}
|
|
5329
|
-
const
|
|
5329
|
+
const Ds = [
|
|
5330
5330
|
{
|
|
5331
5331
|
number: 1,
|
|
5332
5332
|
title: "Set Up Your Company",
|
|
@@ -5464,7 +5464,7 @@ const As = [
|
|
|
5464
5464
|
}
|
|
5465
5465
|
];
|
|
5466
5466
|
function ma() {
|
|
5467
|
-
const t = Le(), { sessions: n, createSession: a } =
|
|
5467
|
+
const t = Le(), { sessions: n, createSession: a } = mt();
|
|
5468
5468
|
return async (s) => {
|
|
5469
5469
|
var i;
|
|
5470
5470
|
let o = ((i = n[0]) == null ? void 0 : i.id) || "";
|
|
@@ -5478,7 +5478,7 @@ function ma() {
|
|
|
5478
5478
|
t(`/chat/${o}`, { state: { prefillMessage: s } });
|
|
5479
5479
|
};
|
|
5480
5480
|
}
|
|
5481
|
-
function
|
|
5481
|
+
function As() {
|
|
5482
5482
|
const { t } = Z(), n = ma();
|
|
5483
5483
|
return /* @__PURE__ */ e($, { className: "border-emerald-200 bg-gradient-to-br from-emerald-50 to-white", children: /* @__PURE__ */ r("div", { className: "flex flex-col gap-4 md:flex-row md:items-start", children: [
|
|
5484
5484
|
/* @__PURE__ */ e("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-emerald-100 text-lg font-bold text-emerald-700", children: "▶" }),
|
|
@@ -5704,11 +5704,11 @@ function Rs() {
|
|
|
5704
5704
|
] }),
|
|
5705
5705
|
/* @__PURE__ */ e("p", { className: "mt-4 text-sm text-gray-500", children: t("tutorial.manualIntro") })
|
|
5706
5706
|
] }),
|
|
5707
|
-
/* @__PURE__ */ e(
|
|
5707
|
+
/* @__PURE__ */ e(As, {}),
|
|
5708
5708
|
/* @__PURE__ */ e(Ps, {}),
|
|
5709
5709
|
/* @__PURE__ */ e(_s, {}),
|
|
5710
5710
|
/* @__PURE__ */ e(Ts, {}),
|
|
5711
|
-
|
|
5711
|
+
Ds.map((n) => {
|
|
5712
5712
|
var a;
|
|
5713
5713
|
return /* @__PURE__ */ e($, { children: /* @__PURE__ */ r("div", { className: "flex gap-4", children: [
|
|
5714
5714
|
/* @__PURE__ */ e("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-blue-100 text-sm font-bold text-blue-700", children: n.number }),
|
|
@@ -5809,25 +5809,25 @@ function Ln(t) {
|
|
|
5809
5809
|
});
|
|
5810
5810
|
}
|
|
5811
5811
|
function On() {
|
|
5812
|
-
const { t } = Z(), { sessionId: n } =
|
|
5812
|
+
const { t } = Z(), { sessionId: n } = ut(), a = Le(), s = Ct(), [o] = qt(), i = o.get("demo") === "1", [l, c] = S(""), [g, m] = S(""), [p, u] = S([]), [N, v] = S(""), [x, f] = S(!1), [R, P] = S("idle"), b = te(null), d = te(null), h = te([]), {
|
|
5813
5813
|
connectionStatus: _,
|
|
5814
5814
|
connectionVersion: y,
|
|
5815
5815
|
createSession: B,
|
|
5816
|
-
startDemo:
|
|
5816
|
+
startDemo: D,
|
|
5817
5817
|
completeDemoTyping: O,
|
|
5818
5818
|
loadHistory: G,
|
|
5819
5819
|
loadMoreHistory: ee,
|
|
5820
5820
|
sendMessage: C,
|
|
5821
5821
|
transcribeAudio: w,
|
|
5822
5822
|
getMessages: q,
|
|
5823
|
-
hasMoreHistory:
|
|
5823
|
+
hasMoreHistory: A,
|
|
5824
5824
|
isLoadingOlder: z,
|
|
5825
5825
|
isThinking: Y,
|
|
5826
5826
|
getDemoStatus: re,
|
|
5827
5827
|
getDemoTypingCue: ce
|
|
5828
|
-
} =
|
|
5829
|
-
vt.current = !0,
|
|
5830
|
-
vt.current = !1,
|
|
5828
|
+
} = mt(), ge = te(null), _e = te(null), pe = te(null), fe = te(null), [Ue, E] = S(0), ne = te(!1), Re = te(null), De = te(0), Ve = te(!0), Me = te(null), vt = te(!1), pt = te(null), Je = q(n), ke = _ === "connected", Te = Y(n), Ke = re(n), Qe = ce(n), Ie = i || Ke === "running", ht = A(n), it = z(n), gt = Je[Je.length - 1], I = gt ? `${gt.type}:${gt.timestamp || ""}:${gt.content}` : "empty", V = Pe(() => {
|
|
5829
|
+
vt.current = !0, pt.current !== null && window.clearTimeout(pt.current), pt.current = window.setTimeout(() => {
|
|
5830
|
+
vt.current = !1, pt.current = null;
|
|
5831
5831
|
}, 600);
|
|
5832
5832
|
}, []), W = Pe((k = "smooth") => {
|
|
5833
5833
|
const U = ge.current;
|
|
@@ -5867,14 +5867,14 @@ function On() {
|
|
|
5867
5867
|
return U.observe(k), () => U.disconnect();
|
|
5868
5868
|
}, []);
|
|
5869
5869
|
const ve = Pe(() => {
|
|
5870
|
-
if (!n || it || !
|
|
5870
|
+
if (!n || it || !ht) return;
|
|
5871
5871
|
const k = ge.current;
|
|
5872
5872
|
Me.current = k ? k.scrollHeight : null, Ve.current = !1, ee(n).catch(() => {
|
|
5873
5873
|
Me.current = null;
|
|
5874
5874
|
});
|
|
5875
|
-
}, [n, it,
|
|
5875
|
+
}, [n, it, ht, ee]), xe = te(null);
|
|
5876
5876
|
se(() => {
|
|
5877
|
-
m(""), Re.current = null,
|
|
5877
|
+
m(""), Re.current = null, De.current += 1, n && sa(n);
|
|
5878
5878
|
const k = s.state;
|
|
5879
5879
|
k != null && k.prefillMessage && xe.current !== k ? (xe.current = k, c(k.prefillMessage), window.setTimeout(() => {
|
|
5880
5880
|
var U;
|
|
@@ -5890,11 +5890,11 @@ function On() {
|
|
|
5890
5890
|
k = !0;
|
|
5891
5891
|
};
|
|
5892
5892
|
}, [n, ke, a]);
|
|
5893
|
-
const
|
|
5893
|
+
const Ae = te(G);
|
|
5894
5894
|
se(() => {
|
|
5895
|
-
|
|
5895
|
+
Ae.current = G;
|
|
5896
5896
|
}, [G]), se(() => {
|
|
5897
|
-
!n || !ke || i || Ke === "running" ||
|
|
5897
|
+
!n || !ke || i || Ke === "running" || Ae.current(n).catch(() => {
|
|
5898
5898
|
});
|
|
5899
5899
|
}, [n, ke, y, i, Ke]), se(() => {
|
|
5900
5900
|
ne.current && !Te && ke && setTimeout(() => {
|
|
@@ -5908,10 +5908,10 @@ function On() {
|
|
|
5908
5908
|
Ve.current = X < 80;
|
|
5909
5909
|
}
|
|
5910
5910
|
se(() => {
|
|
5911
|
-
!n || !ke || !i || Re.current !== n && (Re.current = n, m(""),
|
|
5911
|
+
!n || !ke || !i || Re.current !== n && (Re.current = n, m(""), D(n).catch((k) => {
|
|
5912
5912
|
Re.current = null, m(k instanceof Error ? k.message : t("chat.demoError"));
|
|
5913
5913
|
}));
|
|
5914
|
-
}, [n, ke, i,
|
|
5914
|
+
}, [n, ke, i, D]), se(() => {
|
|
5915
5915
|
!n || !i || Ke !== "complete" || (c(""), a(`/chat/${n}`, { replace: !0 }));
|
|
5916
5916
|
}, [n, i, Ke, a]);
|
|
5917
5917
|
const K = te(O);
|
|
@@ -5922,18 +5922,18 @@ function On() {
|
|
|
5922
5922
|
se(() => {
|
|
5923
5923
|
if (!Qe || !n || Ze.current === Qe.seq) return;
|
|
5924
5924
|
Ze.current = Qe.seq;
|
|
5925
|
-
const k = n, U = Qe.content, X = U.length > 0 ? Math.max(8, Qe.typingMs / U.length) : 0, de = Qe.seq, he = ++
|
|
5925
|
+
const k = n, U = Qe.content, X = U.length > 0 ? Math.max(8, Qe.typingMs / U.length) : 0, de = Qe.seq, he = ++De.current;
|
|
5926
5926
|
async function et() {
|
|
5927
5927
|
c("");
|
|
5928
|
-
for (const
|
|
5929
|
-
if (he !==
|
|
5930
|
-
c((je) => je +
|
|
5928
|
+
for (const yt of U) {
|
|
5929
|
+
if (he !== De.current) return;
|
|
5930
|
+
c((je) => je + yt), await Es(X);
|
|
5931
5931
|
}
|
|
5932
|
-
he ===
|
|
5932
|
+
he === De.current && K.current(k, de);
|
|
5933
5933
|
}
|
|
5934
5934
|
et();
|
|
5935
5935
|
}, [Qe, n]), se(() => {
|
|
5936
|
-
Ke === "complete" && (
|
|
5936
|
+
Ke === "complete" && (De.current += 1, c(""));
|
|
5937
5937
|
}, [Ke]);
|
|
5938
5938
|
const me = Pe((k) => {
|
|
5939
5939
|
if (!n) return;
|
|
@@ -5954,18 +5954,18 @@ function On() {
|
|
|
5954
5954
|
v(`"${he.name}" is too large (max 10 MB).`);
|
|
5955
5955
|
continue;
|
|
5956
5956
|
}
|
|
5957
|
-
const et = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
5957
|
+
const et = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`, yt = he.type.startsWith("image/") ? URL.createObjectURL(he) : void 0, je = { localId: et, file: he, previewUrl: yt, uploading: !0 };
|
|
5958
5958
|
de.push(je), T.uploadChatAttachment(n, he).then((lt) => {
|
|
5959
5959
|
u(
|
|
5960
|
-
(
|
|
5960
|
+
(Dt) => Dt.map(
|
|
5961
5961
|
(Nt) => Nt.localId === et ? { ...Nt, uploading: !1, uploadedId: lt.id } : Nt
|
|
5962
5962
|
)
|
|
5963
5963
|
);
|
|
5964
5964
|
}).catch((lt) => {
|
|
5965
|
-
const
|
|
5966
|
-
v(`"${he.name}": ${
|
|
5965
|
+
const Dt = (lt == null ? void 0 : lt.message) || "Upload failed";
|
|
5966
|
+
v(`"${he.name}": ${Dt}`), u(
|
|
5967
5967
|
(Nt) => Nt.map(
|
|
5968
|
-
(Ut) => Ut.localId === et ? { ...Ut, uploading: !1, error:
|
|
5968
|
+
(Ut) => Ut.localId === et ? { ...Ut, uploading: !1, error: Dt } : Ut
|
|
5969
5969
|
)
|
|
5970
5970
|
);
|
|
5971
5971
|
});
|
|
@@ -5993,7 +5993,7 @@ function On() {
|
|
|
5993
5993
|
}
|
|
5994
5994
|
U.length > 0 && (k.preventDefault(), me(U));
|
|
5995
5995
|
}, Ne = p.some((k) => k.uploading), le = p.some((k) => k.error), ue = p.filter((k) => k.uploadedId && !k.error).map((k) => k.uploadedId);
|
|
5996
|
-
function
|
|
5996
|
+
function ft() {
|
|
5997
5997
|
const k = l.trim();
|
|
5998
5998
|
if (n && !(!k && ue.length === 0) && !Ne && C(n, k, ue.length > 0 ? ue : void 0)) {
|
|
5999
5999
|
for (const U of p)
|
|
@@ -6002,7 +6002,7 @@ function On() {
|
|
|
6002
6002
|
}
|
|
6003
6003
|
}
|
|
6004
6004
|
function xt(k) {
|
|
6005
|
-
k.key === "Enter" && !k.shiftKey && (k.preventDefault(),
|
|
6005
|
+
k.key === "Enter" && !k.shiftKey && (k.preventDefault(), ft());
|
|
6006
6006
|
}
|
|
6007
6007
|
function Xe(k) {
|
|
6008
6008
|
const U = k.trim();
|
|
@@ -6025,14 +6025,14 @@ function On() {
|
|
|
6025
6025
|
d.current = U, h.current = [], U.ondataavailable = (X) => {
|
|
6026
6026
|
X.data.size > 0 && h.current.push(X.data);
|
|
6027
6027
|
}, U.onstop = async () => {
|
|
6028
|
-
var
|
|
6028
|
+
var yt;
|
|
6029
6029
|
k.getTracks().forEach((je) => je.stop());
|
|
6030
6030
|
const X = h.current;
|
|
6031
6031
|
if (h.current = [], d.current = null, X.length === 0) {
|
|
6032
6032
|
P("idle");
|
|
6033
6033
|
return;
|
|
6034
6034
|
}
|
|
6035
|
-
const de = U.mimeType || ((
|
|
6035
|
+
const de = U.mimeType || ((yt = X[0]) == null ? void 0 : yt.type) || "audio/webm", he = new Blob(X, { type: de }), et = (de.split(";")[0].split("/")[1] || "webm").toLowerCase();
|
|
6036
6036
|
P("transcribing");
|
|
6037
6037
|
try {
|
|
6038
6038
|
const je = await Ls(he), lt = await w(je, et, n);
|
|
@@ -6072,11 +6072,11 @@ function On() {
|
|
|
6072
6072
|
className: "mx-auto max-w-3xl space-y-4",
|
|
6073
6073
|
style: { paddingBottom: (Ue || 96) + 16 },
|
|
6074
6074
|
children: [
|
|
6075
|
-
(
|
|
6075
|
+
(ht || it) && Je.length > 0 && /* @__PURE__ */ e("div", { className: "flex justify-center", children: /* @__PURE__ */ e(
|
|
6076
6076
|
"button",
|
|
6077
6077
|
{
|
|
6078
6078
|
onClick: ve,
|
|
6079
|
-
disabled: it || !
|
|
6079
|
+
disabled: it || !ht,
|
|
6080
6080
|
className: "rounded-full bg-surface px-3 py-1 text-xs text-fg-muted ring-1 ring-line transition-colors hover:bg-surface-subtle hover:text-fg disabled:cursor-not-allowed disabled:opacity-60",
|
|
6081
6081
|
children: t(it ? "common.loading" : "chat.loadOlder")
|
|
6082
6082
|
}
|
|
@@ -6204,7 +6204,7 @@ function On() {
|
|
|
6204
6204
|
/* @__PURE__ */ e(
|
|
6205
6205
|
"button",
|
|
6206
6206
|
{
|
|
6207
|
-
onClick:
|
|
6207
|
+
onClick: ft,
|
|
6208
6208
|
disabled: !l.trim() && ue.length === 0 || !ke || !n || Te || Ie || Ne || le,
|
|
6209
6209
|
className: "flex h-11 w-11 shrink-0 items-center justify-center rounded-lg text-brand transition-all hover:bg-brand/10 active:translate-y-px disabled:cursor-not-allowed disabled:text-fg-muted disabled:active:translate-y-0 md:h-10 md:w-10",
|
|
6210
6210
|
children: /* @__PURE__ */ e(
|
|
@@ -6393,7 +6393,7 @@ function Fs(t, n) {
|
|
|
6393
6393
|
return s < t.length && a.push(t.slice(s)), a.length > 0 ? a : [t];
|
|
6394
6394
|
}
|
|
6395
6395
|
function $s() {
|
|
6396
|
-
const t = Le(), [n] = qt(), { user: a, login: s, register: o } = st(), { t: i } = Z(), l = n.get("invite") || "", [c, g] = S(l ? "register" : "login"), [m, p] = S(!1), [u, N] = S(!1), [v, x] = S([]), [f, R] = S(!0), [P, b] = S(""), [d, h] = S(""), [_, y] = S(""), [B,
|
|
6396
|
+
const t = Le(), [n] = qt(), { user: a, login: s, register: o } = st(), { t: i } = Z(), l = n.get("invite") || "", [c, g] = S(l ? "register" : "login"), [m, p] = S(!1), [u, N] = S(!1), [v, x] = S([]), [f, R] = S(!0), [P, b] = S(""), [d, h] = S(""), [_, y] = S(""), [B, D] = S(""), [O, G] = S("");
|
|
6397
6397
|
se(() => {
|
|
6398
6398
|
a && a.role !== "public_manager" && t("/", { replace: !0 });
|
|
6399
6399
|
}, [a, t]), se(() => {
|
|
@@ -6461,7 +6461,7 @@ function $s() {
|
|
|
6461
6461
|
label: i("login.password"),
|
|
6462
6462
|
type: "password",
|
|
6463
6463
|
value: B,
|
|
6464
|
-
onChange: (C) =>
|
|
6464
|
+
onChange: (C) => D(C.target.value),
|
|
6465
6465
|
required: !0
|
|
6466
6466
|
}
|
|
6467
6467
|
),
|
|
@@ -6609,9 +6609,9 @@ function js() {
|
|
|
6609
6609
|
}),
|
|
6610
6610
|
onSuccess: (h) => f((_) => ({ ..._, invoices: h }))
|
|
6611
6611
|
});
|
|
6612
|
-
function d(h, _, y, B,
|
|
6612
|
+
function d(h, _, y, B, D) {
|
|
6613
6613
|
const O = [...h];
|
|
6614
|
-
O[y][B] =
|
|
6614
|
+
O[y][B] = D, _(O);
|
|
6615
6615
|
}
|
|
6616
6616
|
return /* @__PURE__ */ r("div", { className: "space-y-6", children: [
|
|
6617
6617
|
/* @__PURE__ */ e("p", { className: "text-sm text-gray-500", children: "Import balances from your previous system. Each section creates the appropriate documents (Journal Entry, Stock Entry, or Invoices) and submits them automatically." }),
|
|
@@ -6917,7 +6917,7 @@ const Ws = { save: "Save", saving: "Saving...", submit: "Submit", cancel: "Cance
|
|
|
6917
6917
|
tutorial: di,
|
|
6918
6918
|
notesMarkup: ui,
|
|
6919
6919
|
coa: mi
|
|
6920
|
-
}, hi = { save: "Speichern", saving: "Speichern...", submit: "Buchen", cancel: "Abbrechen", cancelDoc: "Stornieren", cancelDocAbort: "Nicht stornieren", cancelDocConfirmBtn: "Definitiv stornieren", discardDraft: "Entwurf verwerfen", keepDraft: "Behalten", discardDraftConfirm: "Verwerfen", showDiscarded: "Verworfene anzeigen", delete: "Löschen", edit: "Bearbeiten", pdf: "PDF", addRow: "Zeile hinzufügen", loading: "Lädt...", enable: "Aktivieren", disable: "Deaktivieren", refresh: "Aktualisieren", refreshing: "Aktualisiert...", areYouSure: "Sind Sie sicher?", all: "Alle", apply: "Anwenden", new: "Neu", prev: "Zurück", next: "Weiter", perPage: "Pro Seite", page: "Seite", of: "von", showing: "Zeige", total: "Gesamt", totals: "Summen", errorOccurred: "Ein Fehler ist aufgetreten" }, gi = { title: "Sprache", help: "Wählen Sie die Sprache der Oberfläche. Ihre Auswahl wird in diesem Browser gespeichert.", label: "Sprache" }, fi = { back: "Zurück", logout: "Abmelden", openMenu: "Menü öffnen", closeMenu: "Menü schließen", new: "Neu: {{label}}" }, yi = { dashboard: "Dashboard", setup: "Unternehmenseinrichtung", tutorial: "Erste Schritte", chat: "Chat", reports: "Berichte", "trial-balance": "Rohbilanz", "general-ledger": "Hauptbuch", "stock-balance": "Lagerbestand", "profit-and-loss": "Gewinn- und Verlustrechnung", "balance-sheet": "Bilanz", "ar-aging": "Offene Posten Debitoren", "ap-aging": "Offene Posten Kreditoren", analytics: "Analysen", "chart-of-accounts": "Kontenplan" }, bi = { quotation: { one: "Angebot", other: "Angebote" }, proposal: { one: "Sammelofferte", other: "Sammelofferten" }, "sales-order": { one: "Kundenauftrag", other: "Kundenaufträge" }, "sales-invoice": { one: "Ausgangsrechnung", other: "Ausgangsrechnungen" }, "pos-invoice": { one: "Kassenbeleg", other: "Kassenbelege" }, "purchase-order": { one: "Bestellung", other: "Bestellungen" }, "purchase-invoice": { one: "Eingangsrechnung", other: "Eingangsrechnungen" }, "payment-entry": { one: "Zahlung", other: "Zahlungen" }, "journal-entry": { one: "Buchungssatz", other: "Buchungssätze" }, "bank-transaction": { one: "Banktransaktion", other: "Banktransaktionen" }, budget: { one: "Budget", other: "Budgets" }, subscription: { one: "Abonnement", other: "Abonnements" }, "stock-entry": { one: "Lagerbuchung", other: "Lagerbuchungen" }, "delivery-note": { one: "Lieferschein", other: "Lieferscheine" }, "purchase-receipt": { one: "Wareneingang", other: "Wareneingänge" }, "pricing-rule": { one: "Preisregel", other: "Preisregeln" } }, vi = { company: { one: "Unternehmen", other: "Unternehmen" }, customer: { one: "Kunde", other: "Kunden" }, supplier: { one: "Lieferant", other: "Lieferanten" }, item: { one: "Artikel", other: "Artikel" }, warehouse: { one: "Lager", other: "Lager" } }, xi = { chats: "Chats", newChat: "Neuer Chat", deleteChat: "Chat löschen", customAnalytics: "Eigene Analysen", newAnalytics: "Neue Analyse", deleteReport: "Bericht löschen", groups: { Introduction: "Einführung", Selling: "Verkauf", Buying: "Einkauf", Accounting: "Buchhaltung", Stock: "Lager", Reports: "Berichte", Masters: "Stammdaten", Settings: "Einstellungen" }, items: { "Getting Started": "Erste Schritte", "Company Setup": "Unternehmenseinrichtung", "Opening Balances": "Eröffnungsbilanzen", Quotation: "Angebot", Proposal: "Sammelofferte", "Sales Order": "Kundenauftrag", "Sales Invoice": "Ausgangsrechnung", "POS Invoice": "Kassenbeleg", "Purchase Order": "Bestellung", "Purchase Invoice": "Eingangsrechnung", "Payment Entry": "Zahlung", "Journal Entry": "Buchungssatz", "Bank Transaction": "Banktransaktion", Budget: "Budget", Subscription: "Abonnement", "Stock Entry": "Lagerbuchung", "Delivery Note": "Lieferschein", "Purchase Receipt": "Wareneingang", "Trial Balance": "Rohbilanz", "Profit & Loss": "Gewinn- und Verlustrechnung", "Balance Sheet": "Bilanz", "General Ledger": "Hauptbuch", "AR Aging": "Offene Posten Debitoren", "AP Aging": "Offene Posten Kreditoren", Analytics: "Analysen", "Stock Balance": "Lagerbestand", Company: "Unternehmen", Customer: "Kunde", Supplier: "Lieferant", Item: "Artikel", Warehouse: "Lager", General: "Allgemein", "Pricing Rule": "Preisregel", "Users & Team": "Benutzer & Team", "Chart of Accounts": "Kontenplan" } }, Ni = { taglineFirstRun: "Erstellen Sie Ihr Administratorkonto, um zu beginnen", taglineRegister: "Erstellen Sie Ihr Konto", taglineSignIn: "Melden Sie sich bei Ihrem Konto an", demoBanner: "Der Demomodus ist aktiv. Melden Sie sich mit einem Administratorkonto an, um Einstellungen zu verwalten oder den öffentlichen Zugriff zu deaktivieren.", fullName: "Vollständiger Name", email: "E-Mail", password: "Passwort", confirmPassword: "Passwort bestätigen", createAdmin: "Administratorkonto erstellen", register: "Registrieren", signIn: "Anmelden", browsingTitle: "Nur am Stöbern?", browsingBody: "Starten Sie eine neue Chat-Sitzung und sehen Sie sich die Live-Demo an.", enterDemo: "Live-Demo starten", haveInvite: "Haben Sie eine Einladung?", noAccountPrompt: "Noch kein Konto?", registerLink: "Registrieren", alreadyHaveAccount: "Haben Sie bereits ein Konto?", signInLink: "Anmelden", passwordsNoMatch: "Passwörter stimmen nicht überein", passwordTooShort: "Das Passwort muss mindestens 6 Zeichen lang sein", registrationFailed: "Registrierung fehlgeschlagen", loginFailed: "Anmeldung fehlgeschlagen", orContinueWith: "oder weiter mit", continueWithProvider: "Weiter mit {{provider}}", oauthError: { generic: "Anmeldung fehlgeschlagen. Bitte erneut versuchen.", email_exists: "Ein Konto mit dieser E-Mail existiert bereits. Melden Sie sich an und verknüpfen Sie diesen Anbieter in den Kontoeinstellungen.", email_unverified: "Ihr Anbieter hat keine bestätigte E-Mail übermittelt, daher ist keine Anmeldung möglich.", registration_closed: "Für diese E-Mail besteht noch kein Konto und die Registrierung ist nur per Einladung möglich.", invite_invalid: "Diese Einladung ist ungültig, bereits verwendet oder für eine andere E-Mail ausgestellt.", identity_taken: "Dieses Anbieterkonto ist bereits mit einem anderen Benutzer verknüpft.", account_disabled: "Dieses Konto wurde deaktiviert.", token_exchange_failed: "Anmeldung beim Anbieter fehlgeschlagen. Bitte erneut versuchen." } }, wi = { pdfTitle: "PDF & Druck", pageSize: "Seitengröße", pdfHelp: "A4 ist international Standard (210 x 297 mm). Letter ist Standard in den USA (8,5 x 11 Zoll).", passwordTitle: "Passwort ändern", currentPassword: "Aktuelles Passwort", newPassword: "Neues Passwort", confirmNewPassword: "Neues Passwort bestätigen", changePassword: "Passwort ändern", changingPassword: "Wird geändert...", passwordChanged: "Passwort geändert.", setPasswordTitle: "Passwort festlegen", setPasswordBody: "Ihr Konto meldet sich mit Google an. Legen Sie ein Passwort fest, um sich auch mit E-Mail und Passwort anzumelden — ein praktischer Rückfall, falls Sie den Zugang zu Ihrem Google-Konto verlieren.", setPassword: "Passwort festlegen", passwordSet: "Passwort festgelegt.", linkedAccountsTitle: "Verknüpfte Konten", linkedAccountsBody: "Verknüpfen Sie ein Google- oder Apple-Konto, um sich ohne Passwort anzumelden.", linked: "Verknüpft", linkProvider: "{{provider}} verknüpfen", openingTitle: "Eröffnungsbilanzen", openingBody: "Auf der Seite Eröffnungsbilanzen können Kontensalden, Lagerbestände und offene Rechnungen aus einem früheren System importiert werden.", openingEnabled: "Derzeit aktiviert — erreichbar unter Einführung > Eröffnungsbilanzen.", openingDisabled: "Derzeit deaktiviert — die Seite ist in der Seitenleiste ausgeblendet.", signupTitle: "Öffentliche Registrierung", signupBody: "Erlauben Sie es jedem, ohne Einladung ein eigenes Konto (als Betrachter) zu erstellen. Wenn deaktiviert, können neue Benutzer nur über einen Einladungslink beitreten.", signupEnabled: "Derzeit aktiviert — jeder mit der URL kann sich als Betrachter registrieren.", signupDisabled: "Derzeit deaktiviert — die Registrierung erfolgt nur per Einladung.", chatApiTitle: "Chat-API", apiTitle: "Programmatische API", restApiBody: "Konnektoren und Skripten erlauben, dieses ERP über seine REST-API (Belege, Stammdaten, Berichte) mit denselben Bearer-API-Schlüsseln zu steuern. Standardmäßig deaktiviert.", restApiEnabled: "Derzeit aktiviert — ausgestellte Schlüssel können /api/documents, /api/masters und die übrige REST-API aufrufen.", restApiDisabled: "Derzeit deaktiviert — die REST-API akzeptiert nur das Sitzungs-Cookie; Schlüssel werden abgewiesen.", restApiDeactivateTitle: "REST-API deaktivieren?", restApiDeactivateBody: "Der Bearer-Schlüssel-Zugriff auf die REST-API wird abgeschaltet — Konnektoren und Skripte werden abgewiesen, bis Sie ihn wieder einschalten. Die Web-App (Sitzungs-Cookie) ist nicht betroffen, und Ihre API-Schlüssel werden NICHT gelöscht: Sie funktionieren wieder, sobald Sie die API erneut aktivieren.", chatApiBody: "Externen Anwendungen erlauben, über eine HTTP-API mit dem Chat-Agenten dieses ERPs zu sprechen — per Bearer-API-Schlüssel. Standardmäßig deaktiviert.", chatApiEnabled: "Derzeit aktiviert — ausgestellte Schlüssel können POST /api/v1/chat aufrufen.", chatApiDisabled: "Derzeit deaktiviert — die API liefert 404 und Schlüssel funktionieren nicht.", chatApiDeactivateTitle: "Chat-API deaktivieren?", chatApiDeactivateBody: "Die Chat-API wird abgeschaltet — jede programmatische Anfrage (Bearer-API-Schlüssel) wird abgewiesen, bis Sie sie wieder einschalten. Ihre API-Schlüssel werden NICHT gelöscht: Sie bleiben gespeichert und funktionieren wieder, sobald Sie die API erneut aktivieren.", chatApiDeactivateConfirm: "API deaktivieren", chatApiKeysTitle: "API-Schlüssel", chatApiTokenOnce: "Kopieren Sie diesen Token jetzt — er wird nicht erneut angezeigt.", chatApiCopy: "Kopieren", chatApiDismiss: "Schließen", chatApiRevoked: "widerrufen", chatApiRevoke: "Widerrufen", chatApiNoKeys: "Noch keine API-Schlüssel.", chatApiName: "Name", chatApiRole: "Rolle", chatApiCreate: "Schlüssel erstellen", chatApiWarn: "Ein Key handelt mit Ihrer Identität und höchstens Ihrer Rolle — wie ein Passwort behandeln. Erst widerrufen, dann löschen.", publicTitle: "Öffentlicher Zugriff (Demomodus)", publicActive: "Aktiv", publicActiveBody: "Der öffentliche Zugriff ist aktiviert. Jeder kann die Anwendung ohne Anmeldung nutzen. Alle Besucher erhalten Manager-Rechte.", disablePublic: "Öffentlichen Zugriff deaktivieren", disabling: "Wird deaktiviert...", publicInactiveBody: "Aktivieren Sie den öffentlichen Zugriff, damit jeder die Anwendung ohne Konto nutzen kann. Nützlich für Demos und Präsentationen. Alle Besucher erhalten Manager-Rechte und teilen sich dieselbe Identität.", enablePublic: "Öffentlichen Zugriff aktivieren", enableWarning: "Dadurch kann jeder ohne Anmeldung auf die Anwendung zugreifen. Besucher können Dokumente erstellen, bearbeiten und buchen. Ihr Administratorkonto erfordert weiterhin eine Anmeldung.", yesEnable: "Ja, aktivieren", enabling: "Wird aktiviert...", tokenSpendTitle: "Token-Ausgaben", chatApiDelete: "Löschen", chatApiYourKeys: "Ihre Schlüssel", chatApiYouBadge: "Sie", chatApiUnknownUser: "Unbekannter Benutzer", chatApiAdminAllNote: "Als Administrator enthält die Liste unten die Schlüssel aller Benutzer, nach Eigentümer gruppiert. Ihre eigenen stehen oben.", chatApiConfirmTitle: "Dieser Schlüssel gehört nicht Ihnen", chatApiConfirmRevokeBody: "„{{key}}“ gehört {{name}}. Beim Widerrufen verliert diese Person sofort den API-Zugriff. Fortfahren?", chatApiConfirmDeleteBody: "„{{key}}“ gehört {{name}}. Beim Löschen wird der Schlüssel dieser Person dauerhaft entfernt. Fortfahren?", chatApiPersonal: "Persönliche Bearer-Keys für die programmatische Chat-API. Ein Key handelt als SIE: begrenzt auf Ihre Rolle, folgt Rollenänderungen live und erlischt mit Ihrem Konto. Setzt voraus, dass der Admin die Chat-API aktiviert hat.", version: "Version {{version}}" }, ki = { Draft: "Entwurf", Open: "Offen", Submitted: "Gebucht", "To Deliver and Bill": "Zu liefern und abzurechnen", "To Deliver": "Zu liefern", "To Bill": "Abzurechnen", Completed: "Abgeschlossen", Ordered: "Bestellt", Paid: "Bezahlt", Unpaid: "Unbezahlt", Cancelled: "Storniert", Discarded: "Verworfen", Overdue: "Überfällig", Return: "Retoure", Closed: "Geschlossen" }, Si = { balanced: "AUSGEGLICHEN", imbalanced: "NICHT AUSGEGLICHEN", income: "Erträge", expenses: "Aufwendungen", totalIncome: "Summe Erträge", totalExpenses: "Summe Aufwendungen", netProfit: "Gewinn", netLoss: "Verlust", assets: "Aktiva", liabilities: "Verbindlichkeiten", equity: "Eigenkapital", totalAssets: "Summe Aktiva", totalLiabilities: "Summe Verbindlichkeiten", totalEquity: "Summe Eigenkapital", totalLiabilitiesEquity: "Summe Verbindlichkeiten + Eigenkapital", current: "Laufend", noData: "Keine Daten gefunden", noEntries: "Keine Buchungen gefunden", noStockData: "Keine Lagerdaten gefunden", noReceivables: "Keine offenen Forderungen", noPayables: "Keine offenen Verbindlichkeiten", noDocuments: "Keine Dokumente gefunden" }, Ci = { required: "Erforderlich: {{fields}}", deleteConfirm: "Diesen Datensatz löschen: {{label}}?", disabledNotice: "Dieser Datensatz ({{label}}) ist deaktiviert. Er verbleibt im System, weil andere Datensätze noch darauf verweisen.", disabledOnDelete: "{{label}} {{name}} wurde deaktiviert statt gelöscht, da er von {{reason}} referenziert wird." }, Ai = { Account: "Konto", Amount: "Betrag", Balance: "Saldo", Credit: "Haben", Debit: "Soll", Date: "Datum", Party: "Partner", "Party Type": "Partnertyp", "Voucher Type": "Belegart", "Voucher No": "Belegnr.", Invoice: "Rechnung", Customer: "Kunde", Supplier: "Lieferant", "Due Date": "Fälligkeitsdatum", Outstanding: "Offen", "Outstanding Amount": "Offener Betrag", "Item Code": "Artikelnr.", "Item Name": "Artikelname", Item: "Artikel", Warehouse: "Lager", Qty: "Menge", "Valuation Rate": "Bewertungspreis", "Stock Value": "Lagerwert", Name: "Name", Status: "Status", Company: "Unternehmen", "From Date": "Von Datum", "To Date": "Bis Datum", "As of Date": "Stichtag", "Valid Till": "Gültig bis", "Net Total": "Nettobetrag", Tax: "Steuer", "Grand Total": "Gesamtbetrag", Frequency: "Frequenz", "Notes / Terms": "Notizen / Bedingungen", "Posting Date": "Buchungsdatum", "Transaction Date": "Belegdatum", "Delivery Date": "Lieferdatum", "% Delivered": "% geliefert", "% Billed": "% abgerechnet", "Update Stock": "Lager aktualisieren", "Payment Type": "Zahlungsart", "Paid From": "Bezahlt von", "Paid To": "Bezahlt an", "Paid Amount": "Zahlbetrag", Type: "Art", Total: "Gesamt", Allocated: "Zugeordnet", Unallocated: "Nicht zugeordnet", Remark: "Bemerkung", "Total Debit": "Summe Soll", "Total Credit": "Summe Haben", "Cost Center": "Kostenstelle", "Source Warehouse": "Quelllager", "Target Warehouse": "Ziellager", Source: "Quelle", Target: "Ziel", "Incoming Value": "Eingangswert", "Outgoing Value": "Ausgangswert", Rate: "Preis", "Income Account": "Ertragskonto", "Expense Account": "Aufwandskonto", Description: "Beschreibung", "Rate (%)": "Satz (%)", Mode: "Art", Change: "Rückgeld", Currency: "Währung", Title: "Titel", Selling: "Verkauf", Buying: "Einkauf", "Discount %": "Rabatt %", "Discount Amt": "Rabattbetrag", "Min Qty": "Mindestmenge", "Valid From": "Gültig ab", "Valid Upto": "Gültig bis", Priority: "Priorität", Enabled: "Aktiviert", "Fiscal Year": "Geschäftsjahr", "Budget Amount": "Budgetbetrag", "If Exceeded": "Bei Überschreitung", Month: "Monat", "Bank Account": "Bankkonto", Deposit: "Einzahlung", Withdrawal: "Auszahlung", "Reference No": "Referenznr.", "Matched Type": "Zugeordnete Art", "Matched Doc": "Zugeordneter Beleg", "Start Date": "Startdatum", "End Date": "Enddatum", "Billing Interval": "Abrechnungsintervall", "Current Period Start": "Aktueller Periodenbeginn", "Current Period End": "Aktuelles Periodenende", "Plan Items": "Planpositionen", "Total Amount": "Gesamtbetrag", "Stock Entry Type": "Lagerbuchungsart", "Rate Or Discount": "Preis oder Rabatt", "Discount Percentage": "Rabattprozentsatz", ID: "ID", "Customer Name": "Kundenname", "Customer Group": "Kundengruppe", Territory: "Region", "Credit Limit": "Kreditlimit", Email: "E-Mail", Phone: "Telefon", Address: "Adresse", City: "Stadt", "Zip Code": "PLZ", Country: "Land", "Tax ID": "Steuernummer", "Contact Person": "Ansprechperson", "Contact Email": "E-Mail Ansprechperson", "Contact Phone": "Telefon Ansprechperson", "Supplier Name": "Lieferantenname", "Supplier Group": "Lieferantengruppe", "Item Group": "Artikelgruppe", "Stock UOM": "Lagereinheit", "Standard Rate": "Standardpreis", "Warehouse Name": "Lagername", "Company Name": "Firmenname" }, Di = { items: "Positionen", taxes: "Steuern", references: "Zahlungsreferenzen", accounts: "Kontobuchungen", payments: "Zahlungen", plans: "Planpositionen", monthly_distribution: "Monatliche Verteilung" }, Pi = { "Create Sales Order": "Kundenauftrag erstellen", "Create Sales Invoice": "Ausgangsrechnung erstellen", "Create Delivery Note": "Lieferschein erstellen", "Create Purchase Invoice": "Eingangsrechnung erstellen", "Create Purchase Receipt": "Wareneingang erstellen", "Create Credit Note": "Gutschrift erstellen", "Create Debit Note": "Lastschrift erstellen", "Create Return": "Retoure erstellen" }, _i = { totalRevenue: "Gesamtumsatz", outstandingReceivable: "Offene Forderungen", outstandingPayable: "Offene Verbindlichkeiten", totalStockValue: "Gesamter Lagerwert", recentDocuments: "Letzte Dokumente", noRecentDocuments: "Keine aktuellen Dokumente" }, Ti = { title: "Lambda ERP Chat", subtitle: "Bitten Sie mich, Dokumente zu erstellen, Daten abzurufen oder Berichte auszuführen.", s1: "Welche Kunden haben wir?", s2: "Zeig mir die Rohbilanz", s3: "Erstelle ein Angebot für 10 Bolt Pack M8", s4: "Liste alle unbezahlten Rechnungen auf", loadOlder: "Ältere Nachrichten laden", uploading: "Wird hochgeladen...", failed: "Fehlgeschlagen", remove: "Entfernen", placeholderDemo: "Live-Demo läuft...", placeholderType: "Nachricht eingeben...", placeholderConnecting: "Verbindung wird hergestellt...", attachTitle: "Datei anhängen (PDF oder Bild, max. 10 MB)", creating: "Chat wird erstellt...", dropToAttach: "Datei zum Anhängen ablegen (Bilder oder PDF, je max. 10 MB)", demoError: "Demo konnte nicht gestartet werden", voiceStart: "Sprachnachricht aufnehmen", voiceStop: "Aufnahme stoppen", voiceTranscribing: "Wird transkribiert...", micDenied: "Zugriff auf das Mikrofon wurde verweigert.", transcribeFailed: "Transkription fehlgeschlagen. Bitte erneut versuchen." }, Ri = /* @__PURE__ */ JSON.parse('{"pageTitle":"Erste Schritte mit Lambda ERP","intro":"Lambda ERP ist ein KI-natives ERP-System, bei dem die gesamte Funktionalität – etwa das Erstellen von Aufträgen, das Prüfen von Beständen und das Erfassen von Zahlungen – über eine Chat-Oberfläche zugänglich ist. Es leitet an, denkt mit und prüft alle Ihre täglichen Geschäftsaufgaben.","openChat":"KI-Chat öffnen","tipLabel":"Tipp:","topTip":"Der KI-Chat kann Ihnen auch direkte Links zu Dokumenten und herunterladbaren PDFs geben. Bitten Sie ihn einfach, ein Dokument zu erstellen oder nachzuschlagen, und er fügt anklickbare Links in seine Antwort ein.","manualIntro":"Wenn Sie genau verstehen möchten, wie die Dinge unter der Haube funktionieren, oder Dinge lieber manuell erledigen, finden Sie hier einen vollständigen Geschäftszyklus Schritt für Schritt.","caTitle":"Dynamische Analysen – Chatten Sie sich zu jedem Diagramm","caBadge":"Kernfunktion","caBody":"Brauchen Sie einen Bericht, den die Vorlagen nicht liefern? Beschreiben Sie ihn einfach im Chat. Der Assistent ruft ein Code-Spezialmodell auf, das den Bericht für Sie schreibt, ihn live über Ihre ERP-Daten ausführt und einen teilbaren Link zurückgibt. Das Diagramm oder die Tabelle wird in Sekunden gerendert und als Entwurf unter „Eigene Analysen“ in der Seitenleiste gespeichert – Sie können ihn erneut öffnen, die URL mit Kollegen teilen oder den Assistenten bitten, ihn zu verfeinern.","caTryAsking":"Versuchen Sie zu fragen (zum Vorausfüllen im Chat klicken):","caPrompt1":"Zeig mir die Top 10 Kunden nach Umsatz dieses Jahr als Balkendiagramm","caPrompt2":"Monatlicher Einkaufstrend nach Lieferant über alle Monate, x-Achse mit Lieferantennamen beschriften","caPrompt3":"Bestseller-Artikel nach Menge, mit Tabelle und Diagramm","caPrompt4":"Welche Kunden schulden mir gerade am meisten?","caTryInChat":"Im Chat ausprobieren","caOpenWorkspace":"Analyse-Arbeitsbereich öffnen","flowTitle":"Überblick Dokumentenfluss","salesCycle":"Verkaufszyklus","purchaseCycle":"Einkaufszyklus","returns":"Retouren","flowShortcut":"Abkürzung: Das Angebot kann den Kundenauftrag überspringen und direkt zur Ausgangsrechnung oder zum Lieferschein führen","legendStock":"Lagerwirkung","legendGl":"Buchungswirkung","legendCash":"Geldwirkung","legendReversal":"Stornierung","lifecycleTitle":"Dokumenten-Lebenszyklus","lcDraftLabel":"Entwurf:","lcDraftDesc":"Bearbeitbar. Keine finanzielle oder Bestandswirkung.","lcSubmittedLabel":"Gebucht:","lcSubmittedDesc":"Gesperrt. Buchungen und Lagerbuchungen werden erzeugt.","lcCancelledLabel":"Storniert:","lcCancelledDesc":"Alle Buchungen storniert. Das Dokument wird dauerhaft archiviert.","lcNoDelete":"Es gibt kein Löschen. Um einen Entwurf zu verwerfen: buchen und dann stornieren.","lcCorrect":"Um ein gebuchtes Dokument zu korrigieren: stornieren und ein neues erstellen.","readyTitle":"Sie sind startklar","readyBody1":"Sie verstehen jetzt den vollständigen Zyklus. Ein typisches Praxisszenario sieht so aus: Sie erhalten einen Kundenauftrag (Angebot → Kundenauftrag), prüfen den Bestand, kaufen, was Sie brauchen (Bestellung → Wareneingang → Eingangsrechnung → Zahlung), liefern an den Kunden (Lieferschein), stellen ihm die Rechnung (Ausgangsrechnung) und ziehen die Zahlung ein (Zahlung). Kommt etwas zurück, erstellen Sie eine Gutschrift und eine Lieferschein-Retoure, um Finanzen und Bestand umzukehren. Die Rohbilanz bestätigt, dass alles ausgeglichen ist.","readyBody2":"Sie können all dies auch über den KI-Chat per natürlicher Konversation erledigen – beschreiben Sie einfach, was Sie brauchen, und er erstellt die richtigen Dokumente für Sie.","chips":{"Quotation":"Angebot","Sales Order":"Kundenauftrag","Delivery Note":"Lieferschein","Sales Invoice":"Ausgangsrechnung","Payment Entry":"Zahlung","Purchase Order":"Bestellung","Purchase Receipt":"Wareneingang","Purchase Invoice":"Eingangsrechnung","Credit Note":"Gutschrift","DN Return":"Lieferschein-Retoure","Debit Note":"Lastschrift","Draft":"Entwurf","Submitted":"Gebucht","Cancelled":"Storniert"},"links":{"Go to Setup":"Zur Einrichtung","Customers":"Kunden","Suppliers":"Lieferanten","Items":"Artikel","Warehouses":"Lager","New Quotation":"Neues Angebot","View Quotations":"Angebote anzeigen","Stock Balance":"Lagerbestand","New Purchase Order":"Neue Bestellung","Purchase Receipts":"Wareneingänge","Purchase Invoices":"Eingangsrechnungen","Delivery Notes":"Lieferscheine","Sales Invoices":"Ausgangsrechnungen","New Payment Entry":"Neue Zahlung","New Stock Entry":"Neue Lagerbuchung","New Journal Entry":"Neuer Buchungssatz","Profit & Loss":"Gewinn- und Verlustrechnung","Balance Sheet":"Bilanz","AR Aging":"Offene Posten Debitoren","AP Aging":"Offene Posten Kreditoren","Trial Balance":"Rohbilanz","General Ledger":"Hauptbuch","Open AI Chat":"KI-Chat öffnen"},"steps":{"1":{"title":"Unternehmen einrichten","description":"Erstellen Sie ein Unternehmen mit einer Basiswährung. Dadurch wird Ihr Kontenplan generiert (30 Standardkonten in den Bereichen Aktiva, Verbindlichkeiten, Eigenkapital, Erträge und Aufwendungen) sowie eine Standard-Kostenstelle. Sie können außerdem Demodaten mit Beispielkunden, -lieferanten und -artikeln anlegen, um schnell loszulegen."},"2":{"title":"Stammdaten anlegen","description":"Bevor Sie buchen können, benötigen Sie Stammdaten. Legen Sie mindestens einen Kunden, einen Lieferanten, einen Artikel (mit Standardpreis) und ein Lager an. Wenn Sie in Schritt 1 Demodaten angelegt haben, existieren diese bereits.","tip":"Artikel haben einen Standardpreis, der beim Hinzufügen zu Dokumenten automatisch ausgefüllt wird. Sie können den Preis pro Transaktion jederzeit überschreiben."},"3":{"title":"Angebot erstellen","description":"Ein Angebot ist eine unverbindliche Offerte an einen Kunden. Wählen Sie einen Kunden, fügen Sie Positionen mit Mengen und Preisen hinzu, optional Steuerzeilen, und speichern Sie. Angebote haben keine finanzielle Auswirkung – sie erzeugen keine Buchungs- oder Lagerbewegungen. Legen Sie ein Gültigkeitsdatum fest, damit das Angebot automatisch abläuft."},"4":{"title":"Buchen und in Kundenauftrag umwandeln","description":"Öffnen Sie Ihr gespeichertes Angebot und klicken Sie auf Buchen, um es zu bestätigen. Klicken Sie dann auf „Kundenauftrag erstellen“, um es umzuwandeln. Der Kundenauftrag stellt eine bestätigte Zusage des Kunden dar. Er hat weiterhin keine finanzielle Auswirkung, reserviert aber Bestand für die Planung.","tip":"Nur gebuchte Dokumente können in den nächsten Schritt umgewandelt werden. Entwurf → Buchen → Umwandeln ist der Standardablauf. Für schnelle Geschäfte können Sie den Kundenauftrag überspringen und direkt vom Angebot zur Ausgangsrechnung oder zum Lieferschein gehen."},"5":{"title":"Bestand vor der Erfüllung prüfen","description":"Bevor Sie liefern können, prüfen Sie, ob der Artikel tatsächlich auf Lager ist. Öffnen Sie den Bericht Lagerbestand und suchen Sie den Artikel. Wenn Ihr Lager eine Menge von null aufweist, müssen Sie zunächst Bestand beschaffen – entweder über eine Bestellung (Einkauf bei einem Lieferanten) oder eine Lagerbuchung (manueller Eingang).","tip":"Dies ist ein häufiges Szenario aus der Praxis: Sie verkaufen etwas und stellen dann fest, dass Sie es erst einkaufen müssen. Das ERP unterstützt beide Abläufe."},"6":{"title":"Einkaufszyklus: Bestand bei einem Lieferanten kaufen","description":"Wenn Sie Bestand einkaufen müssen, haben Sie zwei gültige Wege. Der Standardweg ist Bestellung → Wareneingang → Eingangsrechnung: Nutzen Sie ihn, wenn die Ware vor oder getrennt von der Lieferantenrechnung eintrifft. Treffen Rechnung und Wareneingang gleichzeitig ein, können Sie die Eingangsrechnung direkt erstellen und „Lager aktualisieren“ aktivieren, sodass dasselbe Dokument sowohl den Bestand vereinnahmt als auch die Verbindlichkeit erfasst.","tip":"Verwenden Sie zuerst den Wareneingang, wenn Sie Waren getrennt erhalten. Verwenden Sie die Eingangsrechnung mit „Lager aktualisieren“, wenn ein Schritt sowohl den Bestand vereinnahmen als auch die Lieferantenrechnung buchen soll. Setzen Sie in diesem direkten Weg ein Lager in jeder Bestandszeile."},"7":{"title":"Lieferschein erstellen","description":"Nachdem Sie nun Bestand haben, kehren Sie zu Ihrem gebuchten Kundenauftrag zurück und klicken Sie auf „Lieferschein erstellen“. Setzen Sie in jeder Position das Lager (von dem die Ware versendet wird) und buchen Sie. Dadurch wird Bestand aus dem Lager ausgebucht – Ihr Lagerbestand sinkt.","tip":"Der Lieferschein ist das Versanddokument. Er reduziert den Bestand, erzeugt aber keine Rechnung. Sie können Lieferung und Rechnungsstellung getrennt vornehmen."},"8":{"title":"Ausgangsrechnung erstellen und buchen","description":"Erstellen Sie aus dem gebuchten Kundenauftrag eine Ausgangsrechnung. Beim Buchen der Rechnung werden Buchungen erzeugt: Forderungen aus Lieferungen und Leistungen werden im Soll gebucht (der Kunde schuldet Ihnen Geld) und Umsatzerlöse im Haben (erzielter Ertrag). Sind Steuern konfiguriert, wird auch die Steuerverbindlichkeit im Haben gebucht. Der offene Betrag zeigt, was der Kunde noch schuldet."},"9":{"title":"Kundenzahlungen erfassen","description":"Erstellen Sie eine Zahlung, um vom Kunden erhaltenes Geld zu erfassen. Setzen Sie die Zahlungsart auf „Receive“ (Erhalten), wählen Sie den Kunden, geben Sie den Betrag an und ordnen Sie ihn der Ausgangsrechnung zu. Sie können Teilzahlungen vornehmen – der offene Betrag der Rechnung aktualisiert sich entsprechend. Erstellen Sie weitere Zahlungen, bis die Rechnung vollständig beglichen ist.","tip":"Teilzahlungen sind üblich. Eine Rechnung über 10.000 kann jetzt mit 3.000 und später mit 7.000 bezahlt werden. Jede Zahlung reduziert den offenen Betrag."},"10":{"title":"Lagerbuchungen (manuelle Bestandsführung)","description":"Verwenden Sie Lagerbuchungen für Bestandsbewegungen, die nicht mit Ein- oder Verkäufen verbunden sind. „Material Receipt“ fügt Bestand hinzu (Eröffnungsbestände, Korrekturen). „Material Issue“ bucht Bestand aus (Abschreibungen, interner Verbrauch). „Material Transfer“ verschiebt Bestand zwischen Lägern. Jede Buchung aktualisiert das Lagerbuch mit gleitender Durchschnittsbewertung.","tip":"Verwenden Sie für eingekaufte Waren Wareneingänge statt Lagerbuchungen – sie sind mit der Bestellung verknüpft und bieten einen sauberen Prüfpfad."},"11":{"title":"Buchungssätze","description":"Buchungssätze sind manuelle buchhalterische Anpassungen – Aufwandsabgrenzungen, Korrekturen, Umgliederungen, Eröffnungsbestände. Jeder Satz muss ausgeglichene Soll- und Haben-Beträge haben (Summe Soll = Summe Haben). Verwenden Sie sie, wenn kein anderer Dokumenttyp passt."},"12":{"title":"Gehaltszahlungen","description":"Lambda ERP wickelt Gehälter über die vorhandenen Buchhaltungswerkzeuge ab. Grenzen Sie zunächst den Gehaltsaufwand ab: Erstellen Sie einen Buchungssatz, der Gehaltsaufwand im Soll und Gehaltsverbindlichkeiten im Haben für den gesamten Lohnbetrag bucht. Bezahlen Sie dann die Mitarbeiter: Erstellen Sie einen weiteren Buchungssatz (oder eine Zahlung), der Gehaltsverbindlichkeiten im Soll und Ihr Bankkonto im Haben bucht. Dieser zweistufige Prozess hält Ihre Bücher korrekt – der Aufwand wird in der richtigen Periode erfasst und der Geldabfluss separat nachverfolgt.","tip":"Sie können den KI-Assistenten bitten, dies für Sie zu erledigen: „Grenze 15.000 an Gehältern für April ab“ gefolgt von „Zahle die April-Gehälter von der Bank“. Er erstellt die richtigen Buchungssätze automatisch."},"13":{"title":"Retouren und Gutschriften","description":"Wenn ein Kunde Waren zurückgibt oder Sie eine Gutschrift ausstellen müssen, erstellen Sie eine Retoure. Retouren verwenden denselben Dokumenttyp mit negativen Mengen. Öffnen Sie eine gebuchte Ausgangsrechnung und erstellen Sie eine Gutschrift (Ausgangsrechnungs-Retoure) – dies kehrt die Buchungen um und reduziert den offenen Betrag der ursprünglichen Rechnung. Erstellen Sie für den Bestand eine Lieferschein-Retoure, um Waren zurück ins Lager zu nehmen. Auf der Einkaufsseite erstellen Sie eine Lastschrift (Eingangsrechnungs-Retoure), um eine Lieferantenrechnung umzukehren, oder eine Wareneingangs-Retoure, um Waren zurückzusenden.","tip":"Eine Gutschrift ist einfach eine Ausgangsrechnung mit is_return=1 und negativen Mengen. Dieselbe Buchungslogik läuft – negative Beträge wechseln automatisch auf die richtige Soll-/Haben-Seite. Für eine vollständige Verkaufsretoure benötigen Sie sowohl eine Gutschrift (Finanzen) als auch eine Lieferschein-Retoure (Bestand)."},"14":{"title":"Berichte ausführen","description":"Prüfen Sie Ihre Bücher. Die Gewinn- und Verlustrechnung zeigt Erträge gegenüber Aufwendungen und den Periodengewinn. Die Bilanz zeigt Ihre finanzielle Lage (Aktiva = Verbindlichkeiten + Eigenkapital). Die Offenen Posten Debitoren zeigen, wer Ihnen Geld schuldet und wie überfällig es ist. Die Offenen Posten Kreditoren zeigen, was Sie Lieferanten schulden. Die Rohbilanz überprüft die doppelte Buchführung. Das Hauptbuch zeigt jede einzelne Buchung. Der Lagerbestand zeigt den aktuellen Bestand."},"15":{"title":"Arbeiten in Fremdwährungen","description":"Ihre Bücher werden in einer einzigen Basiswährung geführt (bei der Unternehmenseinrichtung gewählt), aber Sie können in jeder Währung buchen. Setzen Sie eine Währung auf einer Rechnung oder einem Beleg – oder geben Sie einem Kunden oder Lieferanten eine Standardwährung – und der Wechselkurs für dieses Datum wird automatisch ermittelt und auf dem Dokument gespeichert. Das Dokument behält seine Beträge in seiner eigenen Währung, während das Hauptbuch stets in Ihrer Basiswährung bucht. Wenn Sie später zu einem anderen Kurs einnehmen oder zahlen, wird der realisierte Währungsgewinn oder -verlust automatisch auf ein Konto Währungsgewinn/-verlust gebucht. Sie können sogar ein Fremdwährungs-Bankguthaben halten und es später zum Kurs Ihrer Bank umrechnen – die Differenz zum Buchwert wird dann realisiert. Zum Monatsende können Sie offene Fremdwährungssalden zum Stichtagskurs neu bewerten (ein unrealisierter Gewinn/Verlust, der in der nächsten Periode storniert wird), und Sie können jeden Jahresabschluss zur Anzeige in eine andere Währung umgerechnet betrachten.","tip":"Am einfachsten geht das über den KI-Chat – probieren Sie „Erstelle eine Ausgangsrechnung für Lumiere Audio in EUR“, „Zeig mir die Bilanz in EUR“ oder „Wie hoch ist unser unrealisiertes Währungsrisiko zum Monatsende?“. Die Demodaten enthalten bereits einen EUR-Kunden (Lumiere Audio SARL), dessen Rechnung zu einem anderen Kurs eingenommen wurde, sowie eine offene EUR-Lieferantenrechnung – öffnen Sie das Hauptbuch, um die realisierten Währungsbuchungen zu sehen."}},"setupTitle":"Richten Sie Ihr Unternehmen ein — KI-geführt","setupBadge":"Hier starten","setupBody":"Sagen Sie dem Assistenten, welche Art von Unternehmen Sie führen, und er erstellt Ihren Kontenplan für Sie — zugeschnitten auf Ihre Branche, mit den passenden Konten und sinnvollen Voreinstellungen. Er erklärt jede Entscheidung und legt erst dann etwas an, wenn Sie zustimmen.","setupSectors":"Zugeschnitten auf Dienstleistungen, Einzelhandel & POS, Gastronomie, Großhandel & Distribution, Import/Export, Fertigung und Bauwesen.","setupGetStarted":"Im Chat loslegen","setupManual":"Lieber ein manuelles Formular? Nutzen Sie die klassische Einrichtung.","setupManualLink":"Klassische Einrichtung","setupPrompt":"Ich möchte mein Unternehmen einrichten. Können Sie mich durch den Prozess führen?"}'), Ii = { title: "Formatierungshilfe", intro: "Der Text unter Notizen / Konditionen unterstützt eine einfache Formatierung im PDF:", heading: "fette Überschrift", emphasis: "kursiv / fett", rule: "horizontale Trennlinie", price: "rechtsbündiger Preis neben dem Text darüber (z. B. Monatlich | CHF 380.—)", block: "Trennen Sie Blöcke durch eine Leerzeile." }, Bi = { period: "Periode", allTime: "Gesamter Zeitraum", semantics: "Bilanzkonten: Saldo per Periodenende. Erfolgskonten: Bewegung innerhalb der Periode. Konto anklicken für den Kontoauszug.", empty: "Keine Konten gefunden. Zuerst die Firmeneinrichtung abschliessen.", disabled: "deaktiviert", rootType: { Asset: "Aktiven", Liability: "Passiven", Equity: "Eigenkapital", Income: "Ertrag", Expense: "Aufwand" } }, Ei = {
|
|
6920
|
+
}, hi = { save: "Speichern", saving: "Speichern...", submit: "Buchen", cancel: "Abbrechen", cancelDoc: "Stornieren", cancelDocAbort: "Nicht stornieren", cancelDocConfirmBtn: "Definitiv stornieren", discardDraft: "Entwurf verwerfen", keepDraft: "Behalten", discardDraftConfirm: "Verwerfen", showDiscarded: "Verworfene anzeigen", delete: "Löschen", edit: "Bearbeiten", pdf: "PDF", addRow: "Zeile hinzufügen", loading: "Lädt...", enable: "Aktivieren", disable: "Deaktivieren", refresh: "Aktualisieren", refreshing: "Aktualisiert...", areYouSure: "Sind Sie sicher?", all: "Alle", apply: "Anwenden", new: "Neu", prev: "Zurück", next: "Weiter", perPage: "Pro Seite", page: "Seite", of: "von", showing: "Zeige", total: "Gesamt", totals: "Summen", errorOccurred: "Ein Fehler ist aufgetreten" }, gi = { title: "Sprache", help: "Wählen Sie die Sprache der Oberfläche. Ihre Auswahl wird in diesem Browser gespeichert.", label: "Sprache" }, fi = { back: "Zurück", logout: "Abmelden", openMenu: "Menü öffnen", closeMenu: "Menü schließen", new: "Neu: {{label}}" }, yi = { dashboard: "Dashboard", setup: "Unternehmenseinrichtung", tutorial: "Erste Schritte", chat: "Chat", reports: "Berichte", "trial-balance": "Rohbilanz", "general-ledger": "Hauptbuch", "stock-balance": "Lagerbestand", "profit-and-loss": "Gewinn- und Verlustrechnung", "balance-sheet": "Bilanz", "ar-aging": "Offene Posten Debitoren", "ap-aging": "Offene Posten Kreditoren", analytics: "Analysen", "chart-of-accounts": "Kontenplan" }, bi = { quotation: { one: "Angebot", other: "Angebote" }, proposal: { one: "Sammelofferte", other: "Sammelofferten" }, "sales-order": { one: "Kundenauftrag", other: "Kundenaufträge" }, "sales-invoice": { one: "Ausgangsrechnung", other: "Ausgangsrechnungen" }, "pos-invoice": { one: "Kassenbeleg", other: "Kassenbelege" }, "purchase-order": { one: "Bestellung", other: "Bestellungen" }, "purchase-invoice": { one: "Eingangsrechnung", other: "Eingangsrechnungen" }, "payment-entry": { one: "Zahlung", other: "Zahlungen" }, "journal-entry": { one: "Buchungssatz", other: "Buchungssätze" }, "bank-transaction": { one: "Banktransaktion", other: "Banktransaktionen" }, budget: { one: "Budget", other: "Budgets" }, subscription: { one: "Abonnement", other: "Abonnements" }, "stock-entry": { one: "Lagerbuchung", other: "Lagerbuchungen" }, "delivery-note": { one: "Lieferschein", other: "Lieferscheine" }, "purchase-receipt": { one: "Wareneingang", other: "Wareneingänge" }, "pricing-rule": { one: "Preisregel", other: "Preisregeln" } }, vi = { company: { one: "Unternehmen", other: "Unternehmen" }, customer: { one: "Kunde", other: "Kunden" }, supplier: { one: "Lieferant", other: "Lieferanten" }, item: { one: "Artikel", other: "Artikel" }, warehouse: { one: "Lager", other: "Lager" } }, xi = { chats: "Chats", newChat: "Neuer Chat", deleteChat: "Chat löschen", customAnalytics: "Eigene Analysen", newAnalytics: "Neue Analyse", deleteReport: "Bericht löschen", groups: { Introduction: "Einführung", Selling: "Verkauf", Buying: "Einkauf", Accounting: "Buchhaltung", Stock: "Lager", Reports: "Berichte", Masters: "Stammdaten", Settings: "Einstellungen" }, items: { "Getting Started": "Erste Schritte", "Company Setup": "Unternehmenseinrichtung", "Opening Balances": "Eröffnungsbilanzen", Quotation: "Angebot", Proposal: "Sammelofferte", "Sales Order": "Kundenauftrag", "Sales Invoice": "Ausgangsrechnung", "POS Invoice": "Kassenbeleg", "Purchase Order": "Bestellung", "Purchase Invoice": "Eingangsrechnung", "Payment Entry": "Zahlung", "Journal Entry": "Buchungssatz", "Bank Transaction": "Banktransaktion", Budget: "Budget", Subscription: "Abonnement", "Stock Entry": "Lagerbuchung", "Delivery Note": "Lieferschein", "Purchase Receipt": "Wareneingang", "Trial Balance": "Rohbilanz", "Profit & Loss": "Gewinn- und Verlustrechnung", "Balance Sheet": "Bilanz", "General Ledger": "Hauptbuch", "AR Aging": "Offene Posten Debitoren", "AP Aging": "Offene Posten Kreditoren", Analytics: "Analysen", "Stock Balance": "Lagerbestand", Company: "Unternehmen", Customer: "Kunde", Supplier: "Lieferant", Item: "Artikel", Warehouse: "Lager", General: "Allgemein", "Pricing Rule": "Preisregel", "Users & Team": "Benutzer & Team", "Chart of Accounts": "Kontenplan" } }, Ni = { taglineFirstRun: "Erstellen Sie Ihr Administratorkonto, um zu beginnen", taglineRegister: "Erstellen Sie Ihr Konto", taglineSignIn: "Melden Sie sich bei Ihrem Konto an", demoBanner: "Der Demomodus ist aktiv. Melden Sie sich mit einem Administratorkonto an, um Einstellungen zu verwalten oder den öffentlichen Zugriff zu deaktivieren.", fullName: "Vollständiger Name", email: "E-Mail", password: "Passwort", confirmPassword: "Passwort bestätigen", createAdmin: "Administratorkonto erstellen", register: "Registrieren", signIn: "Anmelden", browsingTitle: "Nur am Stöbern?", browsingBody: "Starten Sie eine neue Chat-Sitzung und sehen Sie sich die Live-Demo an.", enterDemo: "Live-Demo starten", haveInvite: "Haben Sie eine Einladung?", noAccountPrompt: "Noch kein Konto?", registerLink: "Registrieren", alreadyHaveAccount: "Haben Sie bereits ein Konto?", signInLink: "Anmelden", passwordsNoMatch: "Passwörter stimmen nicht überein", passwordTooShort: "Das Passwort muss mindestens 6 Zeichen lang sein", registrationFailed: "Registrierung fehlgeschlagen", loginFailed: "Anmeldung fehlgeschlagen", orContinueWith: "oder weiter mit", continueWithProvider: "Weiter mit {{provider}}", oauthError: { generic: "Anmeldung fehlgeschlagen. Bitte erneut versuchen.", email_exists: "Ein Konto mit dieser E-Mail existiert bereits. Melden Sie sich an und verknüpfen Sie diesen Anbieter in den Kontoeinstellungen.", email_unverified: "Ihr Anbieter hat keine bestätigte E-Mail übermittelt, daher ist keine Anmeldung möglich.", registration_closed: "Für diese E-Mail besteht noch kein Konto und die Registrierung ist nur per Einladung möglich.", invite_invalid: "Diese Einladung ist ungültig, bereits verwendet oder für eine andere E-Mail ausgestellt.", identity_taken: "Dieses Anbieterkonto ist bereits mit einem anderen Benutzer verknüpft.", account_disabled: "Dieses Konto wurde deaktiviert.", token_exchange_failed: "Anmeldung beim Anbieter fehlgeschlagen. Bitte erneut versuchen." } }, wi = { pdfTitle: "PDF & Druck", pageSize: "Seitengröße", pdfHelp: "A4 ist international Standard (210 x 297 mm). Letter ist Standard in den USA (8,5 x 11 Zoll).", passwordTitle: "Passwort ändern", currentPassword: "Aktuelles Passwort", newPassword: "Neues Passwort", confirmNewPassword: "Neues Passwort bestätigen", changePassword: "Passwort ändern", changingPassword: "Wird geändert...", passwordChanged: "Passwort geändert.", setPasswordTitle: "Passwort festlegen", setPasswordBody: "Ihr Konto meldet sich mit Google an. Legen Sie ein Passwort fest, um sich auch mit E-Mail und Passwort anzumelden — ein praktischer Rückfall, falls Sie den Zugang zu Ihrem Google-Konto verlieren.", setPassword: "Passwort festlegen", passwordSet: "Passwort festgelegt.", linkedAccountsTitle: "Verknüpfte Konten", linkedAccountsBody: "Verknüpfen Sie ein Google- oder Apple-Konto, um sich ohne Passwort anzumelden.", linked: "Verknüpft", linkProvider: "{{provider}} verknüpfen", openingTitle: "Eröffnungsbilanzen", openingBody: "Auf der Seite Eröffnungsbilanzen können Kontensalden, Lagerbestände und offene Rechnungen aus einem früheren System importiert werden.", openingEnabled: "Derzeit aktiviert — erreichbar unter Einführung > Eröffnungsbilanzen.", openingDisabled: "Derzeit deaktiviert — die Seite ist in der Seitenleiste ausgeblendet.", signupTitle: "Öffentliche Registrierung", signupBody: "Erlauben Sie es jedem, ohne Einladung ein eigenes Konto (als Betrachter) zu erstellen. Wenn deaktiviert, können neue Benutzer nur über einen Einladungslink beitreten.", signupEnabled: "Derzeit aktiviert — jeder mit der URL kann sich als Betrachter registrieren.", signupDisabled: "Derzeit deaktiviert — die Registrierung erfolgt nur per Einladung.", chatApiTitle: "Chat-API", apiTitle: "Programmatische API", restApiBody: "Konnektoren und Skripten erlauben, dieses ERP über seine REST-API (Belege, Stammdaten, Berichte) mit denselben Bearer-API-Schlüsseln zu steuern. Standardmäßig deaktiviert.", restApiEnabled: "Derzeit aktiviert — ausgestellte Schlüssel können /api/documents, /api/masters und die übrige REST-API aufrufen.", restApiDisabled: "Derzeit deaktiviert — die REST-API akzeptiert nur das Sitzungs-Cookie; Schlüssel werden abgewiesen.", restApiDeactivateTitle: "REST-API deaktivieren?", restApiDeactivateBody: "Der Bearer-Schlüssel-Zugriff auf die REST-API wird abgeschaltet — Konnektoren und Skripte werden abgewiesen, bis Sie ihn wieder einschalten. Die Web-App (Sitzungs-Cookie) ist nicht betroffen, und Ihre API-Schlüssel werden NICHT gelöscht: Sie funktionieren wieder, sobald Sie die API erneut aktivieren.", chatApiBody: "Externen Anwendungen erlauben, über eine HTTP-API mit dem Chat-Agenten dieses ERPs zu sprechen — per Bearer-API-Schlüssel. Standardmäßig deaktiviert.", chatApiEnabled: "Derzeit aktiviert — ausgestellte Schlüssel können POST /api/v1/chat aufrufen.", chatApiDisabled: "Derzeit deaktiviert — die API liefert 404 und Schlüssel funktionieren nicht.", chatApiDeactivateTitle: "Chat-API deaktivieren?", chatApiDeactivateBody: "Die Chat-API wird abgeschaltet — jede programmatische Anfrage (Bearer-API-Schlüssel) wird abgewiesen, bis Sie sie wieder einschalten. Ihre API-Schlüssel werden NICHT gelöscht: Sie bleiben gespeichert und funktionieren wieder, sobald Sie die API erneut aktivieren.", chatApiDeactivateConfirm: "API deaktivieren", chatApiKeysTitle: "API-Schlüssel", chatApiTokenOnce: "Kopieren Sie diesen Token jetzt — er wird nicht erneut angezeigt.", chatApiCopy: "Kopieren", chatApiDismiss: "Schließen", chatApiRevoked: "widerrufen", chatApiRevoke: "Widerrufen", chatApiNoKeys: "Noch keine API-Schlüssel.", chatApiName: "Name", chatApiRole: "Rolle", chatApiCreate: "Schlüssel erstellen", chatApiWarn: "Ein Key handelt mit Ihrer Identität und höchstens Ihrer Rolle — wie ein Passwort behandeln. Erst widerrufen, dann löschen.", publicTitle: "Öffentlicher Zugriff (Demomodus)", publicActive: "Aktiv", publicActiveBody: "Der öffentliche Zugriff ist aktiviert. Jeder kann die Anwendung ohne Anmeldung nutzen. Alle Besucher erhalten Manager-Rechte.", disablePublic: "Öffentlichen Zugriff deaktivieren", disabling: "Wird deaktiviert...", publicInactiveBody: "Aktivieren Sie den öffentlichen Zugriff, damit jeder die Anwendung ohne Konto nutzen kann. Nützlich für Demos und Präsentationen. Alle Besucher erhalten Manager-Rechte und teilen sich dieselbe Identität.", enablePublic: "Öffentlichen Zugriff aktivieren", enableWarning: "Dadurch kann jeder ohne Anmeldung auf die Anwendung zugreifen. Besucher können Dokumente erstellen, bearbeiten und buchen. Ihr Administratorkonto erfordert weiterhin eine Anmeldung.", yesEnable: "Ja, aktivieren", enabling: "Wird aktiviert...", tokenSpendTitle: "Token-Ausgaben", chatApiDelete: "Löschen", chatApiYourKeys: "Ihre Schlüssel", chatApiYouBadge: "Sie", chatApiUnknownUser: "Unbekannter Benutzer", chatApiAdminAllNote: "Als Administrator enthält die Liste unten die Schlüssel aller Benutzer, nach Eigentümer gruppiert. Ihre eigenen stehen oben.", chatApiConfirmTitle: "Dieser Schlüssel gehört nicht Ihnen", chatApiConfirmRevokeBody: "„{{key}}“ gehört {{name}}. Beim Widerrufen verliert diese Person sofort den API-Zugriff. Fortfahren?", chatApiConfirmDeleteBody: "„{{key}}“ gehört {{name}}. Beim Löschen wird der Schlüssel dieser Person dauerhaft entfernt. Fortfahren?", chatApiPersonal: "Persönliche Bearer-Keys für die programmatische Chat-API. Ein Key handelt als SIE: begrenzt auf Ihre Rolle, folgt Rollenänderungen live und erlischt mit Ihrem Konto. Setzt voraus, dass der Admin die Chat-API aktiviert hat.", version: "Version {{version}}" }, ki = { Draft: "Entwurf", Open: "Offen", Submitted: "Gebucht", "To Deliver and Bill": "Zu liefern und abzurechnen", "To Deliver": "Zu liefern", "To Bill": "Abzurechnen", Completed: "Abgeschlossen", Ordered: "Bestellt", Paid: "Bezahlt", Unpaid: "Unbezahlt", Cancelled: "Storniert", Discarded: "Verworfen", Overdue: "Überfällig", Return: "Retoure", Closed: "Geschlossen" }, Si = { balanced: "AUSGEGLICHEN", imbalanced: "NICHT AUSGEGLICHEN", income: "Erträge", expenses: "Aufwendungen", totalIncome: "Summe Erträge", totalExpenses: "Summe Aufwendungen", netProfit: "Gewinn", netLoss: "Verlust", assets: "Aktiva", liabilities: "Verbindlichkeiten", equity: "Eigenkapital", totalAssets: "Summe Aktiva", totalLiabilities: "Summe Verbindlichkeiten", totalEquity: "Summe Eigenkapital", totalLiabilitiesEquity: "Summe Verbindlichkeiten + Eigenkapital", current: "Laufend", noData: "Keine Daten gefunden", noEntries: "Keine Buchungen gefunden", noStockData: "Keine Lagerdaten gefunden", noReceivables: "Keine offenen Forderungen", noPayables: "Keine offenen Verbindlichkeiten", noDocuments: "Keine Dokumente gefunden" }, Ci = { required: "Erforderlich: {{fields}}", deleteConfirm: "Diesen Datensatz löschen: {{label}}?", disabledNotice: "Dieser Datensatz ({{label}}) ist deaktiviert. Er verbleibt im System, weil andere Datensätze noch darauf verweisen.", disabledOnDelete: "{{label}} {{name}} wurde deaktiviert statt gelöscht, da er von {{reason}} referenziert wird." }, Di = { Account: "Konto", Amount: "Betrag", Balance: "Saldo", Credit: "Haben", Debit: "Soll", Date: "Datum", Party: "Partner", "Party Type": "Partnertyp", "Voucher Type": "Belegart", "Voucher No": "Belegnr.", Invoice: "Rechnung", Customer: "Kunde", Supplier: "Lieferant", "Due Date": "Fälligkeitsdatum", Outstanding: "Offen", "Outstanding Amount": "Offener Betrag", "Item Code": "Artikelnr.", "Item Name": "Artikelname", Item: "Artikel", Warehouse: "Lager", Qty: "Menge", "Valuation Rate": "Bewertungspreis", "Stock Value": "Lagerwert", Name: "Name", Status: "Status", Company: "Unternehmen", "From Date": "Von Datum", "To Date": "Bis Datum", "As of Date": "Stichtag", "Valid Till": "Gültig bis", "Net Total": "Nettobetrag", Tax: "Steuer", "Grand Total": "Gesamtbetrag", Frequency: "Frequenz", "Notes / Terms": "Notizen / Bedingungen", "Posting Date": "Buchungsdatum", "Transaction Date": "Belegdatum", "Delivery Date": "Lieferdatum", "% Delivered": "% geliefert", "% Billed": "% abgerechnet", "Update Stock": "Lager aktualisieren", "Payment Type": "Zahlungsart", "Paid From": "Bezahlt von", "Paid To": "Bezahlt an", "Paid Amount": "Zahlbetrag", Type: "Art", Total: "Gesamt", Allocated: "Zugeordnet", Unallocated: "Nicht zugeordnet", Remark: "Bemerkung", "Total Debit": "Summe Soll", "Total Credit": "Summe Haben", "Cost Center": "Kostenstelle", "Source Warehouse": "Quelllager", "Target Warehouse": "Ziellager", Source: "Quelle", Target: "Ziel", "Incoming Value": "Eingangswert", "Outgoing Value": "Ausgangswert", Rate: "Preis", "Income Account": "Ertragskonto", "Expense Account": "Aufwandskonto", Description: "Beschreibung", "Rate (%)": "Satz (%)", Mode: "Art", Change: "Rückgeld", Currency: "Währung", Title: "Titel", Selling: "Verkauf", Buying: "Einkauf", "Discount %": "Rabatt %", "Discount Amt": "Rabattbetrag", "Min Qty": "Mindestmenge", "Valid From": "Gültig ab", "Valid Upto": "Gültig bis", Priority: "Priorität", Enabled: "Aktiviert", "Fiscal Year": "Geschäftsjahr", "Budget Amount": "Budgetbetrag", "If Exceeded": "Bei Überschreitung", Month: "Monat", "Bank Account": "Bankkonto", Deposit: "Einzahlung", Withdrawal: "Auszahlung", "Reference No": "Referenznr.", "Matched Type": "Zugeordnete Art", "Matched Doc": "Zugeordneter Beleg", "Start Date": "Startdatum", "End Date": "Enddatum", "Billing Interval": "Abrechnungsintervall", "Current Period Start": "Aktueller Periodenbeginn", "Current Period End": "Aktuelles Periodenende", "Plan Items": "Planpositionen", "Total Amount": "Gesamtbetrag", "Stock Entry Type": "Lagerbuchungsart", "Rate Or Discount": "Preis oder Rabatt", "Discount Percentage": "Rabattprozentsatz", ID: "ID", "Customer Name": "Kundenname", "Customer Group": "Kundengruppe", Territory: "Region", "Credit Limit": "Kreditlimit", Email: "E-Mail", Phone: "Telefon", Address: "Adresse", City: "Stadt", "Zip Code": "PLZ", Country: "Land", "Tax ID": "Steuernummer", "Contact Person": "Ansprechperson", "Contact Email": "E-Mail Ansprechperson", "Contact Phone": "Telefon Ansprechperson", "Supplier Name": "Lieferantenname", "Supplier Group": "Lieferantengruppe", "Item Group": "Artikelgruppe", "Stock UOM": "Lagereinheit", "Standard Rate": "Standardpreis", "Warehouse Name": "Lagername", "Company Name": "Firmenname" }, Ai = { items: "Positionen", taxes: "Steuern", references: "Zahlungsreferenzen", accounts: "Kontobuchungen", payments: "Zahlungen", plans: "Planpositionen", monthly_distribution: "Monatliche Verteilung" }, Pi = { "Create Sales Order": "Kundenauftrag erstellen", "Create Sales Invoice": "Ausgangsrechnung erstellen", "Create Delivery Note": "Lieferschein erstellen", "Create Purchase Invoice": "Eingangsrechnung erstellen", "Create Purchase Receipt": "Wareneingang erstellen", "Create Credit Note": "Gutschrift erstellen", "Create Debit Note": "Lastschrift erstellen", "Create Return": "Retoure erstellen" }, _i = { totalRevenue: "Gesamtumsatz", outstandingReceivable: "Offene Forderungen", outstandingPayable: "Offene Verbindlichkeiten", totalStockValue: "Gesamter Lagerwert", recentDocuments: "Letzte Dokumente", noRecentDocuments: "Keine aktuellen Dokumente" }, Ti = { title: "Lambda ERP Chat", subtitle: "Bitten Sie mich, Dokumente zu erstellen, Daten abzurufen oder Berichte auszuführen.", s1: "Welche Kunden haben wir?", s2: "Zeig mir die Rohbilanz", s3: "Erstelle ein Angebot für 10 Bolt Pack M8", s4: "Liste alle unbezahlten Rechnungen auf", loadOlder: "Ältere Nachrichten laden", uploading: "Wird hochgeladen...", failed: "Fehlgeschlagen", remove: "Entfernen", placeholderDemo: "Live-Demo läuft...", placeholderType: "Nachricht eingeben...", placeholderConnecting: "Verbindung wird hergestellt...", attachTitle: "Datei anhängen (PDF oder Bild, max. 10 MB)", creating: "Chat wird erstellt...", dropToAttach: "Datei zum Anhängen ablegen (Bilder oder PDF, je max. 10 MB)", demoError: "Demo konnte nicht gestartet werden", voiceStart: "Sprachnachricht aufnehmen", voiceStop: "Aufnahme stoppen", voiceTranscribing: "Wird transkribiert...", micDenied: "Zugriff auf das Mikrofon wurde verweigert.", transcribeFailed: "Transkription fehlgeschlagen. Bitte erneut versuchen." }, Ri = /* @__PURE__ */ JSON.parse('{"pageTitle":"Erste Schritte mit Lambda ERP","intro":"Lambda ERP ist ein KI-natives ERP-System, bei dem die gesamte Funktionalität – etwa das Erstellen von Aufträgen, das Prüfen von Beständen und das Erfassen von Zahlungen – über eine Chat-Oberfläche zugänglich ist. Es leitet an, denkt mit und prüft alle Ihre täglichen Geschäftsaufgaben.","openChat":"KI-Chat öffnen","tipLabel":"Tipp:","topTip":"Der KI-Chat kann Ihnen auch direkte Links zu Dokumenten und herunterladbaren PDFs geben. Bitten Sie ihn einfach, ein Dokument zu erstellen oder nachzuschlagen, und er fügt anklickbare Links in seine Antwort ein.","manualIntro":"Wenn Sie genau verstehen möchten, wie die Dinge unter der Haube funktionieren, oder Dinge lieber manuell erledigen, finden Sie hier einen vollständigen Geschäftszyklus Schritt für Schritt.","caTitle":"Dynamische Analysen – Chatten Sie sich zu jedem Diagramm","caBadge":"Kernfunktion","caBody":"Brauchen Sie einen Bericht, den die Vorlagen nicht liefern? Beschreiben Sie ihn einfach im Chat. Der Assistent ruft ein Code-Spezialmodell auf, das den Bericht für Sie schreibt, ihn live über Ihre ERP-Daten ausführt und einen teilbaren Link zurückgibt. Das Diagramm oder die Tabelle wird in Sekunden gerendert und als Entwurf unter „Eigene Analysen“ in der Seitenleiste gespeichert – Sie können ihn erneut öffnen, die URL mit Kollegen teilen oder den Assistenten bitten, ihn zu verfeinern.","caTryAsking":"Versuchen Sie zu fragen (zum Vorausfüllen im Chat klicken):","caPrompt1":"Zeig mir die Top 10 Kunden nach Umsatz dieses Jahr als Balkendiagramm","caPrompt2":"Monatlicher Einkaufstrend nach Lieferant über alle Monate, x-Achse mit Lieferantennamen beschriften","caPrompt3":"Bestseller-Artikel nach Menge, mit Tabelle und Diagramm","caPrompt4":"Welche Kunden schulden mir gerade am meisten?","caTryInChat":"Im Chat ausprobieren","caOpenWorkspace":"Analyse-Arbeitsbereich öffnen","flowTitle":"Überblick Dokumentenfluss","salesCycle":"Verkaufszyklus","purchaseCycle":"Einkaufszyklus","returns":"Retouren","flowShortcut":"Abkürzung: Das Angebot kann den Kundenauftrag überspringen und direkt zur Ausgangsrechnung oder zum Lieferschein führen","legendStock":"Lagerwirkung","legendGl":"Buchungswirkung","legendCash":"Geldwirkung","legendReversal":"Stornierung","lifecycleTitle":"Dokumenten-Lebenszyklus","lcDraftLabel":"Entwurf:","lcDraftDesc":"Bearbeitbar. Keine finanzielle oder Bestandswirkung.","lcSubmittedLabel":"Gebucht:","lcSubmittedDesc":"Gesperrt. Buchungen und Lagerbuchungen werden erzeugt.","lcCancelledLabel":"Storniert:","lcCancelledDesc":"Alle Buchungen storniert. Das Dokument wird dauerhaft archiviert.","lcNoDelete":"Es gibt kein Löschen. Um einen Entwurf zu verwerfen: buchen und dann stornieren.","lcCorrect":"Um ein gebuchtes Dokument zu korrigieren: stornieren und ein neues erstellen.","readyTitle":"Sie sind startklar","readyBody1":"Sie verstehen jetzt den vollständigen Zyklus. Ein typisches Praxisszenario sieht so aus: Sie erhalten einen Kundenauftrag (Angebot → Kundenauftrag), prüfen den Bestand, kaufen, was Sie brauchen (Bestellung → Wareneingang → Eingangsrechnung → Zahlung), liefern an den Kunden (Lieferschein), stellen ihm die Rechnung (Ausgangsrechnung) und ziehen die Zahlung ein (Zahlung). Kommt etwas zurück, erstellen Sie eine Gutschrift und eine Lieferschein-Retoure, um Finanzen und Bestand umzukehren. Die Rohbilanz bestätigt, dass alles ausgeglichen ist.","readyBody2":"Sie können all dies auch über den KI-Chat per natürlicher Konversation erledigen – beschreiben Sie einfach, was Sie brauchen, und er erstellt die richtigen Dokumente für Sie.","chips":{"Quotation":"Angebot","Sales Order":"Kundenauftrag","Delivery Note":"Lieferschein","Sales Invoice":"Ausgangsrechnung","Payment Entry":"Zahlung","Purchase Order":"Bestellung","Purchase Receipt":"Wareneingang","Purchase Invoice":"Eingangsrechnung","Credit Note":"Gutschrift","DN Return":"Lieferschein-Retoure","Debit Note":"Lastschrift","Draft":"Entwurf","Submitted":"Gebucht","Cancelled":"Storniert"},"links":{"Go to Setup":"Zur Einrichtung","Customers":"Kunden","Suppliers":"Lieferanten","Items":"Artikel","Warehouses":"Lager","New Quotation":"Neues Angebot","View Quotations":"Angebote anzeigen","Stock Balance":"Lagerbestand","New Purchase Order":"Neue Bestellung","Purchase Receipts":"Wareneingänge","Purchase Invoices":"Eingangsrechnungen","Delivery Notes":"Lieferscheine","Sales Invoices":"Ausgangsrechnungen","New Payment Entry":"Neue Zahlung","New Stock Entry":"Neue Lagerbuchung","New Journal Entry":"Neuer Buchungssatz","Profit & Loss":"Gewinn- und Verlustrechnung","Balance Sheet":"Bilanz","AR Aging":"Offene Posten Debitoren","AP Aging":"Offene Posten Kreditoren","Trial Balance":"Rohbilanz","General Ledger":"Hauptbuch","Open AI Chat":"KI-Chat öffnen"},"steps":{"1":{"title":"Unternehmen einrichten","description":"Erstellen Sie ein Unternehmen mit einer Basiswährung. Dadurch wird Ihr Kontenplan generiert (30 Standardkonten in den Bereichen Aktiva, Verbindlichkeiten, Eigenkapital, Erträge und Aufwendungen) sowie eine Standard-Kostenstelle. Sie können außerdem Demodaten mit Beispielkunden, -lieferanten und -artikeln anlegen, um schnell loszulegen."},"2":{"title":"Stammdaten anlegen","description":"Bevor Sie buchen können, benötigen Sie Stammdaten. Legen Sie mindestens einen Kunden, einen Lieferanten, einen Artikel (mit Standardpreis) und ein Lager an. Wenn Sie in Schritt 1 Demodaten angelegt haben, existieren diese bereits.","tip":"Artikel haben einen Standardpreis, der beim Hinzufügen zu Dokumenten automatisch ausgefüllt wird. Sie können den Preis pro Transaktion jederzeit überschreiben."},"3":{"title":"Angebot erstellen","description":"Ein Angebot ist eine unverbindliche Offerte an einen Kunden. Wählen Sie einen Kunden, fügen Sie Positionen mit Mengen und Preisen hinzu, optional Steuerzeilen, und speichern Sie. Angebote haben keine finanzielle Auswirkung – sie erzeugen keine Buchungs- oder Lagerbewegungen. Legen Sie ein Gültigkeitsdatum fest, damit das Angebot automatisch abläuft."},"4":{"title":"Buchen und in Kundenauftrag umwandeln","description":"Öffnen Sie Ihr gespeichertes Angebot und klicken Sie auf Buchen, um es zu bestätigen. Klicken Sie dann auf „Kundenauftrag erstellen“, um es umzuwandeln. Der Kundenauftrag stellt eine bestätigte Zusage des Kunden dar. Er hat weiterhin keine finanzielle Auswirkung, reserviert aber Bestand für die Planung.","tip":"Nur gebuchte Dokumente können in den nächsten Schritt umgewandelt werden. Entwurf → Buchen → Umwandeln ist der Standardablauf. Für schnelle Geschäfte können Sie den Kundenauftrag überspringen und direkt vom Angebot zur Ausgangsrechnung oder zum Lieferschein gehen."},"5":{"title":"Bestand vor der Erfüllung prüfen","description":"Bevor Sie liefern können, prüfen Sie, ob der Artikel tatsächlich auf Lager ist. Öffnen Sie den Bericht Lagerbestand und suchen Sie den Artikel. Wenn Ihr Lager eine Menge von null aufweist, müssen Sie zunächst Bestand beschaffen – entweder über eine Bestellung (Einkauf bei einem Lieferanten) oder eine Lagerbuchung (manueller Eingang).","tip":"Dies ist ein häufiges Szenario aus der Praxis: Sie verkaufen etwas und stellen dann fest, dass Sie es erst einkaufen müssen. Das ERP unterstützt beide Abläufe."},"6":{"title":"Einkaufszyklus: Bestand bei einem Lieferanten kaufen","description":"Wenn Sie Bestand einkaufen müssen, haben Sie zwei gültige Wege. Der Standardweg ist Bestellung → Wareneingang → Eingangsrechnung: Nutzen Sie ihn, wenn die Ware vor oder getrennt von der Lieferantenrechnung eintrifft. Treffen Rechnung und Wareneingang gleichzeitig ein, können Sie die Eingangsrechnung direkt erstellen und „Lager aktualisieren“ aktivieren, sodass dasselbe Dokument sowohl den Bestand vereinnahmt als auch die Verbindlichkeit erfasst.","tip":"Verwenden Sie zuerst den Wareneingang, wenn Sie Waren getrennt erhalten. Verwenden Sie die Eingangsrechnung mit „Lager aktualisieren“, wenn ein Schritt sowohl den Bestand vereinnahmen als auch die Lieferantenrechnung buchen soll. Setzen Sie in diesem direkten Weg ein Lager in jeder Bestandszeile."},"7":{"title":"Lieferschein erstellen","description":"Nachdem Sie nun Bestand haben, kehren Sie zu Ihrem gebuchten Kundenauftrag zurück und klicken Sie auf „Lieferschein erstellen“. Setzen Sie in jeder Position das Lager (von dem die Ware versendet wird) und buchen Sie. Dadurch wird Bestand aus dem Lager ausgebucht – Ihr Lagerbestand sinkt.","tip":"Der Lieferschein ist das Versanddokument. Er reduziert den Bestand, erzeugt aber keine Rechnung. Sie können Lieferung und Rechnungsstellung getrennt vornehmen."},"8":{"title":"Ausgangsrechnung erstellen und buchen","description":"Erstellen Sie aus dem gebuchten Kundenauftrag eine Ausgangsrechnung. Beim Buchen der Rechnung werden Buchungen erzeugt: Forderungen aus Lieferungen und Leistungen werden im Soll gebucht (der Kunde schuldet Ihnen Geld) und Umsatzerlöse im Haben (erzielter Ertrag). Sind Steuern konfiguriert, wird auch die Steuerverbindlichkeit im Haben gebucht. Der offene Betrag zeigt, was der Kunde noch schuldet."},"9":{"title":"Kundenzahlungen erfassen","description":"Erstellen Sie eine Zahlung, um vom Kunden erhaltenes Geld zu erfassen. Setzen Sie die Zahlungsart auf „Receive“ (Erhalten), wählen Sie den Kunden, geben Sie den Betrag an und ordnen Sie ihn der Ausgangsrechnung zu. Sie können Teilzahlungen vornehmen – der offene Betrag der Rechnung aktualisiert sich entsprechend. Erstellen Sie weitere Zahlungen, bis die Rechnung vollständig beglichen ist.","tip":"Teilzahlungen sind üblich. Eine Rechnung über 10.000 kann jetzt mit 3.000 und später mit 7.000 bezahlt werden. Jede Zahlung reduziert den offenen Betrag."},"10":{"title":"Lagerbuchungen (manuelle Bestandsführung)","description":"Verwenden Sie Lagerbuchungen für Bestandsbewegungen, die nicht mit Ein- oder Verkäufen verbunden sind. „Material Receipt“ fügt Bestand hinzu (Eröffnungsbestände, Korrekturen). „Material Issue“ bucht Bestand aus (Abschreibungen, interner Verbrauch). „Material Transfer“ verschiebt Bestand zwischen Lägern. Jede Buchung aktualisiert das Lagerbuch mit gleitender Durchschnittsbewertung.","tip":"Verwenden Sie für eingekaufte Waren Wareneingänge statt Lagerbuchungen – sie sind mit der Bestellung verknüpft und bieten einen sauberen Prüfpfad."},"11":{"title":"Buchungssätze","description":"Buchungssätze sind manuelle buchhalterische Anpassungen – Aufwandsabgrenzungen, Korrekturen, Umgliederungen, Eröffnungsbestände. Jeder Satz muss ausgeglichene Soll- und Haben-Beträge haben (Summe Soll = Summe Haben). Verwenden Sie sie, wenn kein anderer Dokumenttyp passt."},"12":{"title":"Gehaltszahlungen","description":"Lambda ERP wickelt Gehälter über die vorhandenen Buchhaltungswerkzeuge ab. Grenzen Sie zunächst den Gehaltsaufwand ab: Erstellen Sie einen Buchungssatz, der Gehaltsaufwand im Soll und Gehaltsverbindlichkeiten im Haben für den gesamten Lohnbetrag bucht. Bezahlen Sie dann die Mitarbeiter: Erstellen Sie einen weiteren Buchungssatz (oder eine Zahlung), der Gehaltsverbindlichkeiten im Soll und Ihr Bankkonto im Haben bucht. Dieser zweistufige Prozess hält Ihre Bücher korrekt – der Aufwand wird in der richtigen Periode erfasst und der Geldabfluss separat nachverfolgt.","tip":"Sie können den KI-Assistenten bitten, dies für Sie zu erledigen: „Grenze 15.000 an Gehältern für April ab“ gefolgt von „Zahle die April-Gehälter von der Bank“. Er erstellt die richtigen Buchungssätze automatisch."},"13":{"title":"Retouren und Gutschriften","description":"Wenn ein Kunde Waren zurückgibt oder Sie eine Gutschrift ausstellen müssen, erstellen Sie eine Retoure. Retouren verwenden denselben Dokumenttyp mit negativen Mengen. Öffnen Sie eine gebuchte Ausgangsrechnung und erstellen Sie eine Gutschrift (Ausgangsrechnungs-Retoure) – dies kehrt die Buchungen um und reduziert den offenen Betrag der ursprünglichen Rechnung. Erstellen Sie für den Bestand eine Lieferschein-Retoure, um Waren zurück ins Lager zu nehmen. Auf der Einkaufsseite erstellen Sie eine Lastschrift (Eingangsrechnungs-Retoure), um eine Lieferantenrechnung umzukehren, oder eine Wareneingangs-Retoure, um Waren zurückzusenden.","tip":"Eine Gutschrift ist einfach eine Ausgangsrechnung mit is_return=1 und negativen Mengen. Dieselbe Buchungslogik läuft – negative Beträge wechseln automatisch auf die richtige Soll-/Haben-Seite. Für eine vollständige Verkaufsretoure benötigen Sie sowohl eine Gutschrift (Finanzen) als auch eine Lieferschein-Retoure (Bestand)."},"14":{"title":"Berichte ausführen","description":"Prüfen Sie Ihre Bücher. Die Gewinn- und Verlustrechnung zeigt Erträge gegenüber Aufwendungen und den Periodengewinn. Die Bilanz zeigt Ihre finanzielle Lage (Aktiva = Verbindlichkeiten + Eigenkapital). Die Offenen Posten Debitoren zeigen, wer Ihnen Geld schuldet und wie überfällig es ist. Die Offenen Posten Kreditoren zeigen, was Sie Lieferanten schulden. Die Rohbilanz überprüft die doppelte Buchführung. Das Hauptbuch zeigt jede einzelne Buchung. Der Lagerbestand zeigt den aktuellen Bestand."},"15":{"title":"Arbeiten in Fremdwährungen","description":"Ihre Bücher werden in einer einzigen Basiswährung geführt (bei der Unternehmenseinrichtung gewählt), aber Sie können in jeder Währung buchen. Setzen Sie eine Währung auf einer Rechnung oder einem Beleg – oder geben Sie einem Kunden oder Lieferanten eine Standardwährung – und der Wechselkurs für dieses Datum wird automatisch ermittelt und auf dem Dokument gespeichert. Das Dokument behält seine Beträge in seiner eigenen Währung, während das Hauptbuch stets in Ihrer Basiswährung bucht. Wenn Sie später zu einem anderen Kurs einnehmen oder zahlen, wird der realisierte Währungsgewinn oder -verlust automatisch auf ein Konto Währungsgewinn/-verlust gebucht. Sie können sogar ein Fremdwährungs-Bankguthaben halten und es später zum Kurs Ihrer Bank umrechnen – die Differenz zum Buchwert wird dann realisiert. Zum Monatsende können Sie offene Fremdwährungssalden zum Stichtagskurs neu bewerten (ein unrealisierter Gewinn/Verlust, der in der nächsten Periode storniert wird), und Sie können jeden Jahresabschluss zur Anzeige in eine andere Währung umgerechnet betrachten.","tip":"Am einfachsten geht das über den KI-Chat – probieren Sie „Erstelle eine Ausgangsrechnung für Lumiere Audio in EUR“, „Zeig mir die Bilanz in EUR“ oder „Wie hoch ist unser unrealisiertes Währungsrisiko zum Monatsende?“. Die Demodaten enthalten bereits einen EUR-Kunden (Lumiere Audio SARL), dessen Rechnung zu einem anderen Kurs eingenommen wurde, sowie eine offene EUR-Lieferantenrechnung – öffnen Sie das Hauptbuch, um die realisierten Währungsbuchungen zu sehen."}},"setupTitle":"Richten Sie Ihr Unternehmen ein — KI-geführt","setupBadge":"Hier starten","setupBody":"Sagen Sie dem Assistenten, welche Art von Unternehmen Sie führen, und er erstellt Ihren Kontenplan für Sie — zugeschnitten auf Ihre Branche, mit den passenden Konten und sinnvollen Voreinstellungen. Er erklärt jede Entscheidung und legt erst dann etwas an, wenn Sie zustimmen.","setupSectors":"Zugeschnitten auf Dienstleistungen, Einzelhandel & POS, Gastronomie, Großhandel & Distribution, Import/Export, Fertigung und Bauwesen.","setupGetStarted":"Im Chat loslegen","setupManual":"Lieber ein manuelles Formular? Nutzen Sie die klassische Einrichtung.","setupManualLink":"Klassische Einrichtung","setupPrompt":"Ich möchte mein Unternehmen einrichten. Können Sie mich durch den Prozess führen?"}'), Ii = { title: "Formatierungshilfe", intro: "Der Text unter Notizen / Konditionen unterstützt eine einfache Formatierung im PDF:", heading: "fette Überschrift", emphasis: "kursiv / fett", rule: "horizontale Trennlinie", price: "rechtsbündiger Preis neben dem Text darüber (z. B. Monatlich | CHF 380.—)", block: "Trennen Sie Blöcke durch eine Leerzeile." }, Bi = { period: "Periode", allTime: "Gesamter Zeitraum", semantics: "Bilanzkonten: Saldo per Periodenende. Erfolgskonten: Bewegung innerhalb der Periode. Konto anklicken für den Kontoauszug.", empty: "Keine Konten gefunden. Zuerst die Firmeneinrichtung abschliessen.", disabled: "deaktiviert", rootType: { Asset: "Aktiven", Liability: "Passiven", Equity: "Eigenkapital", Income: "Ertrag", Expense: "Aufwand" } }, Ei = {
|
|
6921
6921
|
common: hi,
|
|
6922
6922
|
language: gi,
|
|
6923
6923
|
header: fi,
|
|
@@ -6930,8 +6930,8 @@ const Ws = { save: "Save", saving: "Saving...", submit: "Submit", cancel: "Cance
|
|
|
6930
6930
|
status: ki,
|
|
6931
6931
|
reports: Si,
|
|
6932
6932
|
masterForm: Ci,
|
|
6933
|
-
fields:
|
|
6934
|
-
tables:
|
|
6933
|
+
fields: Di,
|
|
6934
|
+
tables: Ai,
|
|
6935
6935
|
conversions: Pi,
|
|
6936
6936
|
dashboard: _i,
|
|
6937
6937
|
chat: Ti,
|
|
@@ -7402,16 +7402,16 @@ function fa({ ownRole: t }) {
|
|
|
7402
7402
|
}), P = (y) => y.is_mine ?? y.user === (a == null ? void 0 : a.name), b = (y) => y.owner_full_name || y.owner_email || y.user || n("settings.chatApiUnknownUser"), d = Ce(() => {
|
|
7403
7403
|
const y = /* @__PURE__ */ new Map();
|
|
7404
7404
|
for (const B of v ?? []) {
|
|
7405
|
-
const
|
|
7405
|
+
const D = B.is_mine ?? B.user === (a == null ? void 0 : a.name), O = D ? "__me__" : B.user ?? "__unknown__";
|
|
7406
7406
|
y.has(O) || y.set(O, {
|
|
7407
|
-
label:
|
|
7408
|
-
sublabel:
|
|
7409
|
-
isMine:
|
|
7407
|
+
label: D ? n("settings.chatApiYourKeys") : B.owner_full_name || B.owner_email || B.user || n("settings.chatApiUnknownUser"),
|
|
7408
|
+
sublabel: D ? void 0 : B.owner_email ?? void 0,
|
|
7409
|
+
isMine: D,
|
|
7410
7410
|
keys: []
|
|
7411
7411
|
}), y.get(O).keys.push(B);
|
|
7412
7412
|
}
|
|
7413
7413
|
return Array.from(y.values()).sort(
|
|
7414
|
-
(B,
|
|
7414
|
+
(B, D) => B.isMine ? -1 : D.isMine ? 1 : B.label.localeCompare(D.label)
|
|
7415
7415
|
);
|
|
7416
7416
|
}, [v, a, n]), h = (y, B) => {
|
|
7417
7417
|
B === "revoke" ? f.mutate(y) : R.mutate(y);
|
|
@@ -7783,7 +7783,7 @@ function mo() {
|
|
|
7783
7783
|
] });
|
|
7784
7784
|
}
|
|
7785
7785
|
const ya = {};
|
|
7786
|
-
function
|
|
7786
|
+
function Mo(t, n) {
|
|
7787
7787
|
ya[t] = n;
|
|
7788
7788
|
}
|
|
7789
7789
|
function po(t, n) {
|
|
@@ -7830,7 +7830,7 @@ const go = [
|
|
|
7830
7830
|
{ path: "admin/users", element: /* @__PURE__ */ e(Gs, {}) },
|
|
7831
7831
|
{ path: "admin/settings", element: /* @__PURE__ */ e(mo, {}) }
|
|
7832
7832
|
], ba = [], va = [];
|
|
7833
|
-
function
|
|
7833
|
+
function yo(t, n) {
|
|
7834
7834
|
(n == null ? void 0 : n.area) === "top" ? ba.push(t) : va.push(t);
|
|
7835
7835
|
}
|
|
7836
7836
|
const Un = (t) => t.index ? "__index__" : t.path ?? "";
|
|
@@ -7842,7 +7842,7 @@ function Vn(t, n) {
|
|
|
7842
7842
|
}
|
|
7843
7843
|
return a;
|
|
7844
7844
|
}
|
|
7845
|
-
function
|
|
7845
|
+
function bo() {
|
|
7846
7846
|
return [
|
|
7847
7847
|
...Vn(go, ba),
|
|
7848
7848
|
{
|
|
@@ -7852,18 +7852,51 @@ function yo() {
|
|
|
7852
7852
|
}
|
|
7853
7853
|
];
|
|
7854
7854
|
}
|
|
7855
|
-
function
|
|
7856
|
-
|
|
7855
|
+
function vo({ slug: t, parentSlug: n, linkField: a }) {
|
|
7856
|
+
const { name: s = "" } = ut(), o = Le();
|
|
7857
|
+
return se(() => {
|
|
7858
|
+
let i = !0;
|
|
7859
|
+
return T.getDocument(t, s).then((l) => {
|
|
7860
|
+
if (!i) return;
|
|
7861
|
+
const c = l == null ? void 0 : l[a];
|
|
7862
|
+
o(c ? `/app/${n}/${c}` : `/app/${t}`, { replace: !0 });
|
|
7863
|
+
}).catch(() => {
|
|
7864
|
+
i && o("/app", { replace: !0 });
|
|
7865
|
+
}), () => {
|
|
7866
|
+
i = !1;
|
|
7867
|
+
};
|
|
7868
|
+
}, [t, s, n, a, o]), /* @__PURE__ */ e("div", { className: "p-6 text-sm text-fg-muted", children: "…" });
|
|
7869
|
+
}
|
|
7870
|
+
async function xo() {
|
|
7871
|
+
try {
|
|
7872
|
+
const t = await L(
|
|
7873
|
+
"/chat-doctypes",
|
|
7874
|
+
{ signal: AbortSignal.timeout(1500) }
|
|
7875
|
+
);
|
|
7876
|
+
for (const n of t.doctypes || []) {
|
|
7877
|
+
const a = n.page;
|
|
7878
|
+
a && a.kind === "via" && yo({
|
|
7879
|
+
path: `app/${n.slug}/:name`,
|
|
7880
|
+
element: /* @__PURE__ */ e(vo, { slug: n.slug, parentSlug: a.parent_slug, linkField: a.link_field })
|
|
7881
|
+
});
|
|
7882
|
+
}
|
|
7883
|
+
} catch {
|
|
7884
|
+
}
|
|
7885
|
+
}
|
|
7886
|
+
function No() {
|
|
7887
|
+
return new Da({
|
|
7857
7888
|
defaultOptions: {
|
|
7858
7889
|
queries: { retry: 1, refetchOnWindowFocus: !1 }
|
|
7859
7890
|
}
|
|
7860
7891
|
});
|
|
7861
7892
|
}
|
|
7862
|
-
function
|
|
7893
|
+
async function Fo(t = {}) {
|
|
7863
7894
|
const n = t.rootElement ?? document.getElementById("root");
|
|
7864
7895
|
if (!n)
|
|
7865
7896
|
throw new Error('bootstrap: no mount element (pass rootElement or add <div id="root">)');
|
|
7866
|
-
const a = t.queryClient ??
|
|
7897
|
+
const a = t.queryClient ?? No();
|
|
7898
|
+
await xo();
|
|
7899
|
+
const s = _a(bo());
|
|
7867
7900
|
Sa(n).render(
|
|
7868
7901
|
/* @__PURE__ */ e(ka, { children: /* @__PURE__ */ e(Ca, { client: a, children: /* @__PURE__ */ e(tr, { children: /* @__PURE__ */ e(Ta, { router: s }) }) }) })
|
|
7869
7902
|
);
|
|
@@ -7874,23 +7907,23 @@ export {
|
|
|
7874
7907
|
tr as AuthProvider,
|
|
7875
7908
|
ha as SUPPORTED_LANGUAGES,
|
|
7876
7909
|
T as api,
|
|
7877
|
-
|
|
7878
|
-
|
|
7879
|
-
|
|
7880
|
-
|
|
7881
|
-
|
|
7882
|
-
|
|
7910
|
+
Fo as bootstrap,
|
|
7911
|
+
bo as buildRoutes,
|
|
7912
|
+
Bo as configureApiBase,
|
|
7913
|
+
Oo as configureBranding,
|
|
7914
|
+
No as createAppQueryClient,
|
|
7915
|
+
zo as getAllDoctypeConfigs,
|
|
7883
7916
|
ir as getBranding,
|
|
7884
7917
|
po as getComponent,
|
|
7885
7918
|
oa as getDoctypeConfig,
|
|
7886
7919
|
sr as getNavGroups,
|
|
7887
7920
|
ao as getStoredLanguage,
|
|
7888
|
-
|
|
7889
|
-
|
|
7890
|
-
|
|
7891
|
-
|
|
7892
|
-
|
|
7893
|
-
|
|
7921
|
+
Vo as i18n,
|
|
7922
|
+
Mo as registerComponent,
|
|
7923
|
+
qo as registerDoctype,
|
|
7924
|
+
Eo as registerNavGroup,
|
|
7925
|
+
Lo as registerNavItem,
|
|
7926
|
+
yo as registerRoute,
|
|
7894
7927
|
L as request,
|
|
7895
7928
|
st as useAuth
|
|
7896
7929
|
};
|