@lambda-development/erp-core 0.6.19 → 0.6.20
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/index.js +394 -390
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { jsx as e, jsxs as r, Fragment as Ce } from "react/jsx-runtime";
|
|
2
|
-
import { useState as w, useEffect as re, useCallback as Pe, useContext as an, createContext as rn, useRef as oe, useMemo as Ne, useLayoutEffect as hn, StrictMode as
|
|
3
|
-
import { createRoot as
|
|
4
|
-
import { useQueryClient as He, useQuery as ue, useMutation as me, QueryClientProvider as
|
|
5
|
-
import { NavLink as qt, useLocation as vt, useNavigate as Ee, Outlet as
|
|
6
|
-
import { useTranslation as X, initReactI18next as
|
|
7
|
-
import { BookOpen as
|
|
2
|
+
import { useState as w, useEffect as re, useCallback as Pe, useContext as an, createContext as rn, useRef as oe, useMemo as Ne, useLayoutEffect as hn, StrictMode as Ea } from "react";
|
|
3
|
+
import { createRoot as La } from "react-dom/client";
|
|
4
|
+
import { useQueryClient as He, useQuery as ue, useMutation as me, QueryClientProvider as Oa, QueryClient as qa } from "@tanstack/react-query";
|
|
5
|
+
import { NavLink as qt, useLocation as vt, useNavigate as Ee, Outlet as za, Navigate as Ma, Link as ve, useSearchParams as zt, useParams as ut, createBrowserRouter as Fa, RouterProvider as $a } from "react-router-dom";
|
|
6
|
+
import { useTranslation as X, initReactI18next as Ua } from "react-i18next";
|
|
7
|
+
import { BookOpen as Va, ShoppingCart as Hn, CreditCard as Ka, FileText as sn, Package as Qn, BarChart3 as ja, Database as Ga, Settings as Wa, MessageCircle as Ha, ChevronDown as Mt, ChevronRight as Dt, Plus as Yn, Trash2 as Jn, LineChart as Qa, ArrowLeft as Ya, TrendingUp as Ja, ArrowDownRight as Za, ArrowUpRight as Xa, Wallet as er, Receipt as gn, ChevronLeft as tr, Info as nr } from "lucide-react";
|
|
8
8
|
import { createColumnHelper as Zn, useReactTable as Xn, getCoreRowModel as ea, flexRender as Bt } from "@tanstack/react-table";
|
|
9
9
|
import { createPortal as ta } from "react-dom";
|
|
10
|
-
import { ResponsiveContainer as
|
|
10
|
+
import { ResponsiveContainer as ar, LineChart as rr, CartesianGrid as fn, XAxis as yn, YAxis as bn, Tooltip as Kt, Line as sr, PieChart as ir, Pie as or, Cell as lr, BarChart as cr, Bar as dr } from "recharts";
|
|
11
11
|
import na from "i18next";
|
|
12
|
-
import { default as
|
|
12
|
+
import { default as ol } from "i18next";
|
|
13
13
|
let ct = "/api";
|
|
14
|
-
function
|
|
14
|
+
function Qo(t) {
|
|
15
15
|
ct = t.replace(/\/+$/, "");
|
|
16
16
|
}
|
|
17
|
-
function
|
|
17
|
+
function ur(t) {
|
|
18
18
|
return new URL(`${ct}${t}`, window.location.origin).toString();
|
|
19
19
|
}
|
|
20
20
|
class Ue extends Error {
|
|
@@ -22,7 +22,7 @@ class Ue extends Error {
|
|
|
22
22
|
super(a), this.status = n;
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
function
|
|
25
|
+
function mr(t) {
|
|
26
26
|
if (!t) return "Request failed";
|
|
27
27
|
if (typeof t == "string") return t;
|
|
28
28
|
if (Array.isArray(t))
|
|
@@ -47,7 +47,7 @@ async function L(t, n) {
|
|
|
47
47
|
if (a.status === 401 && !t.startsWith("/auth/"))
|
|
48
48
|
throw window.location.href = "/login", new Ue(401, "Session expired");
|
|
49
49
|
const s = await a.json().catch(() => ({ detail: a.statusText }));
|
|
50
|
-
throw new Ue(a.status,
|
|
50
|
+
throw new Ue(a.status, mr(s.detail));
|
|
51
51
|
}
|
|
52
52
|
return a.json();
|
|
53
53
|
}
|
|
@@ -202,7 +202,7 @@ const I = {
|
|
|
202
202
|
const a = new URLSearchParams();
|
|
203
203
|
n != null && n.link && a.set("link", "1"), n != null && n.invite && a.set("invite", n.invite);
|
|
204
204
|
const s = a.toString() ? `?${a.toString()}` : "";
|
|
205
|
-
return
|
|
205
|
+
return ur(`/auth/${encodeURIComponent(t)}/login${s}`);
|
|
206
206
|
},
|
|
207
207
|
oauthListIdentities: () => L("/auth/oauth/identities"),
|
|
208
208
|
authRegister: (t) => L("/auth/register", { method: "POST", body: JSON.stringify(t) }),
|
|
@@ -241,7 +241,7 @@ const I = {
|
|
|
241
241
|
),
|
|
242
242
|
getDemoSpend: () => L("/admin/demo-spend")
|
|
243
243
|
}, aa = rn(null);
|
|
244
|
-
function
|
|
244
|
+
function pr({ children: t }) {
|
|
245
245
|
const [n, a] = w(null), [s, o] = w(!0);
|
|
246
246
|
re(() => {
|
|
247
247
|
I.authMe().then((d) => a(d)).catch(() => a(null)).finally(() => o(!1));
|
|
@@ -298,7 +298,7 @@ const ra = rn(null), vn = {
|
|
|
298
298
|
function jt(t) {
|
|
299
299
|
return typeof t != "string" ? null : t.trim().toLowerCase().replace(/\s+/g, "-");
|
|
300
300
|
}
|
|
301
|
-
function
|
|
301
|
+
function hr(t, n) {
|
|
302
302
|
if (t === "create_custom_analytics_report" || t === "update_custom_analytics_report")
|
|
303
303
|
return { group: "Custom Analytics", item: "" };
|
|
304
304
|
if (!n) return null;
|
|
@@ -348,7 +348,7 @@ function wn(t) {
|
|
|
348
348
|
const n = on();
|
|
349
349
|
n.delete(t) && ia(n);
|
|
350
350
|
}
|
|
351
|
-
function
|
|
351
|
+
function gr() {
|
|
352
352
|
return typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID() : `req-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
353
353
|
}
|
|
354
354
|
function tt(t) {
|
|
@@ -356,7 +356,7 @@ function tt(t) {
|
|
|
356
356
|
const n = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(t) ? t.replace(" ", "T") : t, a = new Date(n).getTime();
|
|
357
357
|
return Number.isNaN(a) ? 0 : a;
|
|
358
358
|
}
|
|
359
|
-
function
|
|
359
|
+
function fr({ children: t }) {
|
|
360
360
|
const n = He(), [a, s] = w([]), [o, i] = w({}), [l, c] = w({}), [h, d] = w({}), [p, u] = w({}), [f, v] = w({}), [N, b] = w({}), [C, S] = w({}), [x, y] = w(null), [m, D] = w("connecting"), [T, U] = w(0), Z = oe(null), g = oe(null), R = oe(/* @__PURE__ */ new Map()), W = oe(null), $ = oe({}), de = oe({}), A = oe(null);
|
|
361
361
|
function _(B) {
|
|
362
362
|
for (const K of R.current.values())
|
|
@@ -413,7 +413,7 @@ function gr({ children: t }) {
|
|
|
413
413
|
}
|
|
414
414
|
function ie(B, K, Y) {
|
|
415
415
|
return new Promise((xe, we) => {
|
|
416
|
-
const Re =
|
|
416
|
+
const Re = gr();
|
|
417
417
|
R.current.set(Re, {
|
|
418
418
|
expectedType: Y,
|
|
419
419
|
resolve: xe,
|
|
@@ -626,7 +626,7 @@ function gr({ children: t }) {
|
|
|
626
626
|
const J = typeof j.report_id == "string" ? j.report_id : void 0, Me = typeof ((ot = q.args) == null ? void 0 : ot.report_id) == "string" ? q.args.report_id : void 0;
|
|
627
627
|
V("Custom Analytics", J || Me || ""), n.invalidateQueries({ queryKey: ["runtime-drafts"] });
|
|
628
628
|
} else {
|
|
629
|
-
const J =
|
|
629
|
+
const J = hr(q.tool, q.args);
|
|
630
630
|
J && V(J.group, J.item);
|
|
631
631
|
}
|
|
632
632
|
de.current = {
|
|
@@ -817,7 +817,7 @@ function Zt(t, n = 2) {
|
|
|
817
817
|
}).format(t ?? 0);
|
|
818
818
|
}
|
|
819
819
|
let la;
|
|
820
|
-
function
|
|
820
|
+
function Yo(t) {
|
|
821
821
|
la = t;
|
|
822
822
|
}
|
|
823
823
|
function Ft(t) {
|
|
@@ -831,7 +831,7 @@ function $e(t, n) {
|
|
|
831
831
|
const a = parseFloat(String(t ?? 0)) || 0;
|
|
832
832
|
return n !== void 0 ? parseFloat(a.toFixed(n)) : a;
|
|
833
833
|
}
|
|
834
|
-
const
|
|
834
|
+
const yr = {
|
|
835
835
|
// Primary: brand-coloured fill + a 1px inset top highlight for depth
|
|
836
836
|
// (button-highlight shadow). On press, the button shifts down 1px —
|
|
837
837
|
// tiny detail, large perceived "this is responsive".
|
|
@@ -839,7 +839,7 @@ const fr = {
|
|
|
839
839
|
secondary: "bg-surface text-fg ring-1 ring-line hover:bg-surface-subtle active:translate-y-px focus-visible:ring-fg/20",
|
|
840
840
|
danger: "bg-red-600 text-white shadow-button-highlight hover:bg-red-700 active:translate-y-px focus-visible:ring-red-500/40",
|
|
841
841
|
ghost: "bg-transparent text-fg-muted hover:bg-surface-subtle hover:text-fg focus-visible:ring-fg/20"
|
|
842
|
-
},
|
|
842
|
+
}, br = {
|
|
843
843
|
sm: "h-8 px-3 text-sm",
|
|
844
844
|
md: "h-10 px-4 text-sm",
|
|
845
845
|
lg: "h-11 px-5 text-sm"
|
|
@@ -867,8 +867,8 @@ function Q({
|
|
|
867
867
|
"transition-all duration-150",
|
|
868
868
|
"focus-visible:outline-none focus-visible:ring-2",
|
|
869
869
|
"disabled:cursor-not-allowed disabled:opacity-50 disabled:active:translate-y-0",
|
|
870
|
-
|
|
871
|
-
|
|
870
|
+
yr[t],
|
|
871
|
+
br[n],
|
|
872
872
|
i
|
|
873
873
|
),
|
|
874
874
|
children: o
|
|
@@ -922,7 +922,7 @@ function te({ label: t, hint: n, error: a, className: s, id: o, ...i }) {
|
|
|
922
922
|
] });
|
|
923
923
|
}
|
|
924
924
|
const ca = rn(null);
|
|
925
|
-
function
|
|
925
|
+
function vr({ children: t }) {
|
|
926
926
|
const { t: n } = X(), [a, s] = w(null), [o, i] = w(""), l = Pe(
|
|
927
927
|
(f) => new Promise((v) => s({ kind: "confirm", opts: f, resolve: v })),
|
|
928
928
|
[]
|
|
@@ -982,13 +982,13 @@ function da() {
|
|
|
982
982
|
function ua() {
|
|
983
983
|
return da().confirm;
|
|
984
984
|
}
|
|
985
|
-
function
|
|
985
|
+
function xr() {
|
|
986
986
|
return da().prompt;
|
|
987
987
|
}
|
|
988
988
|
const dt = [
|
|
989
989
|
{
|
|
990
990
|
label: "Introduction",
|
|
991
|
-
icon: /* @__PURE__ */ e(
|
|
991
|
+
icon: /* @__PURE__ */ e(Va, { className: "h-4 w-4" }),
|
|
992
992
|
items: [
|
|
993
993
|
{ label: "Getting Started", path: "/tutorial" },
|
|
994
994
|
{ label: "Company Setup", path: "/setup" },
|
|
@@ -1008,7 +1008,7 @@ const dt = [
|
|
|
1008
1008
|
},
|
|
1009
1009
|
{
|
|
1010
1010
|
label: "Buying",
|
|
1011
|
-
icon: /* @__PURE__ */ e(
|
|
1011
|
+
icon: /* @__PURE__ */ e(Ka, { className: "h-4 w-4" }),
|
|
1012
1012
|
items: [
|
|
1013
1013
|
{ label: "Purchase Order", path: "/app/purchase-order" },
|
|
1014
1014
|
{ label: "Purchase Invoice", path: "/app/purchase-invoice" }
|
|
@@ -1037,7 +1037,7 @@ const dt = [
|
|
|
1037
1037
|
},
|
|
1038
1038
|
{
|
|
1039
1039
|
label: "Reports",
|
|
1040
|
-
icon: /* @__PURE__ */ e(
|
|
1040
|
+
icon: /* @__PURE__ */ e(ja, { className: "h-4 w-4" }),
|
|
1041
1041
|
items: [
|
|
1042
1042
|
{ label: "Trial Balance", path: "/reports/trial-balance" },
|
|
1043
1043
|
{ label: "Profit & Loss", path: "/reports/profit-and-loss" },
|
|
@@ -1051,7 +1051,7 @@ const dt = [
|
|
|
1051
1051
|
},
|
|
1052
1052
|
{
|
|
1053
1053
|
label: "Masters",
|
|
1054
|
-
icon: /* @__PURE__ */ e(
|
|
1054
|
+
icon: /* @__PURE__ */ e(Ga, { className: "h-4 w-4" }),
|
|
1055
1055
|
items: [
|
|
1056
1056
|
{ label: "Company", path: "/masters/company" },
|
|
1057
1057
|
{ label: "Customer", path: "/masters/customer" },
|
|
@@ -1062,7 +1062,7 @@ const dt = [
|
|
|
1062
1062
|
},
|
|
1063
1063
|
{
|
|
1064
1064
|
label: "Settings",
|
|
1065
|
-
icon: /* @__PURE__ */ e(
|
|
1065
|
+
icon: /* @__PURE__ */ e(Wa, { className: "h-4 w-4" }),
|
|
1066
1066
|
items: [
|
|
1067
1067
|
{ label: "General", path: "/admin/settings" },
|
|
1068
1068
|
{ label: "Pricing Rule", path: "/app/pricing-rule" },
|
|
@@ -1070,10 +1070,10 @@ const dt = [
|
|
|
1070
1070
|
]
|
|
1071
1071
|
}
|
|
1072
1072
|
];
|
|
1073
|
-
function
|
|
1073
|
+
function Nr() {
|
|
1074
1074
|
return dt;
|
|
1075
1075
|
}
|
|
1076
|
-
function
|
|
1076
|
+
function Jo(t, n) {
|
|
1077
1077
|
const a = dt.findIndex((s) => s.label === t.label);
|
|
1078
1078
|
if (a >= 0) {
|
|
1079
1079
|
dt[a] = t;
|
|
@@ -1081,19 +1081,19 @@ function Yo(t, n) {
|
|
|
1081
1081
|
}
|
|
1082
1082
|
(n == null ? void 0 : n.index) != null ? dt.splice(n.index, 0, t) : dt.push(t);
|
|
1083
1083
|
}
|
|
1084
|
-
function
|
|
1084
|
+
function Zo(t, n) {
|
|
1085
1085
|
const a = dt.find((s) => s.label === t);
|
|
1086
1086
|
a ? a.items.push(n) : dt.push({ label: t, icon: null, items: [n] });
|
|
1087
1087
|
}
|
|
1088
1088
|
let Xt = { appName: "Lambda ERP" };
|
|
1089
|
-
function
|
|
1089
|
+
function Xo(t) {
|
|
1090
1090
|
if (Xt = { ...Xt, ...t }, !(typeof document > "u") && (t.appName && (document.title = t.appName), t.tokens)) {
|
|
1091
1091
|
const n = document.documentElement;
|
|
1092
1092
|
for (const [a, s] of Object.entries(t.tokens))
|
|
1093
1093
|
n.style.setProperty(a.startsWith("--") ? a : `--${a}`, s);
|
|
1094
1094
|
}
|
|
1095
1095
|
}
|
|
1096
|
-
function
|
|
1096
|
+
function wr() {
|
|
1097
1097
|
return Xt;
|
|
1098
1098
|
}
|
|
1099
1099
|
const ma = "sidebar-collapsed";
|
|
@@ -1134,7 +1134,7 @@ const cn = {
|
|
|
1134
1134
|
Settings: "bg-purple-300 text-purple-950 ring-2 ring-inset ring-purple-100",
|
|
1135
1135
|
"Custom Analytics": "bg-indigo-300 text-indigo-950 ring-2 ring-inset ring-indigo-100"
|
|
1136
1136
|
};
|
|
1137
|
-
function
|
|
1137
|
+
function kr() {
|
|
1138
1138
|
const [t, n] = ln("chats"), a = vt(), s = Ee(), { t: o } = X(), { sessions: i, createSession: l, deleteSession: c } = mt(), h = async () => {
|
|
1139
1139
|
try {
|
|
1140
1140
|
const p = await l();
|
|
@@ -1156,7 +1156,7 @@ function wr() {
|
|
|
1156
1156
|
onClick: n,
|
|
1157
1157
|
className: "flex w-full items-center gap-2 px-4 py-2 text-xs font-semibold uppercase tracking-wider text-fg-muted transition-colors hover:text-fg",
|
|
1158
1158
|
children: [
|
|
1159
|
-
/* @__PURE__ */ e(
|
|
1159
|
+
/* @__PURE__ */ e(Ha, { className: "h-4 w-4" }),
|
|
1160
1160
|
/* @__PURE__ */ e("span", { className: "flex-1 text-left", children: o("nav.chats") }),
|
|
1161
1161
|
t ? /* @__PURE__ */ e(Mt, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ e(Dt, { className: "h-3.5 w-3.5" })
|
|
1162
1162
|
]
|
|
@@ -1212,7 +1212,7 @@ function dn() {
|
|
|
1212
1212
|
}
|
|
1213
1213
|
);
|
|
1214
1214
|
}
|
|
1215
|
-
function
|
|
1215
|
+
function Cr() {
|
|
1216
1216
|
const [t, n, a] = ln("custom-analytics"), s = vt(), o = Ee(), i = He(), { t: l } = X(), { navigationFlash: c, sessions: h, createSession: d } = mt(), p = (c == null ? void 0 : c.group) === "Custom Analytics", u = cn["Custom Analytics"], { data: f } = ue({
|
|
1217
1217
|
queryKey: ["runtime-drafts"],
|
|
1218
1218
|
queryFn: () => I.listRuntimeDrafts(),
|
|
@@ -1252,7 +1252,7 @@ function kr() {
|
|
|
1252
1252
|
p && u
|
|
1253
1253
|
),
|
|
1254
1254
|
children: [
|
|
1255
|
-
/* @__PURE__ */ e(
|
|
1255
|
+
/* @__PURE__ */ e(Qa, { className: "h-4 w-4" }),
|
|
1256
1256
|
/* @__PURE__ */ e("span", { className: "flex-1 text-left", children: l("nav.customAnalytics") }),
|
|
1257
1257
|
t ? /* @__PURE__ */ e(Mt, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ e(Dt, { className: "h-3.5 w-3.5" })
|
|
1258
1258
|
]
|
|
@@ -1302,7 +1302,7 @@ function kr() {
|
|
|
1302
1302
|
] })
|
|
1303
1303
|
] });
|
|
1304
1304
|
}
|
|
1305
|
-
function
|
|
1305
|
+
function Sr({ group: t }) {
|
|
1306
1306
|
const [n, a] = ln(t.label), { t: s } = X(), { navigationFlash: o } = mt(), i = (o == null ? void 0 : o.group) === t.label, l = cn[t.label] ?? "bg-blue-300 text-blue-950 ring-2 ring-inset ring-blue-100";
|
|
1307
1307
|
return /* @__PURE__ */ r("div", { children: [
|
|
1308
1308
|
/* @__PURE__ */ r(
|
|
@@ -1345,10 +1345,10 @@ function Cr({ group: t }) {
|
|
|
1345
1345
|
}) })
|
|
1346
1346
|
] });
|
|
1347
1347
|
}
|
|
1348
|
-
const
|
|
1348
|
+
const Dr = {
|
|
1349
1349
|
"/setup/opening-balances": "opening_balances_enabled"
|
|
1350
1350
|
};
|
|
1351
|
-
function
|
|
1351
|
+
function Ar({ isMobileOpen: t = !1, onClose: n }) {
|
|
1352
1352
|
var c;
|
|
1353
1353
|
const { data: a } = ue({
|
|
1354
1354
|
queryKey: ["settings"],
|
|
@@ -1358,11 +1358,11 @@ function Dr({ isMobileOpen: t = !1, onClose: n }) {
|
|
|
1358
1358
|
queryKey: ["setup-status"],
|
|
1359
1359
|
queryFn: () => I.setupStatus(),
|
|
1360
1360
|
staleTime: 6e4
|
|
1361
|
-
}), o = (c = s == null ? void 0 : s.companies) == null ? void 0 : c[0], i = (o == null ? void 0 : o.company_name) || (o == null ? void 0 : o.name) ||
|
|
1361
|
+
}), o = (c = s == null ? void 0 : s.companies) == null ? void 0 : c[0], i = (o == null ? void 0 : o.company_name) || (o == null ? void 0 : o.name) || wr().appName, l = Ne(() => Nr().map((d) => ({
|
|
1362
1362
|
...d,
|
|
1363
1363
|
items: d.items.filter((p) => {
|
|
1364
1364
|
if (p.path === "/setup" && (s != null && s.setup_complete)) return !1;
|
|
1365
|
-
const u =
|
|
1365
|
+
const u = Dr[p.path];
|
|
1366
1366
|
return !u || !a ? !0 : a[u] !== "0";
|
|
1367
1367
|
})
|
|
1368
1368
|
})), [a, s]);
|
|
@@ -1409,16 +1409,16 @@ function Dr({ isMobileOpen: t = !1, onClose: n }) {
|
|
|
1409
1409
|
)
|
|
1410
1410
|
] }),
|
|
1411
1411
|
/* @__PURE__ */ r("nav", { className: "flex-1 overflow-y-auto py-3", children: [
|
|
1412
|
-
/* @__PURE__ */ e(wr, {}),
|
|
1413
1412
|
/* @__PURE__ */ e(kr, {}),
|
|
1414
|
-
|
|
1413
|
+
/* @__PURE__ */ e(Cr, {}),
|
|
1414
|
+
l.map((h) => /* @__PURE__ */ e(Sr, { group: h }, h.label))
|
|
1415
1415
|
] })
|
|
1416
1416
|
]
|
|
1417
1417
|
}
|
|
1418
1418
|
);
|
|
1419
1419
|
}
|
|
1420
1420
|
const Cn = (t) => t.replace(/-/g, " ").replace(/\b\w/g, (n) => n.toUpperCase());
|
|
1421
|
-
function
|
|
1421
|
+
function Pr(t, n) {
|
|
1422
1422
|
const a = t.split("/").filter(Boolean);
|
|
1423
1423
|
if (a[0] === "setup") return n("titles.setup");
|
|
1424
1424
|
if (a[0] === "tutorial") return n("titles.tutorial");
|
|
@@ -1437,15 +1437,15 @@ function Ar(t, n) {
|
|
|
1437
1437
|
}
|
|
1438
1438
|
return n("titles.dashboard");
|
|
1439
1439
|
}
|
|
1440
|
-
function
|
|
1440
|
+
function _r(t) {
|
|
1441
1441
|
const n = t.split("/").filter(Boolean);
|
|
1442
1442
|
return (n[0] === "app" || n[0] === "masters") && n.length > 2 ? `/${n[0]}/${n[1]}` : n[0] === "setup" && n.length > 1 ? "/setup" : null;
|
|
1443
1443
|
}
|
|
1444
|
-
function _r() {
|
|
1445
|
-
return /* @__PURE__ */ e(br, { children: /* @__PURE__ */ e(gr, { children: /* @__PURE__ */ e(Tr, {}) }) });
|
|
1446
|
-
}
|
|
1447
1444
|
function Tr() {
|
|
1448
|
-
|
|
1445
|
+
return /* @__PURE__ */ e(vr, { children: /* @__PURE__ */ e(fr, { children: /* @__PURE__ */ e(Rr, {}) }) });
|
|
1446
|
+
}
|
|
1447
|
+
function Rr() {
|
|
1448
|
+
const { pathname: t } = vt(), n = Ee(), { user: a, logout: s } = st(), { navigationFlash: o } = mt(), { t: i } = X(), l = Pr(t, i), c = _r(t), h = () => {
|
|
1449
1449
|
var f;
|
|
1450
1450
|
c && (((f = window.history.state) == null ? void 0 : f.idx) > 0 ? n(-1) : n(c));
|
|
1451
1451
|
}, [d, p] = w(!1);
|
|
@@ -1454,7 +1454,7 @@ function Tr() {
|
|
|
1454
1454
|
}, [t]);
|
|
1455
1455
|
const u = o ? cn[o.group] : null;
|
|
1456
1456
|
return /* @__PURE__ */ r("div", { className: "flex h-dvh bg-surface-muted", children: [
|
|
1457
|
-
/* @__PURE__ */ e(
|
|
1457
|
+
/* @__PURE__ */ e(Ar, { isMobileOpen: d, onClose: () => p(!1) }),
|
|
1458
1458
|
d && /* @__PURE__ */ e(
|
|
1459
1459
|
"div",
|
|
1460
1460
|
{
|
|
@@ -1484,7 +1484,7 @@ function Tr() {
|
|
|
1484
1484
|
onClick: h,
|
|
1485
1485
|
className: "-ml-1 rounded p-1 text-gray-500 hover:bg-gray-100 hover:text-gray-900",
|
|
1486
1486
|
"aria-label": i("header.back"),
|
|
1487
|
-
children: /* @__PURE__ */ e(
|
|
1487
|
+
children: /* @__PURE__ */ e(Ya, { className: "h-5 w-5" })
|
|
1488
1488
|
}
|
|
1489
1489
|
),
|
|
1490
1490
|
/* @__PURE__ */ e("h1", { className: "text-base font-semibold text-gray-500 md:text-lg", children: l })
|
|
@@ -1504,13 +1504,13 @@ function Tr() {
|
|
|
1504
1504
|
)
|
|
1505
1505
|
] })
|
|
1506
1506
|
] }),
|
|
1507
|
-
/* @__PURE__ */ e("main", { className: "flex-1 overflow-auto p-4 md:p-6", children: /* @__PURE__ */ e(
|
|
1507
|
+
/* @__PURE__ */ e("main", { className: "flex-1 overflow-auto p-4 md:p-6", children: /* @__PURE__ */ e(za, {}) })
|
|
1508
1508
|
] })
|
|
1509
1509
|
] });
|
|
1510
1510
|
}
|
|
1511
|
-
function
|
|
1511
|
+
function Ir({ children: t }) {
|
|
1512
1512
|
const { user: n, loading: a } = st();
|
|
1513
|
-
return a ? /* @__PURE__ */ e("div", { className: "flex h-dvh items-center justify-center", children: /* @__PURE__ */ e("div", { className: "text-gray-400", children: "Loading..." }) }) : n ? /* @__PURE__ */ e(Ce, { children: t }) : /* @__PURE__ */ e(
|
|
1513
|
+
return a ? /* @__PURE__ */ e("div", { className: "flex h-dvh items-center justify-center", children: /* @__PURE__ */ e("div", { className: "text-gray-400", children: "Loading..." }) }) : n ? /* @__PURE__ */ e(Ce, { children: t }) : /* @__PURE__ */ e(Ma, { to: "/login", replace: !0 });
|
|
1514
1514
|
}
|
|
1515
1515
|
function M({ title: t, children: n, className: a, interactive: s }) {
|
|
1516
1516
|
return /* @__PURE__ */ r(
|
|
@@ -1533,7 +1533,7 @@ function M({ title: t, children: n, className: a, interactive: s }) {
|
|
|
1533
1533
|
}
|
|
1534
1534
|
);
|
|
1535
1535
|
}
|
|
1536
|
-
const
|
|
1536
|
+
const Br = {
|
|
1537
1537
|
default: "bg-brand/10 text-brand ring-1 ring-inset ring-brand/20",
|
|
1538
1538
|
success: "bg-emerald-50 text-emerald-700 ring-1 ring-inset ring-emerald-200",
|
|
1539
1539
|
warning: "bg-amber-50 text-amber-700 ring-1 ring-inset ring-amber-200",
|
|
@@ -1546,7 +1546,7 @@ function Rt({ variant: t = "default", dot: n, children: a, className: s }) {
|
|
|
1546
1546
|
{
|
|
1547
1547
|
className: _e(
|
|
1548
1548
|
"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-xs font-medium",
|
|
1549
|
-
|
|
1549
|
+
Br[t],
|
|
1550
1550
|
s
|
|
1551
1551
|
),
|
|
1552
1552
|
children: [
|
|
@@ -1556,7 +1556,7 @@ function Rt({ variant: t = "default", dot: n, children: a, className: s }) {
|
|
|
1556
1556
|
}
|
|
1557
1557
|
);
|
|
1558
1558
|
}
|
|
1559
|
-
const
|
|
1559
|
+
const Er = {
|
|
1560
1560
|
Draft: "secondary",
|
|
1561
1561
|
Open: "default",
|
|
1562
1562
|
Submitted: "default",
|
|
@@ -1571,7 +1571,7 @@ const Br = {
|
|
|
1571
1571
|
Overdue: "danger"
|
|
1572
1572
|
};
|
|
1573
1573
|
function un({ status: t }) {
|
|
1574
|
-
const { t: n } = X(), a =
|
|
1574
|
+
const { t: n } = X(), a = Er[t] ?? "secondary";
|
|
1575
1575
|
return /* @__PURE__ */ e(Rt, { variant: a, children: n(`status.${t}`, { defaultValue: t }) });
|
|
1576
1576
|
}
|
|
1577
1577
|
function ze(t) {
|
|
@@ -1608,15 +1608,15 @@ function _t() {
|
|
|
1608
1608
|
/* @__PURE__ */ e("div", { className: "h-9 w-9 shrink-0 animate-pulse rounded-lg bg-surface-subtle" })
|
|
1609
1609
|
] }) });
|
|
1610
1610
|
}
|
|
1611
|
-
const
|
|
1611
|
+
const Lr = {
|
|
1612
1612
|
"Sales Invoice": gn,
|
|
1613
1613
|
"Purchase Invoice": gn,
|
|
1614
|
-
"Payment Entry":
|
|
1614
|
+
"Payment Entry": er,
|
|
1615
1615
|
"Sales Order": Hn,
|
|
1616
1616
|
Quotation: sn
|
|
1617
1617
|
};
|
|
1618
|
-
function
|
|
1619
|
-
const { t: n } = X(), a = t.doctype ?? t.type ?? "Document", s = t.creation ?? t.date, o =
|
|
1618
|
+
function Or({ doc: t }) {
|
|
1619
|
+
const { t: n } = X(), a = t.doctype ?? t.type ?? "Document", s = t.creation ?? t.date, o = Lr[a] ?? sn, l = `/app/${a.toLowerCase().replace(/\s+/g, "-")}/${encodeURIComponent(t.name)}`;
|
|
1620
1620
|
return /* @__PURE__ */ r(
|
|
1621
1621
|
ve,
|
|
1622
1622
|
{
|
|
@@ -1645,7 +1645,7 @@ function kt() {
|
|
|
1645
1645
|
/* @__PURE__ */ e("div", { className: "hidden h-3 w-16 animate-pulse rounded bg-surface-subtle sm:block" })
|
|
1646
1646
|
] });
|
|
1647
1647
|
}
|
|
1648
|
-
function
|
|
1648
|
+
function qr() {
|
|
1649
1649
|
const { t } = X(), { data: n, isLoading: a } = ue({
|
|
1650
1650
|
queryKey: ["dashboard-summary"],
|
|
1651
1651
|
queryFn: () => I.dashboardSummary()
|
|
@@ -1662,7 +1662,7 @@ function Or() {
|
|
|
1662
1662
|
{
|
|
1663
1663
|
title: t("dashboard.totalRevenue"),
|
|
1664
1664
|
value: n == null ? void 0 : n.total_revenue,
|
|
1665
|
-
icon:
|
|
1665
|
+
icon: Ja,
|
|
1666
1666
|
tone: "text-emerald-600 bg-emerald-500/10"
|
|
1667
1667
|
}
|
|
1668
1668
|
),
|
|
@@ -1671,7 +1671,7 @@ function Or() {
|
|
|
1671
1671
|
{
|
|
1672
1672
|
title: t("dashboard.outstandingReceivable"),
|
|
1673
1673
|
value: n == null ? void 0 : n.outstanding_receivable,
|
|
1674
|
-
icon:
|
|
1674
|
+
icon: Za,
|
|
1675
1675
|
tone: "text-sky-600 bg-sky-500/10"
|
|
1676
1676
|
}
|
|
1677
1677
|
),
|
|
@@ -1680,7 +1680,7 @@ function Or() {
|
|
|
1680
1680
|
{
|
|
1681
1681
|
title: t("dashboard.outstandingPayable"),
|
|
1682
1682
|
value: n == null ? void 0 : n.outstanding_payable,
|
|
1683
|
-
icon:
|
|
1683
|
+
icon: Xa,
|
|
1684
1684
|
tone: "text-amber-600 bg-amber-500/10"
|
|
1685
1685
|
}
|
|
1686
1686
|
),
|
|
@@ -1700,7 +1700,7 @@ function Or() {
|
|
|
1700
1700
|
/* @__PURE__ */ e(kt, {}),
|
|
1701
1701
|
/* @__PURE__ */ e(kt, {}),
|
|
1702
1702
|
/* @__PURE__ */ e(kt, {})
|
|
1703
|
-
] }) : n != null && n.recent_documents && n.recent_documents.length > 0 ? n.recent_documents.map((s, o) => /* @__PURE__ */ e(
|
|
1703
|
+
] }) : n != null && n.recent_documents && n.recent_documents.length > 0 ? n.recent_documents.map((s, o) => /* @__PURE__ */ e(Or, { doc: s }, `${s.name}-${o}`)) : /* @__PURE__ */ e("div", { className: "px-3 py-10 text-center text-sm text-fg-muted", children: t("dashboard.noRecentDocuments") }) }) })
|
|
1704
1704
|
] });
|
|
1705
1705
|
}
|
|
1706
1706
|
const pa = "lad.docListContext";
|
|
@@ -1718,10 +1718,10 @@ function ga(t, n) {
|
|
|
1718
1718
|
} catch {
|
|
1719
1719
|
}
|
|
1720
1720
|
}
|
|
1721
|
-
function
|
|
1721
|
+
function zr(t) {
|
|
1722
1722
|
return ha()[t];
|
|
1723
1723
|
}
|
|
1724
|
-
function
|
|
1724
|
+
function Mr(t, n) {
|
|
1725
1725
|
const { data: a, isLoading: s, error: o, refetch: i } = ue({
|
|
1726
1726
|
queryKey: ["documents", t, n],
|
|
1727
1727
|
queryFn: () => I.listDocuments(t, n),
|
|
@@ -1780,7 +1780,7 @@ const rt = [
|
|
|
1780
1780
|
{ name: "qty", label: "Qty", type: "number", required: !0 },
|
|
1781
1781
|
{ name: "rate", label: "Rate", type: "currency", required: !0 },
|
|
1782
1782
|
{ name: "amount", label: "Amount", type: "currency", readOnly: !0 }
|
|
1783
|
-
],
|
|
1783
|
+
], Fr = [
|
|
1784
1784
|
...rt,
|
|
1785
1785
|
{
|
|
1786
1786
|
name: "frequency",
|
|
@@ -1827,7 +1827,7 @@ const rt = [
|
|
|
1827
1827
|
{ name: "remarks", label: "Notes / Terms", type: "textarea" }
|
|
1828
1828
|
],
|
|
1829
1829
|
childTables: [
|
|
1830
|
-
{ key: "items", label: "Items", fields:
|
|
1830
|
+
{ key: "items", label: "Items", fields: Fr },
|
|
1831
1831
|
{ key: "taxes", label: "Taxes", fields: at }
|
|
1832
1832
|
],
|
|
1833
1833
|
listColumns: ["name", "customer", "transaction_date", "grand_total", "status"],
|
|
@@ -2417,14 +2417,14 @@ const rt = [
|
|
|
2417
2417
|
function fa(t) {
|
|
2418
2418
|
return mn[t];
|
|
2419
2419
|
}
|
|
2420
|
-
function
|
|
2420
|
+
function el(t) {
|
|
2421
2421
|
mn[t.slug] = t;
|
|
2422
2422
|
}
|
|
2423
|
-
function
|
|
2423
|
+
function tl() {
|
|
2424
2424
|
return Object.values(mn);
|
|
2425
2425
|
}
|
|
2426
2426
|
function ya({ slug: t, name: n, onSave: a, kind: s = "document" }) {
|
|
2427
|
-
const o = Ee(), i = s === "master", l =
|
|
2427
|
+
const o = Ee(), i = s === "master", l = zr(i ? `master:${t}` : t), c = i ? `/masters/${t}` : `/app/${t}`, { data: h } = ue({
|
|
2428
2428
|
queryKey: ["adjacent", s, t, n, (l == null ? void 0 : l.filters) ?? null],
|
|
2429
2429
|
queryFn: () => i ? I.adjacentMaster(t, n) : I.adjacentDocument(t, n, l == null ? void 0 : l.filters)
|
|
2430
2430
|
}), d = (h == null ? void 0 : h.prev) ?? null, p = (h == null ? void 0 : h.next) ?? null;
|
|
@@ -2449,7 +2449,7 @@ function ya({ slug: t, name: n, onSave: a, kind: s = "document" }) {
|
|
|
2449
2449
|
title: "Previous record (k / ←)",
|
|
2450
2450
|
onClick: () => d && o(`${c}/${d}`),
|
|
2451
2451
|
className: u,
|
|
2452
|
-
children: /* @__PURE__ */ e(
|
|
2452
|
+
children: /* @__PURE__ */ e(tr, { className: "h-4 w-4" })
|
|
2453
2453
|
}
|
|
2454
2454
|
),
|
|
2455
2455
|
/* @__PURE__ */ e(
|
|
@@ -2465,7 +2465,7 @@ function ya({ slug: t, name: n, onSave: a, kind: s = "document" }) {
|
|
|
2465
2465
|
)
|
|
2466
2466
|
] });
|
|
2467
2467
|
}
|
|
2468
|
-
function
|
|
2468
|
+
function $r(t) {
|
|
2469
2469
|
return typeof t == "string" ? { value: t, label: t } : t;
|
|
2470
2470
|
}
|
|
2471
2471
|
function Ve({ label: t, options: n, value: a, onChange: s, className: o, required: i, disabled: l }) {
|
|
@@ -2499,7 +2499,7 @@ function Ve({ label: t, options: n, value: a, onChange: s, className: o, require
|
|
|
2499
2499
|
children: [
|
|
2500
2500
|
/* @__PURE__ */ e("option", { value: "", children: "Select..." }),
|
|
2501
2501
|
n.map((h) => {
|
|
2502
|
-
const { value: d, label: p } =
|
|
2502
|
+
const { value: d, label: p } = $r(h);
|
|
2503
2503
|
return /* @__PURE__ */ e("option", { value: d, children: p }, d);
|
|
2504
2504
|
})
|
|
2505
2505
|
]
|
|
@@ -2507,7 +2507,7 @@ function Ve({ label: t, options: n, value: a, onChange: s, className: o, require
|
|
|
2507
2507
|
)
|
|
2508
2508
|
] });
|
|
2509
2509
|
}
|
|
2510
|
-
function
|
|
2510
|
+
function Ur({ text: t }) {
|
|
2511
2511
|
const [n, a] = w(!1);
|
|
2512
2512
|
return /* @__PURE__ */ r("span", { className: "relative ml-1 inline-flex", children: [
|
|
2513
2513
|
/* @__PURE__ */ e(
|
|
@@ -2527,7 +2527,7 @@ function $r({ text: t }) {
|
|
|
2527
2527
|
] })
|
|
2528
2528
|
] });
|
|
2529
2529
|
}
|
|
2530
|
-
function
|
|
2530
|
+
function Vr() {
|
|
2531
2531
|
const { t } = X(), [n, a] = w(!1), s = [
|
|
2532
2532
|
["# Heading", t("notesMarkup.heading", { defaultValue: "bold heading" })],
|
|
2533
2533
|
["*italic* **bold**", t("notesMarkup.emphasis", { defaultValue: "italic / bold" })],
|
|
@@ -2553,7 +2553,7 @@ function Ur() {
|
|
|
2553
2553
|
className: "inline-flex h-4 w-4 items-center justify-center rounded-full text-fg-muted hover:text-fg",
|
|
2554
2554
|
onClick: () => a((o) => !o),
|
|
2555
2555
|
"aria-label": t("notesMarkup.title", { defaultValue: "Formatting help" }),
|
|
2556
|
-
children: /* @__PURE__ */ e(
|
|
2556
|
+
children: /* @__PURE__ */ e(nr, { className: "h-3.5 w-3.5" })
|
|
2557
2557
|
}
|
|
2558
2558
|
),
|
|
2559
2559
|
n && /* @__PURE__ */ r("div", { className: "absolute bottom-full left-0 z-50 mb-2 w-80 rounded-md bg-gray-900 px-3 py-2.5 text-xs leading-relaxed text-white shadow-lg", children: [
|
|
@@ -2570,7 +2570,7 @@ function Ur() {
|
|
|
2570
2570
|
}
|
|
2571
2571
|
);
|
|
2572
2572
|
}
|
|
2573
|
-
function
|
|
2573
|
+
function Kr(t, n = !0) {
|
|
2574
2574
|
const { data: a } = ue({
|
|
2575
2575
|
queryKey: ["currencies", ""],
|
|
2576
2576
|
queryFn: () => I.currencies(t),
|
|
@@ -2579,23 +2579,23 @@ function Vr(t, n = !0) {
|
|
|
2579
2579
|
});
|
|
2580
2580
|
return (a == null ? void 0 : a.currencies) ?? [];
|
|
2581
2581
|
}
|
|
2582
|
-
const
|
|
2582
|
+
const jr = /* @__PURE__ */ new Set([
|
|
2583
2583
|
"customer",
|
|
2584
2584
|
"supplier",
|
|
2585
2585
|
"item",
|
|
2586
2586
|
"warehouse"
|
|
2587
2587
|
]);
|
|
2588
2588
|
function en(t, n) {
|
|
2589
|
-
return !t || !n ? null :
|
|
2589
|
+
return !t || !n ? null : jr.has(t) ? `/masters/${t}/${encodeURIComponent(n)}` : t === "account" ? `/reports/general-ledger?account=${encodeURIComponent(n)}` : null;
|
|
2590
2590
|
}
|
|
2591
2591
|
function Sn({ label: t, hint: n, extra: a }) {
|
|
2592
2592
|
return /* @__PURE__ */ r("label", { className: "mb-1.5 block text-sm font-medium text-fg", children: [
|
|
2593
2593
|
t,
|
|
2594
|
-
n && /* @__PURE__ */ e(
|
|
2594
|
+
n && /* @__PURE__ */ e(Ur, { text: n }),
|
|
2595
2595
|
a
|
|
2596
2596
|
] });
|
|
2597
2597
|
}
|
|
2598
|
-
function
|
|
2598
|
+
function Gr({
|
|
2599
2599
|
field: t,
|
|
2600
2600
|
value: n,
|
|
2601
2601
|
onChange: a,
|
|
@@ -2670,7 +2670,7 @@ function It({
|
|
|
2670
2670
|
currency: l = "USD"
|
|
2671
2671
|
}) {
|
|
2672
2672
|
var v;
|
|
2673
|
-
const { t: c } = X(), h = s || !!t.readOnly, d = () => i ? null : /* @__PURE__ */ e(Sn, { label: c(`fields.${t.label}`, { defaultValue: t.label }), hint: t.hint }), p = t.type === "select" && t.optionsSource === "currency", u =
|
|
2673
|
+
const { t: c } = X(), h = s || !!t.readOnly, d = () => i ? null : /* @__PURE__ */ e(Sn, { label: c(`fields.${t.label}`, { defaultValue: t.label }), hint: t.hint }), p = t.type === "select" && t.optionsSource === "currency", u = Kr(void 0, p);
|
|
2674
2674
|
if (h) {
|
|
2675
2675
|
if (t.type === "link" && n) {
|
|
2676
2676
|
const C = t.linkDoctypeField && o ? String(o[t.linkDoctypeField] ?? "").toLowerCase().replace(/\s+/g, "-") : t.linkDoctype, S = en(C, String(n));
|
|
@@ -2703,7 +2703,7 @@ function It({
|
|
|
2703
2703
|
return /* @__PURE__ */ r("div", { children: [
|
|
2704
2704
|
/* @__PURE__ */ e(d, {}),
|
|
2705
2705
|
/* @__PURE__ */ e(
|
|
2706
|
-
|
|
2706
|
+
Gr,
|
|
2707
2707
|
{
|
|
2708
2708
|
field: N,
|
|
2709
2709
|
value: n ?? "",
|
|
@@ -2736,7 +2736,7 @@ function It({
|
|
|
2736
2736
|
{
|
|
2737
2737
|
label: c(`fields.${t.label}`, { defaultValue: t.label }),
|
|
2738
2738
|
hint: t.hint,
|
|
2739
|
-
extra: N ? /* @__PURE__ */ e(
|
|
2739
|
+
extra: N ? /* @__PURE__ */ e(Vr, {}) : void 0
|
|
2740
2740
|
}
|
|
2741
2741
|
),
|
|
2742
2742
|
/* @__PURE__ */ e(
|
|
@@ -2766,7 +2766,7 @@ function It({
|
|
|
2766
2766
|
)
|
|
2767
2767
|
] });
|
|
2768
2768
|
}
|
|
2769
|
-
function
|
|
2769
|
+
function Wr({
|
|
2770
2770
|
tableDef: t,
|
|
2771
2771
|
rows: n,
|
|
2772
2772
|
onChange: a,
|
|
@@ -2828,7 +2828,7 @@ function Gr({
|
|
|
2828
2828
|
!s && /* @__PURE__ */ e("div", { className: "mt-2", children: /* @__PURE__ */ e(Q, { variant: "secondary", size: "sm", onClick: c, children: i("common.addRow") }) })
|
|
2829
2829
|
] });
|
|
2830
2830
|
}
|
|
2831
|
-
function
|
|
2831
|
+
function Hr({
|
|
2832
2832
|
isNew: t,
|
|
2833
2833
|
doctype: n,
|
|
2834
2834
|
name: a,
|
|
@@ -3036,7 +3036,7 @@ function An() {
|
|
|
3036
3036
|
)
|
|
3037
3037
|
] }),
|
|
3038
3038
|
/* @__PURE__ */ e(
|
|
3039
|
-
|
|
3039
|
+
Hr,
|
|
3040
3040
|
{
|
|
3041
3041
|
isNew: l,
|
|
3042
3042
|
doctype: t,
|
|
@@ -3081,7 +3081,7 @@ function An() {
|
|
|
3081
3081
|
)) })
|
|
3082
3082
|
] }),
|
|
3083
3083
|
i.childTables.map((E) => /* @__PURE__ */ e(
|
|
3084
|
-
|
|
3084
|
+
Wr,
|
|
3085
3085
|
{
|
|
3086
3086
|
tableDef: E,
|
|
3087
3087
|
rows: c[E.key] ?? [],
|
|
@@ -3112,7 +3112,7 @@ function ba(t) {
|
|
|
3112
3112
|
const n = new Date(t), a = n.getDay(), s = a === 0 ? 6 : a - 1;
|
|
3113
3113
|
return n.setDate(n.getDate() - s), n;
|
|
3114
3114
|
}
|
|
3115
|
-
function
|
|
3115
|
+
function Qr(t) {
|
|
3116
3116
|
const n = ba(t);
|
|
3117
3117
|
return n.setDate(n.getDate() + 6), n;
|
|
3118
3118
|
}
|
|
@@ -3136,7 +3136,7 @@ function _n(t) {
|
|
|
3136
3136
|
function Lt(t) {
|
|
3137
3137
|
return new Date(t.getFullYear(), 11, 31);
|
|
3138
3138
|
}
|
|
3139
|
-
const
|
|
3139
|
+
const Yr = [
|
|
3140
3140
|
{
|
|
3141
3141
|
label: "Today",
|
|
3142
3142
|
range: () => {
|
|
@@ -3146,7 +3146,7 @@ const Qr = [
|
|
|
3146
3146
|
},
|
|
3147
3147
|
{
|
|
3148
3148
|
label: "This Week",
|
|
3149
|
-
range: () => [be(ba(/* @__PURE__ */ new Date())), be(
|
|
3149
|
+
range: () => [be(ba(/* @__PURE__ */ new Date())), be(Qr(/* @__PURE__ */ new Date()))]
|
|
3150
3150
|
},
|
|
3151
3151
|
{
|
|
3152
3152
|
label: "This Month",
|
|
@@ -3183,7 +3183,7 @@ const Qr = [
|
|
|
3183
3183
|
}
|
|
3184
3184
|
];
|
|
3185
3185
|
function $t({ onSelect: t }) {
|
|
3186
|
-
return /* @__PURE__ */ e("div", { className: "flex flex-wrap gap-1.5", children:
|
|
3186
|
+
return /* @__PURE__ */ e("div", { className: "flex flex-wrap gap-1.5", children: Yr.map((n) => /* @__PURE__ */ e(
|
|
3187
3187
|
"button",
|
|
3188
3188
|
{
|
|
3189
3189
|
type: "button",
|
|
@@ -3219,14 +3219,14 @@ function pn({ onSelect: t }) {
|
|
|
3219
3219
|
a.label
|
|
3220
3220
|
)) });
|
|
3221
3221
|
}
|
|
3222
|
-
const
|
|
3222
|
+
const Jr = ["All", "Draft", "Submitted", "Cancelled"], Zr = /* @__PURE__ */ new Set([
|
|
3223
3223
|
"grand_total",
|
|
3224
3224
|
"outstanding_amount",
|
|
3225
3225
|
"paid_amount",
|
|
3226
3226
|
"total_debit",
|
|
3227
3227
|
"total_amount",
|
|
3228
3228
|
"net_total"
|
|
3229
|
-
]),
|
|
3229
|
+
]), Xr = /* @__PURE__ */ new Set([
|
|
3230
3230
|
"transaction_date",
|
|
3231
3231
|
"posting_date",
|
|
3232
3232
|
"due_date",
|
|
@@ -3243,12 +3243,12 @@ const Yr = ["All", "Draft", "Submitted", "Cancelled"], Jr = /* @__PURE__ */ new
|
|
|
3243
3243
|
account: "account",
|
|
3244
3244
|
cost_center: "cost-center"
|
|
3245
3245
|
};
|
|
3246
|
-
function
|
|
3246
|
+
function es(t) {
|
|
3247
3247
|
if (typeof t != "string") return null;
|
|
3248
3248
|
const n = t.toLowerCase();
|
|
3249
3249
|
return n === "customer" ? "customer" : n === "supplier" ? "supplier" : null;
|
|
3250
3250
|
}
|
|
3251
|
-
const
|
|
3251
|
+
const ts = ["25", "50", "100", "200"];
|
|
3252
3252
|
function Rn({
|
|
3253
3253
|
page: t,
|
|
3254
3254
|
totalPages: n,
|
|
@@ -3288,7 +3288,7 @@ function Rn({
|
|
|
3288
3288
|
value: a,
|
|
3289
3289
|
onChange: (f) => c(Number(f.target.value)),
|
|
3290
3290
|
className: "h-8 rounded-md bg-surface px-2 text-sm text-fg ring-1 ring-line transition-all focus:outline-none focus:ring-2 focus:ring-brand/30",
|
|
3291
|
-
children:
|
|
3291
|
+
children: ts.map((f) => /* @__PURE__ */ e("option", { value: f, children: f }, f))
|
|
3292
3292
|
}
|
|
3293
3293
|
)
|
|
3294
3294
|
] }),
|
|
@@ -3333,7 +3333,7 @@ function Rn({
|
|
|
3333
3333
|
] })
|
|
3334
3334
|
] });
|
|
3335
3335
|
}
|
|
3336
|
-
function
|
|
3336
|
+
function ns() {
|
|
3337
3337
|
const { t } = X(), n = ze(), { doctype: a } = ut(), s = fa(a ?? ""), o = vt(), i = (s == null ? void 0 : s.listFilters) ?? [], l = Ne(() => {
|
|
3338
3338
|
const P = new URLSearchParams(o.search), V = {};
|
|
3339
3339
|
for (const ne of i) V[ne] = P.get(ne) ?? "";
|
|
@@ -3352,7 +3352,7 @@ function ts() {
|
|
|
3352
3352
|
for (const V of i)
|
|
3353
3353
|
l[V] && (P[V] = l[V]);
|
|
3354
3354
|
return f.length > 0 && v && (P.search = v, P.search_fields = f.join(",")), p && (P.include_discarded = "true"), P.limit = u, P.offset = S * u, P;
|
|
3355
|
-
}, [c, h, d, p, u, S, s == null ? void 0 : s.dateField, i, l, f, v]), { data: R, isLoading: W } =
|
|
3355
|
+
}, [c, h, d, p, u, S, s == null ? void 0 : s.dateField, i, l, f, v]), { data: R, isLoading: W } = Mr(a ?? "", g), $ = (R == null ? void 0 : R.rows) ?? [], de = (R == null ? void 0 : R.total) ?? 0;
|
|
3356
3356
|
re(() => {
|
|
3357
3357
|
const { limit: P, offset: V, ...ne } = g;
|
|
3358
3358
|
ga(a ?? "", { filters: ne, search: o.search });
|
|
@@ -3381,7 +3381,7 @@ function ts() {
|
|
|
3381
3381
|
header: t("fields.Status", { defaultValue: "Status" }),
|
|
3382
3382
|
cell: (H) => /* @__PURE__ */ e(un, { status: H.getValue() })
|
|
3383
3383
|
});
|
|
3384
|
-
if (
|
|
3384
|
+
if (Zr.has(ne))
|
|
3385
3385
|
return P.accessor(ne, {
|
|
3386
3386
|
header: V(ne),
|
|
3387
3387
|
cell: (H) => {
|
|
@@ -3395,7 +3395,7 @@ function ts() {
|
|
|
3395
3395
|
cell: (H) => {
|
|
3396
3396
|
const ce = H.getValue();
|
|
3397
3397
|
if (!ce) return "-";
|
|
3398
|
-
const Se =
|
|
3398
|
+
const Se = es(H.row.original.party_type), E = Se ? en(Se, String(ce)) : null;
|
|
3399
3399
|
return E ? /* @__PURE__ */ e(
|
|
3400
3400
|
ve,
|
|
3401
3401
|
{
|
|
@@ -3427,7 +3427,7 @@ function ts() {
|
|
|
3427
3427
|
}
|
|
3428
3428
|
});
|
|
3429
3429
|
}
|
|
3430
|
-
return
|
|
3430
|
+
return Xr.has(ne) ? P.accessor(ne, {
|
|
3431
3431
|
header: V(ne),
|
|
3432
3432
|
cell: (H) => Ft(H.getValue())
|
|
3433
3433
|
}) : P.accessor(ne, {
|
|
@@ -3457,7 +3457,7 @@ function ts() {
|
|
|
3457
3457
|
Ve,
|
|
3458
3458
|
{
|
|
3459
3459
|
label: t("fields.Status", { defaultValue: "Status" }),
|
|
3460
|
-
options:
|
|
3460
|
+
options: Jr.map((P) => ({
|
|
3461
3461
|
value: P,
|
|
3462
3462
|
label: P === "All" ? t("common.all") : t(`status.${P}`, { defaultValue: P })
|
|
3463
3463
|
})),
|
|
@@ -3669,7 +3669,7 @@ const Tt = () => ({
|
|
|
3669
3669
|
position_title: "",
|
|
3670
3670
|
position_blurb: "",
|
|
3671
3671
|
is_recommended: 0
|
|
3672
|
-
}),
|
|
3672
|
+
}), as = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
3673
3673
|
function In() {
|
|
3674
3674
|
const { name: t } = ut(), n = !t, a = Ee(), s = He(), { t: o } = X(), i = (A, _) => o(A, { defaultValue: _ }), l = ua(), [c, h] = w({
|
|
3675
3675
|
title: "Offerte",
|
|
@@ -3813,7 +3813,7 @@ function In() {
|
|
|
3813
3813
|
] }),
|
|
3814
3814
|
d.map((A, _) => /* @__PURE__ */ r("div", { className: "rounded-lg p-3 ring-1 ring-line", children: [
|
|
3815
3815
|
/* @__PURE__ */ r("div", { className: "mb-2 flex items-center gap-2", children: [
|
|
3816
|
-
/* @__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:
|
|
3816
|
+
/* @__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: as[_] ?? _ + 1 }),
|
|
3817
3817
|
/* @__PURE__ */ e("div", { className: "flex-1", children: /* @__PURE__ */ e(Ae, { label: "", value: A.quotation, onChange: (z) => Z(_, { quotation: z }), linkDoctype: "quotation", readOnly: !1 }) }),
|
|
3818
3818
|
/* @__PURE__ */ e("button", { type: "button", onClick: () => W(_, -1), disabled: _ === 0, className: "px-1 text-fg-muted disabled:opacity-30", children: "↑" }),
|
|
3819
3819
|
/* @__PURE__ */ e("button", { type: "button", onClick: () => W(_, 1), disabled: _ === d.length - 1, className: "px-1 text-fg-muted disabled:opacity-30", children: "↓" }),
|
|
@@ -3848,8 +3848,8 @@ function In() {
|
|
|
3848
3848
|
] })
|
|
3849
3849
|
] });
|
|
3850
3850
|
}
|
|
3851
|
-
const
|
|
3852
|
-
function
|
|
3851
|
+
const rs = ["25", "50", "100", "200"];
|
|
3852
|
+
function ss() {
|
|
3853
3853
|
var y;
|
|
3854
3854
|
const { type: t } = ut(), n = Ee(), a = vt(), s = (y = a.state) == null ? void 0 : y.notice;
|
|
3855
3855
|
re(() => {
|
|
@@ -3941,7 +3941,7 @@ function rs() {
|
|
|
3941
3941
|
value: o,
|
|
3942
3942
|
onChange: (m) => d(Number(m.target.value)),
|
|
3943
3943
|
className: "h-8 rounded-md bg-surface px-2 text-sm text-fg ring-1 ring-line transition-all focus:outline-none focus:ring-2 focus:ring-brand/30",
|
|
3944
|
-
children:
|
|
3944
|
+
children: rs.map((m) => /* @__PURE__ */ e("option", { value: m, children: m }, m))
|
|
3945
3945
|
}
|
|
3946
3946
|
)
|
|
3947
3947
|
] }),
|
|
@@ -3975,7 +3975,7 @@ function rs() {
|
|
|
3975
3975
|
] })
|
|
3976
3976
|
] });
|
|
3977
3977
|
}
|
|
3978
|
-
const
|
|
3978
|
+
const is = {
|
|
3979
3979
|
customer: [
|
|
3980
3980
|
{ name: "name", label: "ID", type: "text", required: !0 },
|
|
3981
3981
|
{ name: "customer_name", label: "Customer Name", type: "text", required: !0 },
|
|
@@ -4038,7 +4038,7 @@ const ss = {
|
|
|
4038
4038
|
{ name: "tax_id", label: "Tax ID", type: "text" },
|
|
4039
4039
|
{ name: "iban", label: "IBAN", type: "text" }
|
|
4040
4040
|
]
|
|
4041
|
-
},
|
|
4041
|
+
}, os = {
|
|
4042
4042
|
customer: "Customer",
|
|
4043
4043
|
supplier: "Supplier",
|
|
4044
4044
|
item: "Item",
|
|
@@ -4047,7 +4047,7 @@ const ss = {
|
|
|
4047
4047
|
}, Bn = /* @__PURE__ */ new Set(["customer", "supplier", "item", "warehouse"]);
|
|
4048
4048
|
function En() {
|
|
4049
4049
|
var Z;
|
|
4050
|
-
const { type: t, name: n } = ut(), a = Ee(), s = He(), { t: o } = X(), i = !n || n === "new", l =
|
|
4050
|
+
const { type: t, name: n } = ut(), a = Ee(), s = He(), { t: o } = X(), i = !n || n === "new", l = os[t ?? ""] ?? t ?? "", c = o(`masters.${t}.one`, { defaultValue: l }), h = is[t ?? ""] ?? [], d = (g) => o(`fields.${g.label}`, { defaultValue: g.label }), [p, u] = w({}), { data: f, isLoading: v } = ue({
|
|
4051
4051
|
queryKey: ["master", t, n],
|
|
4052
4052
|
queryFn: () => I.getMaster(t, n),
|
|
4053
4053
|
enabled: !!t && !!n && !i
|
|
@@ -4187,67 +4187,67 @@ function En() {
|
|
|
4187
4187
|
}) }) })
|
|
4188
4188
|
] });
|
|
4189
4189
|
}
|
|
4190
|
-
function
|
|
4190
|
+
function ls(t) {
|
|
4191
4191
|
const { data: n, isLoading: a, error: s, refetch: o } = ue({
|
|
4192
4192
|
queryKey: ["report", "trial-balance", t],
|
|
4193
4193
|
queryFn: () => I.trialBalance(t)
|
|
4194
4194
|
});
|
|
4195
4195
|
return { data: n, isLoading: a, error: s, refetch: o };
|
|
4196
4196
|
}
|
|
4197
|
-
function
|
|
4197
|
+
function cs(t) {
|
|
4198
4198
|
const { data: n, isLoading: a, error: s, refetch: o } = ue({
|
|
4199
4199
|
queryKey: ["report", "chart-of-accounts", t],
|
|
4200
4200
|
queryFn: () => I.chartOfAccounts(t)
|
|
4201
4201
|
});
|
|
4202
4202
|
return { data: n, isLoading: a, error: s, refetch: o };
|
|
4203
4203
|
}
|
|
4204
|
-
function
|
|
4204
|
+
function ds(t) {
|
|
4205
4205
|
const { data: n, isLoading: a, error: s, refetch: o } = ue({
|
|
4206
4206
|
queryKey: ["report", "general-ledger", t],
|
|
4207
4207
|
queryFn: () => I.generalLedger(t)
|
|
4208
4208
|
});
|
|
4209
4209
|
return { data: n, isLoading: a, error: s, refetch: o };
|
|
4210
4210
|
}
|
|
4211
|
-
function
|
|
4211
|
+
function us(t) {
|
|
4212
4212
|
const { data: n, isLoading: a, error: s, refetch: o } = ue({
|
|
4213
4213
|
queryKey: ["report", "stock-balance", t],
|
|
4214
4214
|
queryFn: () => I.stockBalance(t)
|
|
4215
4215
|
});
|
|
4216
4216
|
return { data: n, isLoading: a, error: s, refetch: o };
|
|
4217
4217
|
}
|
|
4218
|
-
function
|
|
4218
|
+
function ms(t) {
|
|
4219
4219
|
const { data: n, isLoading: a, error: s, refetch: o } = ue({
|
|
4220
4220
|
queryKey: ["report", "profit-and-loss", t],
|
|
4221
4221
|
queryFn: () => I.profitAndLoss(t)
|
|
4222
4222
|
});
|
|
4223
4223
|
return { data: n, isLoading: a, error: s, refetch: o };
|
|
4224
4224
|
}
|
|
4225
|
-
function
|
|
4225
|
+
function ps(t) {
|
|
4226
4226
|
const { data: n, isLoading: a, error: s, refetch: o } = ue({
|
|
4227
4227
|
queryKey: ["report", "balance-sheet", t],
|
|
4228
4228
|
queryFn: () => I.balanceSheet(t)
|
|
4229
4229
|
});
|
|
4230
4230
|
return { data: n, isLoading: a, error: s, refetch: o };
|
|
4231
4231
|
}
|
|
4232
|
-
function
|
|
4232
|
+
function hs(t) {
|
|
4233
4233
|
const { data: n, isLoading: a, error: s, refetch: o } = ue({
|
|
4234
4234
|
queryKey: ["report", "ar-aging", t],
|
|
4235
4235
|
queryFn: () => I.arAging(t)
|
|
4236
4236
|
});
|
|
4237
4237
|
return { data: n, isLoading: a, error: s, refetch: o };
|
|
4238
4238
|
}
|
|
4239
|
-
function
|
|
4239
|
+
function gs(t) {
|
|
4240
4240
|
const { data: n, isLoading: a, error: s, refetch: o } = ue({
|
|
4241
4241
|
queryKey: ["report", "ap-aging", t],
|
|
4242
4242
|
queryFn: () => I.apAging(t)
|
|
4243
4243
|
});
|
|
4244
4244
|
return { data: n, isLoading: a, error: s, refetch: o };
|
|
4245
4245
|
}
|
|
4246
|
-
function
|
|
4246
|
+
function fs() {
|
|
4247
4247
|
const { t } = X(), [n] = le("company", ""), [a] = le("from", ""), [s] = le("to", ""), o = Ye(), [i, l] = w(n), [c, h] = w(a), [d, p] = w(s), u = ze(i), f = (y) => qe(y, u), v = Ne(() => {
|
|
4248
4248
|
const y = {};
|
|
4249
4249
|
return n && (y.company = n), a && (y.from_date = a), s && (y.to_date = s), y;
|
|
4250
|
-
}, [n, a, s]), { data: N, isLoading: b, refetch: C } =
|
|
4250
|
+
}, [n, a, s]), { data: N, isLoading: b, refetch: C } = ls(v), S = () => {
|
|
4251
4251
|
o({
|
|
4252
4252
|
company: i || null,
|
|
4253
4253
|
from: c || null,
|
|
@@ -4320,8 +4320,8 @@ function gs() {
|
|
|
4320
4320
|
] })
|
|
4321
4321
|
] });
|
|
4322
4322
|
}
|
|
4323
|
-
const
|
|
4324
|
-
function
|
|
4323
|
+
const ys = ["Asset", "Liability", "Equity", "Income", "Expense"];
|
|
4324
|
+
function bs() {
|
|
4325
4325
|
const { t } = X(), n = (/* @__PURE__ */ new Date()).getFullYear(), [a, s] = w(String(n)), [o, i] = w(/* @__PURE__ */ new Set()), l = Ne(() => {
|
|
4326
4326
|
const x = [];
|
|
4327
4327
|
for (let y = n; y >= n - 6; y--)
|
|
@@ -4330,7 +4330,7 @@ function ys() {
|
|
|
4330
4330
|
}, [n, t]), c = Ne(() => {
|
|
4331
4331
|
const x = {};
|
|
4332
4332
|
return a !== "all" && (x.from_date = `${a}-01-01`, x.to_date = `${a}-12-31`), x;
|
|
4333
|
-
}, [a]), { data: h, isLoading: d } =
|
|
4333
|
+
}, [a]), { data: h, isLoading: d } = cs(c), p = ze(""), u = (x) => qe(x, p), f = (h == null ? void 0 : h.accounts) ?? [], { childrenOf: v, rootsByType: N } = Ne(() => {
|
|
4334
4334
|
const x = new Map(f.map((D) => [D.name, D])), y = /* @__PURE__ */ new Map(), m = /* @__PURE__ */ new Map();
|
|
4335
4335
|
for (const D of f)
|
|
4336
4336
|
if (D.parent_account && x.has(D.parent_account)) {
|
|
@@ -4400,21 +4400,21 @@ function ys() {
|
|
|
4400
4400
|
] }),
|
|
4401
4401
|
d && /* @__PURE__ */ e(M, { children: /* @__PURE__ */ e("p", { className: "text-sm text-fg-muted", children: t("common.loading", { defaultValue: "Loading…" }) }) }),
|
|
4402
4402
|
!d && f.length === 0 && /* @__PURE__ */ e(M, { children: /* @__PURE__ */ e("p", { className: "text-sm text-fg-muted", children: t("coa.empty", { defaultValue: "No accounts found. Complete the company setup first." }) }) }),
|
|
4403
|
-
!d &&
|
|
4403
|
+
!d && ys.filter((x) => (N.get(x) ?? []).length > 0).map((x) => /* @__PURE__ */ r(M, { children: [
|
|
4404
4404
|
/* @__PURE__ */ e("h3", { className: "mb-2 px-2 text-xs font-semibold uppercase tracking-wider text-fg-muted", children: t(`coa.rootType.${x}`, { defaultValue: x }) }),
|
|
4405
4405
|
/* @__PURE__ */ e("div", { children: (N.get(x) ?? []).map((y) => S(y, 0)) })
|
|
4406
4406
|
] }, x))
|
|
4407
4407
|
] });
|
|
4408
4408
|
}
|
|
4409
|
-
function
|
|
4409
|
+
function vs(t) {
|
|
4410
4410
|
return t.toLowerCase().replace(/\s+/g, "-");
|
|
4411
4411
|
}
|
|
4412
|
-
const
|
|
4413
|
-
function
|
|
4412
|
+
const xs = ["25", "50", "100", "200"];
|
|
4413
|
+
function Ns() {
|
|
4414
4414
|
const { t } = X(), [n] = le("account", ""), [a] = le("party", ""), [s] = le("from", ""), [o] = le("to", ""), [i] = le("per_page", 50), [l] = le("page", 1), c = l - 1, h = Ye(), d = (_) => h({ page: _ === 0 ? null : _ + 1 }), p = (_) => h({ per_page: _, page: null }), [u, f] = w(n), [v, N] = w(a), [b, C] = w(s), [S, x] = w(o), y = ze(), m = (_) => qe(_, y), D = Ne(() => {
|
|
4415
4415
|
const _ = {};
|
|
4416
4416
|
return n && (_.account = n), a && (_.party = a), s && (_.from_date = s), o && (_.to_date = o), _.limit = String(i), _.offset = String(c * i), _;
|
|
4417
|
-
}, [n, a, s, o, i, c]), { data: T, isLoading: U, refetch: Z } =
|
|
4417
|
+
}, [n, a, s, o, i, c]), { data: T, isLoading: U, refetch: Z } = ds(D), g = (T == null ? void 0 : T.rows) ?? [], R = (T == null ? void 0 : T.total) ?? 0, W = Math.max(1, Math.ceil(R / i)), $ = R === 0 ? 0 : c * i + 1, de = Math.min(R, (c + 1) * i), A = () => {
|
|
4418
4418
|
h({
|
|
4419
4419
|
account: u || null,
|
|
4420
4420
|
party: v || null,
|
|
@@ -4491,7 +4491,7 @@ function xs() {
|
|
|
4491
4491
|
/* @__PURE__ */ e("td", { className: "px-4 py-2", children: _.voucher_type && _.voucher_no ? /* @__PURE__ */ e(
|
|
4492
4492
|
ve,
|
|
4493
4493
|
{
|
|
4494
|
-
to: `/app/${
|
|
4494
|
+
to: `/app/${vs(_.voucher_type)}/${_.voucher_no}`,
|
|
4495
4495
|
className: "font-medium text-blue-600 hover:text-blue-800",
|
|
4496
4496
|
children: _.voucher_no
|
|
4497
4497
|
}
|
|
@@ -4521,7 +4521,7 @@ function xs() {
|
|
|
4521
4521
|
value: i,
|
|
4522
4522
|
onChange: (_) => p(Number(_.target.value)),
|
|
4523
4523
|
className: "rounded border border-gray-300 bg-white px-2 py-1 text-sm",
|
|
4524
|
-
children:
|
|
4524
|
+
children: xs.map((_) => /* @__PURE__ */ e("option", { value: _, children: _ }, _))
|
|
4525
4525
|
}
|
|
4526
4526
|
)
|
|
4527
4527
|
] }),
|
|
@@ -4557,11 +4557,11 @@ function xs() {
|
|
|
4557
4557
|
] })
|
|
4558
4558
|
] });
|
|
4559
4559
|
}
|
|
4560
|
-
function
|
|
4560
|
+
function ws() {
|
|
4561
4561
|
const { t } = X(), [n] = le("item_code", ""), [a] = le("warehouse", ""), s = Ye(), [o, i] = w(n), [l, c] = w(a), h = ze(), d = (b) => qe(b, h), p = Ne(() => {
|
|
4562
4562
|
const b = {};
|
|
4563
4563
|
return n && (b.item_code = n), a && (b.warehouse = a), b;
|
|
4564
|
-
}, [n, a]), { data: u, isLoading: f, refetch: v } =
|
|
4564
|
+
}, [n, a]), { data: u, isLoading: f, refetch: v } = us(p), N = () => {
|
|
4565
4565
|
s({
|
|
4566
4566
|
item_code: o || null,
|
|
4567
4567
|
warehouse: l || null
|
|
@@ -4611,11 +4611,11 @@ function Ns() {
|
|
|
4611
4611
|
] }) }) })
|
|
4612
4612
|
] });
|
|
4613
4613
|
}
|
|
4614
|
-
function
|
|
4614
|
+
function ks() {
|
|
4615
4615
|
const { t } = X(), [n] = le("company", ""), [a] = le("from", ""), [s] = le("to", ""), o = Ye(), [i, l] = w(n), c = ze(i), h = (y) => qe(y, c), [d, p] = w(a), [u, f] = w(s), v = Ne(() => {
|
|
4616
4616
|
const y = {};
|
|
4617
4617
|
return n && (y.company = n), a && (y.from_date = a), s && (y.to_date = s), y;
|
|
4618
|
-
}, [n, a, s]), { data: N, isLoading: b, refetch: C } =
|
|
4618
|
+
}, [n, a, s]), { data: N, isLoading: b, refetch: C } = ms(v), S = () => {
|
|
4619
4619
|
o({
|
|
4620
4620
|
company: i || null,
|
|
4621
4621
|
from: d || null,
|
|
@@ -4695,12 +4695,12 @@ function Wt({ title: t, rows: n, total: a, totalLabel: s, currency: o }) {
|
|
|
4695
4695
|
] })
|
|
4696
4696
|
] });
|
|
4697
4697
|
}
|
|
4698
|
-
function
|
|
4698
|
+
function Cs() {
|
|
4699
4699
|
var S, x, y;
|
|
4700
4700
|
const { t } = X(), [n] = le("company", ""), [a] = le("as_of_date", ""), s = Ye(), [o, i] = w(n), [l, c] = w(a), h = ze(o), d = (m) => qe(m, h), p = Ne(() => {
|
|
4701
4701
|
const m = {};
|
|
4702
4702
|
return n && (m.company = n), a && (m.as_of_date = a), m;
|
|
4703
|
-
}, [n, a]), { data: u, isLoading: f, refetch: v } =
|
|
4703
|
+
}, [n, a]), { data: u, isLoading: f, refetch: v } = ps(p), N = () => {
|
|
4704
4704
|
s({ company: o || null, as_of_date: l || null }), v();
|
|
4705
4705
|
}, b = u && (((S = u.assets) == null ? void 0 : S.length) > 0 || ((x = u.liabilities) == null ? void 0 : x.length) > 0 || ((y = u.equity) == null ? void 0 : y.length) > 0), C = u ? Math.abs(u.total_assets - u.total_liabilities_and_equity) < 0.01 : !1;
|
|
4706
4706
|
return /* @__PURE__ */ r("div", { className: "space-y-4", children: [
|
|
@@ -4734,11 +4734,11 @@ function ks() {
|
|
|
4734
4734
|
] }) : /* @__PURE__ */ e("p", { className: "py-8 text-center text-gray-400", children: t("reports.noData") })
|
|
4735
4735
|
] });
|
|
4736
4736
|
}
|
|
4737
|
-
function
|
|
4737
|
+
function Ss() {
|
|
4738
4738
|
const { t } = X(), [n] = le("company", ""), [a] = le("as_of_date", ""), s = Ye(), [o, i] = w(n), [l, c] = w(a), h = ze(o), d = (b) => qe(b, h), p = Ne(() => {
|
|
4739
4739
|
const b = {};
|
|
4740
4740
|
return n && (b.company = n), a && (b.as_of_date = a), b;
|
|
4741
|
-
}, [n, a]), { data: u, isLoading: f, refetch: v } =
|
|
4741
|
+
}, [n, a]), { data: u, isLoading: f, refetch: v } = hs(p), N = () => {
|
|
4742
4742
|
s({ company: o || null, as_of_date: l || null }), v();
|
|
4743
4743
|
};
|
|
4744
4744
|
return /* @__PURE__ */ r("div", { className: "space-y-4", children: [
|
|
@@ -4792,11 +4792,11 @@ function Cs() {
|
|
|
4792
4792
|
] }) }) })
|
|
4793
4793
|
] });
|
|
4794
4794
|
}
|
|
4795
|
-
function
|
|
4795
|
+
function Ds() {
|
|
4796
4796
|
const { t } = X(), [n] = le("company", ""), [a] = le("as_of_date", ""), s = Ye(), [o, i] = w(n), [l, c] = w(a), h = ze(o), d = (b) => qe(b, h), p = Ne(() => {
|
|
4797
4797
|
const b = {};
|
|
4798
4798
|
return n && (b.company = n), a && (b.as_of_date = a), b;
|
|
4799
|
-
}, [n, a]), { data: u, isLoading: f, refetch: v } =
|
|
4799
|
+
}, [n, a]), { data: u, isLoading: f, refetch: v } = gs(p), N = () => {
|
|
4800
4800
|
s({ company: o || null, as_of_date: l || null }), v();
|
|
4801
4801
|
};
|
|
4802
4802
|
return /* @__PURE__ */ r("div", { className: "space-y-4", children: [
|
|
@@ -4851,7 +4851,7 @@ function Ss() {
|
|
|
4851
4851
|
] });
|
|
4852
4852
|
}
|
|
4853
4853
|
const va = '(function(){"use strict";function u(r,t){const e=Number(r??0)||0;return t==null?e:Number(e.toFixed(t))}const p={flt:u,sum(r,t){return r.reduce((e,a)=>typeof t=="function"?e+u(t(a)):typeof t=="string"?e+u(a[t]):e+u(a),0)},count(r){return r.length},sortBy(r,t,e="asc"){const n=(e===!0?"desc":e===!1?"asc":e)==="desc"?-1:1;return[...r].sort((s,i)=>{const c=s[t],o=i[t];return c==null&&o==null?0:c==null?1:o==null?-1:c<o?-1*n:c>o?1*n:0})},topN(r,t,e=10){return typeof t=="number"?r.slice(0,t):p.sortBy(r,t,"desc").slice(0,e)},group(r,t,e){if(typeof t=="function"){const s=new Map;for(const i of r){const c=t(i),o=JSON.stringify(c);s.has(o)||s.set(o,{key:c,rows:[]}),s.get(o).rows.push(i)}return Array.from(s.values())}const a=t,n=new Map;for(const s of r){const i=a.map(f=>s[f]),c=JSON.stringify(i);if(!n.has(c)){const f={};a.forEach((l,m)=>{f[l]=i[m]});for(const[l,[m]]of Object.entries(e||{}))f[l]=0;n.set(c,f)}const o=n.get(c);for(const[f,[l,m]]of Object.entries(e||{}))l==="count"?o[f]=u(o[f])+1:o[f]=u(o[f])+u(s[m||f])}return Array.from(n.values())},leftJoin(r,t,e,a=e){const n=new Map(t.map(s=>[s[a],s]));return r.map(s=>({...s,...n.get(s[e])||{}}))},monthKey(r){return String(r??"").slice(0,7)},quarterKey(r){const t=String(r??""),e=t.slice(0,4),a=Number(t.slice(5,7));return!e||!a?"":`${e}-Q${Math.floor((a+2)/3)}`},yearKey(r){return String(r??"").slice(0,4)},pivot(r,t,e,a){const n=new Map;for(const s of r){const i=String(s[t]??"—"),c=String(s[e]??"—");n.has(i)||n.set(i,{[t]:i});const o=n.get(i);o[c]=u(o[c])+u(s[a])}return Array.from(n.values())}};function y(r){if(!r||typeof r!="object")throw new Error("Transform must return an object");if(r.tables&&!Array.isArray(r.tables))throw new Error("tables must be an array");if(r.charts&&!Array.isArray(r.charts))throw new Error("charts must be an array");if(r.kpis&&!Array.isArray(r.kpis))throw new Error("kpis must be an array");return r}self.onmessage=r=>{try{const t=Object.fromEntries(r.data.datasets.map(s=>[s.name,s.rows])),e=r.data.datasets.map(s=>s.name).filter(s=>/^[$A-Z_][0-9A-Z_$]*$/i.test(s)).map(s=>`const ${s} = datasets[${JSON.stringify(s)}];`).join(`\n`),n=new Function("datasets","params","helpers",`"use strict";\n${e}\n${r.data.transformJs}`)(t,r.data.params||{},p);self.postMessage({ok:!0,output:y(n)})}catch(t){self.postMessage({ok:!1,error:t instanceof Error?t.message:String(t)})}}})();\n//# sourceMappingURL=report-runtime.worker-DrBTCfV6.js.map\n', Ln = typeof self < "u" && self.Blob && new Blob([va], { type: "text/javascript;charset=utf-8" });
|
|
4854
|
-
function
|
|
4854
|
+
function As(t) {
|
|
4855
4855
|
let n;
|
|
4856
4856
|
try {
|
|
4857
4857
|
if (n = Ln && (self.URL || self.webkitURL).createObjectURL(Ln), !n) throw "";
|
|
@@ -4872,7 +4872,7 @@ function Ds(t) {
|
|
|
4872
4872
|
n && (self.URL || self.webkitURL).revokeObjectURL(n);
|
|
4873
4873
|
}
|
|
4874
4874
|
}
|
|
4875
|
-
function
|
|
4875
|
+
function Ps() {
|
|
4876
4876
|
const t = /* @__PURE__ */ new Date(), n = t.toISOString().slice(0, 10), a = new Date(t);
|
|
4877
4877
|
a.setMonth(a.getMonth() - 12);
|
|
4878
4878
|
const s = a.toISOString().slice(0, 10);
|
|
@@ -4943,9 +4943,9 @@ return {
|
|
|
4943
4943
|
2
|
|
4944
4944
|
);
|
|
4945
4945
|
}
|
|
4946
|
-
const xa =
|
|
4947
|
-
function
|
|
4948
|
-
const t = Ee(), { sessions: n, createSession: a } = mt(), [s] = le("report_id", ""), [o] = le("metric", ""), [i] = le("group_by", ""), [l] = le("from", ""), [c] = le("to", ""), [h] = le("company", ""), [d, p] = w(xa), [u, f] = w([]), [v, N] = w(null), [b, C] = w(""), [S, x] = w(!1), [y, m] = w(!1), [D, T] = w(""), U = oe(null), Z = oe(""), g = oe(""), R = oe(0), W = Ne(() => !o || !i ? "" : JSON.stringify(
|
|
4946
|
+
const xa = Ps();
|
|
4947
|
+
function _s() {
|
|
4948
|
+
const t = Ee(), { sessions: n, createSession: a } = mt(), [s] = le("report_id", ""), [o] = le("metric", ""), [i] = le("group_by", ""), [l] = le("from", ""), [c] = le("to", ""), [h] = le("company", ""), [d, p] = w(xa), [u, f] = w([]), [v, N] = w(null), [b, C] = w(""), [S, x] = w(!1), [y, m] = w(!1), [D, T] = w(""), U = oe(null), Z = oe(""), g = oe(""), R = oe(0), W = Ne(() => !o || !i ? "" : JSON.stringify(Bs({
|
|
4949
4949
|
metric: o,
|
|
4950
4950
|
groupBy: i,
|
|
4951
4951
|
fromDate: l || void 0,
|
|
@@ -4959,7 +4959,7 @@ function Ps() {
|
|
|
4959
4959
|
const ne = JSON.parse(z ?? d), H = await I.runtimeData({ requests: ne.data_requests || [] });
|
|
4960
4960
|
if (!se()) return;
|
|
4961
4961
|
f(H.datasets), (P = U.current) == null || P.terminate();
|
|
4962
|
-
const ce = new
|
|
4962
|
+
const ce = new As();
|
|
4963
4963
|
U.current = ce;
|
|
4964
4964
|
const Se = await new Promise((E, ie) => {
|
|
4965
4965
|
const Le = window.setTimeout(() => {
|
|
@@ -4999,7 +4999,7 @@ function Ps() {
|
|
|
4999
4999
|
z = !0;
|
|
5000
5000
|
});
|
|
5001
5001
|
}, [s, W]);
|
|
5002
|
-
const de = !!(!s && W), A = Ne(() =>
|
|
5002
|
+
const de = !!(!s && W), A = Ne(() => Is(v), [v]), _ = async () => {
|
|
5003
5003
|
var H;
|
|
5004
5004
|
const z = d.trim() !== g.current.trim(), ee = s || "unsaved-runtime-report", se = u.map((ce) => ({
|
|
5005
5005
|
name: ce.name,
|
|
@@ -5051,7 +5051,7 @@ function Ps() {
|
|
|
5051
5051
|
/* @__PURE__ */ e(Q, { onClick: () => void $(), disabled: S, children: S ? "Running..." : "Run Report" })
|
|
5052
5052
|
] })
|
|
5053
5053
|
] }) }),
|
|
5054
|
-
y ? /* @__PURE__ */ e(M, { children: /* @__PURE__ */ e("p", { className: "text-sm text-gray-600", children: "Loading draft..." }) }) : b ? /* @__PURE__ */ e(M, { children: /* @__PURE__ */ e("p", { className: "text-sm text-red-600", children: b }) }) : v ? /* @__PURE__ */ e(
|
|
5054
|
+
y ? /* @__PURE__ */ e(M, { children: /* @__PURE__ */ e("p", { className: "text-sm text-gray-600", children: "Loading draft..." }) }) : b ? /* @__PURE__ */ e(M, { children: /* @__PURE__ */ e("p", { className: "text-sm text-red-600", children: b }) }) : v ? /* @__PURE__ */ e(Ts, { output: v }) : /* @__PURE__ */ e(M, { children: /* @__PURE__ */ e("p", { className: "text-sm text-gray-600", children: "Edit the runtime JSON below or open a draft from chat, then run the report." }) }),
|
|
5055
5055
|
u.length > 0 && /* @__PURE__ */ e(M, { title: "Fetched Datasets", children: /* @__PURE__ */ e("div", { className: "space-y-4", children: u.map((z) => /* @__PURE__ */ r("div", { className: "rounded-md border border-gray-200 p-4", children: [
|
|
5056
5056
|
/* @__PURE__ */ r("div", { className: "flex items-baseline justify-between gap-4", children: [
|
|
5057
5057
|
/* @__PURE__ */ r("div", { children: [
|
|
@@ -5080,7 +5080,7 @@ function Ps() {
|
|
|
5080
5080
|
] })
|
|
5081
5081
|
] });
|
|
5082
5082
|
}
|
|
5083
|
-
function
|
|
5083
|
+
function Ts({ output: t }) {
|
|
5084
5084
|
var o, i;
|
|
5085
5085
|
const n = ze(), a = (t.tables ?? []).map((l, c) => ({
|
|
5086
5086
|
...l,
|
|
@@ -5101,10 +5101,10 @@ function _s({ output: t }) {
|
|
|
5101
5101
|
const h = l.dataTable ? s.get(l.dataTable) : void 0, d = l.data ?? (h == null ? void 0 : h.rows) ?? [];
|
|
5102
5102
|
if (!d.length)
|
|
5103
5103
|
return /* @__PURE__ */ e(M, { title: l.title, children: /* @__PURE__ */ e("p", { className: "text-sm text-red-600", children: "Chart has no usable data." }) }, l.id || `chart_${c + 1}`);
|
|
5104
|
-
const p = l.type === "pie" ? [] : d.map((v) => String(v[l.x] ?? "")), u =
|
|
5104
|
+
const p = l.type === "pie" ? [] : d.map((v) => String(v[l.x] ?? "")), u = qs(p), f = Math.max(320, 200 + u.axisHeight);
|
|
5105
5105
|
return /* @__PURE__ */ r(M, { children: [
|
|
5106
5106
|
/* @__PURE__ */ e("div", { className: "pb-3 text-sm font-semibold text-gray-700", children: l.title }),
|
|
5107
|
-
/* @__PURE__ */ e("div", { style: { height: f }, className: "w-full", children: /* @__PURE__ */ e(
|
|
5107
|
+
/* @__PURE__ */ e("div", { style: { height: f }, className: "w-full", children: /* @__PURE__ */ e(ar, { width: "100%", height: "100%", children: l.type === "line" ? /* @__PURE__ */ r(rr, { data: d, margin: { top: 10, right: 20, left: 0, bottom: 0 }, children: [
|
|
5108
5108
|
/* @__PURE__ */ e(fn, { strokeDasharray: "3 3", stroke: "#f3f4f6" }),
|
|
5109
5109
|
/* @__PURE__ */ e(
|
|
5110
5110
|
yn,
|
|
@@ -5119,11 +5119,11 @@ function _s({ output: t }) {
|
|
|
5119
5119
|
),
|
|
5120
5120
|
/* @__PURE__ */ e(bn, { tick: { fill: "#6b7280", fontSize: 12 }, tickFormatter: On }),
|
|
5121
5121
|
/* @__PURE__ */ e(Kt, { formatter: (v) => Ct(v, Ht(h, l.y), n) }),
|
|
5122
|
-
/* @__PURE__ */ e(
|
|
5123
|
-
] }) : l.type === "pie" ? /* @__PURE__ */ r(
|
|
5122
|
+
/* @__PURE__ */ e(sr, { type: "monotone", dataKey: l.y, stroke: "#3b82f6", strokeWidth: 2, dot: { r: 3 } })
|
|
5123
|
+
] }) : l.type === "pie" ? /* @__PURE__ */ r(ir, { children: [
|
|
5124
5124
|
/* @__PURE__ */ e(Kt, { formatter: (v) => Ct(v, Ht(h, l.y), n) }),
|
|
5125
|
-
/* @__PURE__ */ e(
|
|
5126
|
-
] }) : /* @__PURE__ */ r(
|
|
5125
|
+
/* @__PURE__ */ e(or, { data: d, dataKey: l.y, nameKey: l.x, outerRadius: 110, children: d.map((v, N) => /* @__PURE__ */ e(lr, { fill: qn[N % qn.length] }, N)) })
|
|
5126
|
+
] }) : /* @__PURE__ */ r(cr, { data: d, margin: { top: 10, right: 20, left: 0, bottom: 0 }, children: [
|
|
5127
5127
|
/* @__PURE__ */ e(fn, { strokeDasharray: "3 3", stroke: "#f3f4f6" }),
|
|
5128
5128
|
/* @__PURE__ */ e(
|
|
5129
5129
|
yn,
|
|
@@ -5138,7 +5138,7 @@ function _s({ output: t }) {
|
|
|
5138
5138
|
),
|
|
5139
5139
|
/* @__PURE__ */ e(bn, { tick: { fill: "#6b7280", fontSize: 12 }, tickFormatter: On }),
|
|
5140
5140
|
/* @__PURE__ */ e(Kt, { formatter: (v) => Ct(v, Ht(h, l.y), n) }),
|
|
5141
|
-
/* @__PURE__ */ e(
|
|
5141
|
+
/* @__PURE__ */ e(dr, { dataKey: l.y, fill: "#3b82f6", radius: [4, 4, 0, 0] })
|
|
5142
5142
|
] }) }) })
|
|
5143
5143
|
] }, l.id || `chart_${c + 1}`);
|
|
5144
5144
|
}),
|
|
@@ -5148,7 +5148,7 @@ function _s({ output: t }) {
|
|
|
5148
5148
|
] }) }) }, l.id))
|
|
5149
5149
|
] });
|
|
5150
5150
|
}
|
|
5151
|
-
function
|
|
5151
|
+
function Rs(t) {
|
|
5152
5152
|
return t.replace(/_/g, " ").replace(/\b\w/g, (n) => n.toUpperCase());
|
|
5153
5153
|
}
|
|
5154
5154
|
function Na(t) {
|
|
@@ -5157,7 +5157,7 @@ function Na(t) {
|
|
|
5157
5157
|
n.set(a.id, a), a.title && n.set(a.title, a);
|
|
5158
5158
|
return n;
|
|
5159
5159
|
}
|
|
5160
|
-
function
|
|
5160
|
+
function Is(t) {
|
|
5161
5161
|
if (!t) return [];
|
|
5162
5162
|
const n = (t.tables ?? []).map((o, i) => ({
|
|
5163
5163
|
...o,
|
|
@@ -5173,8 +5173,8 @@ function Rs(t) {
|
|
|
5173
5173
|
}
|
|
5174
5174
|
return s;
|
|
5175
5175
|
}
|
|
5176
|
-
function
|
|
5177
|
-
const n = `${
|
|
5176
|
+
function Bs(t) {
|
|
5177
|
+
const n = `${Es(t.metric)} by ${Rs(t.groupBy)}`, a = t.groupBy === "month" ? "helpers.monthKey" : t.groupBy === "quarter" ? "helpers.quarterKey" : "helpers.yearKey";
|
|
5178
5178
|
if (t.metric === "sales_revenue")
|
|
5179
5179
|
return bt({
|
|
5180
5180
|
title: n,
|
|
@@ -5333,7 +5333,7 @@ return {
|
|
|
5333
5333
|
};`
|
|
5334
5334
|
};
|
|
5335
5335
|
}
|
|
5336
|
-
function
|
|
5336
|
+
function Es(t) {
|
|
5337
5337
|
return {
|
|
5338
5338
|
sales_revenue: "Sales Revenue",
|
|
5339
5339
|
sales_returns: "Sales Returns",
|
|
@@ -5356,24 +5356,24 @@ function On(t) {
|
|
|
5356
5356
|
const n = Math.abs(t);
|
|
5357
5357
|
return n >= 1e6 ? `${(t / 1e6).toFixed(1)}M` : n >= 1e3 ? `${(t / 1e3).toFixed(0)}k` : String(t);
|
|
5358
5358
|
}
|
|
5359
|
-
const qn = ["#3b82f6", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6", "#06b6d4"],
|
|
5359
|
+
const qn = ["#3b82f6", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6", "#06b6d4"], Ls = '12px -apple-system, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
|
|
5360
5360
|
let Qt = null;
|
|
5361
|
-
function
|
|
5361
|
+
function Os(t, n = Ls) {
|
|
5362
5362
|
if (typeof document > "u") return t.length * 7;
|
|
5363
5363
|
Qt || (Qt = document.createElement("canvas"));
|
|
5364
5364
|
const a = Qt.getContext("2d");
|
|
5365
5365
|
return a ? (a.font = n, a.measureText(t).width) : t.length * 7;
|
|
5366
5366
|
}
|
|
5367
|
-
function
|
|
5367
|
+
function qs(t) {
|
|
5368
5368
|
if (!t.length) return { angle: 0, axisHeight: 30, maxWidth: 0 };
|
|
5369
|
-
const n = t.map((c) =>
|
|
5369
|
+
const n = t.map((c) => Os(c)), a = Math.max(1, ...n);
|
|
5370
5370
|
let s = 0;
|
|
5371
5371
|
a > 55 && (s = -30), a > 110 && (s = -45), a > 200 && (s = -60), a > 300 && (s = -90);
|
|
5372
5372
|
const o = Math.abs(s) * Math.PI / 180, i = s === 0 ? 20 : Math.abs(s) === 90 ? a : Math.ceil(a * Math.sin(o)), l = Math.min(280, Math.max(30, i + 18));
|
|
5373
5373
|
return { angle: s, axisHeight: l, maxWidth: a };
|
|
5374
5374
|
}
|
|
5375
|
-
const
|
|
5376
|
-
function
|
|
5375
|
+
const zs = ["USD", "EUR", "GBP", "CHF", "JPY", "CAD", "AUD", "CNY", "INR"];
|
|
5376
|
+
function Ms() {
|
|
5377
5377
|
const t = He(), { data: n, isLoading: a } = ue({
|
|
5378
5378
|
queryKey: ["setup-status"],
|
|
5379
5379
|
queryFn: () => I.setupStatus()
|
|
@@ -5406,7 +5406,7 @@ function zs() {
|
|
|
5406
5406
|
return /* @__PURE__ */ e("p", { className: "text-gray-500", children: "Loading..." });
|
|
5407
5407
|
if (n != null && n.setup_complete && !f)
|
|
5408
5408
|
return /* @__PURE__ */ r("div", { className: "space-y-6", children: [
|
|
5409
|
-
/* @__PURE__ */ e(M, { title: "Companies", children: n.companies && n.companies.length > 0 ? /* @__PURE__ */ e("ul", { className: "divide-y divide-gray-100", children: n.companies.map((T, U) => /* @__PURE__ */ e("li", { className: "py-3", children: /* @__PURE__ */ e(
|
|
5409
|
+
/* @__PURE__ */ e(M, { title: "Companies", children: n.companies && n.companies.length > 0 ? /* @__PURE__ */ e("ul", { className: "divide-y divide-gray-100", children: n.companies.map((T, U) => /* @__PURE__ */ e("li", { className: "py-3", children: /* @__PURE__ */ e(Fs, { company: T }) }, U)) }) : /* @__PURE__ */ e("p", { className: "text-gray-400", children: "No companies found" }) }),
|
|
5410
5410
|
/* @__PURE__ */ e(ve, { to: "/", className: "text-blue-600 hover:text-blue-800 text-sm font-medium", children: "Go to Dashboard" })
|
|
5411
5411
|
] });
|
|
5412
5412
|
if (f)
|
|
@@ -5441,7 +5441,7 @@ function zs() {
|
|
|
5441
5441
|
Ve,
|
|
5442
5442
|
{
|
|
5443
5443
|
label: "Currency",
|
|
5444
|
-
options:
|
|
5444
|
+
options: zs,
|
|
5445
5445
|
value: i,
|
|
5446
5446
|
onChange: (T) => l(T.target.value)
|
|
5447
5447
|
}
|
|
@@ -5536,7 +5536,7 @@ function zs() {
|
|
|
5536
5536
|
] }) })
|
|
5537
5537
|
] });
|
|
5538
5538
|
}
|
|
5539
|
-
function
|
|
5539
|
+
function Fs({ company: t }) {
|
|
5540
5540
|
const n = [
|
|
5541
5541
|
[t.city, t.zip_code].filter(Boolean).join(" "),
|
|
5542
5542
|
t.country
|
|
@@ -5577,7 +5577,7 @@ function Ms({ company: t }) {
|
|
|
5577
5577
|
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 })
|
|
5578
5578
|
] });
|
|
5579
5579
|
}
|
|
5580
|
-
const
|
|
5580
|
+
const $s = [
|
|
5581
5581
|
{
|
|
5582
5582
|
number: 1,
|
|
5583
5583
|
title: "Set Up Your Company",
|
|
@@ -5729,7 +5729,7 @@ function wa() {
|
|
|
5729
5729
|
t(`/chat/${o}`, { state: { prefillMessage: s } });
|
|
5730
5730
|
};
|
|
5731
5731
|
}
|
|
5732
|
-
function
|
|
5732
|
+
function Us() {
|
|
5733
5733
|
const { t } = X(), n = wa();
|
|
5734
5734
|
return /* @__PURE__ */ e(M, { 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: [
|
|
5735
5735
|
/* @__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: "▶" }),
|
|
@@ -5765,7 +5765,7 @@ function $s() {
|
|
|
5765
5765
|
] })
|
|
5766
5766
|
] }) });
|
|
5767
5767
|
}
|
|
5768
|
-
function
|
|
5768
|
+
function Vs() {
|
|
5769
5769
|
const { t } = X(), n = wa(), a = [
|
|
5770
5770
|
t("tutorial.caPrompt1"),
|
|
5771
5771
|
t("tutorial.caPrompt2"),
|
|
@@ -5824,7 +5824,7 @@ function Us() {
|
|
|
5824
5824
|
] })
|
|
5825
5825
|
] }) });
|
|
5826
5826
|
}
|
|
5827
|
-
function
|
|
5827
|
+
function Ks() {
|
|
5828
5828
|
const { t } = X(), n = (a) => t(`tutorial.chips.${a}`, { defaultValue: a });
|
|
5829
5829
|
return /* @__PURE__ */ r(M, { children: [
|
|
5830
5830
|
/* @__PURE__ */ e("h3", { className: "text-base font-semibold text-gray-900 mb-3", children: t("tutorial.flowTitle") }),
|
|
@@ -5895,7 +5895,7 @@ function Vs() {
|
|
|
5895
5895
|
] })
|
|
5896
5896
|
] });
|
|
5897
5897
|
}
|
|
5898
|
-
function
|
|
5898
|
+
function js() {
|
|
5899
5899
|
const { t } = X(), n = (a) => t(`tutorial.chips.${a}`, { defaultValue: a });
|
|
5900
5900
|
return /* @__PURE__ */ r(M, { children: [
|
|
5901
5901
|
/* @__PURE__ */ e("h3", { className: "text-base font-semibold text-gray-900 mb-3", children: t("tutorial.lifecycleTitle") }),
|
|
@@ -5931,7 +5931,7 @@ function Ks() {
|
|
|
5931
5931
|
] })
|
|
5932
5932
|
] });
|
|
5933
5933
|
}
|
|
5934
|
-
function
|
|
5934
|
+
function Gs() {
|
|
5935
5935
|
const { t } = X();
|
|
5936
5936
|
return /* @__PURE__ */ r("div", { className: "mx-auto max-w-3xl space-y-6", children: [
|
|
5937
5937
|
/* @__PURE__ */ r("div", { children: [
|
|
@@ -5955,11 +5955,11 @@ function js() {
|
|
|
5955
5955
|
] }),
|
|
5956
5956
|
/* @__PURE__ */ e("p", { className: "mt-4 text-sm text-gray-500", children: t("tutorial.manualIntro") })
|
|
5957
5957
|
] }),
|
|
5958
|
-
/* @__PURE__ */ e($s, {}),
|
|
5959
5958
|
/* @__PURE__ */ e(Us, {}),
|
|
5960
5959
|
/* @__PURE__ */ e(Vs, {}),
|
|
5961
5960
|
/* @__PURE__ */ e(Ks, {}),
|
|
5962
|
-
|
|
5961
|
+
/* @__PURE__ */ e(js, {}),
|
|
5962
|
+
$s.map((n) => {
|
|
5963
5963
|
var a;
|
|
5964
5964
|
return /* @__PURE__ */ e(M, { children: /* @__PURE__ */ r("div", { className: "flex gap-4", children: [
|
|
5965
5965
|
/* @__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 }),
|
|
@@ -6020,7 +6020,7 @@ function js() {
|
|
|
6020
6020
|
] }) })
|
|
6021
6021
|
] });
|
|
6022
6022
|
}
|
|
6023
|
-
const Yt = 5,
|
|
6023
|
+
const Yt = 5, Ws = 10 * 1024 * 1024, Hs = /* @__PURE__ */ new Set([
|
|
6024
6024
|
"image/png",
|
|
6025
6025
|
"image/jpeg",
|
|
6026
6026
|
"image/gif",
|
|
@@ -6050,7 +6050,7 @@ const Yt = 5, Gs = 10 * 1024 * 1024, Ws = /* @__PURE__ */ new Set([
|
|
|
6050
6050
|
// Delimited / text
|
|
6051
6051
|
"text/csv",
|
|
6052
6052
|
"text/plain"
|
|
6053
|
-
]),
|
|
6053
|
+
]), Qs = /* @__PURE__ */ new Set([
|
|
6054
6054
|
"png",
|
|
6055
6055
|
"jpg",
|
|
6056
6056
|
"jpeg",
|
|
@@ -6069,10 +6069,10 @@ const Yt = 5, Gs = 10 * 1024 * 1024, Ws = /* @__PURE__ */ new Set([
|
|
|
6069
6069
|
"csv",
|
|
6070
6070
|
"txt"
|
|
6071
6071
|
]);
|
|
6072
|
-
function
|
|
6072
|
+
function Ys(t) {
|
|
6073
6073
|
return new Promise((n) => window.setTimeout(n, t));
|
|
6074
6074
|
}
|
|
6075
|
-
function
|
|
6075
|
+
function Js(t) {
|
|
6076
6076
|
return new Promise((n, a) => {
|
|
6077
6077
|
const s = new FileReader();
|
|
6078
6078
|
s.onloadend = () => {
|
|
@@ -6220,7 +6220,7 @@ function Fn() {
|
|
|
6220
6220
|
c("");
|
|
6221
6221
|
for (const et of F) {
|
|
6222
6222
|
if (ge !== Te.current) return;
|
|
6223
|
-
c((Ge) => Ge + et), await
|
|
6223
|
+
c((Ge) => Ge + et), await Ys(ae);
|
|
6224
6224
|
}
|
|
6225
6225
|
ge === Te.current && j.current(k, he);
|
|
6226
6226
|
}
|
|
@@ -6240,11 +6240,11 @@ function Fn() {
|
|
|
6240
6240
|
break;
|
|
6241
6241
|
}
|
|
6242
6242
|
const yt = ge.name.includes(".") ? ge.name.split(".").pop().toLowerCase() : "";
|
|
6243
|
-
if (!
|
|
6243
|
+
if (!Hs.has(ge.type) && !Qs.has(yt)) {
|
|
6244
6244
|
v(`Unsupported file type: ${ge.type || ge.name}`);
|
|
6245
6245
|
continue;
|
|
6246
6246
|
}
|
|
6247
|
-
if (ge.size >
|
|
6247
|
+
if (ge.size > Ws) {
|
|
6248
6248
|
v(`"${ge.name}" is too large (max 10 MB).`);
|
|
6249
6249
|
continue;
|
|
6250
6250
|
}
|
|
@@ -6305,7 +6305,7 @@ function Fn() {
|
|
|
6305
6305
|
ae && (ae.focus(), ae.style.height = "auto", ae.style.height = Math.min(Math.max(ae.scrollHeight, 48), 120) + "px");
|
|
6306
6306
|
}, 0));
|
|
6307
6307
|
}
|
|
6308
|
-
async function
|
|
6308
|
+
async function Ra() {
|
|
6309
6309
|
if (C !== "idle") return;
|
|
6310
6310
|
let k;
|
|
6311
6311
|
try {
|
|
@@ -6329,7 +6329,7 @@ function Fn() {
|
|
|
6329
6329
|
const he = F.mimeType || ((et = ae[0]) == null ? void 0 : et.type) || "audio/webm", ge = new Blob(ae, { type: he }), yt = (he.split(";")[0].split("/")[1] || "webm").toLowerCase();
|
|
6330
6330
|
S("transcribing");
|
|
6331
6331
|
try {
|
|
6332
|
-
const Ge = await
|
|
6332
|
+
const Ge = await Js(ge), Ut = await de(Ge, yt, n);
|
|
6333
6333
|
Xe(Ut);
|
|
6334
6334
|
} catch (Ge) {
|
|
6335
6335
|
v(Ge instanceof Error ? Ge.message : t("chat.transcribeFailed"));
|
|
@@ -6338,12 +6338,12 @@ function Fn() {
|
|
|
6338
6338
|
}
|
|
6339
6339
|
}, F.start(), S("recording");
|
|
6340
6340
|
}
|
|
6341
|
-
function
|
|
6341
|
+
function Ia() {
|
|
6342
6342
|
const k = y.current;
|
|
6343
6343
|
k && k.state !== "inactive" && k.stop();
|
|
6344
6344
|
}
|
|
6345
|
-
function
|
|
6346
|
-
C === "recording" ?
|
|
6345
|
+
function Ba() {
|
|
6346
|
+
C === "recording" ? Ia() : C === "idle" && Ra();
|
|
6347
6347
|
}
|
|
6348
6348
|
return n ? /* @__PURE__ */ r(
|
|
6349
6349
|
"div",
|
|
@@ -6397,7 +6397,7 @@ function Fn() {
|
|
|
6397
6397
|
k
|
|
6398
6398
|
)) })
|
|
6399
6399
|
] }),
|
|
6400
|
-
Je.map((k, F) => /* @__PURE__ */ e(
|
|
6400
|
+
Je.map((k, F) => /* @__PURE__ */ e(Xs, { message: k }, F)),
|
|
6401
6401
|
/* @__PURE__ */ e("div", { ref: ne })
|
|
6402
6402
|
]
|
|
6403
6403
|
}
|
|
@@ -6415,7 +6415,7 @@ function Fn() {
|
|
|
6415
6415
|
{
|
|
6416
6416
|
className: "relative flex items-center gap-2 rounded-lg bg-surface px-2 py-1.5 text-xs ring-1 ring-line shadow-card",
|
|
6417
6417
|
children: [
|
|
6418
|
-
k.previewUrl ? /* @__PURE__ */ e("img", { src: k.previewUrl, alt: "", className: "h-10 w-10 rounded object-cover" }) : /* @__PURE__ */ e("div", { className: "flex h-10 w-10 items-center justify-center rounded bg-
|
|
6418
|
+
k.previewUrl ? /* @__PURE__ */ e("img", { src: k.previewUrl, alt: "", className: "h-10 w-10 rounded object-cover" }) : /* @__PURE__ */ e("div", { className: "flex h-10 w-10 items-center justify-center rounded bg-surface-subtle text-[10px] font-bold text-fg-muted", children: ka(k.file.name) }),
|
|
6419
6419
|
/* @__PURE__ */ r("div", { className: "flex min-w-0 flex-col", children: [
|
|
6420
6420
|
/* @__PURE__ */ e("span", { className: "max-w-[160px] truncate text-fg", children: k.file.name }),
|
|
6421
6421
|
/* @__PURE__ */ e("span", { className: "text-[10px] text-fg-muted", children: k.uploading ? t("chat.uploading") : k.error ? t("chat.failed") : `${Math.round(k.file.size / 1024)} KB` })
|
|
@@ -6483,7 +6483,7 @@ function Fn() {
|
|
|
6483
6483
|
/* @__PURE__ */ e(
|
|
6484
6484
|
"button",
|
|
6485
6485
|
{
|
|
6486
|
-
onClick:
|
|
6486
|
+
onClick: Ba,
|
|
6487
6487
|
disabled: !De || !n || Ie || Oe || C === "transcribing",
|
|
6488
6488
|
className: `flex h-11 w-11 shrink-0 items-center justify-center rounded-lg transition-all disabled:cursor-not-allowed disabled:opacity-40 md:h-10 md:w-10 ${C === "recording" ? "bg-rose-500/10 text-rose-600 hover:bg-rose-500/20" : "text-fg-muted hover:bg-surface-subtle hover:text-fg"}`,
|
|
6489
6489
|
title: t(C === "recording" ? "chat.voiceStop" : C === "transcribing" ? "chat.voiceTranscribing" : "chat.voiceStart"),
|
|
@@ -6530,7 +6530,11 @@ function Fn() {
|
|
|
6530
6530
|
}
|
|
6531
6531
|
) : /* @__PURE__ */ e("div", { className: "flex h-full items-center justify-center text-fg-muted", children: t("chat.creating") });
|
|
6532
6532
|
}
|
|
6533
|
-
function
|
|
6533
|
+
function ka(t) {
|
|
6534
|
+
const n = t.includes(".") ? t.split(".").pop().toUpperCase() : "";
|
|
6535
|
+
return n ? n.slice(0, 4) : "FILE";
|
|
6536
|
+
}
|
|
6537
|
+
function Zs({ attachments: t }) {
|
|
6534
6538
|
return !t || t.length === 0 ? null : /* @__PURE__ */ e("div", { className: "mt-1 flex flex-wrap gap-1.5", children: t.map((n) => {
|
|
6535
6539
|
const a = I.getChatAttachmentUrl(n.id), s = n.mime_type.startsWith("image/");
|
|
6536
6540
|
return /* @__PURE__ */ r(
|
|
@@ -6542,7 +6546,7 @@ function Js({ attachments: t }) {
|
|
|
6542
6546
|
className: "flex items-center gap-1.5 rounded bg-black/10 px-1.5 py-1 text-[11px] hover:bg-black/20",
|
|
6543
6547
|
title: n.filename,
|
|
6544
6548
|
children: [
|
|
6545
|
-
s ? /* @__PURE__ */ e("img", { src: a, alt: n.filename, className: "h-8 w-8 rounded object-cover" }) : /* @__PURE__ */ e("span", { className: "flex h-8 w-8 items-center justify-center rounded bg-
|
|
6549
|
+
s ? /* @__PURE__ */ e("img", { src: a, alt: n.filename, className: "h-8 w-8 rounded object-cover" }) : /* @__PURE__ */ e("span", { className: "flex h-8 w-8 items-center justify-center rounded bg-black/20 text-[9px] font-bold", children: ka(n.filename) }),
|
|
6546
6550
|
/* @__PURE__ */ e("span", { className: "max-w-[120px] truncate", children: n.filename })
|
|
6547
6551
|
]
|
|
6548
6552
|
},
|
|
@@ -6550,13 +6554,13 @@ function Js({ attachments: t }) {
|
|
|
6550
6554
|
);
|
|
6551
6555
|
}) });
|
|
6552
6556
|
}
|
|
6553
|
-
function
|
|
6557
|
+
function Xs({ message: t }) {
|
|
6554
6558
|
return t.type === "user" ? /* @__PURE__ */ e("div", { className: "flex justify-end", children: /* @__PURE__ */ r("div", { className: "max-w-[80%] break-words rounded-2xl rounded-br-md bg-gradient-to-b from-brand to-brand/90 px-4 py-2.5 text-sm text-brand-fg ring-1 ring-black/10 shadow-bubble-user", children: [
|
|
6555
6559
|
/* @__PURE__ */ e("div", { className: "whitespace-pre-wrap", children: t.content }),
|
|
6556
|
-
/* @__PURE__ */ e(
|
|
6560
|
+
/* @__PURE__ */ e(Zs, { attachments: t.attachments }),
|
|
6557
6561
|
t.timestamp && /* @__PURE__ */ e("div", { className: "mt-1 text-right text-[10px] text-brand-fg/70", title: Mn(t.timestamp), children: zn(t.timestamp) })
|
|
6558
6562
|
] }) }) : t.type === "assistant" ? /* @__PURE__ */ e("div", { className: "flex justify-start", children: /* @__PURE__ */ r("div", { className: "max-w-[80%] break-words rounded-2xl rounded-bl-md bg-surface px-4 py-2.5 text-sm text-fg ring-1 ring-line shadow-card", children: [
|
|
6559
|
-
/* @__PURE__ */ e(
|
|
6563
|
+
/* @__PURE__ */ e(ei, { content: t.content }),
|
|
6560
6564
|
t.timestamp && /* @__PURE__ */ e("div", { className: "mt-1 text-right text-[10px] text-fg-muted", title: Mn(t.timestamp), children: zn(t.timestamp) })
|
|
6561
6565
|
] }) }) : t.type === "thinking" ? /* @__PURE__ */ e("div", { className: "flex justify-start", children: /* @__PURE__ */ r("div", { className: "flex items-center gap-2 rounded-full bg-surface px-3 py-1.5 text-xs text-fg-muted ring-1 ring-line shadow-card", children: [
|
|
6562
6566
|
/* @__PURE__ */ e("span", { className: "inline-block h-1.5 w-1.5 animate-pulse rounded-full bg-brand" }),
|
|
@@ -6596,7 +6600,7 @@ function Zs({ message: t }) {
|
|
|
6596
6600
|
}
|
|
6597
6601
|
) }) : t.type === "error" ? /* @__PURE__ */ e("div", { className: "flex justify-start", children: /* @__PURE__ */ e("div", { className: "max-w-[80%] rounded-2xl rounded-bl-md bg-rose-50 px-4 py-2.5 text-sm text-rose-700 ring-1 ring-rose-200 shadow-card", children: t.content }) }) : null;
|
|
6598
6602
|
}
|
|
6599
|
-
function
|
|
6603
|
+
function ei({ content: t }) {
|
|
6600
6604
|
const n = t.split(`
|
|
6601
6605
|
`), a = [];
|
|
6602
6606
|
let s = !1, o = [];
|
|
@@ -6640,7 +6644,7 @@ function Xs({ content: t }) {
|
|
|
6640
6644
|
);
|
|
6641
6645
|
}), /* @__PURE__ */ e("div", { children: a });
|
|
6642
6646
|
}
|
|
6643
|
-
function
|
|
6647
|
+
function Ca(t, n, a) {
|
|
6644
6648
|
const s = t.startsWith("/") && !t.startsWith("/api/"), o = "font-medium text-brand underline decoration-brand/40 underline-offset-2 transition-colors hover:decoration-brand";
|
|
6645
6649
|
return s ? /* @__PURE__ */ e(ve, { to: t, className: o, children: n }, a) : /* @__PURE__ */ e(
|
|
6646
6650
|
"a",
|
|
@@ -6654,13 +6658,13 @@ function ka(t, n, a) {
|
|
|
6654
6658
|
a
|
|
6655
6659
|
);
|
|
6656
6660
|
}
|
|
6657
|
-
const
|
|
6661
|
+
const ti = /(https?:\/\/[^\s)\]}"'<>]+|\/(?:reports|app|masters|admin|chat|setup|tutorial)[^\s)\]}"'<>]*)/g;
|
|
6658
6662
|
function Ot(t) {
|
|
6659
6663
|
return t.split(/(\[[^\]]+\]\([^)]+\)|\*\*[^*]+?\*\*|`[^`]+`)/g).flatMap((a, s) => {
|
|
6660
6664
|
const o = a.match(/^\[([^\]]+)\]\(([^)]+)\)$/);
|
|
6661
6665
|
if (o) {
|
|
6662
6666
|
const [, i, l] = o;
|
|
6663
|
-
return
|
|
6667
|
+
return Ca(l, Ot(i), s);
|
|
6664
6668
|
}
|
|
6665
6669
|
return a.startsWith("**") && a.endsWith("**") && a.length > 4 ? /* @__PURE__ */ e("strong", { className: "font-semibold", children: Ot(a.slice(2, -2)) }, s) : a.startsWith("`") && a.endsWith("`") ? /* @__PURE__ */ e(
|
|
6666
6670
|
"code",
|
|
@@ -6669,24 +6673,24 @@ function Ot(t) {
|
|
|
6669
6673
|
children: a.slice(1, -1)
|
|
6670
6674
|
},
|
|
6671
6675
|
s
|
|
6672
|
-
) :
|
|
6676
|
+
) : ni(a, `${s}`);
|
|
6673
6677
|
});
|
|
6674
6678
|
}
|
|
6675
|
-
function
|
|
6679
|
+
function ni(t, n) {
|
|
6676
6680
|
const a = [];
|
|
6677
6681
|
let s = 0, o;
|
|
6678
|
-
const i = new RegExp(
|
|
6682
|
+
const i = new RegExp(ti.source, "g");
|
|
6679
6683
|
let l = 0;
|
|
6680
6684
|
for (; (o = i.exec(t)) !== null; ) {
|
|
6681
6685
|
const c = o.index;
|
|
6682
6686
|
let h = o[0], d = "";
|
|
6683
6687
|
for (; h.length > 0 && /[.,;:!?]$/.test(h); )
|
|
6684
6688
|
d = h.slice(-1) + d, h = h.slice(0, -1);
|
|
6685
|
-
c > s && a.push(t.slice(s, c)), a.push(
|
|
6689
|
+
c > s && a.push(t.slice(s, c)), a.push(Ca(h, h, `${n}-u${l}`)), d && a.push(d), s = c + o[0].length, l += 1;
|
|
6686
6690
|
}
|
|
6687
6691
|
return s < t.length && a.push(t.slice(s)), a.length > 0 ? a : [t];
|
|
6688
6692
|
}
|
|
6689
|
-
function
|
|
6693
|
+
function ai() {
|
|
6690
6694
|
const t = Ee(), [n] = zt(), { user: a, login: s, register: o } = st(), { t: i } = X(), l = n.get("invite") || "", [c, h] = w(l ? "register" : "login"), [d, p] = w(!1), [u, f] = w(!1), [v, N] = w([]), [b, C] = w(!0), [S, x] = w(""), [y, m] = w(""), [D, T] = w(""), [U, Z] = w(""), [g, R] = w("");
|
|
6691
6695
|
re(() => {
|
|
6692
6696
|
a && a.role !== "public_manager" && t("/", { replace: !0 });
|
|
@@ -6786,8 +6790,8 @@ function ni() {
|
|
|
6786
6790
|
},
|
|
6787
6791
|
className: "flex w-full items-center justify-center gap-2 rounded-lg border border-border bg-surface px-4 py-2 text-sm font-medium text-fg transition-colors hover:bg-surface-muted",
|
|
6788
6792
|
children: [
|
|
6789
|
-
/* @__PURE__ */ e(
|
|
6790
|
-
i("login.continueWithProvider", { provider:
|
|
6793
|
+
/* @__PURE__ */ e(si, { provider: $ }),
|
|
6794
|
+
i("login.continueWithProvider", { provider: ri($) })
|
|
6791
6795
|
]
|
|
6792
6796
|
},
|
|
6793
6797
|
$
|
|
@@ -6820,10 +6824,10 @@ function ni() {
|
|
|
6820
6824
|
] }) })
|
|
6821
6825
|
] }) });
|
|
6822
6826
|
}
|
|
6823
|
-
function
|
|
6827
|
+
function ri(t) {
|
|
6824
6828
|
return t.charAt(0).toUpperCase() + t.slice(1);
|
|
6825
6829
|
}
|
|
6826
|
-
function
|
|
6830
|
+
function si({ provider: t }) {
|
|
6827
6831
|
return t === "google" ? /* @__PURE__ */ r("svg", { className: "h-4 w-4", viewBox: "0 0 48 48", "aria-hidden": "true", children: [
|
|
6828
6832
|
/* @__PURE__ */ e("path", { fill: "#EA4335", d: "M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z" }),
|
|
6829
6833
|
/* @__PURE__ */ e("path", { fill: "#4285F4", d: "M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z" }),
|
|
@@ -6831,7 +6835,7 @@ function ri({ provider: t }) {
|
|
|
6831
6835
|
/* @__PURE__ */ e("path", { fill: "#34A853", d: "M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z" })
|
|
6832
6836
|
] }) : t === "apple" ? /* @__PURE__ */ e("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ e("path", { d: "M16.365 1.43c0 1.14-.42 2.22-1.14 3.03-.78.9-2.06 1.6-3.12 1.5-.13-1.1.42-2.28 1.08-3.03.78-.9 2.13-1.56 3.18-1.5zM20.7 17.1c-.56 1.3-.83 1.88-1.55 3.03-1 1.6-2.42 3.6-4.18 3.62-1.56.02-1.96-1.02-4.07-1-2.12.01-2.56 1.02-4.12 1.01-1.76-.02-3.1-1.82-4.1-3.42C-.3 16.9-.6 11.16 1.7 8.1c1.16-1.54 3-2.51 4.85-2.51 1.87 0 3.05 1.02 4.6 1.02 1.5 0 2.42-1.02 4.6-1.02 1.62 0 3.34.88 4.56 2.4-4.01 2.2-3.36 7.92 0 9.11z" }) }) : null;
|
|
6833
6837
|
}
|
|
6834
|
-
function
|
|
6838
|
+
function ii() {
|
|
6835
6839
|
const t = Ee(), n = oe(!1), [a, s] = w("");
|
|
6836
6840
|
return re(() => {
|
|
6837
6841
|
n.current || (n.current = !0, I.createChatSession().then((o) => {
|
|
@@ -6863,7 +6867,7 @@ function Un() {
|
|
|
6863
6867
|
function Vn() {
|
|
6864
6868
|
return { type: "sales", party: "", amount: "", due_date: "", remarks: "" };
|
|
6865
6869
|
}
|
|
6866
|
-
function
|
|
6870
|
+
function oi() {
|
|
6867
6871
|
const t = Ee(), n = He(), [a, s] = w(""), [o, i] = w((/* @__PURE__ */ new Date()).toISOString().split("T")[0]), [l, c] = w(""), [h, d] = w([$n()]), [p, u] = w([Un()]), [f, v] = w([Vn()]), [N, b] = w({}), C = me({
|
|
6868
6872
|
mutationFn: () => I.importAccountBalances({
|
|
6869
6873
|
company: a,
|
|
@@ -7029,7 +7033,7 @@ function ii() {
|
|
|
7029
7033
|
] })
|
|
7030
7034
|
] });
|
|
7031
7035
|
}
|
|
7032
|
-
function
|
|
7036
|
+
function li() {
|
|
7033
7037
|
const { user: t } = st(), n = He(), { data: a, isLoading: s } = ue({
|
|
7034
7038
|
queryKey: ["auth-users"],
|
|
7035
7039
|
queryFn: () => I.authListUsers()
|
|
@@ -7050,7 +7054,7 @@ function oi() {
|
|
|
7050
7054
|
}), N = me({
|
|
7051
7055
|
mutationFn: (m) => I.authRevokeInvite(m),
|
|
7052
7056
|
onSuccess: () => n.invalidateQueries({ queryKey: ["auth-invites"] })
|
|
7053
|
-
}), [b, C] = w(null), S =
|
|
7057
|
+
}), [b, C] = w(null), S = xr(), x = (m) => `${window.location.origin}/login?invite=${m}`, y = async (m) => {
|
|
7054
7058
|
try {
|
|
7055
7059
|
await navigator.clipboard.writeText(x(m)), C(m), setTimeout(() => C((D) => D === m ? null : D), 2e3);
|
|
7056
7060
|
} catch {
|
|
@@ -7190,98 +7194,98 @@ function oi() {
|
|
|
7190
7194
|
] }) })
|
|
7191
7195
|
] });
|
|
7192
7196
|
}
|
|
7193
|
-
const li = { save: "Save", saving: "Saving...", submit: "Submit", cancel: "Cancel", cancelDoc: "Cancel", cancelDocAbort: "Don't cancel", cancelDocConfirmBtn: "Yes, cancel document", discardDraft: "Discard draft", keepDraft: "Keep", discardDraftConfirm: "Discard draft", showDiscarded: "Show discarded", delete: "Delete", edit: "Edit", pdf: "PDF", addRow: "Add Row", loading: "Loading...", enable: "Enable", disable: "Disable", refresh: "Refresh", refreshing: "Refreshing", areYouSure: "Are you sure?", all: "All", apply: "Apply", new: "New", prev: "Prev", next: "Next", perPage: "Per page", page: "Page", of: "of", showing: "Showing", total: "Total", totals: "Totals", errorOccurred: "An error occurred" }, ci = { title: "Language", help: "Choose the language for the interface. Your choice is saved in this browser.", label: "Language" }, di = { back: "Back", logout: "Logout", openMenu: "Open menu", closeMenu: "Close menu", new: "New {{label}}" }, ui = { dashboard: "Dashboard", setup: "Company Setup", tutorial: "Getting Started", chat: "Chat", reports: "Reports", "trial-balance": "Trial Balance", "general-ledger": "General Ledger", "stock-balance": "Stock Balance", "profit-and-loss": "Profit & Loss", "balance-sheet": "Balance Sheet", "ar-aging": "Accounts Receivable Aging", "ap-aging": "Accounts Payable Aging", analytics: "Analytics", "chart-of-accounts": "Chart of Accounts" }, mi = { quotation: { one: "Quotation", other: "Quotations" }, proposal: { one: "Proposal", other: "Proposals" }, "sales-order": { one: "Sales Order", other: "Sales Orders" }, "sales-invoice": { one: "Sales Invoice", other: "Sales Invoices" }, "pos-invoice": { one: "POS Invoice", other: "POS Invoices" }, "purchase-order": { one: "Purchase Order", other: "Purchase Orders" }, "purchase-invoice": { one: "Purchase Invoice", other: "Purchase Invoices" }, "payment-entry": { one: "Payment Entry", other: "Payment Entries" }, "journal-entry": { one: "Journal Entry", other: "Journal Entries" }, "bank-transaction": { one: "Bank Transaction", other: "Bank Transactions" }, budget: { one: "Budget", other: "Budgets" }, subscription: { one: "Subscription", other: "Subscriptions" }, "stock-entry": { one: "Stock Entry", other: "Stock Entries" }, "delivery-note": { one: "Delivery Note", other: "Delivery Notes" }, "purchase-receipt": { one: "Purchase Receipt", other: "Purchase Receipts" }, "pricing-rule": { one: "Pricing Rule", other: "Pricing Rules" } }, pi = { company: { one: "Company", other: "Companies" }, customer: { one: "Customer", other: "Customers" }, supplier: { one: "Supplier", other: "Suppliers" }, item: { one: "Item", other: "Items" }, warehouse: { one: "Warehouse", other: "Warehouses" } }, hi = { chats: "Chats", newChat: "New Chat", deleteChat: "Delete chat", customAnalytics: "Custom Analytics", newAnalytics: "New Analytics", deleteReport: "Delete report", groups: { Introduction: "Introduction", Selling: "Selling", Buying: "Buying", Accounting: "Accounting", Stock: "Stock", Reports: "Reports", Masters: "Masters", Settings: "Settings" }, items: { "Getting Started": "Getting Started", "Company Setup": "Company Setup", "Opening Balances": "Opening Balances", Quotation: "Quotation", Proposal: "Proposals", "Sales Order": "Sales Order", "Sales Invoice": "Sales Invoice", "POS Invoice": "POS Invoice", "Purchase Order": "Purchase Order", "Purchase Invoice": "Purchase Invoice", "Payment Entry": "Payment Entry", "Journal Entry": "Journal Entry", "Bank Transaction": "Bank Transaction", Budget: "Budget", Subscription: "Subscription", "Stock Entry": "Stock Entry", "Delivery Note": "Delivery Note", "Purchase Receipt": "Purchase Receipt", "Trial Balance": "Trial Balance", "Profit & Loss": "Profit & Loss", "Balance Sheet": "Balance Sheet", "General Ledger": "General Ledger", "AR Aging": "AR Aging", "AP Aging": "AP Aging", Analytics: "Analytics", "Stock Balance": "Stock Balance", Company: "Company", Customer: "Customer", Supplier: "Supplier", Item: "Item", Warehouse: "Warehouse", General: "General", "Pricing Rule": "Pricing Rule", "Users & Team": "Users & Team", "Chart of Accounts": "Chart of Accounts" } }, gi = { taglineFirstRun: "Create your admin account to get started", taglineRegister: "Create your account", taglineSignIn: "Sign in to your account", demoBanner: "Demo mode is active. Sign in with an admin account to manage settings or disable public access.", fullName: "Full Name", email: "Email", password: "Password", confirmPassword: "Confirm Password", createAdmin: "Create Admin Account", register: "Register", signIn: "Sign In", browsingTitle: "Just browsing?", browsingBody: "Start a fresh chat session and watch the live demo.", enterDemo: "Enter Live Demo", haveInvite: "Have an invite?", noAccountPrompt: "Need an account?", registerLink: "Register", alreadyHaveAccount: "Already have an account?", signInLink: "Sign in", passwordsNoMatch: "Passwords do not match", passwordTooShort: "Password must be at least 6 characters", registrationFailed: "Registration failed", loginFailed: "Login failed", orContinueWith: "or continue with", continueWithProvider: "Continue with {{provider}}", oauthError: { generic: "Sign-in failed. Please try again.", email_exists: "An account with this email already exists. Sign in, then link this provider from your account settings.", email_unverified: "Your provider did not confirm a verified email, so we can't sign you in.", registration_closed: "This email has no account yet and registration is invite-only.", invite_invalid: "That invite is invalid, already used, or issued for a different email.", identity_taken: "That provider account is already linked to a different user.", account_disabled: "This account has been disabled.", token_exchange_failed: "Sign-in failed while contacting the provider. Please try again." } }, fi = { pdfTitle: "PDF & Print", pageSize: "Page Size", pdfHelp: "A4 is standard internationally (210 x 297 mm). Letter is standard in the US (8.5 x 11 in).", passwordTitle: "Change Password", currentPassword: "Current password", newPassword: "New password", confirmNewPassword: "Confirm new password", changePassword: "Change password", changingPassword: "Changing...", passwordChanged: "Password changed.", setPasswordTitle: "Set a Password", setPasswordBody: "Your account signs in with Google. Set a password to also sign in with email and password — a handy fallback if you ever lose access to your Google account.", setPassword: "Set password", passwordSet: "Password set.", linkedAccountsTitle: "Linked Accounts", linkedAccountsBody: "Link a Google or Apple account to sign in without a password.", linked: "Linked", linkProvider: "Link {{provider}}", openingTitle: "Opening Balances", openingBody: "The Opening Balances page allows importing account balances, stock, and outstanding invoices from a previous system.", openingEnabled: "Currently enabled — accessible under Introduction > Opening Balances.", openingDisabled: "Currently disabled — the page is hidden from the sidebar.", signupTitle: "Public Signup", signupBody: "Allow anyone to create their own account (as a viewer) without an invite. When off, new users can only join via an invite link.", signupEnabled: "Currently enabled — anyone with the URL can register as a viewer.", signupDisabled: "Currently disabled — registration is invite-only.", chatApiTitle: "Chat API", apiTitle: "Programmatic API", restApiBody: "Let connectors and scripts drive this ERP over its REST API (documents, masters, reports) with the same Bearer API keys. Off by default.", restApiEnabled: "Currently enabled — issued keys can call /api/documents, /api/masters, and the rest of the REST API.", restApiDisabled: "Currently disabled — the REST API only accepts the session cookie; keys are rejected.", restApiDeactivateTitle: "Deactivate the REST API?", restApiDeactivateBody: "Bearer-key access to the REST API will be switched off — connectors and scripts are rejected until you turn it back on. The web app (session cookie) is unaffected, and your API keys are NOT deleted: they start working again the instant you re-enable the API.", chatApiBody: "Let external applications talk to this ERP's chat agent over an HTTP API, using Bearer API keys. Off by default.", chatApiEnabled: "Currently enabled — issued keys can call POST /api/v1/chat.", chatApiDisabled: "Currently disabled — the API returns 404 and keys don't work.", chatApiDeactivateTitle: "Deactivate the chat API?", chatApiDeactivateBody: "The chat API will be switched off — every programmatic request (Bearer API keys) is rejected until you turn it back on. Your API keys are NOT deleted: they stay saved and start working again the instant you re-enable the API.", chatApiDeactivateConfirm: "Deactivate API", chatApiKeysTitle: "API keys", chatApiTokenOnce: "Copy this token now — it won't be shown again.", chatApiCopy: "Copy", chatApiDismiss: "Dismiss", chatApiRevoked: "revoked", chatApiRevoke: "Revoke", chatApiNoKeys: "No API keys yet.", chatApiName: "Name", chatApiRole: "Role", chatApiCreate: "Create key", chatApiWarn: "A key acts with your identity and at most your role — treat it like a password. Revoke first, then delete.", publicTitle: "Public Access (Demo Mode)", publicActive: "Active", publicActiveBody: "Public access is enabled. Anyone can use the application without logging in. All visitors get manager-level permissions.", disablePublic: "Disable Public Access", disabling: "Disabling...", publicInactiveBody: "Enable public access to let anyone use the application without an account. Useful for demos and showcases. All visitors get manager-level permissions and share the same identity.", enablePublic: "Enable Public Access", enableWarning: "This will allow anyone to access the application without logging in. They will be able to create, edit, and submit documents. Your admin account still requires login.", yesEnable: "Yes, Enable", enabling: "Enabling...", tokenSpendTitle: "Token Spend", chatApiDelete: "Delete", chatApiYourKeys: "Your keys", chatApiYouBadge: "you", chatApiUnknownUser: "Unknown user", chatApiAdminAllNote: "You're an admin — the list below includes every user's keys, grouped by owner. Your own keys are shown first.", chatApiConfirmTitle: "This key isn't yours", chatApiConfirmRevokeBody: '"{{key}}" belongs to {{name}}. Revoking it will immediately break their API access. Continue?', chatApiConfirmDeleteBody: '"{{key}}" belongs to {{name}}. Deleting it permanently removes their key. Continue?', chatApiPersonal: "Personal Bearer keys for the programmatic chat API. A key acts as YOU: it is capped at your role, follows role changes live, and dies with your account. Requires the admin to have enabled the Chat API.", version: "Version {{version}}" }, yi = { Draft: "Draft", Open: "Open", Submitted: "Submitted", "To Deliver and Bill": "To Deliver and Bill", "To Deliver": "To Deliver", "To Bill": "To Bill", Completed: "Completed", Ordered: "Ordered", Paid: "Paid", Unpaid: "Unpaid", Cancelled: "Cancelled", Discarded: "Discarded", Overdue: "Overdue", Return: "Return", Closed: "Closed" }, bi = { balanced: "BALANCED", imbalanced: "IMBALANCED", income: "Income", expenses: "Expenses", totalIncome: "Total Income", totalExpenses: "Total Expenses", netProfit: "Net Profit", netLoss: "Net Loss", assets: "Assets", liabilities: "Liabilities", equity: "Equity", totalAssets: "Total Assets", totalLiabilities: "Total Liabilities", totalEquity: "Total Equity", totalLiabilitiesEquity: "Total Liabilities + Equity", current: "Current", noData: "No data found", noEntries: "No entries found", noStockData: "No stock data found", noReceivables: "No outstanding receivables", noPayables: "No outstanding payables", noDocuments: "No documents found" }, vi = { required: "Required: {{fields}}", deleteConfirm: "Delete this {{label}}?", disabledNotice: "This {{label}} is disabled. It remains in the system because other records still reference it.", disabledOnDelete: "{{label}} {{name}} was disabled instead of deleted because it is referenced by {{reason}}." }, xi = { totalRevenue: "Total Revenue", outstandingReceivable: "Outstanding Receivable", outstandingPayable: "Outstanding Payable", totalStockValue: "Total Stock Value", recentDocuments: "Recent Documents", noRecentDocuments: "No recent documents" }, Ni = { title: "Lambda ERP Chat", subtitle: "Ask me to create documents, look up data, or run reports.", s1: "What customers do we have?", s2: "Show me the trial balance", s3: "Create a quotation for 10 Bolt Pack M8", s4: "List all unpaid invoices", loadOlder: "Load older messages", uploading: "Uploading...", failed: "Failed", remove: "Remove", placeholderDemo: "Running live demo...", placeholderType: "Type a message...", placeholderConnecting: "Connecting...", attachTitle: "Attach file (PDF or image, max 10 MB)", creating: "Creating chat...", dropToAttach: "Drop file to attach (images or PDF, max 10 MB each)", demoError: "Could not start demo", voiceStart: "Record voice message", voiceStop: "Stop recording", voiceTranscribing: "Transcribing...", micDenied: "Microphone access was denied.", transcribeFailed: "Transcription failed. Please try again." }, wi = { "Create Credit Note": "Create Credit Note", "Create Debit Note": "Create Debit Note", "Create Delivery Note": "Create Delivery Note", "Create Purchase Invoice": "Create Purchase Invoice", "Create Purchase Receipt": "Create Purchase Receipt", "Create Return": "Create Return", "Create Sales Invoice": "Create Sales Invoice", "Create Sales Order": "Create Sales Order" }, ki = { "% Billed": "% Billed", "% Delivered": "% Delivered", Account: "Account", Address: "Address", Allocated: "Allocated", Amount: "Amount", "As of Date": "As of Date", Balance: "Balance", "Bank Account": "Bank Account", "Billing Interval": "Billing Interval", "Budget Amount": "Budget Amount", Buying: "Buying", Change: "Change", City: "City", Company: "Company", "Company Name": "Company Name", "Cost Center": "Cost Center", Country: "Country", Credit: "Credit", "Credit Limit": "Credit Limit", Currency: "Currency", "Current Period End": "Current Period End", "Contact Person": "Contact Person", "Contact Email": "Contact Email", "Contact Phone": "Contact Phone", "Current Period Start": "Current Period Start", Customer: "Customer", "Customer Group": "Customer Group", "Customer Name": "Customer Name", Date: "Date", Debit: "Debit", "Delivery Date": "Delivery Date", Deposit: "Deposit", Description: "Description", "Discount %": "Discount %", "Discount Amt": "Discount Amt", "Discount Percentage": "Discount Percentage", "Due Date": "Due Date", Email: "Email", Enabled: "Enabled", "End Date": "End Date", "Expense Account": "Expense Account", "Fiscal Year": "Fiscal Year", "From Date": "From Date", "Grand Total": "Grand Total", Frequency: "Frequency", ID: "ID", "If Exceeded": "If Exceeded", "Income Account": "Income Account", "Incoming Value": "Incoming Value", Invoice: "Invoice", Item: "Item", "Item Code": "Item Code", "Item Group": "Item Group", "Item Name": "Item Name", "Matched Doc": "Matched Doc", "Matched Type": "Matched Type", "Min Qty": "Min Qty", Mode: "Mode", Month: "Month", Name: "Name", "Net Total": "Net Total", "Notes / Terms": "Notes / Terms", "Outgoing Value": "Outgoing Value", Outstanding: "Outstanding", "Outstanding Amount": "Outstanding Amount", "Paid Amount": "Paid Amount", "Paid From": "Paid From", "Paid To": "Paid To", Party: "Party", "Party Type": "Party Type", "Payment Type": "Payment Type", Phone: "Phone", "Plan Items": "Plan Items", "Posting Date": "Posting Date", Priority: "Priority", Qty: "Qty", Rate: "Rate", "Rate (%)": "Rate (%)", "Rate Or Discount": "Rate Or Discount", "Reference No": "Reference No", Remark: "Remark", Selling: "Selling", Source: "Source", "Source Warehouse": "Source Warehouse", "Standard Rate": "Standard Rate", "Start Date": "Start Date", Status: "Status", "Stock Entry Type": "Stock Entry Type", "Stock UOM": "Stock UOM", "Stock Value": "Stock Value", Supplier: "Supplier", "Supplier Group": "Supplier Group", "Supplier Name": "Supplier Name", Target: "Target", "Target Warehouse": "Target Warehouse", Tax: "Tax", "Tax ID": "Tax ID", Territory: "Territory", Title: "Title", "To Date": "To Date", Total: "Total", "Total Amount": "Total Amount", "Total Credit": "Total Credit", "Total Debit": "Total Debit", "Transaction Date": "Transaction Date", Type: "Type", Unallocated: "Unallocated", "Update Stock": "Update Stock", "Valid From": "Valid From", "Valid Till": "Valid Till", "Valid Upto": "Valid Upto", "Valuation Rate": "Valuation Rate", "Voucher No": "Voucher No", "Voucher Type": "Voucher Type", Warehouse: "Warehouse", "Warehouse Name": "Warehouse Name", Withdrawal: "Withdrawal", "Zip Code": "Zip Code" }, Ci = { accounts: "accounts", items: "items", monthly_distribution: "monthly_distribution", payments: "payments", plans: "plans", references: "references", taxes: "taxes" }, Si = /* @__PURE__ */ JSON.parse(`{"chips":{"Cancelled":"Cancelled","Credit Note":"Credit Note","DN Return":"DN Return","Debit Note":"Debit Note","Delivery Note":"Delivery Note","Draft":"Draft","Payment Entry":"Payment Entry","Purchase Invoice":"Purchase Invoice","Purchase Order":"Purchase Order","Purchase Receipt":"Purchase Receipt","Quotation":"Quotation","Sales Invoice":"Sales Invoice","Sales Order":"Sales Order","Submitted":"Submitted"},"links":{"AP Aging":"AP Aging","AR Aging":"AR Aging","Balance Sheet":"Balance Sheet","Customers":"Customers","Delivery Notes":"Delivery Notes","General Ledger":"General Ledger","Go to Setup":"Go to Setup","Items":"Items","New Journal Entry":"New Journal Entry","New Payment Entry":"New Payment Entry","New Purchase Order":"New Purchase Order","New Quotation":"New Quotation","New Stock Entry":"New Stock Entry","Open AI Chat":"Open AI Chat","Profit & Loss":"Profit & Loss","Purchase Invoices":"Purchase Invoices","Purchase Receipts":"Purchase Receipts","Sales Invoices":"Sales Invoices","Stock Balance":"Stock Balance","Suppliers":"Suppliers","Trial Balance":"Trial Balance","View Quotations":"View Quotations","Warehouses":"Warehouses"},"steps":{"1":{"title":"Set Up Your Company","description":"Create a company with a base currency. This generates your Chart of Accounts (30 standard accounts across Assets, Liabilities, Equity, Income, and Expenses) and a default Cost Center. You can also seed demo data with sample customers, suppliers, and items to get started quickly."},"2":{"title":"Create Master Data","description":"Before you can transact, you need master records. Create at least one Customer, one Supplier, one Item (with a standard rate), and one Warehouse. If you seeded demo data in Step 1, these already exist.","tip":"Items have a standard rate that auto-fills when you add them to documents. You can always override the rate per transaction."},"3":{"title":"Create a Quotation","description":"A Quotation is a non-binding offer to a customer. Select a customer, add line items with quantities and rates, optionally add tax rows, then save. Quotations have no financial impact — they don't create accounting or stock entries. Set a validity date so the offer expires automatically."},"4":{"title":"Submit and Convert to Sales Order","description":"Open your saved Quotation and click Submit to confirm it. Then click “Create Sales Order” to convert it. The Sales Order represents a confirmed commitment from the customer. It still has no financial impact, but it reserves stock for planning purposes.","tip":"Only submitted documents can be converted to the next step. Draft → Submit → Convert is the standard flow. For quick deals, you can skip the Sales Order and go directly from Quotation to Sales Invoice or Delivery Note."},"5":{"title":"Check Stock Before Fulfilling","description":"Before you can deliver, check if you actually have the item in stock. Go to the Stock Balance report and look up the item. If your warehouse has zero quantity, you’ll need to bring stock in first — either through a Purchase Order (buying from a supplier) or a Stock Entry (manual receipt).","tip":"This is a common real-world scenario: you sell something, then realize you need to buy it first. The ERP handles both flows."},"6":{"title":"Purchase Cycle: Buy Stock from a Supplier","description":"If you need to buy stock, you have two valid paths. The standard path is Purchase Order -> Purchase Receipt -> Purchase Invoice: use this when goods arrive before or separately from the supplier bill. If the bill and receipt happen together, you can create the Purchase Invoice directly and enable Update Stock so the same document both receives inventory and records Accounts Payable.","tip":"Use Purchase Receipt first when receiving goods separately. Use Purchase Invoice with Update Stock when one step should both receive stock and book the supplier bill. In that direct path, set a warehouse on each stock item row."},"7":{"title":"Create a Delivery Note","description":"Now that you have stock, go back to your submitted Sales Order and click “Create Delivery Note.” Set the warehouse on each item row (where the goods ship from), then submit. This moves inventory out of the warehouse — your stock balance decreases.","tip":"The Delivery Note is the shipping document. It reduces stock but doesn’t create an invoice. You can deliver and invoice separately."},"8":{"title":"Create and Submit the Sales Invoice","description":"From the submitted Sales Order, create a Sales Invoice. When you submit the invoice, GL entries are posted: Accounts Receivable is debited (the customer owes you) and Sales Revenue is credited (income earned). If taxes are configured, Tax Payable is also credited. The outstanding amount shows what the customer still owes."},"9":{"title":"Record Customer Payments","description":"Create a Payment Entry to record money received from the customer. Set the payment type to “Receive,” select the customer, specify the amount, and allocate it against the Sales Invoice. You can make partial payments — the invoice’s outstanding amount updates accordingly. Create additional Payment Entries until the invoice is fully paid.","tip":"Partial payments are common. A 10,000 invoice might be paid as 3,000 now and 7,000 later. Each Payment Entry reduces the outstanding amount."},"10":{"title":"Stock Entries (Manual Inventory)","description":"Use Stock Entries for inventory movements that aren’t tied to purchases or sales. Material Receipt adds stock (opening balances, adjustments). Material Issue removes stock (write-offs, internal consumption). Material Transfer moves stock between warehouses. Each entry updates the stock ledger with moving-average valuation.","tip":"For purchased goods, use Purchase Receipts instead of Stock Entries — they link to the Purchase Order and give you a proper audit trail."},"11":{"title":"Journal Entries","description":"Journal Entries are manual accounting adjustments — expense accruals, corrections, reclassifications, opening balances. Each entry must have balanced debits and credits (total debit = total credit). Use these when no other document type fits."},"12":{"title":"Salary Payments","description":"Lambda ERP handles salaries through the existing accounting tools. First, accrue the salary expense: create a Journal Entry that debits Salary Expense and credits Salary Payable for the total payroll amount. Then pay the employees: create another Journal Entry (or Payment Entry) that debits Salary Payable and credits your bank account. This two-step process keeps your books accurate — the expense is recorded in the right period, and the cash outflow is tracked separately.","tip":"You can ask the AI assistant to do this for you: “Accrue 15,000 in salaries for April” followed by “Pay the April salaries from bank.” It will create the right journal entries automatically."},"13":{"title":"Returns and Credit Notes","description":"When a customer returns goods or you need to issue a credit, create a return. Returns use the same document type with negative quantities. Open a submitted Sales Invoice and create a Credit Note (Sales Invoice return) — this reverses the GL entries and reduces the original invoice’s outstanding amount. For stock, create a Delivery Note return to bring goods back into the warehouse. On the buying side, create a Debit Note (Purchase Invoice return) to reverse a supplier bill, or a Purchase Receipt return to send goods back.","tip":"A Credit Note is just a Sales Invoice with is_return=1 and negative quantities. The same GL logic runs — negative amounts automatically flip to the correct debit/credit sides. For a full sales return, you need both a Credit Note (financials) and a Delivery Note return (stock)."},"14":{"title":"Run Reports","description":"Check your books. The Profit & Loss shows income vs expenses and net profit for a period. The Balance Sheet shows your financial position (assets = liabilities + equity). AR Aging shows who owes you money and how overdue it is. AP Aging shows what you owe suppliers. The Trial Balance verifies double-entry integrity. The General Ledger shows every individual posting. Stock Balance shows current inventory."},"15":{"title":"Working in Foreign Currencies","description":"Your books are kept in a single base currency (chosen at company setup), but you can transact in any currency. Set a currency on an invoice or bill — or give a customer or supplier a default currency — and the exchange rate for that date is looked up automatically and stored on the document. The document keeps its amounts in its own currency, while the General Ledger always posts in your base currency. When you later collect or pay at a different rate, the realized exchange gain or loss is booked automatically to an Exchange Gain/Loss account. You can even hold a foreign-currency bank balance and convert it later at your bank’s rate — the difference versus its carried value is realized then. At month end you can revalue open foreign balances to the closing rate (an unrealized gain/loss that reverses next period), and you can view any financial statement translated into another currency for display.","tip":"This is easiest through the AI chat — try “Create a sales invoice for Lumiere Audio in EUR,” “Show me the balance sheet in EUR,” or “What’s our unrealized FX exposure at month end?” The seeded demo already includes a EUR customer (Lumiere Audio SARL) whose invoice was collected at a different rate, plus an open EUR supplier bill — open the General Ledger to see the realized FX postings."}},"caTitle":"Dynamic Analytics — Chat Your Way to Any Chart","caBadge":"Signature Feature","caBody":"Need a report the presets can’t give you? Just describe it in chat. The assistant calls a code-specialist model that writes the report for you, runs it live over your ERP data, and returns a sharable link. The chart or table renders in seconds and is saved as a draft under Custom Analytics in the sidebar — you can reopen it, share the URL with teammates, or ask the assistant to refine it.","caTryAsking":"Try asking (click to prefill in chat):","caPrompt1":"Show me top 10 customers by revenue this year as a bar chart","caPrompt2":"Monthly purchases trend by supplier over all months and label x-axis with supplier name","caPrompt3":"Best selling items by quantity, with a table and a chart","caPrompt4":"Which customers owe me the most right now?","caTryInChat":"Try it in chat","caOpenWorkspace":"Open Analytics workspace","flowTitle":"Document Flow Overview","salesCycle":"Sales Cycle","flowShortcut":"Shortcut: Quotation can skip Sales Order and go directly to Sales Invoice or Delivery Note","purchaseCycle":"Purchase Cycle","returns":"Returns","legendStock":"stock impact","legendGl":"GL impact","legendCash":"cash impact","legendReversal":"reversal","lifecycleTitle":"Document Lifecycle","lcDraftLabel":"Draft:","lcDraftDesc":"Editable. No financial or stock impact.","lcSubmittedLabel":"Submitted:","lcSubmittedDesc":"Locked. GL entries and stock ledger entries are posted.","lcCancelledLabel":"Cancelled:","lcCancelledDesc":"All entries reversed. Document is permanently archived.","lcNoDelete":"There is no delete. To void a draft: submit it, then cancel it.","lcCorrect":"To correct a submitted document: cancel it and create a new one.","pageTitle":"Getting Started with Lambda ERP","intro":"Lambda ERP is an AI Native ERP System, with all functionality — like creating orders, checking inventory, recording payments — being accessible through a chat interface. It instructs, reasons and checks all your daily business tasks.","openChat":"Open AI Chat","tipLabel":"Tip:","topTip":"The AI chat can also give you direct links to documents and downloadable PDFs. Just ask it to create or look up a document and it will include clickable links in its response.","manualIntro":"If you want to fully understand how things work under the hood, or prefer to do things manually, here’s a full business cycle step by step.","readyTitle":"You're Ready","readyBody1":"You now understand the full cycle. A typical real-world scenario looks like this: you receive a customer order (Quotation → Sales Order), check stock, buy what you need (Purchase Order → Purchase Receipt → Purchase Invoice → Payment), deliver to the customer (Delivery Note), bill them (Sales Invoice), and collect payment (Payment Entry). If something comes back, create a Credit Note and Delivery Note return to reverse the financials and stock. The Trial Balance confirms everything is balanced.","readyBody2":"You can also use the AI chat to do all of this through natural conversation — just describe what you need and it will create the right documents for you.","setupTitle":"Set Up Your Company — Guided by AI","setupBadge":"Start Here","setupBody":"Tell the assistant what kind of business you run, and it builds your chart of accounts for you — tailored to your sector, with the right accounts and sensible defaults already wired up. It explains each decision and only creates anything once you approve.","setupSectors":"Tailored for services, retail & POS, hospitality, wholesale & distribution, import/export, manufacturing, and construction.","setupGetStarted":"Get started in chat","setupManual":"Prefer a manual form? Use the classic setup.","setupManualLink":"Classic setup","setupPrompt":"I'd like to set up my company. Can you guide me through it?"}`), Di = { title: "Formatting help", intro: "The Notes / Terms text supports light formatting on the PDF:", heading: "bold heading", emphasis: "italic / bold", rule: "horizontal divider line", price: "right-aligned price beside the text above (e.g. Monthly | CHF 380.—)", block: "Separate blocks with a blank line." }, Ai = { period: "Period", allTime: "All time", semantics: "Balance-sheet accounts: closing balance at period end. P&L accounts: movement within the period. Click an account for its ledger.", empty: "No accounts found. Complete the company setup first.", disabled: "disabled", rootType: { Asset: "Assets", Liability: "Liabilities", Equity: "Equity", Income: "Income", Expense: "Expenses" } }, Pi = {
|
|
7194
|
-
common:
|
|
7195
|
-
language:
|
|
7196
|
-
header:
|
|
7197
|
-
titles:
|
|
7198
|
-
doctypes:
|
|
7199
|
-
masters:
|
|
7200
|
-
nav:
|
|
7201
|
-
login:
|
|
7202
|
-
settings:
|
|
7203
|
-
status:
|
|
7204
|
-
reports:
|
|
7205
|
-
masterForm:
|
|
7206
|
-
dashboard:
|
|
7207
|
-
chat:
|
|
7208
|
-
conversions:
|
|
7209
|
-
fields:
|
|
7210
|
-
tables:
|
|
7211
|
-
tutorial:
|
|
7212
|
-
notesMarkup:
|
|
7213
|
-
coa:
|
|
7214
|
-
}, _i = { 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" }, Ti = { title: "Sprache", help: "Wählen Sie die Sprache der Oberfläche. Ihre Auswahl wird in diesem Browser gespeichert.", label: "Sprache" }, Ri = { back: "Zurück", logout: "Abmelden", openMenu: "Menü öffnen", closeMenu: "Menü schließen", new: "Neu: {{label}}" }, Ii = { 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" } }, Ei = { 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" } }, Li = { 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" } }, Oi = { 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." } }, qi = { 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}}" }, zi = { 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" }, Mi = { 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" }, Fi = { 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." }, $i = { 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" }, Ui = { items: "Positionen", taxes: "Steuern", references: "Zahlungsreferenzen", accounts: "Kontobuchungen", payments: "Zahlungen", plans: "Planpositionen", monthly_distribution: "Monatliche Verteilung" }, Vi = { "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" }, Ki = { totalRevenue: "Gesamtumsatz", outstandingReceivable: "Offene Forderungen", outstandingPayable: "Offene Verbindlichkeiten", totalStockValue: "Gesamter Lagerwert", recentDocuments: "Letzte Dokumente", noRecentDocuments: "Keine aktuellen Dokumente" }, ji = { 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." }, Gi = /* @__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?"}'), Wi = { 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." }, Hi = { 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" } }, Qi = {
|
|
7215
|
-
common:
|
|
7216
|
-
language:
|
|
7217
|
-
header:
|
|
7218
|
-
titles:
|
|
7219
|
-
doctypes:
|
|
7220
|
-
masters:
|
|
7221
|
-
nav:
|
|
7222
|
-
login:
|
|
7223
|
-
settings:
|
|
7224
|
-
status:
|
|
7225
|
-
reports:
|
|
7226
|
-
masterForm:
|
|
7227
|
-
fields:
|
|
7228
|
-
tables:
|
|
7229
|
-
conversions:
|
|
7230
|
-
dashboard:
|
|
7231
|
-
chat:
|
|
7232
|
-
tutorial:
|
|
7233
|
-
notesMarkup:
|
|
7234
|
-
coa:
|
|
7235
|
-
}, Yi = { save: "Enregistrer", saving: "Enregistrement...", submit: "Valider", cancel: "Annuler", cancelDoc: "Annuler", cancelDocAbort: "Ne pas annuler", cancelDocConfirmBtn: "Annuler définitivement", discardDraft: "Supprimer le brouillon", keepDraft: "Conserver", discardDraftConfirm: "Supprimer", showDiscarded: "Afficher les supprimés", delete: "Supprimer", edit: "Modifier", pdf: "PDF", addRow: "Ajouter une ligne", loading: "Chargement...", enable: "Activer", disable: "Désactiver", refresh: "Actualiser", refreshing: "Actualisation", areYouSure: "Êtes-vous sûr ?", all: "Tous", apply: "Appliquer", new: "Nouveau", prev: "Précédent", next: "Suivant", perPage: "Par page", page: "Page", of: "sur", showing: "Affichage", total: "Total", totals: "Totaux", errorOccurred: "Une erreur s'est produite" }, Ji = { title: "Langue", help: "Choisissez la langue de l'interface. Votre choix est enregistré dans ce navigateur.", label: "Langue" }, Zi = { back: "Retour", logout: "Déconnexion", openMenu: "Ouvrir le menu", closeMenu: "Fermer le menu", new: "Nouveau : {{label}}" }, Xi = { dashboard: "Tableau de bord", setup: "Configuration de l'entreprise", tutorial: "Premiers pas", chat: "Chat", reports: "Rapports", "trial-balance": "Balance comptable", "general-ledger": "Grand livre", "stock-balance": "Solde de stock", "profit-and-loss": "Compte de résultat", "balance-sheet": "Bilan", "ar-aging": "Balance âgée clients", "ap-aging": "Balance âgée fournisseurs", analytics: "Analyses", "chart-of-accounts": "Plan comptable" }, eo = { quotation: { one: "Devis", other: "Devis" }, proposal: { one: "Offre groupée", other: "Offres groupées" }, "sales-order": { one: "Commande client", other: "Commandes client" }, "sales-invoice": { one: "Facture de vente", other: "Factures de vente" }, "pos-invoice": { one: "Ticket de caisse", other: "Tickets de caisse" }, "purchase-order": { one: "Bon de commande", other: "Bons de commande" }, "purchase-invoice": { one: "Facture d'achat", other: "Factures d'achat" }, "payment-entry": { one: "Paiement", other: "Paiements" }, "journal-entry": { one: "Écriture comptable", other: "Écritures comptables" }, "bank-transaction": { one: "Transaction bancaire", other: "Transactions bancaires" }, budget: { one: "Budget", other: "Budgets" }, subscription: { one: "Abonnement", other: "Abonnements" }, "stock-entry": { one: "Mouvement de stock", other: "Mouvements de stock" }, "delivery-note": { one: "Bon de livraison", other: "Bons de livraison" }, "purchase-receipt": { one: "Bon de réception", other: "Bons de réception" }, "pricing-rule": { one: "Règle de prix", other: "Règles de prix" } }, to = { company: { one: "Société", other: "Sociétés" }, customer: { one: "Client", other: "Clients" }, supplier: { one: "Fournisseur", other: "Fournisseurs" }, item: { one: "Article", other: "Articles" }, warehouse: { one: "Entrepôt", other: "Entrepôts" } }, no = { chats: "Discussions", newChat: "Nouvelle discussion", deleteChat: "Supprimer la discussion", customAnalytics: "Analyses personnalisées", newAnalytics: "Nouvelle analyse", deleteReport: "Supprimer le rapport", groups: { Introduction: "Introduction", Selling: "Ventes", Buying: "Achats", Accounting: "Comptabilité", Stock: "Stock", Reports: "Rapports", Masters: "Données de base", Settings: "Paramètres" }, items: { "Getting Started": "Premiers pas", "Company Setup": "Configuration de l'entreprise", "Opening Balances": "Soldes d'ouverture", Quotation: "Devis", Proposal: "Offre groupée", "Sales Order": "Commande client", "Sales Invoice": "Facture de vente", "POS Invoice": "Ticket de caisse", "Purchase Order": "Bon de commande", "Purchase Invoice": "Facture d'achat", "Payment Entry": "Paiement", "Journal Entry": "Écriture comptable", "Bank Transaction": "Transaction bancaire", Budget: "Budget", Subscription: "Abonnement", "Stock Entry": "Mouvement de stock", "Delivery Note": "Bon de livraison", "Purchase Receipt": "Bon de réception", "Trial Balance": "Balance comptable", "Profit & Loss": "Compte de résultat", "Balance Sheet": "Bilan", "General Ledger": "Grand livre", "AR Aging": "Balance âgée clients", "AP Aging": "Balance âgée fournisseurs", Analytics: "Analyses", "Stock Balance": "Solde de stock", Company: "Société", Customer: "Client", Supplier: "Fournisseur", Item: "Article", Warehouse: "Entrepôt", General: "Général", "Pricing Rule": "Règle de prix", "Users & Team": "Utilisateurs et équipe", "Chart of Accounts": "Plan comptable" } }, ao = { taglineFirstRun: "Créez votre compte administrateur pour commencer", taglineRegister: "Créez votre compte", taglineSignIn: "Connectez-vous à votre compte", demoBanner: "Le mode démo est actif. Connectez-vous avec un compte administrateur pour gérer les paramètres ou désactiver l'accès public.", fullName: "Nom complet", email: "E-mail", password: "Mot de passe", confirmPassword: "Confirmer le mot de passe", createAdmin: "Créer un compte administrateur", register: "S'inscrire", signIn: "Se connecter", browsingTitle: "Simple visite ?", browsingBody: "Démarrez une nouvelle session de chat et regardez la démo en direct.", enterDemo: "Lancer la démo", haveInvite: "Vous avez une invitation ?", noAccountPrompt: "Besoin d'un compte ?", registerLink: "S'inscrire", alreadyHaveAccount: "Vous avez déjà un compte ?", signInLink: "Se connecter", passwordsNoMatch: "Les mots de passe ne correspondent pas", passwordTooShort: "Le mot de passe doit comporter au moins 6 caractères", registrationFailed: "Échec de l'inscription", loginFailed: "Échec de la connexion", orContinueWith: "ou continuer avec", continueWithProvider: "Continuer avec {{provider}}", oauthError: { generic: "Échec de la connexion. Veuillez réessayer.", email_exists: "Un compte avec cet e-mail existe déjà. Connectez-vous, puis liez ce fournisseur depuis les paramètres du compte.", email_unverified: "Votre fournisseur n'a pas confirmé d'e-mail vérifié, la connexion est donc impossible.", registration_closed: "Cet e-mail n'a pas encore de compte et l'inscription se fait uniquement sur invitation.", invite_invalid: "Cette invitation est invalide, déjà utilisée ou émise pour un autre e-mail.", identity_taken: "Ce compte fournisseur est déjà lié à un autre utilisateur.", account_disabled: "Ce compte a été désactivé.", token_exchange_failed: "Échec de la connexion auprès du fournisseur. Veuillez réessayer." } }, ro = { pdfTitle: "PDF et impression", pageSize: "Format de page", pdfHelp: "A4 est la norme internationale (210 x 297 mm). Letter est la norme aux États-Unis (8,5 x 11 po).", passwordTitle: "Changer le mot de passe", currentPassword: "Mot de passe actuel", newPassword: "Nouveau mot de passe", confirmNewPassword: "Confirmer le nouveau mot de passe", changePassword: "Changer le mot de passe", changingPassword: "Modification...", passwordChanged: "Mot de passe modifié.", setPasswordTitle: "Définir un mot de passe", setPasswordBody: "Votre compte se connecte avec Google. Définissez un mot de passe pour vous connecter aussi avec e-mail et mot de passe — un recours pratique si vous perdez l'accès à votre compte Google.", setPassword: "Définir le mot de passe", passwordSet: "Mot de passe défini.", linkedAccountsTitle: "Comptes liés", linkedAccountsBody: "Liez un compte Google ou Apple pour vous connecter sans mot de passe.", linked: "Lié", linkProvider: "Lier {{provider}}", openingTitle: "Soldes d'ouverture", openingBody: "La page Soldes d'ouverture permet d'importer les soldes des comptes, le stock et les factures impayées d'un système précédent.", openingEnabled: "Actuellement activé — accessible sous Introduction > Soldes d'ouverture.", openingDisabled: "Actuellement désactivé — la page est masquée dans la barre latérale.", signupTitle: "Inscription publique", signupBody: "Permettre à quiconque de créer son propre compte (en tant que lecteur) sans invitation. Lorsque désactivé, les nouveaux utilisateurs ne peuvent rejoindre que via un lien d'invitation.", signupEnabled: "Actuellement activé — toute personne disposant de l'URL peut s'inscrire en tant que lecteur.", signupDisabled: "Actuellement désactivé — l'inscription se fait uniquement sur invitation.", chatApiTitle: "API de chat", apiTitle: "API programmatique", restApiBody: "Permettre à des connecteurs et scripts de piloter cet ERP via son API REST (documents, données de base, rapports) avec les mêmes clés API Bearer. Désactivé par défaut.", restApiEnabled: "Actuellement activé — les clés émises peuvent appeler /api/documents, /api/masters et le reste de l'API REST.", restApiDisabled: "Actuellement désactivé — l'API REST n'accepte que le cookie de session ; les clés sont rejetées.", restApiDeactivateTitle: "Désactiver l'API REST ?", restApiDeactivateBody: "L'accès par clé Bearer à l'API REST sera désactivé — les connecteurs et scripts sont rejetés jusqu'à sa réactivation. L'application web (cookie de session) n'est pas affectée, et vos clés API ne sont PAS supprimées : elles fonctionnent à nouveau dès que vous réactivez l'API.", chatApiBody: "Permettre à des applications externes de dialoguer avec l'agent de chat de cet ERP via une API HTTP, à l'aide de clés API Bearer. Désactivé par défaut.", chatApiEnabled: "Actuellement activé — les clés émises peuvent appeler POST /api/v1/chat.", chatApiDisabled: "Actuellement désactivé — l'API renvoie 404 et les clés ne fonctionnent pas.", chatApiDeactivateTitle: "Désactiver l'API chat ?", chatApiDeactivateBody: "L'API chat sera désactivée — toute requête programmatique (clés API Bearer) est rejetée jusqu'à sa réactivation. Vos clés API ne sont PAS supprimées : elles restent enregistrées et fonctionnent à nouveau dès que vous réactivez l'API.", chatApiDeactivateConfirm: "Désactiver l'API", chatApiKeysTitle: "Clés API", chatApiTokenOnce: "Copiez ce jeton maintenant — il ne sera plus affiché.", chatApiCopy: "Copier", chatApiDismiss: "Fermer", chatApiRevoked: "révoquée", chatApiRevoke: "Révoquer", chatApiNoKeys: "Aucune clé API pour l'instant.", chatApiName: "Nom", chatApiRole: "Rôle", chatApiCreate: "Créer une clé", chatApiWarn: "Une clé agit avec votre identité et au plus votre rôle — à traiter comme un mot de passe. Révoquer d'abord, puis supprimer.", publicTitle: "Accès public (mode démo)", publicActive: "Actif", publicActiveBody: "L'accès public est activé. N'importe qui peut utiliser l'application sans se connecter. Tous les visiteurs obtiennent des autorisations de niveau gestionnaire.", disablePublic: "Désactiver l'accès public", disabling: "Désactivation...", publicInactiveBody: "Activez l'accès public pour permettre à quiconque d'utiliser l'application sans compte. Utile pour les démos et présentations. Tous les visiteurs obtiennent des autorisations de niveau gestionnaire et partagent la même identité.", enablePublic: "Activer l'accès public", enableWarning: "Cela permettra à quiconque d'accéder à l'application sans se connecter. Ils pourront créer, modifier et valider des documents. Votre compte administrateur nécessite toujours une connexion.", yesEnable: "Oui, activer", enabling: "Activation...", tokenSpendTitle: "Dépenses de jetons", chatApiDelete: "Supprimer", chatApiYourKeys: "Vos clés", chatApiYouBadge: "vous", chatApiUnknownUser: "Utilisateur inconnu", chatApiAdminAllNote: "En tant qu'administrateur, la liste ci-dessous inclut les clés de tous les utilisateurs, groupées par propriétaire. Les vôtres apparaissent en premier.", chatApiConfirmTitle: "Cette clé ne vous appartient pas", chatApiConfirmRevokeBody: "« {{key}} » appartient à {{name}}. La révoquer coupera immédiatement son accès à l'API. Continuer ?", chatApiConfirmDeleteBody: "« {{key}} » appartient à {{name}}. La supprimer retire définitivement sa clé. Continuer ?", chatApiPersonal: "Clés Bearer personnelles pour l'API de chat programmatique. Une clé agit en VOTRE nom : plafonnée à votre rôle, elle suit les changements de rôle en direct et expire avec votre compte. Nécessite que l'admin ait activé l'API de chat.", version: "Version {{version}}" }, so = { Draft: "Brouillon", Open: "Ouvert", Submitted: "Validé", "To Deliver and Bill": "À livrer et facturer", "To Deliver": "À livrer", "To Bill": "À facturer", Completed: "Terminé", Ordered: "Commandé", Paid: "Payé", Unpaid: "Impayé", Cancelled: "Annulé", Discarded: "Supprimé", Overdue: "En retard", Return: "Retour", Closed: "Clôturé" }, io = { balanced: "ÉQUILIBRÉ", imbalanced: "DÉSÉQUILIBRÉ", income: "Produits", expenses: "Charges", totalIncome: "Total des produits", totalExpenses: "Total des charges", netProfit: "Bénéfice", netLoss: "Perte", assets: "Actif", liabilities: "Passif", equity: "Capitaux propres", totalAssets: "Total de l'actif", totalLiabilities: "Total du passif", totalEquity: "Total des capitaux propres", totalLiabilitiesEquity: "Total passif + capitaux propres", current: "Non échu", noData: "Aucune donnée trouvée", noEntries: "Aucune écriture trouvée", noStockData: "Aucune donnée de stock trouvée", noReceivables: "Aucune créance en cours", noPayables: "Aucune dette en cours", noDocuments: "Aucun document trouvé" }, oo = { required: "Requis : {{fields}}", deleteConfirm: "Supprimer ce {{label}} ?", disabledNotice: "Ce {{label}} est désactivé. Il reste dans le système car d'autres enregistrements y font référence.", disabledOnDelete: "{{label}} {{name}} a été désactivé au lieu d'être supprimé car il est référencé par {{reason}}." }, lo = { Account: "Compte", Amount: "Montant", Balance: "Solde", Credit: "Crédit", Debit: "Débit", Date: "Date", Party: "Tiers", "Party Type": "Type de tiers", "Voucher Type": "Type de pièce", "Voucher No": "N° de pièce", Invoice: "Facture", Customer: "Client", Supplier: "Fournisseur", "Due Date": "Date d'échéance", Outstanding: "Encours", "Outstanding Amount": "Montant dû", "Item Code": "Code article", "Item Name": "Nom de l'article", Item: "Article", Warehouse: "Entrepôt", Qty: "Qté", "Valuation Rate": "Coût unitaire", "Stock Value": "Valeur du stock", Name: "Nom", Status: "Statut", Company: "Société", "From Date": "Date de début", "To Date": "Date de fin", "As of Date": "À la date", "Valid Till": "Valable jusqu'au", "Net Total": "Total net", Tax: "Taxe", "Grand Total": "Total TTC", Frequency: "Fréquence", "Notes / Terms": "Notes / Conditions", "Posting Date": "Date de comptabilisation", "Transaction Date": "Date de transaction", "Delivery Date": "Date de livraison", "% Delivered": "% livré", "% Billed": "% facturé", "Update Stock": "Mettre à jour le stock", "Payment Type": "Type de paiement", "Paid From": "Payé depuis", "Paid To": "Payé à", "Paid Amount": "Montant payé", Type: "Type", Total: "Total", Allocated: "Affecté", Unallocated: "Non affecté", Remark: "Remarque", "Total Debit": "Total débit", "Total Credit": "Total crédit", "Cost Center": "Centre de coûts", "Source Warehouse": "Entrepôt source", "Target Warehouse": "Entrepôt cible", Source: "Source", Target: "Cible", "Incoming Value": "Valeur entrante", "Outgoing Value": "Valeur sortante", Rate: "Prix unitaire", "Income Account": "Compte de produits", "Expense Account": "Compte de charges", Description: "Description", "Rate (%)": "Taux (%)", Mode: "Mode", Change: "Monnaie rendue", Currency: "Devise", Title: "Titre", Selling: "Vente", Buying: "Achat", "Discount %": "Remise %", "Discount Amt": "Montant remise", "Min Qty": "Qté min", "Valid From": "Valable à partir du", "Valid Upto": "Valable jusqu'au", Priority: "Priorité", Enabled: "Activé", "Fiscal Year": "Exercice", "Budget Amount": "Montant du budget", "If Exceeded": "Si dépassé", Month: "Mois", "Bank Account": "Compte bancaire", Deposit: "Dépôt", Withdrawal: "Retrait", "Reference No": "N° de référence", "Matched Type": "Type rapproché", "Matched Doc": "Pièce rapprochée", "Start Date": "Date de début", "End Date": "Date de fin", "Billing Interval": "Intervalle de facturation", "Current Period Start": "Début période actuelle", "Current Period End": "Fin période actuelle", "Plan Items": "Articles du plan", "Total Amount": "Montant total", "Stock Entry Type": "Type de mouvement de stock", "Rate Or Discount": "Prix ou remise", "Discount Percentage": "Pourcentage de remise", ID: "ID", "Customer Name": "Nom du client", "Customer Group": "Groupe de clients", Territory: "Territoire", "Credit Limit": "Limite de crédit", Email: "E-mail", Phone: "Téléphone", Address: "Adresse", City: "Ville", "Zip Code": "Code postal", Country: "Pays", "Tax ID": "N° de TVA", "Contact Person": "Personne de contact", "Contact Email": "E-mail du contact", "Contact Phone": "Téléphone du contact", "Supplier Name": "Nom du fournisseur", "Supplier Group": "Groupe de fournisseurs", "Item Group": "Groupe d'articles", "Stock UOM": "Unité de stock", "Standard Rate": "Prix standard", "Warehouse Name": "Nom de l'entrepôt", "Company Name": "Nom de la société" }, co = { items: "Lignes", taxes: "Taxes", references: "Références de paiement", accounts: "Écritures de compte", payments: "Paiements", plans: "Articles du plan", monthly_distribution: "Répartition mensuelle" }, uo = { "Create Sales Order": "Créer une commande client", "Create Sales Invoice": "Créer une facture de vente", "Create Delivery Note": "Créer un bon de livraison", "Create Purchase Invoice": "Créer une facture d'achat", "Create Purchase Receipt": "Créer un bon de réception", "Create Credit Note": "Créer un avoir", "Create Debit Note": "Créer une note de débit", "Create Return": "Créer un retour" }, mo = { totalRevenue: "Chiffre d'affaires total", outstandingReceivable: "Créances en cours", outstandingPayable: "Dettes en cours", totalStockValue: "Valeur totale du stock", recentDocuments: "Documents récents", noRecentDocuments: "Aucun document récent" }, po = { title: "Chat Lambda ERP", subtitle: "Demandez-moi de créer des documents, de consulter des données ou d'exécuter des rapports.", s1: "Quels clients avons-nous ?", s2: "Affiche la balance comptable", s3: "Crée un devis pour 10 Bolt Pack M8", s4: "Liste toutes les factures impayées", loadOlder: "Charger les messages plus anciens", uploading: "Téléversement...", failed: "Échec", remove: "Supprimer", placeholderDemo: "Démo en direct en cours...", placeholderType: "Tapez un message...", placeholderConnecting: "Connexion...", attachTitle: "Joindre un fichier (PDF ou image, max 10 Mo)", creating: "Création du chat...", dropToAttach: "Déposez un fichier à joindre (images ou PDF, max 10 Mo chacun)", demoError: "Impossible de démarrer la démo", voiceStart: "Enregistrer un message vocal", voiceStop: "Arrêter l'enregistrement", voiceTranscribing: "Transcription...", micDenied: "L'accès au microphone a été refusé.", transcribeFailed: "Échec de la transcription. Veuillez réessayer." }, ho = /* @__PURE__ */ JSON.parse(`{"pageTitle":"Premiers pas avec Lambda ERP","intro":"Lambda ERP est un système ERP nativement IA, où toutes les fonctionnalités – comme créer des commandes, vérifier l'inventaire ou enregistrer des paiements – sont accessibles via une interface de chat. Il guide, raisonne et vérifie toutes vos tâches quotidiennes.","openChat":"Ouvrir le chat IA","tipLabel":"Astuce :","topTip":"Le chat IA peut aussi vous donner des liens directs vers des documents et des PDF téléchargeables. Demandez-lui simplement de créer ou de rechercher un document et il inclura des liens cliquables dans sa réponse.","manualIntro":"Si vous souhaitez comprendre pleinement le fonctionnement interne, ou préférez procéder manuellement, voici un cycle commercial complet étape par étape.","caTitle":"Analyses dynamiques – discutez pour obtenir n'importe quel graphique","caBadge":"Fonctionnalité phare","caBody":"Besoin d'un rapport que les modèles prédéfinis ne fournissent pas ? Décrivez-le simplement dans le chat. L'assistant appelle un modèle spécialiste du code qui écrit le rapport pour vous, l'exécute en direct sur vos données ERP et renvoie un lien partageable. Le graphique ou le tableau s'affiche en quelques secondes et est enregistré comme brouillon sous « Analyses personnalisées » dans la barre latérale – vous pouvez le rouvrir, partager l'URL avec vos collègues ou demander à l'assistant de l'affiner.","caTryAsking":"Essayez de demander (cliquez pour préremplir dans le chat) :","caPrompt1":"Montre-moi les 10 meilleurs clients par chiffre d'affaires cette année en diagramme à barres","caPrompt2":"Tendance mensuelle des achats par fournisseur sur tous les mois, étiquette l'axe des x avec le nom du fournisseur","caPrompt3":"Articles les plus vendus par quantité, avec un tableau et un graphique","caPrompt4":"Quels clients me doivent le plus en ce moment ?","caTryInChat":"Essayer dans le chat","caOpenWorkspace":"Ouvrir l'espace d'analyse","flowTitle":"Aperçu du flux des documents","salesCycle":"Cycle de vente","purchaseCycle":"Cycle d'achat","returns":"Retours","flowShortcut":"Raccourci : le devis peut ignorer la commande client et aller directement à la facture de vente ou au bon de livraison","legendStock":"impact stock","legendGl":"impact comptable","legendCash":"impact trésorerie","legendReversal":"annulation","lifecycleTitle":"Cycle de vie du document","lcDraftLabel":"Brouillon :","lcDraftDesc":"Modifiable. Aucun impact financier ni sur le stock.","lcSubmittedLabel":"Validé :","lcSubmittedDesc":"Verrouillé. Les écritures comptables et de stock sont générées.","lcCancelledLabel":"Annulé :","lcCancelledDesc":"Toutes les écritures sont inversées. Le document est archivé définitivement.","lcNoDelete":"Il n'y a pas de suppression. Pour annuler un brouillon : validez-le, puis annulez-le.","lcCorrect":"Pour corriger un document validé : annulez-le et créez-en un nouveau.","readyTitle":"Vous êtes prêt","readyBody1":"Vous comprenez maintenant le cycle complet. Un scénario réel typique ressemble à ceci : vous recevez une commande client (Devis → Commande client), vérifiez le stock, achetez ce dont vous avez besoin (Bon de commande → Bon de réception → Facture d'achat → Paiement), livrez au client (Bon de livraison), facturez-le (Facture de vente) et encaissez le paiement (Paiement). Si quelque chose revient, créez un avoir et un retour de bon de livraison pour inverser les finances et le stock. La Balance comptable confirme que tout est équilibré.","readyBody2":"Vous pouvez aussi tout faire via le chat IA en conversation naturelle – décrivez simplement ce dont vous avez besoin et il créera les bons documents pour vous.","chips":{"Quotation":"Devis","Sales Order":"Commande client","Delivery Note":"Bon de livraison","Sales Invoice":"Facture de vente","Payment Entry":"Paiement","Purchase Order":"Bon de commande","Purchase Receipt":"Bon de réception","Purchase Invoice":"Facture d'achat","Credit Note":"Avoir","DN Return":"Retour BL","Debit Note":"Note de débit","Draft":"Brouillon","Submitted":"Validé","Cancelled":"Annulé"},"links":{"Go to Setup":"Aller à la configuration","Customers":"Clients","Suppliers":"Fournisseurs","Items":"Articles","Warehouses":"Entrepôts","New Quotation":"Nouveau devis","View Quotations":"Voir les devis","Stock Balance":"Solde de stock","New Purchase Order":"Nouveau bon de commande","Purchase Receipts":"Bons de réception","Purchase Invoices":"Factures d'achat","Delivery Notes":"Bons de livraison","Sales Invoices":"Factures de vente","New Payment Entry":"Nouveau paiement","New Stock Entry":"Nouveau mouvement de stock","New Journal Entry":"Nouvelle écriture de journal","Profit & Loss":"Compte de résultat","Balance Sheet":"Bilan","AR Aging":"Balance âgée clients","AP Aging":"Balance âgée fournisseurs","Trial Balance":"Balance comptable","General Ledger":"Grand livre","Open AI Chat":"Ouvrir le chat IA"},"steps":{"1":{"title":"Configurer votre société","description":"Créez une société avec une devise de base. Cela génère votre plan comptable (30 comptes standard répartis entre Actif, Passif, Capitaux propres, Produits et Charges) ainsi qu'un centre de coûts par défaut. Vous pouvez aussi charger des données de démonstration avec des clients, fournisseurs et articles d'exemple pour démarrer rapidement."},"2":{"title":"Créer les données de base","description":"Avant de pouvoir effectuer des transactions, vous avez besoin de fiches de base. Créez au moins un client, un fournisseur, un article (avec un prix standard) et un entrepôt. Si vous avez chargé les données de démonstration à l'étape 1, elles existent déjà.","tip":"Les articles ont un prix standard qui se remplit automatiquement lorsque vous les ajoutez à des documents. Vous pouvez toujours modifier le prix par transaction."},"3":{"title":"Créer un devis","description":"Un devis est une offre non contraignante adressée à un client. Sélectionnez un client, ajoutez des lignes avec quantités et prix, éventuellement des lignes de taxe, puis enregistrez. Les devis n'ont aucun impact financier – ils ne créent ni écritures comptables ni mouvements de stock. Définissez une date de validité pour que l'offre expire automatiquement."},"4":{"title":"Valider et convertir en commande client","description":"Ouvrez votre devis enregistré et cliquez sur Valider pour le confirmer. Cliquez ensuite sur « Créer une commande client » pour le convertir. La commande client représente un engagement confirmé du client. Elle n'a toujours aucun impact financier, mais réserve du stock à des fins de planification.","tip":"Seuls les documents validés peuvent être convertis à l'étape suivante. Brouillon → Valider → Convertir est le flux standard. Pour les affaires rapides, vous pouvez ignorer la commande client et passer directement du devis à la facture de vente ou au bon de livraison."},"5":{"title":"Vérifier le stock avant l'exécution","description":"Avant de pouvoir livrer, vérifiez si vous avez réellement l'article en stock. Ouvrez le rapport Solde de stock et recherchez l'article. Si votre entrepôt affiche une quantité nulle, vous devrez d'abord approvisionner le stock – soit par un bon de commande (achat auprès d'un fournisseur), soit par un mouvement de stock (réception manuelle).","tip":"C'est un scénario courant dans la pratique : vous vendez quelque chose, puis réalisez que vous devez d'abord l'acheter. L'ERP gère les deux flux."},"6":{"title":"Cycle d'achat : acheter du stock à un fournisseur","description":"Si vous devez acheter du stock, vous avez deux chemins valides. Le chemin standard est Bon de commande → Bon de réception → Facture d'achat : utilisez-le lorsque les marchandises arrivent avant ou séparément de la facture du fournisseur. Si la facture et la réception arrivent ensemble, vous pouvez créer directement la facture d'achat et activer « Mettre à jour le stock » afin que le même document réceptionne le stock et enregistre la dette fournisseur.","tip":"Utilisez d'abord le bon de réception lorsque vous recevez les marchandises séparément. Utilisez la facture d'achat avec « Mettre à jour le stock » lorsqu'une seule étape doit à la fois réceptionner le stock et comptabiliser la facture fournisseur. Dans ce chemin direct, indiquez un entrepôt sur chaque ligne d'article en stock."},"7":{"title":"Créer un bon de livraison","description":"Maintenant que vous avez du stock, revenez à votre commande client validée et cliquez sur « Créer un bon de livraison ». Indiquez l'entrepôt sur chaque ligne d'article (d'où partent les marchandises), puis validez. Cela sort le stock de l'entrepôt – votre solde de stock diminue.","tip":"Le bon de livraison est le document d'expédition. Il réduit le stock mais ne crée pas de facture. Vous pouvez livrer et facturer séparément."},"8":{"title":"Créer et valider la facture de vente","description":"À partir de la commande client validée, créez une facture de vente. Lorsque vous validez la facture, des écritures comptables sont générées : les Clients (créances) sont débités (le client vous doit de l'argent) et les Produits des ventes crédités (revenu acquis). Si des taxes sont configurées, la TVA collectée est également créditée. Le montant dû indique ce que le client doit encore."},"9":{"title":"Enregistrer les paiements clients","description":"Créez un paiement pour enregistrer l'argent reçu du client. Définissez le type de paiement sur « Receive » (Recevoir), sélectionnez le client, indiquez le montant et affectez-le à la facture de vente. Vous pouvez effectuer des paiements partiels – le montant dû de la facture se met à jour en conséquence. Créez des paiements supplémentaires jusqu'à ce que la facture soit entièrement réglée.","tip":"Les paiements partiels sont courants. Une facture de 10 000 peut être payée 3 000 maintenant et 7 000 plus tard. Chaque paiement réduit le montant dû."},"10":{"title":"Mouvements de stock (inventaire manuel)","description":"Utilisez les mouvements de stock pour les mouvements d'inventaire non liés aux achats ou aux ventes. « Material Receipt » ajoute du stock (soldes d'ouverture, ajustements). « Material Issue » sort du stock (pertes, consommation interne). « Material Transfer » déplace du stock entre entrepôts. Chaque mouvement met à jour le livre de stock avec une valorisation au coût moyen pondéré.","tip":"Pour les marchandises achetées, utilisez des bons de réception plutôt que des mouvements de stock – ils sont liés au bon de commande et offrent une piste d'audit appropriée."},"11":{"title":"Écritures de journal","description":"Les écritures de journal sont des ajustements comptables manuels – charges à payer, corrections, reclassements, soldes d'ouverture. Chaque écriture doit avoir des débits et crédits équilibrés (total débit = total crédit). Utilisez-les lorsqu'aucun autre type de document ne convient."},"12":{"title":"Paiements des salaires","description":"Lambda ERP gère les salaires à l'aide des outils comptables existants. Comptabilisez d'abord la charge salariale : créez une écriture de journal qui débite la Charge salariale et crédite les Salaires à payer pour le montant total de la paie. Payez ensuite les employés : créez une autre écriture de journal (ou un paiement) qui débite les Salaires à payer et crédite votre compte bancaire. Ce processus en deux étapes garde vos comptes exacts – la charge est enregistrée dans la bonne période et la sortie de trésorerie est suivie séparément.","tip":"Vous pouvez demander à l'assistant IA de le faire pour vous : « Comptabilise 15 000 de salaires pour avril » suivi de « Paie les salaires d'avril depuis la banque ». Il créera automatiquement les bonnes écritures de journal."},"13":{"title":"Retours et avoirs","description":"Lorsqu'un client retourne des marchandises ou que vous devez émettre un avoir, créez un retour. Les retours utilisent le même type de document avec des quantités négatives. Ouvrez une facture de vente validée et créez un avoir (retour de facture de vente) – cela inverse les écritures comptables et réduit le montant dû de la facture d'origine. Pour le stock, créez un retour de bon de livraison pour réintégrer les marchandises en entrepôt. Côté achats, créez une note de débit (retour de facture d'achat) pour inverser une facture fournisseur, ou un retour de bon de réception pour renvoyer des marchandises.","tip":"Un avoir est simplement une facture de vente avec is_return=1 et des quantités négatives. La même logique comptable s'applique – les montants négatifs basculent automatiquement du bon côté débit/crédit. Pour un retour de vente complet, vous avez besoin à la fois d'un avoir (financier) et d'un retour de bon de livraison (stock)."},"14":{"title":"Exécuter les rapports","description":"Vérifiez vos comptes. Le Compte de résultat montre les produits face aux charges et le résultat net d'une période. Le Bilan montre votre situation financière (actif = passif + capitaux propres). La Balance âgée clients montre qui vous doit de l'argent et le retard. La Balance âgée fournisseurs montre ce que vous devez aux fournisseurs. La Balance comptable vérifie l'intégrité de la partie double. Le Grand livre montre chaque écriture individuelle. Le Solde de stock montre l'inventaire actuel."},"15":{"title":"Travailler en devises étrangères","description":"Vos comptes sont tenus dans une seule devise de base (choisie à la configuration de la société), mais vous pouvez effectuer des transactions dans n'importe quelle devise. Définissez une devise sur une facture ou un effet – ou attribuez une devise par défaut à un client ou un fournisseur – et le taux de change de cette date est recherché automatiquement et enregistré sur le document. Le document conserve ses montants dans sa propre devise, tandis que le Grand livre comptabilise toujours dans votre devise de base. Lorsque vous encaissez ou payez ultérieurement à un taux différent, le gain ou la perte de change réalisé est comptabilisé automatiquement sur un compte Gain/Perte de change. Vous pouvez même détenir un solde bancaire en devise étrangère et le convertir plus tard au taux de votre banque – l'écart par rapport à sa valeur comptable est alors réalisé. En fin de mois, vous pouvez réévaluer les soldes en devises ouverts au taux de clôture (un gain/perte latent qui s'inverse à la période suivante), et vous pouvez consulter n'importe quel état financier converti dans une autre devise pour l'affichage.","tip":"Le plus simple est de passer par le chat IA – essayez « Crée une facture de vente pour Lumiere Audio en EUR », « Montre-moi le bilan en EUR » ou « Quelle est notre exposition de change latente en fin de mois ? ». Les données de démonstration incluent déjà un client EUR (Lumiere Audio SARL) dont la facture a été encaissée à un taux différent, ainsi qu'une facture fournisseur EUR ouverte – ouvrez le Grand livre pour voir les écritures de change réalisées."}},"setupTitle":"Configurez votre entreprise — guidé par l'IA","setupBadge":"Commencez ici","setupBody":"Dites à l'assistant quel type d'entreprise vous dirigez, et il construit votre plan comptable pour vous — adapté à votre secteur, avec les bons comptes et des valeurs par défaut cohérentes déjà en place. Il explique chaque décision et ne crée quoi que ce soit qu'après votre approbation.","setupSectors":"Adapté aux services, au commerce de détail & POS, à l'hôtellerie-restauration, au commerce de gros & distribution, à l'import/export, à la fabrication et à la construction.","setupGetStarted":"Commencer dans le chat","setupManual":"Vous préférez un formulaire manuel ? Utilisez la configuration classique.","setupManualLink":"Configuration classique","setupPrompt":"Je souhaite configurer mon entreprise. Pouvez-vous me guider ?"}`), go = { title: "Aide au formatage", intro: "Le texte des Notes / Conditions prend en charge une mise en forme légère sur le PDF :", heading: "titre en gras", emphasis: "italique / gras", rule: "ligne de séparation horizontale", price: "prix aligné à droite à côté du texte ci-dessus (p. ex. Mensuel | CHF 380.—)", block: "Séparez les blocs par une ligne vide." }, fo = { period: "Période", allTime: "Toute la période", semantics: "Comptes de bilan : solde à la fin de la période. Comptes de résultat : mouvement de la période. Cliquez sur un compte pour son grand livre.", empty: "Aucun compte trouvé. Terminez d'abord la configuration de l'entreprise.", disabled: "désactivé", rootType: { Asset: "Actifs", Liability: "Passifs", Equity: "Capitaux propres", Income: "Produits", Expense: "Charges" } }, yo = {
|
|
7236
|
-
common:
|
|
7237
|
-
language:
|
|
7238
|
-
header:
|
|
7239
|
-
titles:
|
|
7240
|
-
doctypes:
|
|
7241
|
-
masters:
|
|
7242
|
-
nav:
|
|
7243
|
-
login:
|
|
7244
|
-
settings:
|
|
7245
|
-
status:
|
|
7246
|
-
reports:
|
|
7247
|
-
masterForm:
|
|
7248
|
-
fields:
|
|
7249
|
-
tables:
|
|
7250
|
-
conversions:
|
|
7251
|
-
dashboard:
|
|
7252
|
-
chat:
|
|
7253
|
-
tutorial:
|
|
7254
|
-
notesMarkup:
|
|
7255
|
-
coa:
|
|
7256
|
-
},
|
|
7197
|
+
const ci = { save: "Save", saving: "Saving...", submit: "Submit", cancel: "Cancel", cancelDoc: "Cancel", cancelDocAbort: "Don't cancel", cancelDocConfirmBtn: "Yes, cancel document", discardDraft: "Discard draft", keepDraft: "Keep", discardDraftConfirm: "Discard draft", showDiscarded: "Show discarded", delete: "Delete", edit: "Edit", pdf: "PDF", addRow: "Add Row", loading: "Loading...", enable: "Enable", disable: "Disable", refresh: "Refresh", refreshing: "Refreshing", areYouSure: "Are you sure?", all: "All", apply: "Apply", new: "New", prev: "Prev", next: "Next", perPage: "Per page", page: "Page", of: "of", showing: "Showing", total: "Total", totals: "Totals", errorOccurred: "An error occurred" }, di = { title: "Language", help: "Choose the language for the interface. Your choice is saved in this browser.", label: "Language" }, ui = { back: "Back", logout: "Logout", openMenu: "Open menu", closeMenu: "Close menu", new: "New {{label}}" }, mi = { dashboard: "Dashboard", setup: "Company Setup", tutorial: "Getting Started", chat: "Chat", reports: "Reports", "trial-balance": "Trial Balance", "general-ledger": "General Ledger", "stock-balance": "Stock Balance", "profit-and-loss": "Profit & Loss", "balance-sheet": "Balance Sheet", "ar-aging": "Accounts Receivable Aging", "ap-aging": "Accounts Payable Aging", analytics: "Analytics", "chart-of-accounts": "Chart of Accounts" }, pi = { quotation: { one: "Quotation", other: "Quotations" }, proposal: { one: "Proposal", other: "Proposals" }, "sales-order": { one: "Sales Order", other: "Sales Orders" }, "sales-invoice": { one: "Sales Invoice", other: "Sales Invoices" }, "pos-invoice": { one: "POS Invoice", other: "POS Invoices" }, "purchase-order": { one: "Purchase Order", other: "Purchase Orders" }, "purchase-invoice": { one: "Purchase Invoice", other: "Purchase Invoices" }, "payment-entry": { one: "Payment Entry", other: "Payment Entries" }, "journal-entry": { one: "Journal Entry", other: "Journal Entries" }, "bank-transaction": { one: "Bank Transaction", other: "Bank Transactions" }, budget: { one: "Budget", other: "Budgets" }, subscription: { one: "Subscription", other: "Subscriptions" }, "stock-entry": { one: "Stock Entry", other: "Stock Entries" }, "delivery-note": { one: "Delivery Note", other: "Delivery Notes" }, "purchase-receipt": { one: "Purchase Receipt", other: "Purchase Receipts" }, "pricing-rule": { one: "Pricing Rule", other: "Pricing Rules" } }, hi = { company: { one: "Company", other: "Companies" }, customer: { one: "Customer", other: "Customers" }, supplier: { one: "Supplier", other: "Suppliers" }, item: { one: "Item", other: "Items" }, warehouse: { one: "Warehouse", other: "Warehouses" } }, gi = { chats: "Chats", newChat: "New Chat", deleteChat: "Delete chat", customAnalytics: "Custom Analytics", newAnalytics: "New Analytics", deleteReport: "Delete report", groups: { Introduction: "Introduction", Selling: "Selling", Buying: "Buying", Accounting: "Accounting", Stock: "Stock", Reports: "Reports", Masters: "Masters", Settings: "Settings" }, items: { "Getting Started": "Getting Started", "Company Setup": "Company Setup", "Opening Balances": "Opening Balances", Quotation: "Quotation", Proposal: "Proposals", "Sales Order": "Sales Order", "Sales Invoice": "Sales Invoice", "POS Invoice": "POS Invoice", "Purchase Order": "Purchase Order", "Purchase Invoice": "Purchase Invoice", "Payment Entry": "Payment Entry", "Journal Entry": "Journal Entry", "Bank Transaction": "Bank Transaction", Budget: "Budget", Subscription: "Subscription", "Stock Entry": "Stock Entry", "Delivery Note": "Delivery Note", "Purchase Receipt": "Purchase Receipt", "Trial Balance": "Trial Balance", "Profit & Loss": "Profit & Loss", "Balance Sheet": "Balance Sheet", "General Ledger": "General Ledger", "AR Aging": "AR Aging", "AP Aging": "AP Aging", Analytics: "Analytics", "Stock Balance": "Stock Balance", Company: "Company", Customer: "Customer", Supplier: "Supplier", Item: "Item", Warehouse: "Warehouse", General: "General", "Pricing Rule": "Pricing Rule", "Users & Team": "Users & Team", "Chart of Accounts": "Chart of Accounts" } }, fi = { taglineFirstRun: "Create your admin account to get started", taglineRegister: "Create your account", taglineSignIn: "Sign in to your account", demoBanner: "Demo mode is active. Sign in with an admin account to manage settings or disable public access.", fullName: "Full Name", email: "Email", password: "Password", confirmPassword: "Confirm Password", createAdmin: "Create Admin Account", register: "Register", signIn: "Sign In", browsingTitle: "Just browsing?", browsingBody: "Start a fresh chat session and watch the live demo.", enterDemo: "Enter Live Demo", haveInvite: "Have an invite?", noAccountPrompt: "Need an account?", registerLink: "Register", alreadyHaveAccount: "Already have an account?", signInLink: "Sign in", passwordsNoMatch: "Passwords do not match", passwordTooShort: "Password must be at least 6 characters", registrationFailed: "Registration failed", loginFailed: "Login failed", orContinueWith: "or continue with", continueWithProvider: "Continue with {{provider}}", oauthError: { generic: "Sign-in failed. Please try again.", email_exists: "An account with this email already exists. Sign in, then link this provider from your account settings.", email_unverified: "Your provider did not confirm a verified email, so we can't sign you in.", registration_closed: "This email has no account yet and registration is invite-only.", invite_invalid: "That invite is invalid, already used, or issued for a different email.", identity_taken: "That provider account is already linked to a different user.", account_disabled: "This account has been disabled.", token_exchange_failed: "Sign-in failed while contacting the provider. Please try again." } }, yi = { pdfTitle: "PDF & Print", pageSize: "Page Size", pdfHelp: "A4 is standard internationally (210 x 297 mm). Letter is standard in the US (8.5 x 11 in).", passwordTitle: "Change Password", currentPassword: "Current password", newPassword: "New password", confirmNewPassword: "Confirm new password", changePassword: "Change password", changingPassword: "Changing...", passwordChanged: "Password changed.", setPasswordTitle: "Set a Password", setPasswordBody: "Your account signs in with Google. Set a password to also sign in with email and password — a handy fallback if you ever lose access to your Google account.", setPassword: "Set password", passwordSet: "Password set.", linkedAccountsTitle: "Linked Accounts", linkedAccountsBody: "Link a Google or Apple account to sign in without a password.", linked: "Linked", linkProvider: "Link {{provider}}", openingTitle: "Opening Balances", openingBody: "The Opening Balances page allows importing account balances, stock, and outstanding invoices from a previous system.", openingEnabled: "Currently enabled — accessible under Introduction > Opening Balances.", openingDisabled: "Currently disabled — the page is hidden from the sidebar.", signupTitle: "Public Signup", signupBody: "Allow anyone to create their own account (as a viewer) without an invite. When off, new users can only join via an invite link.", signupEnabled: "Currently enabled — anyone with the URL can register as a viewer.", signupDisabled: "Currently disabled — registration is invite-only.", chatApiTitle: "Chat API", apiTitle: "Programmatic API", restApiBody: "Let connectors and scripts drive this ERP over its REST API (documents, masters, reports) with the same Bearer API keys. Off by default.", restApiEnabled: "Currently enabled — issued keys can call /api/documents, /api/masters, and the rest of the REST API.", restApiDisabled: "Currently disabled — the REST API only accepts the session cookie; keys are rejected.", restApiDeactivateTitle: "Deactivate the REST API?", restApiDeactivateBody: "Bearer-key access to the REST API will be switched off — connectors and scripts are rejected until you turn it back on. The web app (session cookie) is unaffected, and your API keys are NOT deleted: they start working again the instant you re-enable the API.", chatApiBody: "Let external applications talk to this ERP's chat agent over an HTTP API, using Bearer API keys. Off by default.", chatApiEnabled: "Currently enabled — issued keys can call POST /api/v1/chat.", chatApiDisabled: "Currently disabled — the API returns 404 and keys don't work.", chatApiDeactivateTitle: "Deactivate the chat API?", chatApiDeactivateBody: "The chat API will be switched off — every programmatic request (Bearer API keys) is rejected until you turn it back on. Your API keys are NOT deleted: they stay saved and start working again the instant you re-enable the API.", chatApiDeactivateConfirm: "Deactivate API", chatApiKeysTitle: "API keys", chatApiTokenOnce: "Copy this token now — it won't be shown again.", chatApiCopy: "Copy", chatApiDismiss: "Dismiss", chatApiRevoked: "revoked", chatApiRevoke: "Revoke", chatApiNoKeys: "No API keys yet.", chatApiName: "Name", chatApiRole: "Role", chatApiCreate: "Create key", chatApiWarn: "A key acts with your identity and at most your role — treat it like a password. Revoke first, then delete.", publicTitle: "Public Access (Demo Mode)", publicActive: "Active", publicActiveBody: "Public access is enabled. Anyone can use the application without logging in. All visitors get manager-level permissions.", disablePublic: "Disable Public Access", disabling: "Disabling...", publicInactiveBody: "Enable public access to let anyone use the application without an account. Useful for demos and showcases. All visitors get manager-level permissions and share the same identity.", enablePublic: "Enable Public Access", enableWarning: "This will allow anyone to access the application without logging in. They will be able to create, edit, and submit documents. Your admin account still requires login.", yesEnable: "Yes, Enable", enabling: "Enabling...", tokenSpendTitle: "Token Spend", chatApiDelete: "Delete", chatApiYourKeys: "Your keys", chatApiYouBadge: "you", chatApiUnknownUser: "Unknown user", chatApiAdminAllNote: "You're an admin — the list below includes every user's keys, grouped by owner. Your own keys are shown first.", chatApiConfirmTitle: "This key isn't yours", chatApiConfirmRevokeBody: '"{{key}}" belongs to {{name}}. Revoking it will immediately break their API access. Continue?', chatApiConfirmDeleteBody: '"{{key}}" belongs to {{name}}. Deleting it permanently removes their key. Continue?', chatApiPersonal: "Personal Bearer keys for the programmatic chat API. A key acts as YOU: it is capped at your role, follows role changes live, and dies with your account. Requires the admin to have enabled the Chat API.", version: "Version {{version}}" }, bi = { Draft: "Draft", Open: "Open", Submitted: "Submitted", "To Deliver and Bill": "To Deliver and Bill", "To Deliver": "To Deliver", "To Bill": "To Bill", Completed: "Completed", Ordered: "Ordered", Paid: "Paid", Unpaid: "Unpaid", Cancelled: "Cancelled", Discarded: "Discarded", Overdue: "Overdue", Return: "Return", Closed: "Closed" }, vi = { balanced: "BALANCED", imbalanced: "IMBALANCED", income: "Income", expenses: "Expenses", totalIncome: "Total Income", totalExpenses: "Total Expenses", netProfit: "Net Profit", netLoss: "Net Loss", assets: "Assets", liabilities: "Liabilities", equity: "Equity", totalAssets: "Total Assets", totalLiabilities: "Total Liabilities", totalEquity: "Total Equity", totalLiabilitiesEquity: "Total Liabilities + Equity", current: "Current", noData: "No data found", noEntries: "No entries found", noStockData: "No stock data found", noReceivables: "No outstanding receivables", noPayables: "No outstanding payables", noDocuments: "No documents found" }, xi = { required: "Required: {{fields}}", deleteConfirm: "Delete this {{label}}?", disabledNotice: "This {{label}} is disabled. It remains in the system because other records still reference it.", disabledOnDelete: "{{label}} {{name}} was disabled instead of deleted because it is referenced by {{reason}}." }, Ni = { totalRevenue: "Total Revenue", outstandingReceivable: "Outstanding Receivable", outstandingPayable: "Outstanding Payable", totalStockValue: "Total Stock Value", recentDocuments: "Recent Documents", noRecentDocuments: "No recent documents" }, wi = { title: "Lambda ERP Chat", subtitle: "Ask me to create documents, look up data, or run reports.", s1: "What customers do we have?", s2: "Show me the trial balance", s3: "Create a quotation for 10 Bolt Pack M8", s4: "List all unpaid invoices", loadOlder: "Load older messages", uploading: "Uploading...", failed: "Failed", remove: "Remove", placeholderDemo: "Running live demo...", placeholderType: "Type a message...", placeholderConnecting: "Connecting...", attachTitle: "Attach file (PDF or image, max 10 MB)", creating: "Creating chat...", dropToAttach: "Drop file to attach (images or PDF, max 10 MB each)", demoError: "Could not start demo", voiceStart: "Record voice message", voiceStop: "Stop recording", voiceTranscribing: "Transcribing...", micDenied: "Microphone access was denied.", transcribeFailed: "Transcription failed. Please try again." }, ki = { "Create Credit Note": "Create Credit Note", "Create Debit Note": "Create Debit Note", "Create Delivery Note": "Create Delivery Note", "Create Purchase Invoice": "Create Purchase Invoice", "Create Purchase Receipt": "Create Purchase Receipt", "Create Return": "Create Return", "Create Sales Invoice": "Create Sales Invoice", "Create Sales Order": "Create Sales Order" }, Ci = { "% Billed": "% Billed", "% Delivered": "% Delivered", Account: "Account", Address: "Address", Allocated: "Allocated", Amount: "Amount", "As of Date": "As of Date", Balance: "Balance", "Bank Account": "Bank Account", "Billing Interval": "Billing Interval", "Budget Amount": "Budget Amount", Buying: "Buying", Change: "Change", City: "City", Company: "Company", "Company Name": "Company Name", "Cost Center": "Cost Center", Country: "Country", Credit: "Credit", "Credit Limit": "Credit Limit", Currency: "Currency", "Current Period End": "Current Period End", "Contact Person": "Contact Person", "Contact Email": "Contact Email", "Contact Phone": "Contact Phone", "Current Period Start": "Current Period Start", Customer: "Customer", "Customer Group": "Customer Group", "Customer Name": "Customer Name", Date: "Date", Debit: "Debit", "Delivery Date": "Delivery Date", Deposit: "Deposit", Description: "Description", "Discount %": "Discount %", "Discount Amt": "Discount Amt", "Discount Percentage": "Discount Percentage", "Due Date": "Due Date", Email: "Email", Enabled: "Enabled", "End Date": "End Date", "Expense Account": "Expense Account", "Fiscal Year": "Fiscal Year", "From Date": "From Date", "Grand Total": "Grand Total", Frequency: "Frequency", ID: "ID", "If Exceeded": "If Exceeded", "Income Account": "Income Account", "Incoming Value": "Incoming Value", Invoice: "Invoice", Item: "Item", "Item Code": "Item Code", "Item Group": "Item Group", "Item Name": "Item Name", "Matched Doc": "Matched Doc", "Matched Type": "Matched Type", "Min Qty": "Min Qty", Mode: "Mode", Month: "Month", Name: "Name", "Net Total": "Net Total", "Notes / Terms": "Notes / Terms", "Outgoing Value": "Outgoing Value", Outstanding: "Outstanding", "Outstanding Amount": "Outstanding Amount", "Paid Amount": "Paid Amount", "Paid From": "Paid From", "Paid To": "Paid To", Party: "Party", "Party Type": "Party Type", "Payment Type": "Payment Type", Phone: "Phone", "Plan Items": "Plan Items", "Posting Date": "Posting Date", Priority: "Priority", Qty: "Qty", Rate: "Rate", "Rate (%)": "Rate (%)", "Rate Or Discount": "Rate Or Discount", "Reference No": "Reference No", Remark: "Remark", Selling: "Selling", Source: "Source", "Source Warehouse": "Source Warehouse", "Standard Rate": "Standard Rate", "Start Date": "Start Date", Status: "Status", "Stock Entry Type": "Stock Entry Type", "Stock UOM": "Stock UOM", "Stock Value": "Stock Value", Supplier: "Supplier", "Supplier Group": "Supplier Group", "Supplier Name": "Supplier Name", Target: "Target", "Target Warehouse": "Target Warehouse", Tax: "Tax", "Tax ID": "Tax ID", Territory: "Territory", Title: "Title", "To Date": "To Date", Total: "Total", "Total Amount": "Total Amount", "Total Credit": "Total Credit", "Total Debit": "Total Debit", "Transaction Date": "Transaction Date", Type: "Type", Unallocated: "Unallocated", "Update Stock": "Update Stock", "Valid From": "Valid From", "Valid Till": "Valid Till", "Valid Upto": "Valid Upto", "Valuation Rate": "Valuation Rate", "Voucher No": "Voucher No", "Voucher Type": "Voucher Type", Warehouse: "Warehouse", "Warehouse Name": "Warehouse Name", Withdrawal: "Withdrawal", "Zip Code": "Zip Code" }, Si = { accounts: "accounts", items: "items", monthly_distribution: "monthly_distribution", payments: "payments", plans: "plans", references: "references", taxes: "taxes" }, Di = /* @__PURE__ */ JSON.parse(`{"chips":{"Cancelled":"Cancelled","Credit Note":"Credit Note","DN Return":"DN Return","Debit Note":"Debit Note","Delivery Note":"Delivery Note","Draft":"Draft","Payment Entry":"Payment Entry","Purchase Invoice":"Purchase Invoice","Purchase Order":"Purchase Order","Purchase Receipt":"Purchase Receipt","Quotation":"Quotation","Sales Invoice":"Sales Invoice","Sales Order":"Sales Order","Submitted":"Submitted"},"links":{"AP Aging":"AP Aging","AR Aging":"AR Aging","Balance Sheet":"Balance Sheet","Customers":"Customers","Delivery Notes":"Delivery Notes","General Ledger":"General Ledger","Go to Setup":"Go to Setup","Items":"Items","New Journal Entry":"New Journal Entry","New Payment Entry":"New Payment Entry","New Purchase Order":"New Purchase Order","New Quotation":"New Quotation","New Stock Entry":"New Stock Entry","Open AI Chat":"Open AI Chat","Profit & Loss":"Profit & Loss","Purchase Invoices":"Purchase Invoices","Purchase Receipts":"Purchase Receipts","Sales Invoices":"Sales Invoices","Stock Balance":"Stock Balance","Suppliers":"Suppliers","Trial Balance":"Trial Balance","View Quotations":"View Quotations","Warehouses":"Warehouses"},"steps":{"1":{"title":"Set Up Your Company","description":"Create a company with a base currency. This generates your Chart of Accounts (30 standard accounts across Assets, Liabilities, Equity, Income, and Expenses) and a default Cost Center. You can also seed demo data with sample customers, suppliers, and items to get started quickly."},"2":{"title":"Create Master Data","description":"Before you can transact, you need master records. Create at least one Customer, one Supplier, one Item (with a standard rate), and one Warehouse. If you seeded demo data in Step 1, these already exist.","tip":"Items have a standard rate that auto-fills when you add them to documents. You can always override the rate per transaction."},"3":{"title":"Create a Quotation","description":"A Quotation is a non-binding offer to a customer. Select a customer, add line items with quantities and rates, optionally add tax rows, then save. Quotations have no financial impact — they don't create accounting or stock entries. Set a validity date so the offer expires automatically."},"4":{"title":"Submit and Convert to Sales Order","description":"Open your saved Quotation and click Submit to confirm it. Then click “Create Sales Order” to convert it. The Sales Order represents a confirmed commitment from the customer. It still has no financial impact, but it reserves stock for planning purposes.","tip":"Only submitted documents can be converted to the next step. Draft → Submit → Convert is the standard flow. For quick deals, you can skip the Sales Order and go directly from Quotation to Sales Invoice or Delivery Note."},"5":{"title":"Check Stock Before Fulfilling","description":"Before you can deliver, check if you actually have the item in stock. Go to the Stock Balance report and look up the item. If your warehouse has zero quantity, you’ll need to bring stock in first — either through a Purchase Order (buying from a supplier) or a Stock Entry (manual receipt).","tip":"This is a common real-world scenario: you sell something, then realize you need to buy it first. The ERP handles both flows."},"6":{"title":"Purchase Cycle: Buy Stock from a Supplier","description":"If you need to buy stock, you have two valid paths. The standard path is Purchase Order -> Purchase Receipt -> Purchase Invoice: use this when goods arrive before or separately from the supplier bill. If the bill and receipt happen together, you can create the Purchase Invoice directly and enable Update Stock so the same document both receives inventory and records Accounts Payable.","tip":"Use Purchase Receipt first when receiving goods separately. Use Purchase Invoice with Update Stock when one step should both receive stock and book the supplier bill. In that direct path, set a warehouse on each stock item row."},"7":{"title":"Create a Delivery Note","description":"Now that you have stock, go back to your submitted Sales Order and click “Create Delivery Note.” Set the warehouse on each item row (where the goods ship from), then submit. This moves inventory out of the warehouse — your stock balance decreases.","tip":"The Delivery Note is the shipping document. It reduces stock but doesn’t create an invoice. You can deliver and invoice separately."},"8":{"title":"Create and Submit the Sales Invoice","description":"From the submitted Sales Order, create a Sales Invoice. When you submit the invoice, GL entries are posted: Accounts Receivable is debited (the customer owes you) and Sales Revenue is credited (income earned). If taxes are configured, Tax Payable is also credited. The outstanding amount shows what the customer still owes."},"9":{"title":"Record Customer Payments","description":"Create a Payment Entry to record money received from the customer. Set the payment type to “Receive,” select the customer, specify the amount, and allocate it against the Sales Invoice. You can make partial payments — the invoice’s outstanding amount updates accordingly. Create additional Payment Entries until the invoice is fully paid.","tip":"Partial payments are common. A 10,000 invoice might be paid as 3,000 now and 7,000 later. Each Payment Entry reduces the outstanding amount."},"10":{"title":"Stock Entries (Manual Inventory)","description":"Use Stock Entries for inventory movements that aren’t tied to purchases or sales. Material Receipt adds stock (opening balances, adjustments). Material Issue removes stock (write-offs, internal consumption). Material Transfer moves stock between warehouses. Each entry updates the stock ledger with moving-average valuation.","tip":"For purchased goods, use Purchase Receipts instead of Stock Entries — they link to the Purchase Order and give you a proper audit trail."},"11":{"title":"Journal Entries","description":"Journal Entries are manual accounting adjustments — expense accruals, corrections, reclassifications, opening balances. Each entry must have balanced debits and credits (total debit = total credit). Use these when no other document type fits."},"12":{"title":"Salary Payments","description":"Lambda ERP handles salaries through the existing accounting tools. First, accrue the salary expense: create a Journal Entry that debits Salary Expense and credits Salary Payable for the total payroll amount. Then pay the employees: create another Journal Entry (or Payment Entry) that debits Salary Payable and credits your bank account. This two-step process keeps your books accurate — the expense is recorded in the right period, and the cash outflow is tracked separately.","tip":"You can ask the AI assistant to do this for you: “Accrue 15,000 in salaries for April” followed by “Pay the April salaries from bank.” It will create the right journal entries automatically."},"13":{"title":"Returns and Credit Notes","description":"When a customer returns goods or you need to issue a credit, create a return. Returns use the same document type with negative quantities. Open a submitted Sales Invoice and create a Credit Note (Sales Invoice return) — this reverses the GL entries and reduces the original invoice’s outstanding amount. For stock, create a Delivery Note return to bring goods back into the warehouse. On the buying side, create a Debit Note (Purchase Invoice return) to reverse a supplier bill, or a Purchase Receipt return to send goods back.","tip":"A Credit Note is just a Sales Invoice with is_return=1 and negative quantities. The same GL logic runs — negative amounts automatically flip to the correct debit/credit sides. For a full sales return, you need both a Credit Note (financials) and a Delivery Note return (stock)."},"14":{"title":"Run Reports","description":"Check your books. The Profit & Loss shows income vs expenses and net profit for a period. The Balance Sheet shows your financial position (assets = liabilities + equity). AR Aging shows who owes you money and how overdue it is. AP Aging shows what you owe suppliers. The Trial Balance verifies double-entry integrity. The General Ledger shows every individual posting. Stock Balance shows current inventory."},"15":{"title":"Working in Foreign Currencies","description":"Your books are kept in a single base currency (chosen at company setup), but you can transact in any currency. Set a currency on an invoice or bill — or give a customer or supplier a default currency — and the exchange rate for that date is looked up automatically and stored on the document. The document keeps its amounts in its own currency, while the General Ledger always posts in your base currency. When you later collect or pay at a different rate, the realized exchange gain or loss is booked automatically to an Exchange Gain/Loss account. You can even hold a foreign-currency bank balance and convert it later at your bank’s rate — the difference versus its carried value is realized then. At month end you can revalue open foreign balances to the closing rate (an unrealized gain/loss that reverses next period), and you can view any financial statement translated into another currency for display.","tip":"This is easiest through the AI chat — try “Create a sales invoice for Lumiere Audio in EUR,” “Show me the balance sheet in EUR,” or “What’s our unrealized FX exposure at month end?” The seeded demo already includes a EUR customer (Lumiere Audio SARL) whose invoice was collected at a different rate, plus an open EUR supplier bill — open the General Ledger to see the realized FX postings."}},"caTitle":"Dynamic Analytics — Chat Your Way to Any Chart","caBadge":"Signature Feature","caBody":"Need a report the presets can’t give you? Just describe it in chat. The assistant calls a code-specialist model that writes the report for you, runs it live over your ERP data, and returns a sharable link. The chart or table renders in seconds and is saved as a draft under Custom Analytics in the sidebar — you can reopen it, share the URL with teammates, or ask the assistant to refine it.","caTryAsking":"Try asking (click to prefill in chat):","caPrompt1":"Show me top 10 customers by revenue this year as a bar chart","caPrompt2":"Monthly purchases trend by supplier over all months and label x-axis with supplier name","caPrompt3":"Best selling items by quantity, with a table and a chart","caPrompt4":"Which customers owe me the most right now?","caTryInChat":"Try it in chat","caOpenWorkspace":"Open Analytics workspace","flowTitle":"Document Flow Overview","salesCycle":"Sales Cycle","flowShortcut":"Shortcut: Quotation can skip Sales Order and go directly to Sales Invoice or Delivery Note","purchaseCycle":"Purchase Cycle","returns":"Returns","legendStock":"stock impact","legendGl":"GL impact","legendCash":"cash impact","legendReversal":"reversal","lifecycleTitle":"Document Lifecycle","lcDraftLabel":"Draft:","lcDraftDesc":"Editable. No financial or stock impact.","lcSubmittedLabel":"Submitted:","lcSubmittedDesc":"Locked. GL entries and stock ledger entries are posted.","lcCancelledLabel":"Cancelled:","lcCancelledDesc":"All entries reversed. Document is permanently archived.","lcNoDelete":"There is no delete. To void a draft: submit it, then cancel it.","lcCorrect":"To correct a submitted document: cancel it and create a new one.","pageTitle":"Getting Started with Lambda ERP","intro":"Lambda ERP is an AI Native ERP System, with all functionality — like creating orders, checking inventory, recording payments — being accessible through a chat interface. It instructs, reasons and checks all your daily business tasks.","openChat":"Open AI Chat","tipLabel":"Tip:","topTip":"The AI chat can also give you direct links to documents and downloadable PDFs. Just ask it to create or look up a document and it will include clickable links in its response.","manualIntro":"If you want to fully understand how things work under the hood, or prefer to do things manually, here’s a full business cycle step by step.","readyTitle":"You're Ready","readyBody1":"You now understand the full cycle. A typical real-world scenario looks like this: you receive a customer order (Quotation → Sales Order), check stock, buy what you need (Purchase Order → Purchase Receipt → Purchase Invoice → Payment), deliver to the customer (Delivery Note), bill them (Sales Invoice), and collect payment (Payment Entry). If something comes back, create a Credit Note and Delivery Note return to reverse the financials and stock. The Trial Balance confirms everything is balanced.","readyBody2":"You can also use the AI chat to do all of this through natural conversation — just describe what you need and it will create the right documents for you.","setupTitle":"Set Up Your Company — Guided by AI","setupBadge":"Start Here","setupBody":"Tell the assistant what kind of business you run, and it builds your chart of accounts for you — tailored to your sector, with the right accounts and sensible defaults already wired up. It explains each decision and only creates anything once you approve.","setupSectors":"Tailored for services, retail & POS, hospitality, wholesale & distribution, import/export, manufacturing, and construction.","setupGetStarted":"Get started in chat","setupManual":"Prefer a manual form? Use the classic setup.","setupManualLink":"Classic setup","setupPrompt":"I'd like to set up my company. Can you guide me through it?"}`), Ai = { title: "Formatting help", intro: "The Notes / Terms text supports light formatting on the PDF:", heading: "bold heading", emphasis: "italic / bold", rule: "horizontal divider line", price: "right-aligned price beside the text above (e.g. Monthly | CHF 380.—)", block: "Separate blocks with a blank line." }, Pi = { period: "Period", allTime: "All time", semantics: "Balance-sheet accounts: closing balance at period end. P&L accounts: movement within the period. Click an account for its ledger.", empty: "No accounts found. Complete the company setup first.", disabled: "disabled", rootType: { Asset: "Assets", Liability: "Liabilities", Equity: "Equity", Income: "Income", Expense: "Expenses" } }, _i = {
|
|
7198
|
+
common: ci,
|
|
7199
|
+
language: di,
|
|
7200
|
+
header: ui,
|
|
7201
|
+
titles: mi,
|
|
7202
|
+
doctypes: pi,
|
|
7203
|
+
masters: hi,
|
|
7204
|
+
nav: gi,
|
|
7205
|
+
login: fi,
|
|
7206
|
+
settings: yi,
|
|
7207
|
+
status: bi,
|
|
7208
|
+
reports: vi,
|
|
7209
|
+
masterForm: xi,
|
|
7210
|
+
dashboard: Ni,
|
|
7211
|
+
chat: wi,
|
|
7212
|
+
conversions: ki,
|
|
7213
|
+
fields: Ci,
|
|
7214
|
+
tables: Si,
|
|
7215
|
+
tutorial: Di,
|
|
7216
|
+
notesMarkup: Ai,
|
|
7217
|
+
coa: Pi
|
|
7218
|
+
}, Ti = { 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" }, Ri = { title: "Sprache", help: "Wählen Sie die Sprache der Oberfläche. Ihre Auswahl wird in diesem Browser gespeichert.", label: "Sprache" }, Ii = { back: "Zurück", logout: "Abmelden", openMenu: "Menü öffnen", closeMenu: "Menü schließen", new: "Neu: {{label}}" }, Bi = { 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" }, Ei = { 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" } }, Li = { 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" } }, Oi = { 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" } }, qi = { 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." } }, zi = { 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}}" }, Mi = { 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" }, Fi = { 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" }, $i = { 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." }, Ui = { 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" }, Vi = { items: "Positionen", taxes: "Steuern", references: "Zahlungsreferenzen", accounts: "Kontobuchungen", payments: "Zahlungen", plans: "Planpositionen", monthly_distribution: "Monatliche Verteilung" }, Ki = { "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" }, ji = { totalRevenue: "Gesamtumsatz", outstandingReceivable: "Offene Forderungen", outstandingPayable: "Offene Verbindlichkeiten", totalStockValue: "Gesamter Lagerwert", recentDocuments: "Letzte Dokumente", noRecentDocuments: "Keine aktuellen Dokumente" }, Gi = { 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." }, Wi = /* @__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?"}'), Hi = { 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." }, Qi = { 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" } }, Yi = {
|
|
7219
|
+
common: Ti,
|
|
7220
|
+
language: Ri,
|
|
7221
|
+
header: Ii,
|
|
7222
|
+
titles: Bi,
|
|
7223
|
+
doctypes: Ei,
|
|
7224
|
+
masters: Li,
|
|
7225
|
+
nav: Oi,
|
|
7226
|
+
login: qi,
|
|
7227
|
+
settings: zi,
|
|
7228
|
+
status: Mi,
|
|
7229
|
+
reports: Fi,
|
|
7230
|
+
masterForm: $i,
|
|
7231
|
+
fields: Ui,
|
|
7232
|
+
tables: Vi,
|
|
7233
|
+
conversions: Ki,
|
|
7234
|
+
dashboard: ji,
|
|
7235
|
+
chat: Gi,
|
|
7236
|
+
tutorial: Wi,
|
|
7237
|
+
notesMarkup: Hi,
|
|
7238
|
+
coa: Qi
|
|
7239
|
+
}, Ji = { save: "Enregistrer", saving: "Enregistrement...", submit: "Valider", cancel: "Annuler", cancelDoc: "Annuler", cancelDocAbort: "Ne pas annuler", cancelDocConfirmBtn: "Annuler définitivement", discardDraft: "Supprimer le brouillon", keepDraft: "Conserver", discardDraftConfirm: "Supprimer", showDiscarded: "Afficher les supprimés", delete: "Supprimer", edit: "Modifier", pdf: "PDF", addRow: "Ajouter une ligne", loading: "Chargement...", enable: "Activer", disable: "Désactiver", refresh: "Actualiser", refreshing: "Actualisation", areYouSure: "Êtes-vous sûr ?", all: "Tous", apply: "Appliquer", new: "Nouveau", prev: "Précédent", next: "Suivant", perPage: "Par page", page: "Page", of: "sur", showing: "Affichage", total: "Total", totals: "Totaux", errorOccurred: "Une erreur s'est produite" }, Zi = { title: "Langue", help: "Choisissez la langue de l'interface. Votre choix est enregistré dans ce navigateur.", label: "Langue" }, Xi = { back: "Retour", logout: "Déconnexion", openMenu: "Ouvrir le menu", closeMenu: "Fermer le menu", new: "Nouveau : {{label}}" }, eo = { dashboard: "Tableau de bord", setup: "Configuration de l'entreprise", tutorial: "Premiers pas", chat: "Chat", reports: "Rapports", "trial-balance": "Balance comptable", "general-ledger": "Grand livre", "stock-balance": "Solde de stock", "profit-and-loss": "Compte de résultat", "balance-sheet": "Bilan", "ar-aging": "Balance âgée clients", "ap-aging": "Balance âgée fournisseurs", analytics: "Analyses", "chart-of-accounts": "Plan comptable" }, to = { quotation: { one: "Devis", other: "Devis" }, proposal: { one: "Offre groupée", other: "Offres groupées" }, "sales-order": { one: "Commande client", other: "Commandes client" }, "sales-invoice": { one: "Facture de vente", other: "Factures de vente" }, "pos-invoice": { one: "Ticket de caisse", other: "Tickets de caisse" }, "purchase-order": { one: "Bon de commande", other: "Bons de commande" }, "purchase-invoice": { one: "Facture d'achat", other: "Factures d'achat" }, "payment-entry": { one: "Paiement", other: "Paiements" }, "journal-entry": { one: "Écriture comptable", other: "Écritures comptables" }, "bank-transaction": { one: "Transaction bancaire", other: "Transactions bancaires" }, budget: { one: "Budget", other: "Budgets" }, subscription: { one: "Abonnement", other: "Abonnements" }, "stock-entry": { one: "Mouvement de stock", other: "Mouvements de stock" }, "delivery-note": { one: "Bon de livraison", other: "Bons de livraison" }, "purchase-receipt": { one: "Bon de réception", other: "Bons de réception" }, "pricing-rule": { one: "Règle de prix", other: "Règles de prix" } }, no = { company: { one: "Société", other: "Sociétés" }, customer: { one: "Client", other: "Clients" }, supplier: { one: "Fournisseur", other: "Fournisseurs" }, item: { one: "Article", other: "Articles" }, warehouse: { one: "Entrepôt", other: "Entrepôts" } }, ao = { chats: "Discussions", newChat: "Nouvelle discussion", deleteChat: "Supprimer la discussion", customAnalytics: "Analyses personnalisées", newAnalytics: "Nouvelle analyse", deleteReport: "Supprimer le rapport", groups: { Introduction: "Introduction", Selling: "Ventes", Buying: "Achats", Accounting: "Comptabilité", Stock: "Stock", Reports: "Rapports", Masters: "Données de base", Settings: "Paramètres" }, items: { "Getting Started": "Premiers pas", "Company Setup": "Configuration de l'entreprise", "Opening Balances": "Soldes d'ouverture", Quotation: "Devis", Proposal: "Offre groupée", "Sales Order": "Commande client", "Sales Invoice": "Facture de vente", "POS Invoice": "Ticket de caisse", "Purchase Order": "Bon de commande", "Purchase Invoice": "Facture d'achat", "Payment Entry": "Paiement", "Journal Entry": "Écriture comptable", "Bank Transaction": "Transaction bancaire", Budget: "Budget", Subscription: "Abonnement", "Stock Entry": "Mouvement de stock", "Delivery Note": "Bon de livraison", "Purchase Receipt": "Bon de réception", "Trial Balance": "Balance comptable", "Profit & Loss": "Compte de résultat", "Balance Sheet": "Bilan", "General Ledger": "Grand livre", "AR Aging": "Balance âgée clients", "AP Aging": "Balance âgée fournisseurs", Analytics: "Analyses", "Stock Balance": "Solde de stock", Company: "Société", Customer: "Client", Supplier: "Fournisseur", Item: "Article", Warehouse: "Entrepôt", General: "Général", "Pricing Rule": "Règle de prix", "Users & Team": "Utilisateurs et équipe", "Chart of Accounts": "Plan comptable" } }, ro = { taglineFirstRun: "Créez votre compte administrateur pour commencer", taglineRegister: "Créez votre compte", taglineSignIn: "Connectez-vous à votre compte", demoBanner: "Le mode démo est actif. Connectez-vous avec un compte administrateur pour gérer les paramètres ou désactiver l'accès public.", fullName: "Nom complet", email: "E-mail", password: "Mot de passe", confirmPassword: "Confirmer le mot de passe", createAdmin: "Créer un compte administrateur", register: "S'inscrire", signIn: "Se connecter", browsingTitle: "Simple visite ?", browsingBody: "Démarrez une nouvelle session de chat et regardez la démo en direct.", enterDemo: "Lancer la démo", haveInvite: "Vous avez une invitation ?", noAccountPrompt: "Besoin d'un compte ?", registerLink: "S'inscrire", alreadyHaveAccount: "Vous avez déjà un compte ?", signInLink: "Se connecter", passwordsNoMatch: "Les mots de passe ne correspondent pas", passwordTooShort: "Le mot de passe doit comporter au moins 6 caractères", registrationFailed: "Échec de l'inscription", loginFailed: "Échec de la connexion", orContinueWith: "ou continuer avec", continueWithProvider: "Continuer avec {{provider}}", oauthError: { generic: "Échec de la connexion. Veuillez réessayer.", email_exists: "Un compte avec cet e-mail existe déjà. Connectez-vous, puis liez ce fournisseur depuis les paramètres du compte.", email_unverified: "Votre fournisseur n'a pas confirmé d'e-mail vérifié, la connexion est donc impossible.", registration_closed: "Cet e-mail n'a pas encore de compte et l'inscription se fait uniquement sur invitation.", invite_invalid: "Cette invitation est invalide, déjà utilisée ou émise pour un autre e-mail.", identity_taken: "Ce compte fournisseur est déjà lié à un autre utilisateur.", account_disabled: "Ce compte a été désactivé.", token_exchange_failed: "Échec de la connexion auprès du fournisseur. Veuillez réessayer." } }, so = { pdfTitle: "PDF et impression", pageSize: "Format de page", pdfHelp: "A4 est la norme internationale (210 x 297 mm). Letter est la norme aux États-Unis (8,5 x 11 po).", passwordTitle: "Changer le mot de passe", currentPassword: "Mot de passe actuel", newPassword: "Nouveau mot de passe", confirmNewPassword: "Confirmer le nouveau mot de passe", changePassword: "Changer le mot de passe", changingPassword: "Modification...", passwordChanged: "Mot de passe modifié.", setPasswordTitle: "Définir un mot de passe", setPasswordBody: "Votre compte se connecte avec Google. Définissez un mot de passe pour vous connecter aussi avec e-mail et mot de passe — un recours pratique si vous perdez l'accès à votre compte Google.", setPassword: "Définir le mot de passe", passwordSet: "Mot de passe défini.", linkedAccountsTitle: "Comptes liés", linkedAccountsBody: "Liez un compte Google ou Apple pour vous connecter sans mot de passe.", linked: "Lié", linkProvider: "Lier {{provider}}", openingTitle: "Soldes d'ouverture", openingBody: "La page Soldes d'ouverture permet d'importer les soldes des comptes, le stock et les factures impayées d'un système précédent.", openingEnabled: "Actuellement activé — accessible sous Introduction > Soldes d'ouverture.", openingDisabled: "Actuellement désactivé — la page est masquée dans la barre latérale.", signupTitle: "Inscription publique", signupBody: "Permettre à quiconque de créer son propre compte (en tant que lecteur) sans invitation. Lorsque désactivé, les nouveaux utilisateurs ne peuvent rejoindre que via un lien d'invitation.", signupEnabled: "Actuellement activé — toute personne disposant de l'URL peut s'inscrire en tant que lecteur.", signupDisabled: "Actuellement désactivé — l'inscription se fait uniquement sur invitation.", chatApiTitle: "API de chat", apiTitle: "API programmatique", restApiBody: "Permettre à des connecteurs et scripts de piloter cet ERP via son API REST (documents, données de base, rapports) avec les mêmes clés API Bearer. Désactivé par défaut.", restApiEnabled: "Actuellement activé — les clés émises peuvent appeler /api/documents, /api/masters et le reste de l'API REST.", restApiDisabled: "Actuellement désactivé — l'API REST n'accepte que le cookie de session ; les clés sont rejetées.", restApiDeactivateTitle: "Désactiver l'API REST ?", restApiDeactivateBody: "L'accès par clé Bearer à l'API REST sera désactivé — les connecteurs et scripts sont rejetés jusqu'à sa réactivation. L'application web (cookie de session) n'est pas affectée, et vos clés API ne sont PAS supprimées : elles fonctionnent à nouveau dès que vous réactivez l'API.", chatApiBody: "Permettre à des applications externes de dialoguer avec l'agent de chat de cet ERP via une API HTTP, à l'aide de clés API Bearer. Désactivé par défaut.", chatApiEnabled: "Actuellement activé — les clés émises peuvent appeler POST /api/v1/chat.", chatApiDisabled: "Actuellement désactivé — l'API renvoie 404 et les clés ne fonctionnent pas.", chatApiDeactivateTitle: "Désactiver l'API chat ?", chatApiDeactivateBody: "L'API chat sera désactivée — toute requête programmatique (clés API Bearer) est rejetée jusqu'à sa réactivation. Vos clés API ne sont PAS supprimées : elles restent enregistrées et fonctionnent à nouveau dès que vous réactivez l'API.", chatApiDeactivateConfirm: "Désactiver l'API", chatApiKeysTitle: "Clés API", chatApiTokenOnce: "Copiez ce jeton maintenant — il ne sera plus affiché.", chatApiCopy: "Copier", chatApiDismiss: "Fermer", chatApiRevoked: "révoquée", chatApiRevoke: "Révoquer", chatApiNoKeys: "Aucune clé API pour l'instant.", chatApiName: "Nom", chatApiRole: "Rôle", chatApiCreate: "Créer une clé", chatApiWarn: "Une clé agit avec votre identité et au plus votre rôle — à traiter comme un mot de passe. Révoquer d'abord, puis supprimer.", publicTitle: "Accès public (mode démo)", publicActive: "Actif", publicActiveBody: "L'accès public est activé. N'importe qui peut utiliser l'application sans se connecter. Tous les visiteurs obtiennent des autorisations de niveau gestionnaire.", disablePublic: "Désactiver l'accès public", disabling: "Désactivation...", publicInactiveBody: "Activez l'accès public pour permettre à quiconque d'utiliser l'application sans compte. Utile pour les démos et présentations. Tous les visiteurs obtiennent des autorisations de niveau gestionnaire et partagent la même identité.", enablePublic: "Activer l'accès public", enableWarning: "Cela permettra à quiconque d'accéder à l'application sans se connecter. Ils pourront créer, modifier et valider des documents. Votre compte administrateur nécessite toujours une connexion.", yesEnable: "Oui, activer", enabling: "Activation...", tokenSpendTitle: "Dépenses de jetons", chatApiDelete: "Supprimer", chatApiYourKeys: "Vos clés", chatApiYouBadge: "vous", chatApiUnknownUser: "Utilisateur inconnu", chatApiAdminAllNote: "En tant qu'administrateur, la liste ci-dessous inclut les clés de tous les utilisateurs, groupées par propriétaire. Les vôtres apparaissent en premier.", chatApiConfirmTitle: "Cette clé ne vous appartient pas", chatApiConfirmRevokeBody: "« {{key}} » appartient à {{name}}. La révoquer coupera immédiatement son accès à l'API. Continuer ?", chatApiConfirmDeleteBody: "« {{key}} » appartient à {{name}}. La supprimer retire définitivement sa clé. Continuer ?", chatApiPersonal: "Clés Bearer personnelles pour l'API de chat programmatique. Une clé agit en VOTRE nom : plafonnée à votre rôle, elle suit les changements de rôle en direct et expire avec votre compte. Nécessite que l'admin ait activé l'API de chat.", version: "Version {{version}}" }, io = { Draft: "Brouillon", Open: "Ouvert", Submitted: "Validé", "To Deliver and Bill": "À livrer et facturer", "To Deliver": "À livrer", "To Bill": "À facturer", Completed: "Terminé", Ordered: "Commandé", Paid: "Payé", Unpaid: "Impayé", Cancelled: "Annulé", Discarded: "Supprimé", Overdue: "En retard", Return: "Retour", Closed: "Clôturé" }, oo = { balanced: "ÉQUILIBRÉ", imbalanced: "DÉSÉQUILIBRÉ", income: "Produits", expenses: "Charges", totalIncome: "Total des produits", totalExpenses: "Total des charges", netProfit: "Bénéfice", netLoss: "Perte", assets: "Actif", liabilities: "Passif", equity: "Capitaux propres", totalAssets: "Total de l'actif", totalLiabilities: "Total du passif", totalEquity: "Total des capitaux propres", totalLiabilitiesEquity: "Total passif + capitaux propres", current: "Non échu", noData: "Aucune donnée trouvée", noEntries: "Aucune écriture trouvée", noStockData: "Aucune donnée de stock trouvée", noReceivables: "Aucune créance en cours", noPayables: "Aucune dette en cours", noDocuments: "Aucun document trouvé" }, lo = { required: "Requis : {{fields}}", deleteConfirm: "Supprimer ce {{label}} ?", disabledNotice: "Ce {{label}} est désactivé. Il reste dans le système car d'autres enregistrements y font référence.", disabledOnDelete: "{{label}} {{name}} a été désactivé au lieu d'être supprimé car il est référencé par {{reason}}." }, co = { Account: "Compte", Amount: "Montant", Balance: "Solde", Credit: "Crédit", Debit: "Débit", Date: "Date", Party: "Tiers", "Party Type": "Type de tiers", "Voucher Type": "Type de pièce", "Voucher No": "N° de pièce", Invoice: "Facture", Customer: "Client", Supplier: "Fournisseur", "Due Date": "Date d'échéance", Outstanding: "Encours", "Outstanding Amount": "Montant dû", "Item Code": "Code article", "Item Name": "Nom de l'article", Item: "Article", Warehouse: "Entrepôt", Qty: "Qté", "Valuation Rate": "Coût unitaire", "Stock Value": "Valeur du stock", Name: "Nom", Status: "Statut", Company: "Société", "From Date": "Date de début", "To Date": "Date de fin", "As of Date": "À la date", "Valid Till": "Valable jusqu'au", "Net Total": "Total net", Tax: "Taxe", "Grand Total": "Total TTC", Frequency: "Fréquence", "Notes / Terms": "Notes / Conditions", "Posting Date": "Date de comptabilisation", "Transaction Date": "Date de transaction", "Delivery Date": "Date de livraison", "% Delivered": "% livré", "% Billed": "% facturé", "Update Stock": "Mettre à jour le stock", "Payment Type": "Type de paiement", "Paid From": "Payé depuis", "Paid To": "Payé à", "Paid Amount": "Montant payé", Type: "Type", Total: "Total", Allocated: "Affecté", Unallocated: "Non affecté", Remark: "Remarque", "Total Debit": "Total débit", "Total Credit": "Total crédit", "Cost Center": "Centre de coûts", "Source Warehouse": "Entrepôt source", "Target Warehouse": "Entrepôt cible", Source: "Source", Target: "Cible", "Incoming Value": "Valeur entrante", "Outgoing Value": "Valeur sortante", Rate: "Prix unitaire", "Income Account": "Compte de produits", "Expense Account": "Compte de charges", Description: "Description", "Rate (%)": "Taux (%)", Mode: "Mode", Change: "Monnaie rendue", Currency: "Devise", Title: "Titre", Selling: "Vente", Buying: "Achat", "Discount %": "Remise %", "Discount Amt": "Montant remise", "Min Qty": "Qté min", "Valid From": "Valable à partir du", "Valid Upto": "Valable jusqu'au", Priority: "Priorité", Enabled: "Activé", "Fiscal Year": "Exercice", "Budget Amount": "Montant du budget", "If Exceeded": "Si dépassé", Month: "Mois", "Bank Account": "Compte bancaire", Deposit: "Dépôt", Withdrawal: "Retrait", "Reference No": "N° de référence", "Matched Type": "Type rapproché", "Matched Doc": "Pièce rapprochée", "Start Date": "Date de début", "End Date": "Date de fin", "Billing Interval": "Intervalle de facturation", "Current Period Start": "Début période actuelle", "Current Period End": "Fin période actuelle", "Plan Items": "Articles du plan", "Total Amount": "Montant total", "Stock Entry Type": "Type de mouvement de stock", "Rate Or Discount": "Prix ou remise", "Discount Percentage": "Pourcentage de remise", ID: "ID", "Customer Name": "Nom du client", "Customer Group": "Groupe de clients", Territory: "Territoire", "Credit Limit": "Limite de crédit", Email: "E-mail", Phone: "Téléphone", Address: "Adresse", City: "Ville", "Zip Code": "Code postal", Country: "Pays", "Tax ID": "N° de TVA", "Contact Person": "Personne de contact", "Contact Email": "E-mail du contact", "Contact Phone": "Téléphone du contact", "Supplier Name": "Nom du fournisseur", "Supplier Group": "Groupe de fournisseurs", "Item Group": "Groupe d'articles", "Stock UOM": "Unité de stock", "Standard Rate": "Prix standard", "Warehouse Name": "Nom de l'entrepôt", "Company Name": "Nom de la société" }, uo = { items: "Lignes", taxes: "Taxes", references: "Références de paiement", accounts: "Écritures de compte", payments: "Paiements", plans: "Articles du plan", monthly_distribution: "Répartition mensuelle" }, mo = { "Create Sales Order": "Créer une commande client", "Create Sales Invoice": "Créer une facture de vente", "Create Delivery Note": "Créer un bon de livraison", "Create Purchase Invoice": "Créer une facture d'achat", "Create Purchase Receipt": "Créer un bon de réception", "Create Credit Note": "Créer un avoir", "Create Debit Note": "Créer une note de débit", "Create Return": "Créer un retour" }, po = { totalRevenue: "Chiffre d'affaires total", outstandingReceivable: "Créances en cours", outstandingPayable: "Dettes en cours", totalStockValue: "Valeur totale du stock", recentDocuments: "Documents récents", noRecentDocuments: "Aucun document récent" }, ho = { title: "Chat Lambda ERP", subtitle: "Demandez-moi de créer des documents, de consulter des données ou d'exécuter des rapports.", s1: "Quels clients avons-nous ?", s2: "Affiche la balance comptable", s3: "Crée un devis pour 10 Bolt Pack M8", s4: "Liste toutes les factures impayées", loadOlder: "Charger les messages plus anciens", uploading: "Téléversement...", failed: "Échec", remove: "Supprimer", placeholderDemo: "Démo en direct en cours...", placeholderType: "Tapez un message...", placeholderConnecting: "Connexion...", attachTitle: "Joindre un fichier (PDF ou image, max 10 Mo)", creating: "Création du chat...", dropToAttach: "Déposez un fichier à joindre (images ou PDF, max 10 Mo chacun)", demoError: "Impossible de démarrer la démo", voiceStart: "Enregistrer un message vocal", voiceStop: "Arrêter l'enregistrement", voiceTranscribing: "Transcription...", micDenied: "L'accès au microphone a été refusé.", transcribeFailed: "Échec de la transcription. Veuillez réessayer." }, go = /* @__PURE__ */ JSON.parse(`{"pageTitle":"Premiers pas avec Lambda ERP","intro":"Lambda ERP est un système ERP nativement IA, où toutes les fonctionnalités – comme créer des commandes, vérifier l'inventaire ou enregistrer des paiements – sont accessibles via une interface de chat. Il guide, raisonne et vérifie toutes vos tâches quotidiennes.","openChat":"Ouvrir le chat IA","tipLabel":"Astuce :","topTip":"Le chat IA peut aussi vous donner des liens directs vers des documents et des PDF téléchargeables. Demandez-lui simplement de créer ou de rechercher un document et il inclura des liens cliquables dans sa réponse.","manualIntro":"Si vous souhaitez comprendre pleinement le fonctionnement interne, ou préférez procéder manuellement, voici un cycle commercial complet étape par étape.","caTitle":"Analyses dynamiques – discutez pour obtenir n'importe quel graphique","caBadge":"Fonctionnalité phare","caBody":"Besoin d'un rapport que les modèles prédéfinis ne fournissent pas ? Décrivez-le simplement dans le chat. L'assistant appelle un modèle spécialiste du code qui écrit le rapport pour vous, l'exécute en direct sur vos données ERP et renvoie un lien partageable. Le graphique ou le tableau s'affiche en quelques secondes et est enregistré comme brouillon sous « Analyses personnalisées » dans la barre latérale – vous pouvez le rouvrir, partager l'URL avec vos collègues ou demander à l'assistant de l'affiner.","caTryAsking":"Essayez de demander (cliquez pour préremplir dans le chat) :","caPrompt1":"Montre-moi les 10 meilleurs clients par chiffre d'affaires cette année en diagramme à barres","caPrompt2":"Tendance mensuelle des achats par fournisseur sur tous les mois, étiquette l'axe des x avec le nom du fournisseur","caPrompt3":"Articles les plus vendus par quantité, avec un tableau et un graphique","caPrompt4":"Quels clients me doivent le plus en ce moment ?","caTryInChat":"Essayer dans le chat","caOpenWorkspace":"Ouvrir l'espace d'analyse","flowTitle":"Aperçu du flux des documents","salesCycle":"Cycle de vente","purchaseCycle":"Cycle d'achat","returns":"Retours","flowShortcut":"Raccourci : le devis peut ignorer la commande client et aller directement à la facture de vente ou au bon de livraison","legendStock":"impact stock","legendGl":"impact comptable","legendCash":"impact trésorerie","legendReversal":"annulation","lifecycleTitle":"Cycle de vie du document","lcDraftLabel":"Brouillon :","lcDraftDesc":"Modifiable. Aucun impact financier ni sur le stock.","lcSubmittedLabel":"Validé :","lcSubmittedDesc":"Verrouillé. Les écritures comptables et de stock sont générées.","lcCancelledLabel":"Annulé :","lcCancelledDesc":"Toutes les écritures sont inversées. Le document est archivé définitivement.","lcNoDelete":"Il n'y a pas de suppression. Pour annuler un brouillon : validez-le, puis annulez-le.","lcCorrect":"Pour corriger un document validé : annulez-le et créez-en un nouveau.","readyTitle":"Vous êtes prêt","readyBody1":"Vous comprenez maintenant le cycle complet. Un scénario réel typique ressemble à ceci : vous recevez une commande client (Devis → Commande client), vérifiez le stock, achetez ce dont vous avez besoin (Bon de commande → Bon de réception → Facture d'achat → Paiement), livrez au client (Bon de livraison), facturez-le (Facture de vente) et encaissez le paiement (Paiement). Si quelque chose revient, créez un avoir et un retour de bon de livraison pour inverser les finances et le stock. La Balance comptable confirme que tout est équilibré.","readyBody2":"Vous pouvez aussi tout faire via le chat IA en conversation naturelle – décrivez simplement ce dont vous avez besoin et il créera les bons documents pour vous.","chips":{"Quotation":"Devis","Sales Order":"Commande client","Delivery Note":"Bon de livraison","Sales Invoice":"Facture de vente","Payment Entry":"Paiement","Purchase Order":"Bon de commande","Purchase Receipt":"Bon de réception","Purchase Invoice":"Facture d'achat","Credit Note":"Avoir","DN Return":"Retour BL","Debit Note":"Note de débit","Draft":"Brouillon","Submitted":"Validé","Cancelled":"Annulé"},"links":{"Go to Setup":"Aller à la configuration","Customers":"Clients","Suppliers":"Fournisseurs","Items":"Articles","Warehouses":"Entrepôts","New Quotation":"Nouveau devis","View Quotations":"Voir les devis","Stock Balance":"Solde de stock","New Purchase Order":"Nouveau bon de commande","Purchase Receipts":"Bons de réception","Purchase Invoices":"Factures d'achat","Delivery Notes":"Bons de livraison","Sales Invoices":"Factures de vente","New Payment Entry":"Nouveau paiement","New Stock Entry":"Nouveau mouvement de stock","New Journal Entry":"Nouvelle écriture de journal","Profit & Loss":"Compte de résultat","Balance Sheet":"Bilan","AR Aging":"Balance âgée clients","AP Aging":"Balance âgée fournisseurs","Trial Balance":"Balance comptable","General Ledger":"Grand livre","Open AI Chat":"Ouvrir le chat IA"},"steps":{"1":{"title":"Configurer votre société","description":"Créez une société avec une devise de base. Cela génère votre plan comptable (30 comptes standard répartis entre Actif, Passif, Capitaux propres, Produits et Charges) ainsi qu'un centre de coûts par défaut. Vous pouvez aussi charger des données de démonstration avec des clients, fournisseurs et articles d'exemple pour démarrer rapidement."},"2":{"title":"Créer les données de base","description":"Avant de pouvoir effectuer des transactions, vous avez besoin de fiches de base. Créez au moins un client, un fournisseur, un article (avec un prix standard) et un entrepôt. Si vous avez chargé les données de démonstration à l'étape 1, elles existent déjà.","tip":"Les articles ont un prix standard qui se remplit automatiquement lorsque vous les ajoutez à des documents. Vous pouvez toujours modifier le prix par transaction."},"3":{"title":"Créer un devis","description":"Un devis est une offre non contraignante adressée à un client. Sélectionnez un client, ajoutez des lignes avec quantités et prix, éventuellement des lignes de taxe, puis enregistrez. Les devis n'ont aucun impact financier – ils ne créent ni écritures comptables ni mouvements de stock. Définissez une date de validité pour que l'offre expire automatiquement."},"4":{"title":"Valider et convertir en commande client","description":"Ouvrez votre devis enregistré et cliquez sur Valider pour le confirmer. Cliquez ensuite sur « Créer une commande client » pour le convertir. La commande client représente un engagement confirmé du client. Elle n'a toujours aucun impact financier, mais réserve du stock à des fins de planification.","tip":"Seuls les documents validés peuvent être convertis à l'étape suivante. Brouillon → Valider → Convertir est le flux standard. Pour les affaires rapides, vous pouvez ignorer la commande client et passer directement du devis à la facture de vente ou au bon de livraison."},"5":{"title":"Vérifier le stock avant l'exécution","description":"Avant de pouvoir livrer, vérifiez si vous avez réellement l'article en stock. Ouvrez le rapport Solde de stock et recherchez l'article. Si votre entrepôt affiche une quantité nulle, vous devrez d'abord approvisionner le stock – soit par un bon de commande (achat auprès d'un fournisseur), soit par un mouvement de stock (réception manuelle).","tip":"C'est un scénario courant dans la pratique : vous vendez quelque chose, puis réalisez que vous devez d'abord l'acheter. L'ERP gère les deux flux."},"6":{"title":"Cycle d'achat : acheter du stock à un fournisseur","description":"Si vous devez acheter du stock, vous avez deux chemins valides. Le chemin standard est Bon de commande → Bon de réception → Facture d'achat : utilisez-le lorsque les marchandises arrivent avant ou séparément de la facture du fournisseur. Si la facture et la réception arrivent ensemble, vous pouvez créer directement la facture d'achat et activer « Mettre à jour le stock » afin que le même document réceptionne le stock et enregistre la dette fournisseur.","tip":"Utilisez d'abord le bon de réception lorsque vous recevez les marchandises séparément. Utilisez la facture d'achat avec « Mettre à jour le stock » lorsqu'une seule étape doit à la fois réceptionner le stock et comptabiliser la facture fournisseur. Dans ce chemin direct, indiquez un entrepôt sur chaque ligne d'article en stock."},"7":{"title":"Créer un bon de livraison","description":"Maintenant que vous avez du stock, revenez à votre commande client validée et cliquez sur « Créer un bon de livraison ». Indiquez l'entrepôt sur chaque ligne d'article (d'où partent les marchandises), puis validez. Cela sort le stock de l'entrepôt – votre solde de stock diminue.","tip":"Le bon de livraison est le document d'expédition. Il réduit le stock mais ne crée pas de facture. Vous pouvez livrer et facturer séparément."},"8":{"title":"Créer et valider la facture de vente","description":"À partir de la commande client validée, créez une facture de vente. Lorsque vous validez la facture, des écritures comptables sont générées : les Clients (créances) sont débités (le client vous doit de l'argent) et les Produits des ventes crédités (revenu acquis). Si des taxes sont configurées, la TVA collectée est également créditée. Le montant dû indique ce que le client doit encore."},"9":{"title":"Enregistrer les paiements clients","description":"Créez un paiement pour enregistrer l'argent reçu du client. Définissez le type de paiement sur « Receive » (Recevoir), sélectionnez le client, indiquez le montant et affectez-le à la facture de vente. Vous pouvez effectuer des paiements partiels – le montant dû de la facture se met à jour en conséquence. Créez des paiements supplémentaires jusqu'à ce que la facture soit entièrement réglée.","tip":"Les paiements partiels sont courants. Une facture de 10 000 peut être payée 3 000 maintenant et 7 000 plus tard. Chaque paiement réduit le montant dû."},"10":{"title":"Mouvements de stock (inventaire manuel)","description":"Utilisez les mouvements de stock pour les mouvements d'inventaire non liés aux achats ou aux ventes. « Material Receipt » ajoute du stock (soldes d'ouverture, ajustements). « Material Issue » sort du stock (pertes, consommation interne). « Material Transfer » déplace du stock entre entrepôts. Chaque mouvement met à jour le livre de stock avec une valorisation au coût moyen pondéré.","tip":"Pour les marchandises achetées, utilisez des bons de réception plutôt que des mouvements de stock – ils sont liés au bon de commande et offrent une piste d'audit appropriée."},"11":{"title":"Écritures de journal","description":"Les écritures de journal sont des ajustements comptables manuels – charges à payer, corrections, reclassements, soldes d'ouverture. Chaque écriture doit avoir des débits et crédits équilibrés (total débit = total crédit). Utilisez-les lorsqu'aucun autre type de document ne convient."},"12":{"title":"Paiements des salaires","description":"Lambda ERP gère les salaires à l'aide des outils comptables existants. Comptabilisez d'abord la charge salariale : créez une écriture de journal qui débite la Charge salariale et crédite les Salaires à payer pour le montant total de la paie. Payez ensuite les employés : créez une autre écriture de journal (ou un paiement) qui débite les Salaires à payer et crédite votre compte bancaire. Ce processus en deux étapes garde vos comptes exacts – la charge est enregistrée dans la bonne période et la sortie de trésorerie est suivie séparément.","tip":"Vous pouvez demander à l'assistant IA de le faire pour vous : « Comptabilise 15 000 de salaires pour avril » suivi de « Paie les salaires d'avril depuis la banque ». Il créera automatiquement les bonnes écritures de journal."},"13":{"title":"Retours et avoirs","description":"Lorsqu'un client retourne des marchandises ou que vous devez émettre un avoir, créez un retour. Les retours utilisent le même type de document avec des quantités négatives. Ouvrez une facture de vente validée et créez un avoir (retour de facture de vente) – cela inverse les écritures comptables et réduit le montant dû de la facture d'origine. Pour le stock, créez un retour de bon de livraison pour réintégrer les marchandises en entrepôt. Côté achats, créez une note de débit (retour de facture d'achat) pour inverser une facture fournisseur, ou un retour de bon de réception pour renvoyer des marchandises.","tip":"Un avoir est simplement une facture de vente avec is_return=1 et des quantités négatives. La même logique comptable s'applique – les montants négatifs basculent automatiquement du bon côté débit/crédit. Pour un retour de vente complet, vous avez besoin à la fois d'un avoir (financier) et d'un retour de bon de livraison (stock)."},"14":{"title":"Exécuter les rapports","description":"Vérifiez vos comptes. Le Compte de résultat montre les produits face aux charges et le résultat net d'une période. Le Bilan montre votre situation financière (actif = passif + capitaux propres). La Balance âgée clients montre qui vous doit de l'argent et le retard. La Balance âgée fournisseurs montre ce que vous devez aux fournisseurs. La Balance comptable vérifie l'intégrité de la partie double. Le Grand livre montre chaque écriture individuelle. Le Solde de stock montre l'inventaire actuel."},"15":{"title":"Travailler en devises étrangères","description":"Vos comptes sont tenus dans une seule devise de base (choisie à la configuration de la société), mais vous pouvez effectuer des transactions dans n'importe quelle devise. Définissez une devise sur une facture ou un effet – ou attribuez une devise par défaut à un client ou un fournisseur – et le taux de change de cette date est recherché automatiquement et enregistré sur le document. Le document conserve ses montants dans sa propre devise, tandis que le Grand livre comptabilise toujours dans votre devise de base. Lorsque vous encaissez ou payez ultérieurement à un taux différent, le gain ou la perte de change réalisé est comptabilisé automatiquement sur un compte Gain/Perte de change. Vous pouvez même détenir un solde bancaire en devise étrangère et le convertir plus tard au taux de votre banque – l'écart par rapport à sa valeur comptable est alors réalisé. En fin de mois, vous pouvez réévaluer les soldes en devises ouverts au taux de clôture (un gain/perte latent qui s'inverse à la période suivante), et vous pouvez consulter n'importe quel état financier converti dans une autre devise pour l'affichage.","tip":"Le plus simple est de passer par le chat IA – essayez « Crée une facture de vente pour Lumiere Audio en EUR », « Montre-moi le bilan en EUR » ou « Quelle est notre exposition de change latente en fin de mois ? ». Les données de démonstration incluent déjà un client EUR (Lumiere Audio SARL) dont la facture a été encaissée à un taux différent, ainsi qu'une facture fournisseur EUR ouverte – ouvrez le Grand livre pour voir les écritures de change réalisées."}},"setupTitle":"Configurez votre entreprise — guidé par l'IA","setupBadge":"Commencez ici","setupBody":"Dites à l'assistant quel type d'entreprise vous dirigez, et il construit votre plan comptable pour vous — adapté à votre secteur, avec les bons comptes et des valeurs par défaut cohérentes déjà en place. Il explique chaque décision et ne crée quoi que ce soit qu'après votre approbation.","setupSectors":"Adapté aux services, au commerce de détail & POS, à l'hôtellerie-restauration, au commerce de gros & distribution, à l'import/export, à la fabrication et à la construction.","setupGetStarted":"Commencer dans le chat","setupManual":"Vous préférez un formulaire manuel ? Utilisez la configuration classique.","setupManualLink":"Configuration classique","setupPrompt":"Je souhaite configurer mon entreprise. Pouvez-vous me guider ?"}`), fo = { title: "Aide au formatage", intro: "Le texte des Notes / Conditions prend en charge une mise en forme légère sur le PDF :", heading: "titre en gras", emphasis: "italique / gras", rule: "ligne de séparation horizontale", price: "prix aligné à droite à côté du texte ci-dessus (p. ex. Mensuel | CHF 380.—)", block: "Séparez les blocs par une ligne vide." }, yo = { period: "Période", allTime: "Toute la période", semantics: "Comptes de bilan : solde à la fin de la période. Comptes de résultat : mouvement de la période. Cliquez sur un compte pour son grand livre.", empty: "Aucun compte trouvé. Terminez d'abord la configuration de l'entreprise.", disabled: "désactivé", rootType: { Asset: "Actifs", Liability: "Passifs", Equity: "Capitaux propres", Income: "Produits", Expense: "Charges" } }, bo = {
|
|
7240
|
+
common: Ji,
|
|
7241
|
+
language: Zi,
|
|
7242
|
+
header: Xi,
|
|
7243
|
+
titles: eo,
|
|
7244
|
+
doctypes: to,
|
|
7245
|
+
masters: no,
|
|
7246
|
+
nav: ao,
|
|
7247
|
+
login: ro,
|
|
7248
|
+
settings: so,
|
|
7249
|
+
status: io,
|
|
7250
|
+
reports: oo,
|
|
7251
|
+
masterForm: lo,
|
|
7252
|
+
fields: co,
|
|
7253
|
+
tables: uo,
|
|
7254
|
+
conversions: mo,
|
|
7255
|
+
dashboard: po,
|
|
7256
|
+
chat: ho,
|
|
7257
|
+
tutorial: go,
|
|
7258
|
+
notesMarkup: fo,
|
|
7259
|
+
coa: yo
|
|
7260
|
+
}, Sa = [
|
|
7257
7261
|
{ code: "en", label: "English" },
|
|
7258
7262
|
{ code: "de", label: "Deutsch" },
|
|
7259
7263
|
{ code: "fr", label: "Français" }
|
|
7260
|
-
],
|
|
7261
|
-
function
|
|
7262
|
-
return !!t &&
|
|
7264
|
+
], Da = "lambda-erp:language";
|
|
7265
|
+
function vo(t) {
|
|
7266
|
+
return !!t && Sa.some((n) => n.code === t);
|
|
7263
7267
|
}
|
|
7264
|
-
function
|
|
7268
|
+
function xo() {
|
|
7265
7269
|
try {
|
|
7266
|
-
const t = localStorage.getItem(
|
|
7267
|
-
if (
|
|
7270
|
+
const t = localStorage.getItem(Da);
|
|
7271
|
+
if (vo(t)) return t;
|
|
7268
7272
|
} catch {
|
|
7269
7273
|
}
|
|
7270
7274
|
return "en";
|
|
7271
7275
|
}
|
|
7272
|
-
function
|
|
7276
|
+
function No(t) {
|
|
7273
7277
|
try {
|
|
7274
|
-
localStorage.setItem(
|
|
7278
|
+
localStorage.setItem(Da, t);
|
|
7275
7279
|
} catch {
|
|
7276
7280
|
}
|
|
7277
7281
|
}
|
|
7278
|
-
na.use(
|
|
7282
|
+
na.use(Ua).init({
|
|
7279
7283
|
resources: {
|
|
7280
|
-
en: { translation:
|
|
7281
|
-
de: { translation:
|
|
7282
|
-
fr: { translation:
|
|
7284
|
+
en: { translation: _i },
|
|
7285
|
+
de: { translation: Yi },
|
|
7286
|
+
fr: { translation: bo }
|
|
7283
7287
|
},
|
|
7284
|
-
lng:
|
|
7288
|
+
lng: xo(),
|
|
7285
7289
|
fallbackLng: "en",
|
|
7286
7290
|
// any key missing in de/fr falls back to the English value
|
|
7287
7291
|
interpolation: { escapeValue: !1 },
|
|
@@ -7289,15 +7293,15 @@ na.use($a).init({
|
|
|
7289
7293
|
react: { useSuspense: !1 }
|
|
7290
7294
|
// resources are bundled synchronously — no Suspense needed
|
|
7291
7295
|
});
|
|
7292
|
-
na.on("languageChanged",
|
|
7293
|
-
function
|
|
7296
|
+
na.on("languageChanged", No);
|
|
7297
|
+
function wo({ label: t }) {
|
|
7294
7298
|
var o;
|
|
7295
7299
|
const { t: n, i18n: a } = X(), s = ((o = a.language) == null ? void 0 : o.split("-")[0]) ?? "en";
|
|
7296
7300
|
return /* @__PURE__ */ e(
|
|
7297
7301
|
Ve,
|
|
7298
7302
|
{
|
|
7299
7303
|
label: t === null ? void 0 : t ?? n("language.label"),
|
|
7300
|
-
options:
|
|
7304
|
+
options: Sa.map((i) => ({ value: i.code, label: i.label })),
|
|
7301
7305
|
value: s,
|
|
7302
7306
|
onChange: (i) => a.changeLanguage(i.target.value)
|
|
7303
7307
|
}
|
|
@@ -7314,7 +7318,7 @@ const Kn = [
|
|
|
7314
7318
|
function We(t) {
|
|
7315
7319
|
return t === 0 ? "$0.00" : t < 0.01 ? `$${t.toFixed(4)}` : `$${t.toFixed(2)}`;
|
|
7316
7320
|
}
|
|
7317
|
-
function
|
|
7321
|
+
function ko({ demoActive: t }) {
|
|
7318
7322
|
var S, x;
|
|
7319
7323
|
const { t: n } = X(), [a, s] = w("1h"), { data: o, isLoading: i, isFetching: l, error: c, refetch: h, dataUpdatedAt: d } = ue({
|
|
7320
7324
|
queryKey: ["demo-spend"],
|
|
@@ -7498,7 +7502,7 @@ function St({ label: t, value: n }) {
|
|
|
7498
7502
|
/* @__PURE__ */ e("div", { className: "mt-0.5 text-sm font-semibold tabular-nums text-gray-900", children: n })
|
|
7499
7503
|
] });
|
|
7500
7504
|
}
|
|
7501
|
-
function
|
|
7505
|
+
function Co() {
|
|
7502
7506
|
const { t } = X(), { user: n } = st(), [a, s] = w(""), [o, i] = w(""), [l, c] = w(""), [h, d] = w(""), [p, u] = w(!1), f = me({
|
|
7503
7507
|
mutationFn: () => I.authChangePassword(a, o),
|
|
7504
7508
|
onSuccess: () => {
|
|
@@ -7575,7 +7579,7 @@ function ko() {
|
|
|
7575
7579
|
/* @__PURE__ */ e(Q, { type: "submit", disabled: f.isPending || !a || !o || !l, children: f.isPending ? t("settings.changingPassword") : t("settings.changePassword") })
|
|
7576
7580
|
] }) });
|
|
7577
7581
|
}
|
|
7578
|
-
function
|
|
7582
|
+
function So() {
|
|
7579
7583
|
const { t } = X(), { user: n, refreshUser: a } = st(), [s, o] = w(""), [i, l] = w(""), [c, h] = w(""), [d, p] = w(!1), u = me({
|
|
7580
7584
|
mutationFn: () => I.authSetPassword(s),
|
|
7581
7585
|
onSuccess: async () => {
|
|
@@ -7641,7 +7645,7 @@ function Co() {
|
|
|
7641
7645
|
] })
|
|
7642
7646
|
] });
|
|
7643
7647
|
}
|
|
7644
|
-
function
|
|
7648
|
+
function Do() {
|
|
7645
7649
|
const { t } = X(), { data: n } = ue({
|
|
7646
7650
|
queryKey: ["auth-setup-status"],
|
|
7647
7651
|
queryFn: () => I.authSetupStatus()
|
|
@@ -7676,7 +7680,7 @@ function So() {
|
|
|
7676
7680
|
] });
|
|
7677
7681
|
}
|
|
7678
7682
|
const Jt = { viewer: 1, manager: 2, admin: 3 };
|
|
7679
|
-
function
|
|
7683
|
+
function Aa({ ownRole: t }) {
|
|
7680
7684
|
const { t: n } = X(), { user: a } = st(), s = He(), [o, i] = w(""), [l, c] = w(t in Jt ? t : "viewer"), [h, d] = w(null), [p, u] = w(null), f = ["viewer", "manager", "admin"].filter(
|
|
7681
7685
|
(g) => Jt[g] <= (Jt[t] ?? 1)
|
|
7682
7686
|
), v = `${window.location.origin}/api/mcp`, N = h ? `claude mcp add --transport http --scope user lambda-erp ${v} \\
|
|
@@ -7874,7 +7878,7 @@ function jn({
|
|
|
7874
7878
|
)
|
|
7875
7879
|
] });
|
|
7876
7880
|
}
|
|
7877
|
-
function
|
|
7881
|
+
function Ao({
|
|
7878
7882
|
chatEnabled: t,
|
|
7879
7883
|
restEnabled: n,
|
|
7880
7884
|
onToggleChat: a,
|
|
@@ -7908,7 +7912,7 @@ function Do({
|
|
|
7908
7912
|
] }),
|
|
7909
7913
|
(t || n) && /* @__PURE__ */ r("div", { className: "mt-4 border-t border-gray-100 pt-4", children: [
|
|
7910
7914
|
/* @__PURE__ */ e("div", { className: "mb-2 text-xs font-medium text-gray-500", children: i("settings.chatApiKeysTitle") }),
|
|
7911
|
-
/* @__PURE__ */ e(
|
|
7915
|
+
/* @__PURE__ */ e(Aa, { ownRole: o })
|
|
7912
7916
|
] }),
|
|
7913
7917
|
l && /* @__PURE__ */ e(
|
|
7914
7918
|
"div",
|
|
@@ -7946,7 +7950,7 @@ function Do({
|
|
|
7946
7950
|
)
|
|
7947
7951
|
] });
|
|
7948
7952
|
}
|
|
7949
|
-
function
|
|
7953
|
+
function Po() {
|
|
7950
7954
|
const { user: t } = st(), { t: n } = X(), a = He(), s = (t == null ? void 0 : t.role) === "admin", { data: o, isLoading: i } = ue({
|
|
7951
7955
|
queryKey: ["settings"],
|
|
7952
7956
|
queryFn: () => I.getSettings()
|
|
@@ -7972,11 +7976,11 @@ function Ao() {
|
|
|
7972
7976
|
});
|
|
7973
7977
|
return i ? /* @__PURE__ */ e("p", { className: "text-gray-500", children: n("common.loading") }) : /* @__PURE__ */ r("div", { className: "space-y-6", children: [
|
|
7974
7978
|
/* @__PURE__ */ r(M, { title: n("language.title"), children: [
|
|
7975
|
-
/* @__PURE__ */ e("div", { className: "flex flex-wrap items-end gap-4", children: /* @__PURE__ */ e("div", { className: "w-64", children: /* @__PURE__ */ e(
|
|
7979
|
+
/* @__PURE__ */ e("div", { className: "flex flex-wrap items-end gap-4", children: /* @__PURE__ */ e("div", { className: "w-64", children: /* @__PURE__ */ e(wo, {}) }) }),
|
|
7976
7980
|
/* @__PURE__ */ e("p", { className: "mt-2 text-xs text-gray-400", children: n("language.help") })
|
|
7977
7981
|
] }),
|
|
7978
|
-
(t == null ? void 0 : t.role) !== "public_manager" && ((t == null ? void 0 : t.has_password) === !1 ? /* @__PURE__ */ e(
|
|
7979
|
-
(t == null ? void 0 : t.role) !== "public_manager" && /* @__PURE__ */ e(
|
|
7982
|
+
(t == null ? void 0 : t.role) !== "public_manager" && ((t == null ? void 0 : t.has_password) === !1 ? /* @__PURE__ */ e(So, {}) : /* @__PURE__ */ e(Co, {})),
|
|
7983
|
+
(t == null ? void 0 : t.role) !== "public_manager" && /* @__PURE__ */ e(Do, {}),
|
|
7980
7984
|
/* @__PURE__ */ r(M, { title: n("settings.pdfTitle"), children: [
|
|
7981
7985
|
/* @__PURE__ */ e("div", { className: "flex flex-wrap items-end gap-4", children: s ? /* @__PURE__ */ e(
|
|
7982
7986
|
Ve,
|
|
@@ -8025,7 +8029,7 @@ function Ao() {
|
|
|
8025
8029
|
)
|
|
8026
8030
|
] }) }),
|
|
8027
8031
|
s && /* @__PURE__ */ e(
|
|
8028
|
-
|
|
8032
|
+
Ao,
|
|
8029
8033
|
{
|
|
8030
8034
|
chatEnabled: (o == null ? void 0 : o.chat_api_enabled) === "1",
|
|
8031
8035
|
restEnabled: (o == null ? void 0 : o.rest_api_enabled) === "1",
|
|
@@ -8040,9 +8044,9 @@ function Ao() {
|
|
|
8040
8044
|
),
|
|
8041
8045
|
!s && (t == null ? void 0 : t.role) !== "public_manager" && /* @__PURE__ */ r(M, { title: n("settings.chatApiKeysTitle"), children: [
|
|
8042
8046
|
/* @__PURE__ */ e("p", { className: "mb-3 text-sm text-gray-700", children: n("settings.chatApiPersonal") }),
|
|
8043
|
-
/* @__PURE__ */ e(
|
|
8047
|
+
/* @__PURE__ */ e(Aa, { ownRole: (t == null ? void 0 : t.role) ?? "viewer" })
|
|
8044
8048
|
] }),
|
|
8045
|
-
s && /* @__PURE__ */ e(
|
|
8049
|
+
s && /* @__PURE__ */ e(ko, { demoActive: !!(c != null && c.active) }),
|
|
8046
8050
|
s && /* @__PURE__ */ e(M, { title: n("settings.publicTitle"), children: c != null && c.active ? /* @__PURE__ */ r("div", { children: [
|
|
8047
8051
|
/* @__PURE__ */ r("div", { className: "flex items-center gap-2", children: [
|
|
8048
8052
|
/* @__PURE__ */ e("span", { className: "inline-block h-2 w-2 rounded-full bg-green-500" }),
|
|
@@ -8094,25 +8098,25 @@ function Ao() {
|
|
|
8094
8098
|
(h == null ? void 0 : h.version) && /* @__PURE__ */ e("p", { className: "pt-2 text-center text-xs text-gray-400", children: n("settings.version", { version: h.version }) })
|
|
8095
8099
|
] });
|
|
8096
8100
|
}
|
|
8097
|
-
const
|
|
8098
|
-
function
|
|
8099
|
-
|
|
8101
|
+
const Pa = {};
|
|
8102
|
+
function nl(t, n) {
|
|
8103
|
+
Pa[t] = n;
|
|
8100
8104
|
}
|
|
8101
|
-
function
|
|
8102
|
-
return
|
|
8105
|
+
function _o(t, n) {
|
|
8106
|
+
return Pa[t] ?? n;
|
|
8103
8107
|
}
|
|
8104
|
-
function
|
|
8105
|
-
const t =
|
|
8108
|
+
function To() {
|
|
8109
|
+
const t = _o("Dashboard", qr);
|
|
8106
8110
|
return /* @__PURE__ */ e(t, {});
|
|
8107
8111
|
}
|
|
8108
|
-
const
|
|
8109
|
-
{ path: "/login", element: /* @__PURE__ */ e(
|
|
8110
|
-
{ path: "/demo", element: /* @__PURE__ */ e(
|
|
8111
|
-
],
|
|
8112
|
-
{ index: !0, element: /* @__PURE__ */ e(
|
|
8113
|
-
{ path: "setup", element: /* @__PURE__ */ e(
|
|
8114
|
-
{ path: "setup/opening-balances", element: /* @__PURE__ */ e(
|
|
8115
|
-
{ path: "tutorial", element: /* @__PURE__ */ e(
|
|
8112
|
+
const Ro = [
|
|
8113
|
+
{ path: "/login", element: /* @__PURE__ */ e(ai, {}) },
|
|
8114
|
+
{ path: "/demo", element: /* @__PURE__ */ e(ii, {}) }
|
|
8115
|
+
], Io = [
|
|
8116
|
+
{ index: !0, element: /* @__PURE__ */ e(To, {}) },
|
|
8117
|
+
{ path: "setup", element: /* @__PURE__ */ e(Ms, {}) },
|
|
8118
|
+
{ path: "setup/opening-balances", element: /* @__PURE__ */ e(oi, {}) },
|
|
8119
|
+
{ path: "tutorial", element: /* @__PURE__ */ e(Gs, {}) },
|
|
8116
8120
|
{ path: "chat", element: /* @__PURE__ */ e(Fn, {}) },
|
|
8117
8121
|
{ path: "chat/:sessionId", element: /* @__PURE__ */ e(Fn, {}) },
|
|
8118
8122
|
// Proposal (Sammelofferte) — a custom builder; the list reuses the generic
|
|
@@ -8121,29 +8125,29 @@ const To = [
|
|
|
8121
8125
|
{ path: "app/proposal/new", element: /* @__PURE__ */ e(In, {}) },
|
|
8122
8126
|
{ path: "app/proposal/:name", element: /* @__PURE__ */ e(In, {}) },
|
|
8123
8127
|
// Documents
|
|
8124
|
-
{ path: "app/:doctype", element: /* @__PURE__ */ e(
|
|
8128
|
+
{ path: "app/:doctype", element: /* @__PURE__ */ e(ns, {}) },
|
|
8125
8129
|
{ path: "app/:doctype/new", element: /* @__PURE__ */ e(An, {}) },
|
|
8126
8130
|
{ path: "app/:doctype/:name", element: /* @__PURE__ */ e(An, {}) },
|
|
8127
8131
|
// Masters (reuse same routes - the components detect whether it's a doctype or master)
|
|
8128
|
-
{ path: "masters/:type", element: /* @__PURE__ */ e(
|
|
8132
|
+
{ path: "masters/:type", element: /* @__PURE__ */ e(ss, {}) },
|
|
8129
8133
|
{ path: "masters/:type/new", element: /* @__PURE__ */ e(En, {}) },
|
|
8130
8134
|
{ path: "masters/:type/:name", element: /* @__PURE__ */ e(En, {}) },
|
|
8131
8135
|
// Reports
|
|
8132
|
-
{ path: "reports/chart-of-accounts", element: /* @__PURE__ */ e(
|
|
8133
|
-
{ path: "reports/trial-balance", element: /* @__PURE__ */ e(
|
|
8134
|
-
{ path: "reports/general-ledger", element: /* @__PURE__ */ e(
|
|
8135
|
-
{ path: "reports/stock-balance", element: /* @__PURE__ */ e(
|
|
8136
|
-
{ path: "reports/profit-and-loss", element: /* @__PURE__ */ e(
|
|
8137
|
-
{ path: "reports/balance-sheet", element: /* @__PURE__ */ e(
|
|
8138
|
-
{ path: "reports/ar-aging", element: /* @__PURE__ */ e(
|
|
8139
|
-
{ path: "reports/ap-aging", element: /* @__PURE__ */ e(
|
|
8140
|
-
{ path: "reports/analytics", element: /* @__PURE__ */ e(
|
|
8136
|
+
{ path: "reports/chart-of-accounts", element: /* @__PURE__ */ e(bs, {}) },
|
|
8137
|
+
{ path: "reports/trial-balance", element: /* @__PURE__ */ e(fs, {}) },
|
|
8138
|
+
{ path: "reports/general-ledger", element: /* @__PURE__ */ e(Ns, {}) },
|
|
8139
|
+
{ path: "reports/stock-balance", element: /* @__PURE__ */ e(ws, {}) },
|
|
8140
|
+
{ path: "reports/profit-and-loss", element: /* @__PURE__ */ e(ks, {}) },
|
|
8141
|
+
{ path: "reports/balance-sheet", element: /* @__PURE__ */ e(Cs, {}) },
|
|
8142
|
+
{ path: "reports/ar-aging", element: /* @__PURE__ */ e(Ss, {}) },
|
|
8143
|
+
{ path: "reports/ap-aging", element: /* @__PURE__ */ e(Ds, {}) },
|
|
8144
|
+
{ path: "reports/analytics", element: /* @__PURE__ */ e(_s, {}) },
|
|
8141
8145
|
// Admin
|
|
8142
|
-
{ path: "admin/users", element: /* @__PURE__ */ e(
|
|
8143
|
-
{ path: "admin/settings", element: /* @__PURE__ */ e(
|
|
8144
|
-
],
|
|
8145
|
-
function
|
|
8146
|
-
(n == null ? void 0 : n.area) === "top" ?
|
|
8146
|
+
{ path: "admin/users", element: /* @__PURE__ */ e(li, {}) },
|
|
8147
|
+
{ path: "admin/settings", element: /* @__PURE__ */ e(Po, {}) }
|
|
8148
|
+
], _a = [], Ta = [];
|
|
8149
|
+
function Bo(t, n) {
|
|
8150
|
+
(n == null ? void 0 : n.area) === "top" ? _a.push(t) : Ta.push(t);
|
|
8147
8151
|
}
|
|
8148
8152
|
const Gn = (t) => t.index ? "__index__" : t.path ?? "";
|
|
8149
8153
|
function Wn(t, n) {
|
|
@@ -8154,17 +8158,17 @@ function Wn(t, n) {
|
|
|
8154
8158
|
}
|
|
8155
8159
|
return a;
|
|
8156
8160
|
}
|
|
8157
|
-
function
|
|
8161
|
+
function Eo() {
|
|
8158
8162
|
return [
|
|
8159
|
-
...Wn(
|
|
8163
|
+
...Wn(Ro, _a),
|
|
8160
8164
|
{
|
|
8161
8165
|
path: "/",
|
|
8162
|
-
element: /* @__PURE__ */ e(
|
|
8163
|
-
children: Wn(
|
|
8166
|
+
element: /* @__PURE__ */ e(Ir, { children: /* @__PURE__ */ e(Tr, {}) }),
|
|
8167
|
+
children: Wn(Io, Ta)
|
|
8164
8168
|
}
|
|
8165
8169
|
];
|
|
8166
8170
|
}
|
|
8167
|
-
function
|
|
8171
|
+
function Lo({ slug: t, parentSlug: n, linkField: a }) {
|
|
8168
8172
|
const { name: s = "" } = ut(), o = Ee();
|
|
8169
8173
|
return re(() => {
|
|
8170
8174
|
let i = !0;
|
|
@@ -8179,7 +8183,7 @@ function Eo({ slug: t, parentSlug: n, linkField: a }) {
|
|
|
8179
8183
|
};
|
|
8180
8184
|
}, [t, s, n, a, o]), /* @__PURE__ */ e("div", { className: "p-6 text-sm text-fg-muted", children: "…" });
|
|
8181
8185
|
}
|
|
8182
|
-
async function
|
|
8186
|
+
async function Oo() {
|
|
8183
8187
|
try {
|
|
8184
8188
|
const t = await L(
|
|
8185
8189
|
"/chat-doctypes",
|
|
@@ -8187,33 +8191,33 @@ async function Lo() {
|
|
|
8187
8191
|
);
|
|
8188
8192
|
for (const n of t.doctypes || []) {
|
|
8189
8193
|
const a = n.page;
|
|
8190
|
-
a && a.kind === "via" &&
|
|
8194
|
+
a && a.kind === "via" && Bo({
|
|
8191
8195
|
path: `app/${n.slug}/:name`,
|
|
8192
|
-
element: /* @__PURE__ */ e(
|
|
8196
|
+
element: /* @__PURE__ */ e(Lo, { slug: n.slug, parentSlug: a.parent_slug, linkField: a.link_field })
|
|
8193
8197
|
});
|
|
8194
8198
|
}
|
|
8195
8199
|
} catch {
|
|
8196
8200
|
}
|
|
8197
8201
|
}
|
|
8198
|
-
function
|
|
8199
|
-
return new
|
|
8202
|
+
function qo() {
|
|
8203
|
+
return new qa({
|
|
8200
8204
|
defaultOptions: {
|
|
8201
8205
|
queries: { retry: 1, refetchOnWindowFocus: !1 }
|
|
8202
8206
|
}
|
|
8203
8207
|
});
|
|
8204
8208
|
}
|
|
8205
|
-
async function
|
|
8209
|
+
async function al(t = {}) {
|
|
8206
8210
|
const n = t.rootElement ?? document.getElementById("root");
|
|
8207
8211
|
if (!n)
|
|
8208
8212
|
throw new Error('bootstrap: no mount element (pass rootElement or add <div id="root">)');
|
|
8209
|
-
const a = t.queryClient ??
|
|
8210
|
-
await
|
|
8211
|
-
const s =
|
|
8212
|
-
|
|
8213
|
-
/* @__PURE__ */ e(
|
|
8213
|
+
const a = t.queryClient ?? qo();
|
|
8214
|
+
await Oo();
|
|
8215
|
+
const s = Fa(Eo());
|
|
8216
|
+
La(n).render(
|
|
8217
|
+
/* @__PURE__ */ e(Ea, { children: /* @__PURE__ */ e(Oa, { client: a, children: /* @__PURE__ */ e(pr, { children: /* @__PURE__ */ e($a, { router: s }) }) }) })
|
|
8214
8218
|
);
|
|
8215
8219
|
}
|
|
8216
|
-
function
|
|
8220
|
+
function rl({
|
|
8217
8221
|
onConfirm: t,
|
|
8218
8222
|
children: n,
|
|
8219
8223
|
confirmLabel: a,
|
|
@@ -8281,37 +8285,37 @@ function al({
|
|
|
8281
8285
|
}
|
|
8282
8286
|
export {
|
|
8283
8287
|
Ue as ApiError,
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
+
Tr as AppShell,
|
|
8289
|
+
pr as AuthProvider,
|
|
8290
|
+
rl as ConfirmButton,
|
|
8291
|
+
vr as DialogProvider,
|
|
8288
8292
|
ya as DocPager,
|
|
8289
|
-
|
|
8293
|
+
Sa as SUPPORTED_LANGUAGES,
|
|
8290
8294
|
I as api,
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8295
|
+
al as bootstrap,
|
|
8296
|
+
Eo as buildRoutes,
|
|
8297
|
+
Qo as configureApiBase,
|
|
8298
|
+
Xo as configureBranding,
|
|
8299
|
+
qo as createAppQueryClient,
|
|
8296
8300
|
Ft as formatDate,
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
8301
|
+
tl as getAllDoctypeConfigs,
|
|
8302
|
+
wr as getBranding,
|
|
8303
|
+
_o as getComponent,
|
|
8300
8304
|
fa as getDoctypeConfig,
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
|
|
8305
|
-
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
8305
|
+
zr as getListContext,
|
|
8306
|
+
Nr as getNavGroups,
|
|
8307
|
+
xo as getStoredLanguage,
|
|
8308
|
+
ol as i18n,
|
|
8309
|
+
nl as registerComponent,
|
|
8310
|
+
el as registerDoctype,
|
|
8311
|
+
Jo as registerNavGroup,
|
|
8312
|
+
Zo as registerNavItem,
|
|
8313
|
+
Bo as registerRoute,
|
|
8310
8314
|
L as request,
|
|
8311
|
-
|
|
8315
|
+
Yo as setDateLocale,
|
|
8312
8316
|
ga as setListContext,
|
|
8313
8317
|
st as useAuth,
|
|
8314
8318
|
ua as useConfirm,
|
|
8315
|
-
|
|
8319
|
+
xr as usePrompt
|
|
8316
8320
|
};
|
|
8317
8321
|
//# sourceMappingURL=index.js.map
|