@lambda-development/erp-core 0.6.13 → 0.6.15
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 +758 -715
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
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
|
|
3
|
-
import { createRoot as
|
|
4
|
-
import { useQueryClient as He, useQuery as ue, useMutation as me, QueryClientProvider as
|
|
5
|
-
import { NavLink as qt, useLocation as
|
|
6
|
-
import { useTranslation as X, initReactI18next as
|
|
7
|
-
import { BookOpen as
|
|
8
|
-
import { createColumnHelper as
|
|
9
|
-
import { createPortal as
|
|
10
|
-
import { ResponsiveContainer as
|
|
11
|
-
import
|
|
12
|
-
import { default as
|
|
13
|
-
let
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
function
|
|
18
|
-
return new URL(`${
|
|
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 Ba } from "react";
|
|
3
|
+
import { createRoot as Ea } from "react-dom/client";
|
|
4
|
+
import { useQueryClient as He, useQuery as ue, useMutation as me, QueryClientProvider as La, QueryClient as Oa } from "@tanstack/react-query";
|
|
5
|
+
import { NavLink as qt, useLocation as bt, useNavigate as Ee, Outlet as qa, Navigate as za, Link as ve, useSearchParams as zt, useParams as dt, createBrowserRouter as Ma, RouterProvider as Fa } from "react-router-dom";
|
|
6
|
+
import { useTranslation as X, initReactI18next as $a } from "react-i18next";
|
|
7
|
+
import { BookOpen as Ua, ShoppingCart as Hn, CreditCard as Va, FileText as sn, Package as Qn, BarChart3 as Ka, Database as ja, Settings as Ga, MessageCircle as Wa, ChevronDown as Mt, ChevronRight as Dt, Plus as Yn, Trash2 as Jn, LineChart as Ha, ArrowLeft as Qa, TrendingUp as Ya, ArrowDownRight as Ja, ArrowUpRight as Za, Wallet as Xa, Receipt as gn, ChevronLeft as er, Info as tr } from "lucide-react";
|
|
8
|
+
import { createColumnHelper as Zn, useReactTable as Xn, getCoreRowModel as ea, flexRender as Bt } from "@tanstack/react-table";
|
|
9
|
+
import { createPortal as ta } from "react-dom";
|
|
10
|
+
import { ResponsiveContainer as nr, LineChart as ar, CartesianGrid as fn, XAxis as yn, YAxis as bn, Tooltip as Kt, Line as rr, PieChart as sr, Pie as ir, Cell as or, BarChart as lr, Bar as cr } from "recharts";
|
|
11
|
+
import na from "i18next";
|
|
12
|
+
import { default as il } from "i18next";
|
|
13
|
+
let lt = "/api";
|
|
14
|
+
function Ho(t) {
|
|
15
|
+
lt = t.replace(/\/+$/, "");
|
|
16
|
+
}
|
|
17
|
+
function dr(t) {
|
|
18
|
+
return new URL(`${lt}${t}`, window.location.origin).toString();
|
|
19
19
|
}
|
|
20
20
|
class Ue extends Error {
|
|
21
21
|
constructor(n, a) {
|
|
22
22
|
super(a), this.status = n;
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
function
|
|
25
|
+
function ur(t) {
|
|
26
26
|
if (!t) return "Request failed";
|
|
27
27
|
if (typeof t == "string") return t;
|
|
28
28
|
if (Array.isArray(t))
|
|
@@ -38,7 +38,7 @@ function dr(t) {
|
|
|
38
38
|
return String(t);
|
|
39
39
|
}
|
|
40
40
|
async function L(t, n) {
|
|
41
|
-
const a = await fetch(`${
|
|
41
|
+
const a = await fetch(`${lt}${t}`, {
|
|
42
42
|
headers: { "Content-Type": "application/json" },
|
|
43
43
|
credentials: "include",
|
|
44
44
|
...n
|
|
@@ -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, ur(s.detail));
|
|
51
51
|
}
|
|
52
52
|
return a.json();
|
|
53
53
|
}
|
|
@@ -65,7 +65,7 @@ const I = {
|
|
|
65
65
|
uploadChatAttachment: async (t, n) => {
|
|
66
66
|
const a = new FormData();
|
|
67
67
|
a.append("file", n), a.append("session_id", t);
|
|
68
|
-
const s = await fetch(`${
|
|
68
|
+
const s = await fetch(`${lt}/chat/attachments`, {
|
|
69
69
|
method: "POST",
|
|
70
70
|
credentials: "include",
|
|
71
71
|
body: a
|
|
@@ -78,7 +78,7 @@ const I = {
|
|
|
78
78
|
}
|
|
79
79
|
return s.json();
|
|
80
80
|
},
|
|
81
|
-
getChatAttachmentUrl: (t) => `${
|
|
81
|
+
getChatAttachmentUrl: (t) => `${lt}/chat/attachments/${encodeURIComponent(t)}`,
|
|
82
82
|
// Chat
|
|
83
83
|
createChatSession: () => L(
|
|
84
84
|
"/chat/sessions",
|
|
@@ -120,7 +120,7 @@ const I = {
|
|
|
120
120
|
uploadProposalAppendix: async (t, n) => {
|
|
121
121
|
const a = new FormData();
|
|
122
122
|
a.append("file", n);
|
|
123
|
-
const s = await fetch(`${
|
|
123
|
+
const s = await fetch(`${lt}/proposals/${encodeURIComponent(t)}/appendix`, {
|
|
124
124
|
method: "POST",
|
|
125
125
|
credentials: "include",
|
|
126
126
|
body: a
|
|
@@ -134,7 +134,7 @@ const I = {
|
|
|
134
134
|
return s.json();
|
|
135
135
|
},
|
|
136
136
|
deleteProposalAppendix: (t) => L(`/proposals/${encodeURIComponent(t)}/appendix`, { method: "DELETE" }),
|
|
137
|
-
proposalPdfUrl: (t) => `${
|
|
137
|
+
proposalPdfUrl: (t) => `${lt}/documents/proposal/${encodeURIComponent(t)}/pdf`,
|
|
138
138
|
// Masters
|
|
139
139
|
listMasters: (t, n) => L(
|
|
140
140
|
`/masters/${t}${Be(n)}`
|
|
@@ -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 dr(`/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) }),
|
|
@@ -240,8 +240,8 @@ const I = {
|
|
|
240
240
|
{ method: "DELETE" }
|
|
241
241
|
),
|
|
242
242
|
getDemoSpend: () => L("/admin/demo-spend")
|
|
243
|
-
},
|
|
244
|
-
function
|
|
243
|
+
}, aa = rn(null);
|
|
244
|
+
function mr({ 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));
|
|
@@ -265,14 +265,14 @@ function ur({ children: t }) {
|
|
|
265
265
|
} catch {
|
|
266
266
|
}
|
|
267
267
|
}, []);
|
|
268
|
-
return /* @__PURE__ */ e(
|
|
268
|
+
return /* @__PURE__ */ e(aa.Provider, { value: { user: n, loading: s, login: i, register: l, logout: c, refreshUser: h }, children: t });
|
|
269
269
|
}
|
|
270
270
|
function st() {
|
|
271
|
-
const t =
|
|
271
|
+
const t = an(aa);
|
|
272
272
|
if (!t) throw new Error("useAuth must be used within AuthProvider");
|
|
273
273
|
return t;
|
|
274
274
|
}
|
|
275
|
-
const
|
|
275
|
+
const ra = rn(null), vn = {
|
|
276
276
|
quotation: { group: "Selling", item: "Quotation" },
|
|
277
277
|
"sales-order": { group: "Selling", item: "Sales Order" },
|
|
278
278
|
"sales-invoice": { group: "Selling", item: "Sales Invoice" },
|
|
@@ -288,31 +288,31 @@ const aa = an(null), bn = {
|
|
|
288
288
|
"delivery-note": { group: "Stock", item: "Delivery Note" },
|
|
289
289
|
"purchase-receipt": { group: "Stock", item: "Purchase Receipt" },
|
|
290
290
|
"pricing-rule": { group: "Settings", item: "Pricing Rule" }
|
|
291
|
-
},
|
|
291
|
+
}, xn = {
|
|
292
292
|
customer: { group: "Masters", item: "Customer" },
|
|
293
293
|
supplier: { group: "Masters", item: "Supplier" },
|
|
294
294
|
item: { group: "Masters", item: "Item" },
|
|
295
295
|
warehouse: { group: "Masters", item: "Warehouse" },
|
|
296
296
|
company: { group: "Masters", item: "Company" }
|
|
297
297
|
};
|
|
298
|
-
function
|
|
298
|
+
function jt(t) {
|
|
299
299
|
return typeof t != "string" ? null : t.trim().toLowerCase().replace(/\s+/g, "-");
|
|
300
300
|
}
|
|
301
|
-
function
|
|
301
|
+
function pr(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;
|
|
305
305
|
let a = null;
|
|
306
|
-
if (t === "create_document" || t === "update_document" || t === "submit_document" || t === "cancel_document" ? a =
|
|
307
|
-
return
|
|
306
|
+
if (t === "create_document" || t === "update_document" || t === "submit_document" || t === "cancel_document" ? a = jt(n.doctype) : t === "convert_document" && (a = jt(n.target_doctype)), a && vn[a])
|
|
307
|
+
return vn[a];
|
|
308
308
|
if (t === "create_master" || t === "update_master") {
|
|
309
|
-
const s =
|
|
310
|
-
if (s &&
|
|
311
|
-
return
|
|
309
|
+
const s = jt(n.master_type);
|
|
310
|
+
if (s && xn[s])
|
|
311
|
+
return xn[s];
|
|
312
312
|
}
|
|
313
313
|
return null;
|
|
314
314
|
}
|
|
315
|
-
function
|
|
315
|
+
function Nn(t) {
|
|
316
316
|
return {
|
|
317
317
|
id: t.id,
|
|
318
318
|
type: t.role === "user" ? "user" : "assistant",
|
|
@@ -321,11 +321,11 @@ function xn(t) {
|
|
|
321
321
|
attachments: t.attachments
|
|
322
322
|
};
|
|
323
323
|
}
|
|
324
|
-
const
|
|
325
|
-
function
|
|
324
|
+
const sa = "lambda-erp:known-chat-sessions";
|
|
325
|
+
function on() {
|
|
326
326
|
if (typeof localStorage > "u") return /* @__PURE__ */ new Set();
|
|
327
327
|
try {
|
|
328
|
-
const t = localStorage.getItem(
|
|
328
|
+
const t = localStorage.getItem(sa);
|
|
329
329
|
if (!t) return /* @__PURE__ */ new Set();
|
|
330
330
|
const n = JSON.parse(t);
|
|
331
331
|
return new Set(Array.isArray(n) ? n.filter((a) => typeof a == "string") : []);
|
|
@@ -333,22 +333,22 @@ function sn() {
|
|
|
333
333
|
return /* @__PURE__ */ new Set();
|
|
334
334
|
}
|
|
335
335
|
}
|
|
336
|
-
function
|
|
336
|
+
function ia(t) {
|
|
337
337
|
if (!(typeof localStorage > "u"))
|
|
338
338
|
try {
|
|
339
|
-
localStorage.setItem(
|
|
339
|
+
localStorage.setItem(sa, JSON.stringify([...t]));
|
|
340
340
|
} catch {
|
|
341
341
|
}
|
|
342
342
|
}
|
|
343
|
-
function
|
|
344
|
-
const n =
|
|
345
|
-
n.has(t) || (n.add(t),
|
|
343
|
+
function oa(t) {
|
|
344
|
+
const n = on();
|
|
345
|
+
n.has(t) || (n.add(t), ia(n));
|
|
346
346
|
}
|
|
347
|
-
function
|
|
348
|
-
const n =
|
|
349
|
-
n.delete(t) &&
|
|
347
|
+
function wn(t) {
|
|
348
|
+
const n = on();
|
|
349
|
+
n.delete(t) && ia(n);
|
|
350
350
|
}
|
|
351
|
-
function
|
|
351
|
+
function hr() {
|
|
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 gr({ 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 hr({ children: t }) {
|
|
|
413
413
|
}
|
|
414
414
|
function ie(B, K, Y) {
|
|
415
415
|
return new Promise((xe, we) => {
|
|
416
|
-
const Re =
|
|
416
|
+
const Re = hr();
|
|
417
417
|
R.current.set(Re, {
|
|
418
418
|
expectedType: Y,
|
|
419
419
|
resolve: xe,
|
|
@@ -441,24 +441,24 @@ function hr({ children: t }) {
|
|
|
441
441
|
}, we.onmessage = (Re) => {
|
|
442
442
|
var ot;
|
|
443
443
|
try {
|
|
444
|
-
const j = JSON.parse(Re.data), Ze = typeof j.request_id == "string" ? j.request_id : null,
|
|
444
|
+
const j = JSON.parse(Re.data), Ze = typeof j.request_id == "string" ? j.request_id : null, ye = typeof j.type == "string" ? j.type : null, O = typeof j.session_id == "string" ? j.session_id : null;
|
|
445
445
|
if (Ze) {
|
|
446
446
|
const q = R.current.get(Ze);
|
|
447
|
-
q && (
|
|
447
|
+
q && (ye === "error" ? (R.current.delete(Ze), q.reject(new Error(String(j.content || "Request failed.")))) : ye === q.expectedType && (R.current.delete(Ze), q.resolve(j)));
|
|
448
448
|
}
|
|
449
|
-
if (
|
|
449
|
+
if (ye === "sessions_list") {
|
|
450
450
|
const q = Array.isArray(j.sessions) ? j.sessions : [];
|
|
451
451
|
Se(q), s(
|
|
452
452
|
ne(
|
|
453
453
|
q
|
|
454
454
|
)
|
|
455
455
|
);
|
|
456
|
-
const G = new Set(q.map((ke) => ke.id)), Me = [...
|
|
456
|
+
const G = new Set(q.map((ke) => ke.id)), Me = [...on()].filter((ke) => !G.has(ke));
|
|
457
457
|
Me.length > 0 && Promise.all(
|
|
458
458
|
Me.map(async (ke) => {
|
|
459
459
|
try {
|
|
460
460
|
const pe = await I.getChatSession(ke);
|
|
461
|
-
return !pe || pe.detail || !pe.id ? (
|
|
461
|
+
return !pe || pe.detail || !pe.id ? (wn(ke), null) : pe;
|
|
462
462
|
} catch {
|
|
463
463
|
return null;
|
|
464
464
|
}
|
|
@@ -466,20 +466,20 @@ function hr({ children: t }) {
|
|
|
466
466
|
).then((ke) => {
|
|
467
467
|
const pe = ke.filter((ge) => !!ge);
|
|
468
468
|
pe.length && (Se(pe), H((ge) => [
|
|
469
|
-
...pe.filter((
|
|
469
|
+
...pe.filter((gt) => !ge.some((xt) => xt.id === gt.id)),
|
|
470
470
|
...ge
|
|
471
471
|
]));
|
|
472
472
|
});
|
|
473
473
|
return;
|
|
474
474
|
}
|
|
475
|
-
if (
|
|
475
|
+
if (ye === "session_created") {
|
|
476
476
|
const q = j.session;
|
|
477
477
|
if (!q) return;
|
|
478
|
-
|
|
478
|
+
oa(q.id), Se([q]), H((G) => [q, ...G.filter((J) => J.id !== q.id)]);
|
|
479
479
|
return;
|
|
480
480
|
}
|
|
481
|
-
if (
|
|
482
|
-
|
|
481
|
+
if (ye === "session_deleted" && O) {
|
|
482
|
+
wn(O), H((G) => G.filter((J) => J.id !== O)), i((G) => {
|
|
483
483
|
const J = { ...G };
|
|
484
484
|
return delete J[O], J;
|
|
485
485
|
}), v((G) => {
|
|
@@ -505,16 +505,16 @@ function hr({ children: t }) {
|
|
|
505
505
|
delete q[O], $.current = q;
|
|
506
506
|
return;
|
|
507
507
|
}
|
|
508
|
-
if (
|
|
509
|
-
const q = Array.isArray(j.messages) ? j.messages.map(
|
|
508
|
+
if (ye === "history_loaded" && O) {
|
|
509
|
+
const q = Array.isArray(j.messages) ? j.messages.map(Nn) : [], G = j.before_id != null, J = !!j.has_more, Me = typeof j.oldest_id == "number" ? j.oldest_id : null;
|
|
510
510
|
i((pe) => {
|
|
511
511
|
if (G) {
|
|
512
|
-
const ge = pe[O] ?? [],
|
|
512
|
+
const ge = pe[O] ?? [], gt = new Set(
|
|
513
513
|
ge.map((Xe) => Xe.id).filter((Xe) => typeof Xe == "number")
|
|
514
|
-
),
|
|
515
|
-
(Xe) => Xe.id === void 0 || !
|
|
514
|
+
), xt = q.filter(
|
|
515
|
+
(Xe) => Xe.id === void 0 || !gt.has(Xe.id)
|
|
516
516
|
);
|
|
517
|
-
return { ...pe, [O]: [...
|
|
517
|
+
return { ...pe, [O]: [...xt, ...ge] };
|
|
518
518
|
}
|
|
519
519
|
return { ...pe, [O]: q };
|
|
520
520
|
}), c((pe) => ({ ...pe, [O]: J })), d((pe) => ({ ...pe, [O]: Me })), u((pe) => ({ ...pe, [O]: !1 }));
|
|
@@ -527,24 +527,24 @@ function hr({ children: t }) {
|
|
|
527
527
|
}
|
|
528
528
|
return;
|
|
529
529
|
}
|
|
530
|
-
if (
|
|
530
|
+
if (ye === "history_cleared" && O) {
|
|
531
531
|
i((q) => ({ ...q, [O]: [] })), c((q) => ({ ...q, [O]: !1 })), d((q) => ({ ...q, [O]: null })), u((q) => ({ ...q, [O]: !1 })), ee(O, !1), se(O, "idle"), P(O, null);
|
|
532
532
|
return;
|
|
533
533
|
}
|
|
534
|
-
if (
|
|
534
|
+
if (ye === "message_added" && O) {
|
|
535
535
|
const q = j.message;
|
|
536
536
|
if (!q) return;
|
|
537
537
|
ce(O, q.created_at), q.role === "user" && P(O, null), z(O, (G) => [
|
|
538
538
|
...G.filter((J) => J.type !== "thinking"),
|
|
539
|
-
|
|
539
|
+
Nn(q)
|
|
540
540
|
]), H((G) => G);
|
|
541
541
|
return;
|
|
542
542
|
}
|
|
543
|
-
if (
|
|
543
|
+
if (ye === "demo_started" && O) {
|
|
544
544
|
se(O, "running"), P(O, null);
|
|
545
545
|
return;
|
|
546
546
|
}
|
|
547
|
-
if (
|
|
547
|
+
if (ye === "demo_typing" && O) {
|
|
548
548
|
se(O, "running"), P(O, {
|
|
549
549
|
content: String(j.content || ""),
|
|
550
550
|
seq: Math.max(0, Number(j.seq || 0)),
|
|
@@ -552,23 +552,23 @@ function hr({ children: t }) {
|
|
|
552
552
|
});
|
|
553
553
|
return;
|
|
554
554
|
}
|
|
555
|
-
if (
|
|
555
|
+
if (ye === "demo_replay_complete" && O) {
|
|
556
556
|
se(O, "complete"), P(O, null);
|
|
557
557
|
return;
|
|
558
558
|
}
|
|
559
|
-
if (
|
|
559
|
+
if (ye === "navigation_flash") {
|
|
560
560
|
const q = typeof j.group == "string" ? j.group : "", G = typeof j.item == "string" ? j.item : void 0;
|
|
561
561
|
q && V(q, G);
|
|
562
562
|
return;
|
|
563
563
|
}
|
|
564
|
-
if (
|
|
564
|
+
if (ye === "session_title_updated" && O) {
|
|
565
565
|
const q = typeof j.title == "string" ? j.title : "";
|
|
566
566
|
H(
|
|
567
567
|
(G) => G.map((J) => J.id === O ? { ...J, title: q } : J)
|
|
568
568
|
);
|
|
569
569
|
return;
|
|
570
570
|
}
|
|
571
|
-
if (
|
|
571
|
+
if (ye === "thinking" && O) {
|
|
572
572
|
ee(O, !0), z(O, (q) => {
|
|
573
573
|
const G = q.find((J) => J.type === "thinking");
|
|
574
574
|
return [
|
|
@@ -583,7 +583,7 @@ function hr({ children: t }) {
|
|
|
583
583
|
});
|
|
584
584
|
return;
|
|
585
585
|
}
|
|
586
|
-
if (
|
|
586
|
+
if (ye === "llm_provider" && O) {
|
|
587
587
|
const q = typeof j.provider == "string" ? j.provider : void 0, G = typeof j.model == "string" ? j.model : void 0, Me = (typeof j.role == "string" ? j.role : void 0) === "code_specialist" ? "Delegating to code specialist..." : void 0;
|
|
588
588
|
ee(O, !0), z(O, (ke) => ke.some((ge) => ge.type === "thinking") ? ke.map((ge) => ge.type === "thinking" ? {
|
|
589
589
|
...ge,
|
|
@@ -601,7 +601,7 @@ function hr({ children: t }) {
|
|
|
601
601
|
]);
|
|
602
602
|
return;
|
|
603
603
|
}
|
|
604
|
-
if (
|
|
604
|
+
if (ye === "tool_call" && O) {
|
|
605
605
|
de.current = {
|
|
606
606
|
...de.current,
|
|
607
607
|
[O]: {
|
|
@@ -619,14 +619,14 @@ function hr({ children: t }) {
|
|
|
619
619
|
]);
|
|
620
620
|
return;
|
|
621
621
|
}
|
|
622
|
-
if (
|
|
622
|
+
if (ye === "tool_result" && O) {
|
|
623
623
|
const q = de.current[O];
|
|
624
624
|
if (q && q.tool === String(j.tool || "") && j.success)
|
|
625
625
|
if (q.tool === "create_custom_analytics_report" || q.tool === "update_custom_analytics_report") {
|
|
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 = pr(q.tool, q.args);
|
|
630
630
|
J && V(J.group, J.item);
|
|
631
631
|
}
|
|
632
632
|
de.current = {
|
|
@@ -643,11 +643,11 @@ function hr({ children: t }) {
|
|
|
643
643
|
]);
|
|
644
644
|
return;
|
|
645
645
|
}
|
|
646
|
-
if (
|
|
646
|
+
if (ye === "complete" && O) {
|
|
647
647
|
ee(O, !1), z(O, (q) => q.filter((G) => G.type !== "thinking"));
|
|
648
648
|
return;
|
|
649
649
|
}
|
|
650
|
-
if (
|
|
650
|
+
if (ye === "error") {
|
|
651
651
|
if (Ze)
|
|
652
652
|
return;
|
|
653
653
|
O && (ee(O, !1), z(O, (q) => [
|
|
@@ -701,10 +701,10 @@ function hr({ children: t }) {
|
|
|
701
701
|
async function Fe(B) {
|
|
702
702
|
await ie("delete_session", { session_id: B }, "session_deleted");
|
|
703
703
|
}
|
|
704
|
-
async function
|
|
704
|
+
async function vt(B) {
|
|
705
705
|
await ie("load_history", { session_id: B }, "history_loaded");
|
|
706
706
|
}
|
|
707
|
-
async function
|
|
707
|
+
async function mt(B) {
|
|
708
708
|
if (p[B]) return;
|
|
709
709
|
const K = h[B];
|
|
710
710
|
if (K != null && l[B]) {
|
|
@@ -757,17 +757,17 @@ function hr({ children: t }) {
|
|
|
757
757
|
function Oe(B) {
|
|
758
758
|
return B ? !!l[B] : !1;
|
|
759
759
|
}
|
|
760
|
-
function
|
|
760
|
+
function pt(B) {
|
|
761
761
|
return B ? !!p[B] : !1;
|
|
762
762
|
}
|
|
763
763
|
function it(B) {
|
|
764
764
|
return B ? N[B] ?? "idle" : "idle";
|
|
765
765
|
}
|
|
766
|
-
function
|
|
766
|
+
function ht(B) {
|
|
767
767
|
return B ? C[B] ?? null : null;
|
|
768
768
|
}
|
|
769
769
|
return /* @__PURE__ */ e(
|
|
770
|
-
|
|
770
|
+
ra.Provider,
|
|
771
771
|
{
|
|
772
772
|
value: {
|
|
773
773
|
sessions: a,
|
|
@@ -778,24 +778,24 @@ function hr({ children: t }) {
|
|
|
778
778
|
startDemo: Te,
|
|
779
779
|
completeDemoTyping: Ke,
|
|
780
780
|
deleteSession: Fe,
|
|
781
|
-
loadHistory:
|
|
782
|
-
loadMoreHistory:
|
|
781
|
+
loadHistory: vt,
|
|
782
|
+
loadMoreHistory: mt,
|
|
783
783
|
clearHistory: Je,
|
|
784
784
|
sendMessage: De,
|
|
785
785
|
transcribeAudio: Ie,
|
|
786
786
|
getMessages: je,
|
|
787
787
|
hasMoreHistory: Oe,
|
|
788
|
-
isLoadingOlder:
|
|
788
|
+
isLoadingOlder: pt,
|
|
789
789
|
isThinking: Qe,
|
|
790
790
|
getDemoStatus: it,
|
|
791
|
-
getDemoTypingCue:
|
|
791
|
+
getDemoTypingCue: ht
|
|
792
792
|
},
|
|
793
793
|
children: t
|
|
794
794
|
}
|
|
795
795
|
);
|
|
796
796
|
}
|
|
797
|
-
function
|
|
798
|
-
const t =
|
|
797
|
+
function ut() {
|
|
798
|
+
const t = an(ra);
|
|
799
799
|
if (!t)
|
|
800
800
|
throw new Error("useChat must be used within ChatProvider.");
|
|
801
801
|
return t;
|
|
@@ -810,18 +810,18 @@ function qe(t, n = "USD") {
|
|
|
810
810
|
minimumFractionDigits: 2
|
|
811
811
|
}).format(t ?? 0);
|
|
812
812
|
}
|
|
813
|
-
function
|
|
813
|
+
function Zt(t, n = 2) {
|
|
814
814
|
return new Intl.NumberFormat("en-US", {
|
|
815
815
|
minimumFractionDigits: n,
|
|
816
816
|
maximumFractionDigits: n
|
|
817
817
|
}).format(t ?? 0);
|
|
818
818
|
}
|
|
819
|
-
let
|
|
820
|
-
function
|
|
821
|
-
|
|
819
|
+
let la;
|
|
820
|
+
function Qo(t) {
|
|
821
|
+
la = t;
|
|
822
822
|
}
|
|
823
823
|
function Ft(t) {
|
|
824
|
-
return t ? new Date(t).toLocaleDateString(
|
|
824
|
+
return t ? new Date(t).toLocaleDateString(la, {
|
|
825
825
|
year: "numeric",
|
|
826
826
|
month: "2-digit",
|
|
827
827
|
day: "2-digit"
|
|
@@ -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 fr = {
|
|
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 gr = {
|
|
|
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
|
+
}, yr = {
|
|
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
|
+
fr[t],
|
|
871
|
+
yr[n],
|
|
872
872
|
i
|
|
873
873
|
),
|
|
874
874
|
children: o
|
|
@@ -921,8 +921,8 @@ function te({ label: t, hint: n, error: a, className: s, id: o, ...i }) {
|
|
|
921
921
|
)
|
|
922
922
|
] });
|
|
923
923
|
}
|
|
924
|
-
const
|
|
925
|
-
function
|
|
924
|
+
const ca = rn(null);
|
|
925
|
+
function br({ 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
|
[]
|
|
@@ -934,7 +934,7 @@ function yr({ children: t }) {
|
|
|
934
934
|
), h = Ne(() => ({ confirm: l, prompt: c }), [l, c]), d = (f) => {
|
|
935
935
|
a && (a.resolve(f), s(null));
|
|
936
936
|
}, p = () => d((a == null ? void 0 : a.kind) === "prompt" ? o : !0), u = () => d((a == null ? void 0 : a.kind) === "prompt" ? null : !1);
|
|
937
|
-
return /* @__PURE__ */ r(
|
|
937
|
+
return /* @__PURE__ */ r(ca.Provider, { value: h, children: [
|
|
938
938
|
t,
|
|
939
939
|
a && /* @__PURE__ */ r(
|
|
940
940
|
"div",
|
|
@@ -974,21 +974,21 @@ function yr({ children: t }) {
|
|
|
974
974
|
)
|
|
975
975
|
] });
|
|
976
976
|
}
|
|
977
|
-
function
|
|
978
|
-
const t =
|
|
977
|
+
function da() {
|
|
978
|
+
const t = an(ca);
|
|
979
979
|
if (!t) throw new Error("useConfirm/usePrompt must be used within <DialogProvider>");
|
|
980
980
|
return t;
|
|
981
981
|
}
|
|
982
|
-
function
|
|
983
|
-
return
|
|
982
|
+
function ua() {
|
|
983
|
+
return da().confirm;
|
|
984
984
|
}
|
|
985
|
-
function
|
|
986
|
-
return
|
|
985
|
+
function vr() {
|
|
986
|
+
return da().prompt;
|
|
987
987
|
}
|
|
988
|
-
const
|
|
988
|
+
const ct = [
|
|
989
989
|
{
|
|
990
990
|
label: "Introduction",
|
|
991
|
-
icon: /* @__PURE__ */ e(
|
|
991
|
+
icon: /* @__PURE__ */ e(Ua, { className: "h-4 w-4" }),
|
|
992
992
|
items: [
|
|
993
993
|
{ label: "Getting Started", path: "/tutorial" },
|
|
994
994
|
{ label: "Company Setup", path: "/setup" },
|
|
@@ -997,7 +997,7 @@ const dt = [
|
|
|
997
997
|
},
|
|
998
998
|
{
|
|
999
999
|
label: "Selling",
|
|
1000
|
-
icon: /* @__PURE__ */ e(
|
|
1000
|
+
icon: /* @__PURE__ */ e(Hn, { className: "h-4 w-4" }),
|
|
1001
1001
|
items: [
|
|
1002
1002
|
{ label: "Quotation", path: "/app/quotation" },
|
|
1003
1003
|
{ label: "Proposal", path: "/app/proposal" },
|
|
@@ -1008,7 +1008,7 @@ const dt = [
|
|
|
1008
1008
|
},
|
|
1009
1009
|
{
|
|
1010
1010
|
label: "Buying",
|
|
1011
|
-
icon: /* @__PURE__ */ e(
|
|
1011
|
+
icon: /* @__PURE__ */ e(Va, { 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" }
|
|
@@ -1016,7 +1016,7 @@ const dt = [
|
|
|
1016
1016
|
},
|
|
1017
1017
|
{
|
|
1018
1018
|
label: "Accounting",
|
|
1019
|
-
icon: /* @__PURE__ */ e(
|
|
1019
|
+
icon: /* @__PURE__ */ e(sn, { className: "h-4 w-4" }),
|
|
1020
1020
|
items: [
|
|
1021
1021
|
{ label: "Chart of Accounts", path: "/reports/chart-of-accounts" },
|
|
1022
1022
|
{ label: "Payment Entry", path: "/app/payment-entry" },
|
|
@@ -1028,7 +1028,7 @@ const dt = [
|
|
|
1028
1028
|
},
|
|
1029
1029
|
{
|
|
1030
1030
|
label: "Stock",
|
|
1031
|
-
icon: /* @__PURE__ */ e(
|
|
1031
|
+
icon: /* @__PURE__ */ e(Qn, { className: "h-4 w-4" }),
|
|
1032
1032
|
items: [
|
|
1033
1033
|
{ label: "Stock Entry", path: "/app/stock-entry" },
|
|
1034
1034
|
{ label: "Delivery Note", path: "/app/delivery-note" },
|
|
@@ -1037,7 +1037,7 @@ const dt = [
|
|
|
1037
1037
|
},
|
|
1038
1038
|
{
|
|
1039
1039
|
label: "Reports",
|
|
1040
|
-
icon: /* @__PURE__ */ e(
|
|
1040
|
+
icon: /* @__PURE__ */ e(Ka, { 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(ja, { 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(Ga, { 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,60 +1070,60 @@ const dt = [
|
|
|
1070
1070
|
]
|
|
1071
1071
|
}
|
|
1072
1072
|
];
|
|
1073
|
-
function
|
|
1074
|
-
return
|
|
1073
|
+
function xr() {
|
|
1074
|
+
return ct;
|
|
1075
1075
|
}
|
|
1076
|
-
function
|
|
1077
|
-
const a =
|
|
1076
|
+
function Yo(t, n) {
|
|
1077
|
+
const a = ct.findIndex((s) => s.label === t.label);
|
|
1078
1078
|
if (a >= 0) {
|
|
1079
|
-
|
|
1079
|
+
ct[a] = t;
|
|
1080
1080
|
return;
|
|
1081
1081
|
}
|
|
1082
|
-
(n == null ? void 0 : n.index) != null ?
|
|
1082
|
+
(n == null ? void 0 : n.index) != null ? ct.splice(n.index, 0, t) : ct.push(t);
|
|
1083
1083
|
}
|
|
1084
|
-
function
|
|
1085
|
-
const a =
|
|
1086
|
-
a ? a.items.push(n) :
|
|
1084
|
+
function Jo(t, n) {
|
|
1085
|
+
const a = ct.find((s) => s.label === t);
|
|
1086
|
+
a ? a.items.push(n) : ct.push({ label: t, icon: null, items: [n] });
|
|
1087
1087
|
}
|
|
1088
|
-
let
|
|
1089
|
-
function
|
|
1090
|
-
if (
|
|
1088
|
+
let Xt = { appName: "Lambda ERP" };
|
|
1089
|
+
function Zo(t) {
|
|
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
|
|
1097
|
-
return
|
|
1096
|
+
function Nr() {
|
|
1097
|
+
return Xt;
|
|
1098
1098
|
}
|
|
1099
|
-
const
|
|
1100
|
-
function
|
|
1099
|
+
const ma = "sidebar-collapsed";
|
|
1100
|
+
function Gt() {
|
|
1101
1101
|
try {
|
|
1102
|
-
const t = localStorage.getItem(
|
|
1102
|
+
const t = localStorage.getItem(ma);
|
|
1103
1103
|
return t ? new Set(JSON.parse(t)) : /* @__PURE__ */ new Set();
|
|
1104
1104
|
} catch {
|
|
1105
1105
|
return /* @__PURE__ */ new Set();
|
|
1106
1106
|
}
|
|
1107
1107
|
}
|
|
1108
|
-
function
|
|
1109
|
-
localStorage.setItem(
|
|
1108
|
+
function kn(t) {
|
|
1109
|
+
localStorage.setItem(ma, JSON.stringify([...t]));
|
|
1110
1110
|
}
|
|
1111
|
-
function
|
|
1112
|
-
const [n, a] = w(() => !
|
|
1111
|
+
function ln(t) {
|
|
1112
|
+
const [n, a] = w(() => !Gt().has(t)), s = Pe(() => {
|
|
1113
1113
|
a((i) => {
|
|
1114
|
-
const l =
|
|
1115
|
-
return i ? l.add(t) : l.delete(t),
|
|
1114
|
+
const l = Gt();
|
|
1115
|
+
return i ? l.add(t) : l.delete(t), kn(l), !i;
|
|
1116
1116
|
});
|
|
1117
1117
|
}, [t]), o = Pe(() => {
|
|
1118
1118
|
a((i) => {
|
|
1119
1119
|
if (i) return i;
|
|
1120
|
-
const l =
|
|
1121
|
-
return l.delete(t),
|
|
1120
|
+
const l = Gt();
|
|
1121
|
+
return l.delete(t), kn(l), !0;
|
|
1122
1122
|
});
|
|
1123
1123
|
}, [t]);
|
|
1124
1124
|
return [n, s, o];
|
|
1125
1125
|
}
|
|
1126
|
-
const
|
|
1126
|
+
const cn = {
|
|
1127
1127
|
Introduction: "bg-fuchsia-300 text-fuchsia-950 ring-2 ring-inset ring-fuchsia-100",
|
|
1128
1128
|
Selling: "bg-emerald-300 text-emerald-950 ring-2 ring-inset ring-emerald-100",
|
|
1129
1129
|
Buying: "bg-rose-300 text-rose-950 ring-2 ring-inset ring-rose-100",
|
|
@@ -1134,8 +1134,8 @@ const ln = {
|
|
|
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
|
|
1138
|
-
const [t, n] =
|
|
1137
|
+
function wr() {
|
|
1138
|
+
const [t, n] = ln("chats"), a = bt(), s = Ee(), { t: o } = X(), { sessions: i, createSession: l, deleteSession: c } = ut(), h = async () => {
|
|
1139
1139
|
try {
|
|
1140
1140
|
const p = await l();
|
|
1141
1141
|
s(`/chat/${p.id}`);
|
|
@@ -1156,7 +1156,7 @@ function Nr() {
|
|
|
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(Wa, { 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
|
]
|
|
@@ -1169,7 +1169,7 @@ function Nr() {
|
|
|
1169
1169
|
onClick: h,
|
|
1170
1170
|
className: "flex w-full items-center gap-2 px-4 py-1.5 pl-10 text-sm text-brand transition-colors hover:bg-brand/5",
|
|
1171
1171
|
children: [
|
|
1172
|
-
/* @__PURE__ */ e(
|
|
1172
|
+
/* @__PURE__ */ e(Yn, { className: "h-3.5 w-3.5" }),
|
|
1173
1173
|
o("nav.newChat")
|
|
1174
1174
|
]
|
|
1175
1175
|
}
|
|
@@ -1188,14 +1188,14 @@ function Nr() {
|
|
|
1188
1188
|
children: p.title
|
|
1189
1189
|
}
|
|
1190
1190
|
),
|
|
1191
|
-
u && /* @__PURE__ */ e(
|
|
1191
|
+
u && /* @__PURE__ */ e(dn, {}),
|
|
1192
1192
|
/* @__PURE__ */ e(
|
|
1193
1193
|
"button",
|
|
1194
1194
|
{
|
|
1195
1195
|
onClick: (f) => d(f, p.id),
|
|
1196
1196
|
className: "absolute right-2 top-1/2 -translate-y-1/2 rounded p-0.5 text-fg-muted opacity-0 transition-opacity hover:text-red-500 group-hover:opacity-100",
|
|
1197
1197
|
title: o("nav.deleteChat"),
|
|
1198
|
-
children: /* @__PURE__ */ e(
|
|
1198
|
+
children: /* @__PURE__ */ e(Jn, { className: "h-3.5 w-3.5" })
|
|
1199
1199
|
}
|
|
1200
1200
|
)
|
|
1201
1201
|
] }, p.id);
|
|
@@ -1203,7 +1203,7 @@ function Nr() {
|
|
|
1203
1203
|
] })
|
|
1204
1204
|
] });
|
|
1205
1205
|
}
|
|
1206
|
-
function
|
|
1206
|
+
function dn() {
|
|
1207
1207
|
return /* @__PURE__ */ e(
|
|
1208
1208
|
"span",
|
|
1209
1209
|
{
|
|
@@ -1212,8 +1212,8 @@ function cn() {
|
|
|
1212
1212
|
}
|
|
1213
1213
|
);
|
|
1214
1214
|
}
|
|
1215
|
-
function
|
|
1216
|
-
const [t, n, a] =
|
|
1215
|
+
function kr() {
|
|
1216
|
+
const [t, n, a] = ln("custom-analytics"), s = bt(), o = Ee(), i = He(), { t: l } = X(), { navigationFlash: c, sessions: h, createSession: d } = ut(), 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(),
|
|
1219
1219
|
staleTime: 3e4
|
|
@@ -1252,7 +1252,7 @@ function wr() {
|
|
|
1252
1252
|
p && u
|
|
1253
1253
|
),
|
|
1254
1254
|
children: [
|
|
1255
|
-
/* @__PURE__ */ e(
|
|
1255
|
+
/* @__PURE__ */ e(Ha, { 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
|
]
|
|
@@ -1265,7 +1265,7 @@ function wr() {
|
|
|
1265
1265
|
onClick: C,
|
|
1266
1266
|
className: "flex w-full items-center gap-2 px-4 py-1.5 pl-10 text-sm text-brand transition-colors hover:bg-brand/5",
|
|
1267
1267
|
children: [
|
|
1268
|
-
/* @__PURE__ */ e(
|
|
1268
|
+
/* @__PURE__ */ e(Yn, { className: "h-3.5 w-3.5" }),
|
|
1269
1269
|
l("nav.newAnalytics")
|
|
1270
1270
|
]
|
|
1271
1271
|
}
|
|
@@ -1287,14 +1287,14 @@ function wr() {
|
|
|
1287
1287
|
children: S.title
|
|
1288
1288
|
}
|
|
1289
1289
|
),
|
|
1290
|
-
y && /* @__PURE__ */ e(
|
|
1290
|
+
y && /* @__PURE__ */ e(dn, {}),
|
|
1291
1291
|
/* @__PURE__ */ e(
|
|
1292
1292
|
"button",
|
|
1293
1293
|
{
|
|
1294
1294
|
onClick: (D) => b(D, S.id),
|
|
1295
1295
|
className: "absolute right-2 top-1/2 -translate-y-1/2 rounded p-0.5 text-fg-muted opacity-0 transition-opacity hover:text-red-500 group-hover:opacity-100",
|
|
1296
1296
|
title: l("nav.deleteReport"),
|
|
1297
|
-
children: /* @__PURE__ */ e(
|
|
1297
|
+
children: /* @__PURE__ */ e(Jn, { className: "h-3.5 w-3.5" })
|
|
1298
1298
|
}
|
|
1299
1299
|
)
|
|
1300
1300
|
] }, S.id);
|
|
@@ -1302,8 +1302,8 @@ function wr() {
|
|
|
1302
1302
|
] })
|
|
1303
1303
|
] });
|
|
1304
1304
|
}
|
|
1305
|
-
function
|
|
1306
|
-
const [n, a] =
|
|
1305
|
+
function Cr({ group: t }) {
|
|
1306
|
+
const [n, a] = ln(t.label), { t: s } = X(), { navigationFlash: o } = ut(), 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(
|
|
1309
1309
|
"button",
|
|
@@ -1337,7 +1337,7 @@ function kr({ group: t }) {
|
|
|
1337
1337
|
(o == null ? void 0 : o.group) === t.label && (o == null ? void 0 : o.item) === c.label && l
|
|
1338
1338
|
),
|
|
1339
1339
|
children: ({ isActive: d }) => /* @__PURE__ */ r(Ce, { children: [
|
|
1340
|
-
d && /* @__PURE__ */ e(
|
|
1340
|
+
d && /* @__PURE__ */ e(dn, {}),
|
|
1341
1341
|
s(`nav.items.${c.label}`, { defaultValue: c.label })
|
|
1342
1342
|
] })
|
|
1343
1343
|
}
|
|
@@ -1345,10 +1345,10 @@ function kr({ group: t }) {
|
|
|
1345
1345
|
}) })
|
|
1346
1346
|
] });
|
|
1347
1347
|
}
|
|
1348
|
-
const
|
|
1348
|
+
const Sr = {
|
|
1349
1349
|
"/setup/opening-balances": "opening_balances_enabled"
|
|
1350
1350
|
};
|
|
1351
|
-
function
|
|
1351
|
+
function Dr({ isMobileOpen: t = !1, onClose: n }) {
|
|
1352
1352
|
var c;
|
|
1353
1353
|
const { data: a } = ue({
|
|
1354
1354
|
queryKey: ["settings"],
|
|
@@ -1358,11 +1358,11 @@ function Sr({ 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) || Nr().appName, l = Ne(() => xr().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 = Sr[p.path];
|
|
1366
1366
|
return !u || !a ? !0 : a[u] !== "0";
|
|
1367
1367
|
})
|
|
1368
1368
|
})), [a, s]);
|
|
@@ -1409,52 +1409,52 @@ function Sr({ 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(Nr, {}),
|
|
1413
1412
|
/* @__PURE__ */ e(wr, {}),
|
|
1414
|
-
|
|
1413
|
+
/* @__PURE__ */ e(kr, {}),
|
|
1414
|
+
l.map((h) => /* @__PURE__ */ e(Cr, { group: h }, h.label))
|
|
1415
1415
|
] })
|
|
1416
1416
|
]
|
|
1417
1417
|
}
|
|
1418
1418
|
);
|
|
1419
1419
|
}
|
|
1420
|
-
const
|
|
1421
|
-
function
|
|
1420
|
+
const Cn = (t) => t.replace(/-/g, " ").replace(/\b\w/g, (n) => n.toUpperCase());
|
|
1421
|
+
function Ar(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");
|
|
1425
1425
|
if (a[0] === "chat") return n("titles.chat");
|
|
1426
1426
|
if (a[0] === "reports") {
|
|
1427
1427
|
const s = a[1] || "";
|
|
1428
|
-
return n(`titles.${s}`, { defaultValue: s ?
|
|
1428
|
+
return n(`titles.${s}`, { defaultValue: s ? Cn(s) : n("titles.reports") });
|
|
1429
1429
|
}
|
|
1430
1430
|
if (a[0] === "masters") {
|
|
1431
1431
|
const s = a[1] || "", o = s.charAt(0).toUpperCase() + s.slice(1), i = n(`masters.${s}.one`, { defaultValue: o });
|
|
1432
1432
|
return a[2] === "new" ? n("header.new", { label: i }) : a[2] ? `${i}: ${decodeURIComponent(a[2])}` : n(`masters.${s}.other`, { defaultValue: `${o}s` });
|
|
1433
1433
|
}
|
|
1434
1434
|
if (a[0] === "app") {
|
|
1435
|
-
const s = a[1] || "", o =
|
|
1435
|
+
const s = a[1] || "", o = Cn(s), i = n(`doctypes.${s}.one`, { defaultValue: o });
|
|
1436
1436
|
return a[2] === "new" ? n("header.new", { label: i }) : a[2] ? `${i}: ${decodeURIComponent(a[2])}` : n(`doctypes.${s}.other`, { defaultValue: `${o}s` });
|
|
1437
1437
|
}
|
|
1438
1438
|
return n("titles.dashboard");
|
|
1439
1439
|
}
|
|
1440
|
-
function
|
|
1440
|
+
function Pr(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 Pr() {
|
|
1445
|
-
return /* @__PURE__ */ e(yr, { children: /* @__PURE__ */ e(hr, { children: /* @__PURE__ */ e(_r, {}) }) });
|
|
1446
|
-
}
|
|
1447
1444
|
function _r() {
|
|
1448
|
-
|
|
1445
|
+
return /* @__PURE__ */ e(br, { children: /* @__PURE__ */ e(gr, { children: /* @__PURE__ */ e(Tr, {}) }) });
|
|
1446
|
+
}
|
|
1447
|
+
function Tr() {
|
|
1448
|
+
const { pathname: t } = bt(), n = Ee(), { user: a, logout: s } = st(), { navigationFlash: o } = ut(), { t: i } = X(), l = Ar(t, i), c = Pr(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);
|
|
1452
1452
|
re(() => {
|
|
1453
1453
|
p(!1);
|
|
1454
1454
|
}, [t]);
|
|
1455
|
-
const u = o ?
|
|
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(Dr, { isMobileOpen: d, onClose: () => p(!1) }),
|
|
1458
1458
|
d && /* @__PURE__ */ e(
|
|
1459
1459
|
"div",
|
|
1460
1460
|
{
|
|
@@ -1484,7 +1484,7 @@ function _r() {
|
|
|
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(Qa, { 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 _r() {
|
|
|
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(qa, {}) })
|
|
1508
1508
|
] })
|
|
1509
1509
|
] });
|
|
1510
1510
|
}
|
|
1511
|
-
function
|
|
1511
|
+
function Rr({ 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(za, { 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 Ir = {
|
|
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
|
+
Ir[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 Br = {
|
|
1560
1560
|
Draft: "secondary",
|
|
1561
1561
|
Open: "default",
|
|
1562
1562
|
Submitted: "default",
|
|
@@ -1570,8 +1570,8 @@ const Ir = {
|
|
|
1570
1570
|
Discarded: "secondary",
|
|
1571
1571
|
Overdue: "danger"
|
|
1572
1572
|
};
|
|
1573
|
-
function
|
|
1574
|
-
const { t: n } = X(), a =
|
|
1573
|
+
function un({ status: t }) {
|
|
1574
|
+
const { t: n } = X(), a = Br[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
|
|
1612
|
-
"Sales Invoice":
|
|
1613
|
-
"Purchase Invoice":
|
|
1614
|
-
"Payment Entry":
|
|
1615
|
-
"Sales Order":
|
|
1616
|
-
Quotation:
|
|
1611
|
+
const Er = {
|
|
1612
|
+
"Sales Invoice": gn,
|
|
1613
|
+
"Purchase Invoice": gn,
|
|
1614
|
+
"Payment Entry": Xa,
|
|
1615
|
+
"Sales Order": Hn,
|
|
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 Lr({ doc: t }) {
|
|
1619
|
+
const { t: n } = X(), a = t.doctype ?? t.type ?? "Document", s = t.creation ?? t.date, o = Er[a] ?? sn, l = `/app/${a.toLowerCase().replace(/\s+/g, "-")}/${encodeURIComponent(t.name)}`;
|
|
1620
1620
|
return /* @__PURE__ */ r(
|
|
1621
1621
|
ve,
|
|
1622
1622
|
{
|
|
@@ -1628,7 +1628,7 @@ function Er({ doc: t }) {
|
|
|
1628
1628
|
/* @__PURE__ */ e("div", { className: "truncate text-sm font-medium text-fg", children: t.name }),
|
|
1629
1629
|
/* @__PURE__ */ e("div", { className: "truncate text-xs text-fg-muted", children: n(`nav.items.${a}`, { defaultValue: a }) })
|
|
1630
1630
|
] }),
|
|
1631
|
-
/* @__PURE__ */ e(
|
|
1631
|
+
/* @__PURE__ */ e(un, { status: t.status }),
|
|
1632
1632
|
/* @__PURE__ */ e("div", { className: "hidden text-xs tabular-nums text-fg-muted sm:block", children: s ? Ft(s) : "—" })
|
|
1633
1633
|
]
|
|
1634
1634
|
}
|
|
@@ -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 Or() {
|
|
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 Lr() {
|
|
|
1662
1662
|
{
|
|
1663
1663
|
title: t("dashboard.totalRevenue"),
|
|
1664
1664
|
value: n == null ? void 0 : n.total_revenue,
|
|
1665
|
-
icon:
|
|
1665
|
+
icon: Ya,
|
|
1666
1666
|
tone: "text-emerald-600 bg-emerald-500/10"
|
|
1667
1667
|
}
|
|
1668
1668
|
),
|
|
@@ -1671,7 +1671,7 @@ function Lr() {
|
|
|
1671
1671
|
{
|
|
1672
1672
|
title: t("dashboard.outstandingReceivable"),
|
|
1673
1673
|
value: n == null ? void 0 : n.outstanding_receivable,
|
|
1674
|
-
icon:
|
|
1674
|
+
icon: Ja,
|
|
1675
1675
|
tone: "text-sky-600 bg-sky-500/10"
|
|
1676
1676
|
}
|
|
1677
1677
|
),
|
|
@@ -1680,7 +1680,7 @@ function Lr() {
|
|
|
1680
1680
|
{
|
|
1681
1681
|
title: t("dashboard.outstandingPayable"),
|
|
1682
1682
|
value: n == null ? void 0 : n.outstanding_payable,
|
|
1683
|
-
icon:
|
|
1683
|
+
icon: Za,
|
|
1684
1684
|
tone: "text-amber-600 bg-amber-500/10"
|
|
1685
1685
|
}
|
|
1686
1686
|
),
|
|
@@ -1689,7 +1689,7 @@ function Lr() {
|
|
|
1689
1689
|
{
|
|
1690
1690
|
title: t("dashboard.totalStockValue"),
|
|
1691
1691
|
value: n == null ? void 0 : n.total_stock_value,
|
|
1692
|
-
icon:
|
|
1692
|
+
icon: Qn,
|
|
1693
1693
|
tone: "text-brand bg-brand/10"
|
|
1694
1694
|
}
|
|
1695
1695
|
)
|
|
@@ -1700,28 +1700,28 @@ function Lr() {
|
|
|
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(Lr, { 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
|
-
const
|
|
1707
|
-
function
|
|
1706
|
+
const pa = "lad.docListContext";
|
|
1707
|
+
function ha() {
|
|
1708
1708
|
try {
|
|
1709
|
-
return JSON.parse(sessionStorage.getItem(
|
|
1709
|
+
return JSON.parse(sessionStorage.getItem(pa) || "{}");
|
|
1710
1710
|
} catch {
|
|
1711
1711
|
return {};
|
|
1712
1712
|
}
|
|
1713
1713
|
}
|
|
1714
|
-
function
|
|
1714
|
+
function ga(t, n) {
|
|
1715
1715
|
try {
|
|
1716
|
-
const a =
|
|
1717
|
-
a[t] = n, sessionStorage.setItem(
|
|
1716
|
+
const a = ha();
|
|
1717
|
+
a[t] = n, sessionStorage.setItem(pa, JSON.stringify(a));
|
|
1718
1718
|
} catch {
|
|
1719
1719
|
}
|
|
1720
1720
|
}
|
|
1721
|
-
function
|
|
1722
|
-
return
|
|
1721
|
+
function qr(t) {
|
|
1722
|
+
return ha()[t];
|
|
1723
1723
|
}
|
|
1724
|
-
function
|
|
1724
|
+
function zr(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
|
+
], Mr = [
|
|
1784
1784
|
...rt,
|
|
1785
1785
|
{
|
|
1786
1786
|
name: "frequency",
|
|
@@ -1807,7 +1807,7 @@ const rt = [
|
|
|
1807
1807
|
{ name: "description", label: "Description", type: "text" },
|
|
1808
1808
|
{ name: "rate", label: "Rate (%)", type: "number" },
|
|
1809
1809
|
{ name: "tax_amount", label: "Amount", type: "currency", readOnly: !0 }
|
|
1810
|
-
],
|
|
1810
|
+
], mn = {
|
|
1811
1811
|
quotation: {
|
|
1812
1812
|
slug: "quotation",
|
|
1813
1813
|
label: "Quotation",
|
|
@@ -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: Mr },
|
|
1831
1831
|
{ key: "taxes", label: "Taxes", fields: at }
|
|
1832
1832
|
],
|
|
1833
1833
|
listColumns: ["name", "customer", "transaction_date", "grand_total", "status"],
|
|
@@ -2414,17 +2414,17 @@ const rt = [
|
|
|
2414
2414
|
conversions: []
|
|
2415
2415
|
}
|
|
2416
2416
|
};
|
|
2417
|
-
function
|
|
2418
|
-
return
|
|
2417
|
+
function fa(t) {
|
|
2418
|
+
return mn[t];
|
|
2419
2419
|
}
|
|
2420
|
-
function
|
|
2421
|
-
|
|
2420
|
+
function Xo(t) {
|
|
2421
|
+
mn[t.slug] = t;
|
|
2422
2422
|
}
|
|
2423
|
-
function
|
|
2424
|
-
return Object.values(
|
|
2423
|
+
function el() {
|
|
2424
|
+
return Object.values(mn);
|
|
2425
2425
|
}
|
|
2426
|
-
function
|
|
2427
|
-
const o = Ee(), i = s === "master", l =
|
|
2426
|
+
function ya({ slug: t, name: n, onSave: a, kind: s = "document" }) {
|
|
2427
|
+
const o = Ee(), i = s === "master", l = qr(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 fa({ 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(er, { className: "h-4 w-4" })
|
|
2453
2453
|
}
|
|
2454
2454
|
),
|
|
2455
2455
|
/* @__PURE__ */ e(
|
|
@@ -2465,7 +2465,7 @@ function fa({ slug: t, name: n, onSave: a, kind: s = "document" }) {
|
|
|
2465
2465
|
)
|
|
2466
2466
|
] });
|
|
2467
2467
|
}
|
|
2468
|
-
function
|
|
2468
|
+
function Fr(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 } = Fr(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 $r({ 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 Fr({ text: t }) {
|
|
|
2527
2527
|
] })
|
|
2528
2528
|
] });
|
|
2529
2529
|
}
|
|
2530
|
-
function
|
|
2530
|
+
function Ur() {
|
|
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 $r() {
|
|
|
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(tr, { 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 $r() {
|
|
|
2570
2570
|
}
|
|
2571
2571
|
);
|
|
2572
2572
|
}
|
|
2573
|
-
function
|
|
2573
|
+
function Vr(t, n = !0) {
|
|
2574
2574
|
const { data: a } = ue({
|
|
2575
2575
|
queryKey: ["currencies", ""],
|
|
2576
2576
|
queryFn: () => I.currencies(t),
|
|
@@ -2579,23 +2579,23 @@ function Ur(t, n = !0) {
|
|
|
2579
2579
|
});
|
|
2580
2580
|
return (a == null ? void 0 : a.currencies) ?? [];
|
|
2581
2581
|
}
|
|
2582
|
-
const
|
|
2582
|
+
const Kr = /* @__PURE__ */ new Set([
|
|
2583
2583
|
"customer",
|
|
2584
2584
|
"supplier",
|
|
2585
2585
|
"item",
|
|
2586
2586
|
"warehouse"
|
|
2587
2587
|
]);
|
|
2588
|
-
function
|
|
2589
|
-
return !t || !n ? null :
|
|
2588
|
+
function en(t, n) {
|
|
2589
|
+
return !t || !n ? null : Kr.has(t) ? `/masters/${t}/${encodeURIComponent(n)}` : t === "account" ? `/reports/general-ledger?account=${encodeURIComponent(n)}` : null;
|
|
2590
2590
|
}
|
|
2591
|
-
function
|
|
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($r, { text: n }),
|
|
2595
2595
|
a
|
|
2596
2596
|
] });
|
|
2597
2597
|
}
|
|
2598
|
-
function
|
|
2598
|
+
function jr({
|
|
2599
2599
|
field: t,
|
|
2600
2600
|
value: n,
|
|
2601
2601
|
onChange: a,
|
|
@@ -2637,7 +2637,7 @@ function Kr({
|
|
|
2637
2637
|
onBlur: () => setTimeout(() => h(!1), 200)
|
|
2638
2638
|
}
|
|
2639
2639
|
),
|
|
2640
|
-
c && f && f.length > 0 && p &&
|
|
2640
|
+
c && f && f.length > 0 && p && ta(
|
|
2641
2641
|
/* @__PURE__ */ e(
|
|
2642
2642
|
"ul",
|
|
2643
2643
|
{
|
|
@@ -2670,10 +2670,10 @@ 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(
|
|
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 = Vr(void 0, p);
|
|
2674
2674
|
if (h) {
|
|
2675
2675
|
if (t.type === "link" && n) {
|
|
2676
|
-
const C = t.linkDoctypeField && o ? String(o[t.linkDoctypeField] ?? "").toLowerCase().replace(/\s+/g, "-") : t.linkDoctype, S =
|
|
2676
|
+
const C = t.linkDoctypeField && o ? String(o[t.linkDoctypeField] ?? "").toLowerCase().replace(/\s+/g, "-") : t.linkDoctype, S = en(C, String(n));
|
|
2677
2677
|
if (S)
|
|
2678
2678
|
return /* @__PURE__ */ r("div", { children: [
|
|
2679
2679
|
/* @__PURE__ */ e(d, {}),
|
|
@@ -2703,7 +2703,7 @@ function It({
|
|
|
2703
2703
|
return /* @__PURE__ */ r("div", { children: [
|
|
2704
2704
|
/* @__PURE__ */ e(d, {}),
|
|
2705
2705
|
/* @__PURE__ */ e(
|
|
2706
|
-
|
|
2706
|
+
jr,
|
|
2707
2707
|
{
|
|
2708
2708
|
field: N,
|
|
2709
2709
|
value: n ?? "",
|
|
@@ -2732,11 +2732,11 @@ function It({
|
|
|
2732
2732
|
const N = t.name === "remarks";
|
|
2733
2733
|
return /* @__PURE__ */ r("div", { children: [
|
|
2734
2734
|
!i && /* @__PURE__ */ e(
|
|
2735
|
-
|
|
2735
|
+
Sn,
|
|
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(Ur, {}) : 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 Gr({
|
|
2770
2770
|
tableDef: t,
|
|
2771
2771
|
rows: n,
|
|
2772
2772
|
onChange: a,
|
|
@@ -2828,7 +2828,7 @@ function jr({
|
|
|
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 Wr({
|
|
2832
2832
|
isNew: t,
|
|
2833
2833
|
doctype: n,
|
|
2834
2834
|
name: a,
|
|
@@ -2885,7 +2885,7 @@ function Gr({
|
|
|
2885
2885
|
)
|
|
2886
2886
|
] });
|
|
2887
2887
|
}
|
|
2888
|
-
function
|
|
2888
|
+
function Dn(t, n) {
|
|
2889
2889
|
if (!n) return t;
|
|
2890
2890
|
const a = { ...t };
|
|
2891
2891
|
if (n.childTables.some((i) => i.key === "items") && Array.isArray(a.items) && (a.items = a.items.map((i) => ({
|
|
@@ -2907,9 +2907,9 @@ function Sn(t, n) {
|
|
|
2907
2907
|
}
|
|
2908
2908
|
return a;
|
|
2909
2909
|
}
|
|
2910
|
-
function
|
|
2910
|
+
function An() {
|
|
2911
2911
|
var Se;
|
|
2912
|
-
const { doctype: t, name: n } =
|
|
2912
|
+
const { doctype: t, name: n } = dt(), a = Ee(), s = He(), { t: o } = X(), i = fa(t ?? ""), l = !n, [c, h] = w({}), [d, p] = w(!1), { data: u, isLoading: f } = ue({
|
|
2913
2913
|
queryKey: ["document", t, n],
|
|
2914
2914
|
queryFn: () => I.getDocument(t, n),
|
|
2915
2915
|
enabled: !!t && !!n && !l
|
|
@@ -2984,7 +2984,7 @@ function Dn() {
|
|
|
2984
2984
|
(E, ie) => {
|
|
2985
2985
|
E === "currency" && p(!0), h((Le) => {
|
|
2986
2986
|
const Te = { ...Le, [E]: ie };
|
|
2987
|
-
return E === "currency" && (Te.conversion_rate = 0),
|
|
2987
|
+
return E === "currency" && (Te.conversion_rate = 0), Dn(Te, i);
|
|
2988
2988
|
});
|
|
2989
2989
|
},
|
|
2990
2990
|
[i]
|
|
@@ -2992,7 +2992,7 @@ function Dn() {
|
|
|
2992
2992
|
(E, ie) => {
|
|
2993
2993
|
h((Le) => {
|
|
2994
2994
|
const Te = { ...Le, [E]: ie };
|
|
2995
|
-
return
|
|
2995
|
+
return Dn(Te, i);
|
|
2996
2996
|
});
|
|
2997
2997
|
},
|
|
2998
2998
|
[i]
|
|
@@ -3018,8 +3018,8 @@ function Dn() {
|
|
|
3018
3018
|
return /* @__PURE__ */ r("div", { className: "space-y-6", children: [
|
|
3019
3019
|
/* @__PURE__ */ r("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
3020
3020
|
/* @__PURE__ */ r("div", { className: "flex items-center gap-3", children: [
|
|
3021
|
-
!l && /* @__PURE__ */ e(
|
|
3022
|
-
!l && c.status && /* @__PURE__ */ e(
|
|
3021
|
+
!l && /* @__PURE__ */ e(ya, { slug: i.slug, name: n, onSave: R }),
|
|
3022
|
+
!l && c.status && /* @__PURE__ */ e(un, { status: c.status }),
|
|
3023
3023
|
!l && c.currency && /* @__PURE__ */ r(
|
|
3024
3024
|
"span",
|
|
3025
3025
|
{
|
|
@@ -3036,7 +3036,7 @@ function Dn() {
|
|
|
3036
3036
|
)
|
|
3037
3037
|
] }),
|
|
3038
3038
|
/* @__PURE__ */ e(
|
|
3039
|
-
|
|
3039
|
+
Wr,
|
|
3040
3040
|
{
|
|
3041
3041
|
isNew: l,
|
|
3042
3042
|
doctype: t,
|
|
@@ -3081,7 +3081,7 @@ function Dn() {
|
|
|
3081
3081
|
)) })
|
|
3082
3082
|
] }),
|
|
3083
3083
|
i.childTables.map((E) => /* @__PURE__ */ e(
|
|
3084
|
-
|
|
3084
|
+
Gr,
|
|
3085
3085
|
{
|
|
3086
3086
|
tableDef: E,
|
|
3087
3087
|
rows: c[E.key] ?? [],
|
|
@@ -3108,35 +3108,35 @@ function Dn() {
|
|
|
3108
3108
|
function be(t) {
|
|
3109
3109
|
return t.toISOString().split("T")[0];
|
|
3110
3110
|
}
|
|
3111
|
-
function
|
|
3111
|
+
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
|
|
3116
|
-
const n =
|
|
3115
|
+
function Hr(t) {
|
|
3116
|
+
const n = ba(t);
|
|
3117
3117
|
return n.setDate(n.getDate() + 6), n;
|
|
3118
3118
|
}
|
|
3119
|
-
function
|
|
3119
|
+
function Pn(t) {
|
|
3120
3120
|
return new Date(t.getFullYear(), t.getMonth(), 1);
|
|
3121
3121
|
}
|
|
3122
3122
|
function Et(t) {
|
|
3123
3123
|
return new Date(t.getFullYear(), t.getMonth() + 1, 0);
|
|
3124
3124
|
}
|
|
3125
|
-
function
|
|
3125
|
+
function tn(t) {
|
|
3126
3126
|
const n = Math.floor(t.getMonth() / 3);
|
|
3127
3127
|
return new Date(t.getFullYear(), n * 3, 1);
|
|
3128
3128
|
}
|
|
3129
|
-
function
|
|
3130
|
-
const n =
|
|
3129
|
+
function nn(t) {
|
|
3130
|
+
const n = tn(t);
|
|
3131
3131
|
return new Date(n.getFullYear(), n.getMonth() + 3, 0);
|
|
3132
3132
|
}
|
|
3133
|
-
function
|
|
3133
|
+
function _n(t) {
|
|
3134
3134
|
return new Date(t.getFullYear(), 0, 1);
|
|
3135
3135
|
}
|
|
3136
3136
|
function Lt(t) {
|
|
3137
3137
|
return new Date(t.getFullYear(), 11, 31);
|
|
3138
3138
|
}
|
|
3139
|
-
const
|
|
3139
|
+
const Qr = [
|
|
3140
3140
|
{
|
|
3141
3141
|
label: "Today",
|
|
3142
3142
|
range: () => {
|
|
@@ -3146,44 +3146,44 @@ const Hr = [
|
|
|
3146
3146
|
},
|
|
3147
3147
|
{
|
|
3148
3148
|
label: "This Week",
|
|
3149
|
-
range: () => [be(
|
|
3149
|
+
range: () => [be(ba(/* @__PURE__ */ new Date())), be(Hr(/* @__PURE__ */ new Date()))]
|
|
3150
3150
|
},
|
|
3151
3151
|
{
|
|
3152
3152
|
label: "This Month",
|
|
3153
|
-
range: () => [be(
|
|
3153
|
+
range: () => [be(Pn(/* @__PURE__ */ new Date())), be(Et(/* @__PURE__ */ new Date()))]
|
|
3154
3154
|
},
|
|
3155
3155
|
{
|
|
3156
3156
|
label: "This Quarter",
|
|
3157
|
-
range: () => [be(
|
|
3157
|
+
range: () => [be(tn(/* @__PURE__ */ new Date())), be(nn(/* @__PURE__ */ new Date()))]
|
|
3158
3158
|
},
|
|
3159
3159
|
{
|
|
3160
3160
|
label: "This Year",
|
|
3161
|
-
range: () => [be(
|
|
3161
|
+
range: () => [be(_n(/* @__PURE__ */ new Date())), be(Lt(/* @__PURE__ */ new Date()))]
|
|
3162
3162
|
},
|
|
3163
3163
|
{
|
|
3164
3164
|
label: "Last Month",
|
|
3165
3165
|
range: () => {
|
|
3166
3166
|
const t = /* @__PURE__ */ new Date(), n = new Date(t.getFullYear(), t.getMonth() - 1, 1);
|
|
3167
|
-
return [be(
|
|
3167
|
+
return [be(Pn(n)), be(Et(n))];
|
|
3168
3168
|
}
|
|
3169
3169
|
},
|
|
3170
3170
|
{
|
|
3171
3171
|
label: "Last Quarter",
|
|
3172
3172
|
range: () => {
|
|
3173
3173
|
const t = /* @__PURE__ */ new Date(), n = new Date(t.getFullYear(), t.getMonth() - 3, 1);
|
|
3174
|
-
return [be(
|
|
3174
|
+
return [be(tn(n)), be(nn(n))];
|
|
3175
3175
|
}
|
|
3176
3176
|
},
|
|
3177
3177
|
{
|
|
3178
3178
|
label: "Last Year",
|
|
3179
3179
|
range: () => {
|
|
3180
3180
|
const t = new Date((/* @__PURE__ */ new Date()).getFullYear() - 1, 6, 1);
|
|
3181
|
-
return [be(
|
|
3181
|
+
return [be(_n(t)), be(Lt(t))];
|
|
3182
3182
|
}
|
|
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: Qr.map((n) => /* @__PURE__ */ e(
|
|
3187
3187
|
"button",
|
|
3188
3188
|
{
|
|
3189
3189
|
type: "button",
|
|
@@ -3197,7 +3197,7 @@ function $t({ onSelect: t }) {
|
|
|
3197
3197
|
n.label
|
|
3198
3198
|
)) });
|
|
3199
3199
|
}
|
|
3200
|
-
function
|
|
3200
|
+
function pn({ onSelect: t }) {
|
|
3201
3201
|
return /* @__PURE__ */ e("div", { className: "flex flex-wrap gap-1.5", children: [
|
|
3202
3202
|
{ label: "Today", value: () => be(/* @__PURE__ */ new Date()) },
|
|
3203
3203
|
{ label: "End of This Month", value: () => be(Et(/* @__PURE__ */ new Date())) },
|
|
@@ -3205,7 +3205,7 @@ function mn({ onSelect: t }) {
|
|
|
3205
3205
|
const a = /* @__PURE__ */ new Date();
|
|
3206
3206
|
return be(Et(new Date(a.getFullYear(), a.getMonth() - 1, 1)));
|
|
3207
3207
|
} },
|
|
3208
|
-
{ label: "End of This Quarter", value: () => be(
|
|
3208
|
+
{ label: "End of This Quarter", value: () => be(nn(/* @__PURE__ */ new Date())) },
|
|
3209
3209
|
{ label: "End of This Year", value: () => be(Lt(/* @__PURE__ */ new Date())) },
|
|
3210
3210
|
{ label: "End of Last Year", value: () => be(Lt(new Date((/* @__PURE__ */ new Date()).getFullYear() - 1, 0, 1))) }
|
|
3211
3211
|
].map((a) => /* @__PURE__ */ e(
|
|
@@ -3219,21 +3219,21 @@ function mn({ onSelect: t }) {
|
|
|
3219
3219
|
a.label
|
|
3220
3220
|
)) });
|
|
3221
3221
|
}
|
|
3222
|
-
const
|
|
3222
|
+
const Yr = ["All", "Draft", "Submitted", "Cancelled"], Jr = /* @__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
|
+
]), Zr = /* @__PURE__ */ new Set([
|
|
3230
3230
|
"transaction_date",
|
|
3231
3231
|
"posting_date",
|
|
3232
3232
|
"due_date",
|
|
3233
3233
|
"delivery_date",
|
|
3234
3234
|
"valid_till",
|
|
3235
3235
|
"date"
|
|
3236
|
-
]),
|
|
3236
|
+
]), Tn = {
|
|
3237
3237
|
customer: "customer",
|
|
3238
3238
|
supplier: "supplier",
|
|
3239
3239
|
item_code: "item",
|
|
@@ -3243,13 +3243,13 @@ const Qr = ["All", "Draft", "Submitted", "Cancelled"], Yr = /* @__PURE__ */ new
|
|
|
3243
3243
|
account: "account",
|
|
3244
3244
|
cost_center: "cost-center"
|
|
3245
3245
|
};
|
|
3246
|
-
function
|
|
3246
|
+
function Xr(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
|
|
3252
|
-
function
|
|
3251
|
+
const es = ["25", "50", "100", "200"];
|
|
3252
|
+
function Rn({
|
|
3253
3253
|
page: t,
|
|
3254
3254
|
totalPages: n,
|
|
3255
3255
|
pageSize: a,
|
|
@@ -3288,7 +3288,7 @@ function Tn({
|
|
|
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: es.map((f) => /* @__PURE__ */ e("option", { value: f, children: f }, f))
|
|
3292
3292
|
}
|
|
3293
3293
|
)
|
|
3294
3294
|
] }),
|
|
@@ -3333,8 +3333,8 @@ function Tn({
|
|
|
3333
3333
|
] })
|
|
3334
3334
|
] });
|
|
3335
3335
|
}
|
|
3336
|
-
function
|
|
3337
|
-
const { t } = X(), n = ze(), { doctype: a } =
|
|
3336
|
+
function ts() {
|
|
3337
|
+
const { t } = X(), n = ze(), { doctype: a } = dt(), s = fa(a ?? ""), o = bt(), 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) ?? "";
|
|
3340
3340
|
return V;
|
|
@@ -3352,14 +3352,14 @@ function es() {
|
|
|
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 } = zr(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 });
|
|
3359
3359
|
}, [a, g, o.search]);
|
|
3360
3360
|
const A = Math.max(1, Math.ceil(de / u)), _ = de === 0 ? 0 : S * u + 1, z = Math.min(de, (S + 1) * u), ee = Ne(() => {
|
|
3361
3361
|
if (!s) return [];
|
|
3362
|
-
const P =
|
|
3362
|
+
const P = Zn(), V = (ne) => {
|
|
3363
3363
|
const H = ne.split("_").map((ce) => ce.charAt(0).toUpperCase() + ce.slice(1)).join(" ");
|
|
3364
3364
|
return t(`fields.${H}`, { defaultValue: H });
|
|
3365
3365
|
};
|
|
@@ -3379,9 +3379,9 @@ function es() {
|
|
|
3379
3379
|
if (ne === "status")
|
|
3380
3380
|
return P.accessor("status", {
|
|
3381
3381
|
header: t("fields.Status", { defaultValue: "Status" }),
|
|
3382
|
-
cell: (H) => /* @__PURE__ */ e(
|
|
3382
|
+
cell: (H) => /* @__PURE__ */ e(un, { status: H.getValue() })
|
|
3383
3383
|
});
|
|
3384
|
-
if (
|
|
3384
|
+
if (Jr.has(ne))
|
|
3385
3385
|
return P.accessor(ne, {
|
|
3386
3386
|
header: V(ne),
|
|
3387
3387
|
cell: (H) => {
|
|
@@ -3395,7 +3395,7 @@ function es() {
|
|
|
3395
3395
|
cell: (H) => {
|
|
3396
3396
|
const ce = H.getValue();
|
|
3397
3397
|
if (!ce) return "-";
|
|
3398
|
-
const Se =
|
|
3398
|
+
const Se = Xr(H.row.original.party_type), E = Se ? en(Se, String(ce)) : null;
|
|
3399
3399
|
return E ? /* @__PURE__ */ e(
|
|
3400
3400
|
ve,
|
|
3401
3401
|
{
|
|
@@ -3407,14 +3407,14 @@ function es() {
|
|
|
3407
3407
|
) : String(ce);
|
|
3408
3408
|
}
|
|
3409
3409
|
});
|
|
3410
|
-
if (
|
|
3411
|
-
const H =
|
|
3410
|
+
if (Tn[ne]) {
|
|
3411
|
+
const H = Tn[ne];
|
|
3412
3412
|
return P.accessor(ne, {
|
|
3413
3413
|
header: V(ne),
|
|
3414
3414
|
cell: (ce) => {
|
|
3415
3415
|
const Se = ce.getValue();
|
|
3416
3416
|
if (!Se) return "-";
|
|
3417
|
-
const E =
|
|
3417
|
+
const E = en(H, String(Se));
|
|
3418
3418
|
return E ? /* @__PURE__ */ e(
|
|
3419
3419
|
ve,
|
|
3420
3420
|
{
|
|
@@ -3427,17 +3427,17 @@ function es() {
|
|
|
3427
3427
|
}
|
|
3428
3428
|
});
|
|
3429
3429
|
}
|
|
3430
|
-
return
|
|
3430
|
+
return Zr.has(ne) ? P.accessor(ne, {
|
|
3431
3431
|
header: V(ne),
|
|
3432
3432
|
cell: (H) => Ft(H.getValue())
|
|
3433
3433
|
}) : P.accessor(ne, {
|
|
3434
3434
|
header: V(ne)
|
|
3435
3435
|
});
|
|
3436
3436
|
});
|
|
3437
|
-
}, [s, t, n]), se =
|
|
3437
|
+
}, [s, t, n]), se = Xn({
|
|
3438
3438
|
data: $,
|
|
3439
3439
|
columns: ee,
|
|
3440
|
-
getCoreRowModel:
|
|
3440
|
+
getCoreRowModel: ea()
|
|
3441
3441
|
});
|
|
3442
3442
|
return s ? /* @__PURE__ */ r("div", { className: "space-y-4", children: [
|
|
3443
3443
|
/* @__PURE__ */ e("div", { className: "flex items-center justify-end", children: /* @__PURE__ */ e(ve, { to: `/app/${s.slug}/new`, children: /* @__PURE__ */ e(Q, { children: t("common.new") }) }) }),
|
|
@@ -3457,7 +3457,7 @@ function es() {
|
|
|
3457
3457
|
Ve,
|
|
3458
3458
|
{
|
|
3459
3459
|
label: t("fields.Status", { defaultValue: "Status" }),
|
|
3460
|
-
options:
|
|
3460
|
+
options: Yr.map((P) => ({
|
|
3461
3461
|
value: P,
|
|
3462
3462
|
label: P === "All" ? t("common.all") : t(`status.${P}`, { defaultValue: P })
|
|
3463
3463
|
})),
|
|
@@ -3513,7 +3513,7 @@ function es() {
|
|
|
3513
3513
|
/* @__PURE__ */ e($t, { onSelect: (P, V) => x({ from: P, to: V, page: null }) }),
|
|
3514
3514
|
W ? /* @__PURE__ */ e("p", { className: "text-fg-muted", children: t("common.loading") }) : $.length === 0 ? /* @__PURE__ */ e("p", { className: "py-8 text-center text-fg-muted", children: t("reports.noDocuments") }) : /* @__PURE__ */ r(Ce, { children: [
|
|
3515
3515
|
/* @__PURE__ */ e(
|
|
3516
|
-
|
|
3516
|
+
Rn,
|
|
3517
3517
|
{
|
|
3518
3518
|
page: S,
|
|
3519
3519
|
totalPages: A,
|
|
@@ -3543,7 +3543,7 @@ function es() {
|
|
|
3543
3543
|
) }, V.id)) }, P.id)) })
|
|
3544
3544
|
] }) }),
|
|
3545
3545
|
/* @__PURE__ */ e(
|
|
3546
|
-
|
|
3546
|
+
Rn,
|
|
3547
3547
|
{
|
|
3548
3548
|
page: S,
|
|
3549
3549
|
totalPages: A,
|
|
@@ -3643,7 +3643,7 @@ function Ae({
|
|
|
3643
3643
|
)
|
|
3644
3644
|
}
|
|
3645
3645
|
),
|
|
3646
|
-
d && c.length > 0 &&
|
|
3646
|
+
d && c.length > 0 && ta(
|
|
3647
3647
|
/* @__PURE__ */ e("div", { ref: S, style: v, className: "max-h-48 overflow-y-auto rounded-lg bg-surface ring-1 ring-line shadow-card-hover", children: c.map((g, R) => {
|
|
3648
3648
|
const W = g.name ?? g.id ?? String(g);
|
|
3649
3649
|
return /* @__PURE__ */ e(
|
|
@@ -3669,9 +3669,9 @@ const Tt = () => ({
|
|
|
3669
3669
|
position_title: "",
|
|
3670
3670
|
position_blurb: "",
|
|
3671
3671
|
is_recommended: 0
|
|
3672
|
-
}),
|
|
3673
|
-
function
|
|
3674
|
-
const { name: t } =
|
|
3672
|
+
}), ns = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
3673
|
+
function In() {
|
|
3674
|
+
const { name: t } = dt(), n = !t, a = Ee(), s = He(), { t: o } = X(), i = (A, _) => o(A, { defaultValue: _ }), l = ua(), [c, h] = w({
|
|
3675
3675
|
title: "Offerte",
|
|
3676
3676
|
customer: "",
|
|
3677
3677
|
company: "",
|
|
@@ -3813,7 +3813,7 @@ function Rn() {
|
|
|
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: ns[_] ?? _ + 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,12 +3848,12 @@ function Rn() {
|
|
|
3848
3848
|
] })
|
|
3849
3849
|
] });
|
|
3850
3850
|
}
|
|
3851
|
-
const
|
|
3852
|
-
function
|
|
3851
|
+
const as = ["25", "50", "100", "200"];
|
|
3852
|
+
function rs() {
|
|
3853
3853
|
var y;
|
|
3854
|
-
const { type: t } =
|
|
3854
|
+
const { type: t } = dt(), n = Ee(), a = bt(), s = (y = a.state) == null ? void 0 : y.notice;
|
|
3855
3855
|
re(() => {
|
|
3856
|
-
t &&
|
|
3856
|
+
t && ga(`master:${t}`, { filters: {}, search: a.search });
|
|
3857
3857
|
}, [t, a.search]);
|
|
3858
3858
|
const [o] = le("per_page", 50), [i] = le("page", 1), l = i - 1, c = Ye(), h = (m) => c({ page: m === 0 ? null : m + 1 }), d = (m) => c({ per_page: m, page: null }), { data: p, isLoading: u } = ue({
|
|
3859
3859
|
queryKey: ["masters", t, l, o],
|
|
@@ -3865,7 +3865,7 @@ function as() {
|
|
|
3865
3865
|
enabled: !!t
|
|
3866
3866
|
}), f = (p == null ? void 0 : p.rows) ?? [], v = (p == null ? void 0 : p.total) ?? 0, N = Math.max(1, Math.ceil(v / o)), b = v === 0 ? 0 : l * o + 1, C = Math.min(v, (l + 1) * o), S = Ne(() => {
|
|
3867
3867
|
if (!f || f.length === 0) return [];
|
|
3868
|
-
const m =
|
|
3868
|
+
const m = Zn();
|
|
3869
3869
|
return Object.keys(f[0]).map(
|
|
3870
3870
|
(T) => m.accessor(T, {
|
|
3871
3871
|
header: T.split("_").map((U) => U.charAt(0).toUpperCase() + U.slice(1)).join(" "),
|
|
@@ -3886,10 +3886,10 @@ function as() {
|
|
|
3886
3886
|
}
|
|
3887
3887
|
})
|
|
3888
3888
|
);
|
|
3889
|
-
}, [f, t]), x =
|
|
3889
|
+
}, [f, t]), x = Xn({
|
|
3890
3890
|
data: f,
|
|
3891
3891
|
columns: S,
|
|
3892
|
-
getCoreRowModel:
|
|
3892
|
+
getCoreRowModel: ea()
|
|
3893
3893
|
});
|
|
3894
3894
|
return /* @__PURE__ */ r("div", { className: "space-y-4", children: [
|
|
3895
3895
|
s && /* @__PURE__ */ e("div", { className: "rounded-md bg-amber-50 px-4 py-3 text-sm text-amber-800", children: s }),
|
|
@@ -3941,7 +3941,7 @@ function as() {
|
|
|
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: as.map((m) => /* @__PURE__ */ e("option", { value: m, children: m }, m))
|
|
3945
3945
|
}
|
|
3946
3946
|
)
|
|
3947
3947
|
] }),
|
|
@@ -3975,7 +3975,7 @@ function as() {
|
|
|
3975
3975
|
] })
|
|
3976
3976
|
] });
|
|
3977
3977
|
}
|
|
3978
|
-
const
|
|
3978
|
+
const ss = {
|
|
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,16 +4038,16 @@ const rs = {
|
|
|
4038
4038
|
{ name: "tax_id", label: "Tax ID", type: "text" },
|
|
4039
4039
|
{ name: "iban", label: "IBAN", type: "text" }
|
|
4040
4040
|
]
|
|
4041
|
-
},
|
|
4041
|
+
}, is = {
|
|
4042
4042
|
customer: "Customer",
|
|
4043
4043
|
supplier: "Supplier",
|
|
4044
4044
|
item: "Item",
|
|
4045
4045
|
warehouse: "Warehouse",
|
|
4046
4046
|
company: "Company"
|
|
4047
|
-
},
|
|
4048
|
-
function
|
|
4047
|
+
}, Bn = /* @__PURE__ */ new Set(["customer", "supplier", "item", "warehouse"]);
|
|
4048
|
+
function En() {
|
|
4049
4049
|
var Z;
|
|
4050
|
-
const { type: t, name: n } =
|
|
4050
|
+
const { type: t, name: n } = dt(), a = Ee(), s = He(), { t: o } = X(), i = !n || n === "new", l = is[t ?? ""] ?? t ?? "", c = o(`masters.${t}.one`, { defaultValue: l }), h = ss[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
|
|
@@ -4099,7 +4099,7 @@ function Bn() {
|
|
|
4099
4099
|
if (U.length > 0) return;
|
|
4100
4100
|
const g = t === "company" && !p.name ? { ...p, name: p.company_name } : p;
|
|
4101
4101
|
i ? b.mutate(g) : C.mutate(g);
|
|
4102
|
-
}, y =
|
|
4102
|
+
}, y = ua(), m = async () => {
|
|
4103
4103
|
await y({
|
|
4104
4104
|
title: o("masterForm.deleteConfirm", { label: c }),
|
|
4105
4105
|
confirmLabel: o("common.delete", { defaultValue: "Delete" }),
|
|
@@ -4111,13 +4111,13 @@ function Bn() {
|
|
|
4111
4111
|
if (!i && v)
|
|
4112
4112
|
return /* @__PURE__ */ e("p", { className: "text-fg-muted", children: o("common.loading") });
|
|
4113
4113
|
const T = b.isPending || C.isPending, U = h.filter((g) => {
|
|
4114
|
-
if (!g.required || g.readOnly || i && g.name === "name" &&
|
|
4114
|
+
if (!g.required || g.readOnly || i && g.name === "name" && Bn.has(t ?? "")) return !1;
|
|
4115
4115
|
const R = p[g.name];
|
|
4116
4116
|
return R == null || String(R).trim() === "";
|
|
4117
4117
|
});
|
|
4118
4118
|
return /* @__PURE__ */ r("div", { className: "space-y-6", children: [
|
|
4119
4119
|
/* @__PURE__ */ r("div", { className: "flex items-center justify-between", children: [
|
|
4120
|
-
i ? /* @__PURE__ */ e("div", {}) : /* @__PURE__ */ e(
|
|
4120
|
+
i ? /* @__PURE__ */ e("div", {}) : /* @__PURE__ */ e(ya, { kind: "master", slug: t, name: n, onSave: x }),
|
|
4121
4121
|
/* @__PURE__ */ r("div", { className: "flex gap-2", children: [
|
|
4122
4122
|
/* @__PURE__ */ e(Q, { onClick: x, disabled: T || U.length > 0, children: o(T ? "common.saving" : "common.save") }),
|
|
4123
4123
|
!i && /* @__PURE__ */ e(
|
|
@@ -4135,7 +4135,7 @@ function Bn() {
|
|
|
4135
4135
|
U.length > 0 && /* @__PURE__ */ e("div", { className: "rounded-lg bg-amber-50 p-4 text-sm text-amber-800 ring-1 ring-amber-200", children: o("masterForm.required", { fields: U.map(d).join(", ") }) }),
|
|
4136
4136
|
p.disabled === 1 && /* @__PURE__ */ e("div", { className: "rounded-lg bg-amber-50 p-4 text-sm text-amber-800 ring-1 ring-amber-200", children: o("masterForm.disabledNotice", { label: c }) }),
|
|
4137
4137
|
/* @__PURE__ */ e(M, { children: /* @__PURE__ */ e("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: h.map((g) => {
|
|
4138
|
-
const W = g.name === "name" && !i || g.readOnly, $ = g.required && !(i && g.name === "name" &&
|
|
4138
|
+
const W = g.name === "name" && !i || g.readOnly, $ = g.required && !(i && g.name === "name" && Bn.has(t ?? ""));
|
|
4139
4139
|
if (g.type === "select" && g.options) {
|
|
4140
4140
|
const A = p[g.name], _ = typeof A == "string" && A !== "" && !g.options.includes(A) ? [...g.options, A] : g.options;
|
|
4141
4141
|
return /* @__PURE__ */ e("div", { children: /* @__PURE__ */ e(
|
|
@@ -4187,67 +4187,67 @@ function Bn() {
|
|
|
4187
4187
|
}) }) })
|
|
4188
4188
|
] });
|
|
4189
4189
|
}
|
|
4190
|
-
function
|
|
4190
|
+
function os(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 ls(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 cs(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 ds(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 us(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 ms(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 ps(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 hs(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 gs() {
|
|
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 } = os(v), S = () => {
|
|
4251
4251
|
o({
|
|
4252
4252
|
company: i || null,
|
|
4253
4253
|
from: c || null,
|
|
@@ -4320,8 +4320,8 @@ function hs() {
|
|
|
4320
4320
|
] })
|
|
4321
4321
|
] });
|
|
4322
4322
|
}
|
|
4323
|
-
const
|
|
4324
|
-
function
|
|
4323
|
+
const fs = ["Asset", "Liability", "Equity", "Income", "Expense"];
|
|
4324
|
+
function ys() {
|
|
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 fs() {
|
|
|
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 } = ls(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 fs() {
|
|
|
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 && fs.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 bs(t) {
|
|
4410
4410
|
return t.toLowerCase().replace(/\s+/g, "-");
|
|
4411
4411
|
}
|
|
4412
|
-
const
|
|
4413
|
-
function
|
|
4412
|
+
const vs = ["25", "50", "100", "200"];
|
|
4413
|
+
function xs() {
|
|
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 } = cs(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 vs() {
|
|
|
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/${bs(_.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 vs() {
|
|
|
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: vs.map((_) => /* @__PURE__ */ e("option", { value: _, children: _ }, _))
|
|
4525
4525
|
}
|
|
4526
4526
|
)
|
|
4527
4527
|
] }),
|
|
@@ -4557,11 +4557,11 @@ function vs() {
|
|
|
4557
4557
|
] })
|
|
4558
4558
|
] });
|
|
4559
4559
|
}
|
|
4560
|
-
function
|
|
4560
|
+
function Ns() {
|
|
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 } = ds(p), N = () => {
|
|
4565
4565
|
s({
|
|
4566
4566
|
item_code: o || null,
|
|
4567
4567
|
warehouse: l || null
|
|
@@ -4604,18 +4604,18 @@ function xs() {
|
|
|
4604
4604
|
/* @__PURE__ */ e("td", { className: "px-4 py-2 font-medium text-gray-900", children: b.item_code }),
|
|
4605
4605
|
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-gray-700", children: b.item_name }),
|
|
4606
4606
|
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-gray-700", children: b.warehouse }),
|
|
4607
|
-
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-right", children:
|
|
4607
|
+
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-right", children: Zt(b.actual_qty) }),
|
|
4608
4608
|
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-right", children: d(b.valuation_rate) }),
|
|
4609
4609
|
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-right font-medium", children: d(b.stock_value) })
|
|
4610
4610
|
] }, C)) })
|
|
4611
4611
|
] }) }) })
|
|
4612
4612
|
] });
|
|
4613
4613
|
}
|
|
4614
|
-
function
|
|
4614
|
+
function ws() {
|
|
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 } = us(v), S = () => {
|
|
4619
4619
|
o({
|
|
4620
4620
|
company: i || null,
|
|
4621
4621
|
from: d || null,
|
|
@@ -4675,7 +4675,7 @@ function Ns() {
|
|
|
4675
4675
|
] }) : /* @__PURE__ */ e("p", { className: "py-8 text-center text-gray-400", children: t("reports.noData") })
|
|
4676
4676
|
] });
|
|
4677
4677
|
}
|
|
4678
|
-
function
|
|
4678
|
+
function Wt({ title: t, rows: n, total: a, totalLabel: s, currency: o }) {
|
|
4679
4679
|
const { t: i } = X(), l = (c) => qe(c, o);
|
|
4680
4680
|
return /* @__PURE__ */ r(M, { children: [
|
|
4681
4681
|
/* @__PURE__ */ e("h3", { className: "mb-3 text-base font-semibold text-gray-800", children: t }),
|
|
@@ -4695,12 +4695,12 @@ function Gt({ title: t, rows: n, total: a, totalLabel: s, currency: o }) {
|
|
|
4695
4695
|
] })
|
|
4696
4696
|
] });
|
|
4697
4697
|
}
|
|
4698
|
-
function
|
|
4698
|
+
function ks() {
|
|
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 } = ms(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: [
|
|
@@ -4709,13 +4709,13 @@ function ws() {
|
|
|
4709
4709
|
/* @__PURE__ */ e(te, { label: t("fields.As of Date", { defaultValue: "As of Date" }), type: "date", value: l, onChange: (m) => c(m.target.value) }),
|
|
4710
4710
|
/* @__PURE__ */ e(Q, { onClick: N, children: t("common.apply") })
|
|
4711
4711
|
] }),
|
|
4712
|
-
/* @__PURE__ */ e(
|
|
4712
|
+
/* @__PURE__ */ e(pn, { onSelect: (m) => {
|
|
4713
4713
|
c(m), s({ as_of_date: m });
|
|
4714
4714
|
} }),
|
|
4715
4715
|
f ? /* @__PURE__ */ e("p", { className: "text-gray-500", children: t("common.loading") }) : b ? /* @__PURE__ */ r("div", { className: "space-y-4", children: [
|
|
4716
|
-
/* @__PURE__ */ e(
|
|
4717
|
-
/* @__PURE__ */ e(
|
|
4718
|
-
/* @__PURE__ */ e(
|
|
4716
|
+
/* @__PURE__ */ e(Wt, { title: t("reports.assets"), rows: u.assets || [], total: u.total_assets, totalLabel: t("reports.totalAssets"), currency: h }),
|
|
4717
|
+
/* @__PURE__ */ e(Wt, { title: t("reports.liabilities"), rows: u.liabilities || [], total: u.total_liabilities, totalLabel: t("reports.totalLiabilities"), currency: h }),
|
|
4718
|
+
/* @__PURE__ */ e(Wt, { title: t("reports.equity"), rows: u.equity || [], total: u.total_equity, totalLabel: t("reports.totalEquity"), currency: h }),
|
|
4719
4719
|
/* @__PURE__ */ e(M, { children: /* @__PURE__ */ r("div", { className: "flex items-center justify-between", children: [
|
|
4720
4720
|
/* @__PURE__ */ r("div", { className: "text-sm", children: [
|
|
4721
4721
|
/* @__PURE__ */ r("div", { className: "text-gray-500", children: [
|
|
@@ -4734,11 +4734,11 @@ function ws() {
|
|
|
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 Cs() {
|
|
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 } = ps(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: [
|
|
@@ -4747,7 +4747,7 @@ function ks() {
|
|
|
4747
4747
|
/* @__PURE__ */ e(te, { label: t("fields.As of Date", { defaultValue: "As of Date" }), type: "date", value: l, onChange: (b) => c(b.target.value) }),
|
|
4748
4748
|
/* @__PURE__ */ e(Q, { onClick: N, children: t("common.apply") })
|
|
4749
4749
|
] }),
|
|
4750
|
-
/* @__PURE__ */ e(
|
|
4750
|
+
/* @__PURE__ */ e(pn, { onSelect: (b) => {
|
|
4751
4751
|
c(b), s({ as_of_date: b });
|
|
4752
4752
|
} }),
|
|
4753
4753
|
f ? /* @__PURE__ */ e("p", { className: "text-gray-500", children: t("common.loading") }) : !u || !u.rows || u.rows.length === 0 ? /* @__PURE__ */ e("p", { className: "py-8 text-center text-gray-400", children: t("reports.noReceivables") }) : /* @__PURE__ */ e(M, { children: /* @__PURE__ */ e("div", { className: "overflow-x-auto", children: /* @__PURE__ */ r("table", { className: "min-w-full divide-y divide-gray-200 text-sm", children: [
|
|
@@ -4792,11 +4792,11 @@ function ks() {
|
|
|
4792
4792
|
] }) }) })
|
|
4793
4793
|
] });
|
|
4794
4794
|
}
|
|
4795
|
-
function
|
|
4795
|
+
function Ss() {
|
|
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 } = hs(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: [
|
|
@@ -4805,7 +4805,7 @@ function Cs() {
|
|
|
4805
4805
|
/* @__PURE__ */ e(te, { label: t("fields.As of Date", { defaultValue: "As of Date" }), type: "date", value: l, onChange: (b) => c(b.target.value) }),
|
|
4806
4806
|
/* @__PURE__ */ e(Q, { onClick: N, children: t("common.apply") })
|
|
4807
4807
|
] }),
|
|
4808
|
-
/* @__PURE__ */ e(
|
|
4808
|
+
/* @__PURE__ */ e(pn, { onSelect: (b) => {
|
|
4809
4809
|
c(b), s({ as_of_date: b });
|
|
4810
4810
|
} }),
|
|
4811
4811
|
f ? /* @__PURE__ */ e("p", { className: "text-gray-500", children: t("common.loading") }) : !u || !u.rows || u.rows.length === 0 ? /* @__PURE__ */ e("p", { className: "py-8 text-center text-gray-400", children: t("reports.noPayables") }) : /* @__PURE__ */ e(M, { children: /* @__PURE__ */ e("div", { className: "overflow-x-auto", children: /* @__PURE__ */ r("table", { className: "min-w-full divide-y divide-gray-200 text-sm", children: [
|
|
@@ -4850,11 +4850,11 @@ function Cs() {
|
|
|
4850
4850
|
] }) }) })
|
|
4851
4851
|
] });
|
|
4852
4852
|
}
|
|
4853
|
-
const
|
|
4854
|
-
function
|
|
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 Ds(t) {
|
|
4855
4855
|
let n;
|
|
4856
4856
|
try {
|
|
4857
|
-
if (n =
|
|
4857
|
+
if (n = Ln && (self.URL || self.webkitURL).createObjectURL(Ln), !n) throw "";
|
|
4858
4858
|
const a = new Worker(n, {
|
|
4859
4859
|
name: t == null ? void 0 : t.name
|
|
4860
4860
|
});
|
|
@@ -4863,7 +4863,7 @@ function Ss(t) {
|
|
|
4863
4863
|
}), a;
|
|
4864
4864
|
} catch {
|
|
4865
4865
|
return new Worker(
|
|
4866
|
-
"data:text/javascript;charset=utf-8," + encodeURIComponent(
|
|
4866
|
+
"data:text/javascript;charset=utf-8," + encodeURIComponent(va),
|
|
4867
4867
|
{
|
|
4868
4868
|
name: t == null ? void 0 : t.name
|
|
4869
4869
|
}
|
|
@@ -4872,7 +4872,7 @@ function Ss(t) {
|
|
|
4872
4872
|
n && (self.URL || self.webkitURL).revokeObjectURL(n);
|
|
4873
4873
|
}
|
|
4874
4874
|
}
|
|
4875
|
-
function
|
|
4875
|
+
function As() {
|
|
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
|
|
4947
|
-
function
|
|
4948
|
-
const t = Ee(), { sessions: n, createSession: a } =
|
|
4946
|
+
const xa = As();
|
|
4947
|
+
function Ps() {
|
|
4948
|
+
const t = Ee(), { sessions: n, createSession: a } = ut(), [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(Is({
|
|
4949
4949
|
metric: o,
|
|
4950
4950
|
groupBy: i,
|
|
4951
4951
|
fromDate: l || void 0,
|
|
@@ -4959,7 +4959,7 @@ function As() {
|
|
|
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 Ds();
|
|
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 As() {
|
|
|
4999
4999
|
z = !0;
|
|
5000
5000
|
});
|
|
5001
5001
|
}, [s, W]);
|
|
5002
|
-
const de = !!(!s && W), A = Ne(() =>
|
|
5002
|
+
const de = !!(!s && W), A = Ne(() => Rs(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 As() {
|
|
|
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(_s, { 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,12 +5080,12 @@ function As() {
|
|
|
5080
5080
|
] })
|
|
5081
5081
|
] });
|
|
5082
5082
|
}
|
|
5083
|
-
function
|
|
5083
|
+
function _s({ output: t }) {
|
|
5084
5084
|
var o, i;
|
|
5085
5085
|
const n = ze(), a = (t.tables ?? []).map((l, c) => ({
|
|
5086
5086
|
...l,
|
|
5087
5087
|
id: l.id || `table_${c + 1}`
|
|
5088
|
-
})), s =
|
|
5088
|
+
})), s = Na(a);
|
|
5089
5089
|
return /* @__PURE__ */ r("div", { className: "space-y-4", children: [
|
|
5090
5090
|
/* @__PURE__ */ r(M, { children: [
|
|
5091
5091
|
/* @__PURE__ */ e("div", { className: "flex items-baseline justify-between gap-4", children: /* @__PURE__ */ r("div", { children: [
|
|
@@ -5101,13 +5101,13 @@ function Ps({ 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 = Os(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(
|
|
5108
|
-
/* @__PURE__ */ e(
|
|
5107
|
+
/* @__PURE__ */ e("div", { style: { height: f }, className: "w-full", children: /* @__PURE__ */ e(nr, { width: "100%", height: "100%", children: l.type === "line" ? /* @__PURE__ */ r(ar, { data: d, margin: { top: 10, right: 20, left: 0, bottom: 0 }, children: [
|
|
5108
|
+
/* @__PURE__ */ e(fn, { strokeDasharray: "3 3", stroke: "#f3f4f6" }),
|
|
5109
5109
|
/* @__PURE__ */ e(
|
|
5110
|
-
|
|
5110
|
+
yn,
|
|
5111
5111
|
{
|
|
5112
5112
|
dataKey: l.x,
|
|
5113
5113
|
tick: { fill: "#6b7280", fontSize: 12 },
|
|
@@ -5117,16 +5117,16 @@ function Ps({ output: t }) {
|
|
|
5117
5117
|
height: u.axisHeight
|
|
5118
5118
|
}
|
|
5119
5119
|
),
|
|
5120
|
-
/* @__PURE__ */ e(
|
|
5121
|
-
/* @__PURE__ */ e(
|
|
5122
|
-
/* @__PURE__ */ e(
|
|
5123
|
-
] }) : l.type === "pie" ? /* @__PURE__ */ r(
|
|
5124
|
-
/* @__PURE__ */ e(
|
|
5125
|
-
/* @__PURE__ */ e(
|
|
5126
|
-
] }) : /* @__PURE__ */ r(
|
|
5127
|
-
/* @__PURE__ */ e(
|
|
5120
|
+
/* @__PURE__ */ e(bn, { tick: { fill: "#6b7280", fontSize: 12 }, tickFormatter: On }),
|
|
5121
|
+
/* @__PURE__ */ e(Kt, { formatter: (v) => Ct(v, Ht(h, l.y), n) }),
|
|
5122
|
+
/* @__PURE__ */ e(rr, { type: "monotone", dataKey: l.y, stroke: "#3b82f6", strokeWidth: 2, dot: { r: 3 } })
|
|
5123
|
+
] }) : l.type === "pie" ? /* @__PURE__ */ r(sr, { children: [
|
|
5124
|
+
/* @__PURE__ */ e(Kt, { formatter: (v) => Ct(v, Ht(h, l.y), n) }),
|
|
5125
|
+
/* @__PURE__ */ e(ir, { data: d, dataKey: l.y, nameKey: l.x, outerRadius: 110, children: d.map((v, N) => /* @__PURE__ */ e(or, { fill: qn[N % qn.length] }, N)) })
|
|
5126
|
+
] }) : /* @__PURE__ */ r(lr, { data: d, margin: { top: 10, right: 20, left: 0, bottom: 0 }, children: [
|
|
5127
|
+
/* @__PURE__ */ e(fn, { strokeDasharray: "3 3", stroke: "#f3f4f6" }),
|
|
5128
5128
|
/* @__PURE__ */ e(
|
|
5129
|
-
|
|
5129
|
+
yn,
|
|
5130
5130
|
{
|
|
5131
5131
|
dataKey: l.x,
|
|
5132
5132
|
tick: { fill: "#6b7280", fontSize: 12 },
|
|
@@ -5136,9 +5136,9 @@ function Ps({ output: t }) {
|
|
|
5136
5136
|
height: u.axisHeight
|
|
5137
5137
|
}
|
|
5138
5138
|
),
|
|
5139
|
-
/* @__PURE__ */ e(
|
|
5140
|
-
/* @__PURE__ */ e(
|
|
5141
|
-
/* @__PURE__ */ e(
|
|
5139
|
+
/* @__PURE__ */ e(bn, { tick: { fill: "#6b7280", fontSize: 12 }, tickFormatter: On }),
|
|
5140
|
+
/* @__PURE__ */ e(Kt, { formatter: (v) => Ct(v, Ht(h, l.y), n) }),
|
|
5141
|
+
/* @__PURE__ */ e(cr, { dataKey: l.y, fill: "#3b82f6", radius: [4, 4, 0, 0] })
|
|
5142
5142
|
] }) }) })
|
|
5143
5143
|
] }, l.id || `chart_${c + 1}`);
|
|
5144
5144
|
}),
|
|
@@ -5148,21 +5148,21 @@ function Ps({ output: t }) {
|
|
|
5148
5148
|
] }) }) }, l.id))
|
|
5149
5149
|
] });
|
|
5150
5150
|
}
|
|
5151
|
-
function
|
|
5151
|
+
function Ts(t) {
|
|
5152
5152
|
return t.replace(/_/g, " ").replace(/\b\w/g, (n) => n.toUpperCase());
|
|
5153
5153
|
}
|
|
5154
|
-
function
|
|
5154
|
+
function Na(t) {
|
|
5155
5155
|
const n = /* @__PURE__ */ new Map();
|
|
5156
5156
|
for (const a of 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 Rs(t) {
|
|
5161
5161
|
if (!t) return [];
|
|
5162
5162
|
const n = (t.tables ?? []).map((o, i) => ({
|
|
5163
5163
|
...o,
|
|
5164
5164
|
id: o.id || `table_${i + 1}`
|
|
5165
|
-
})), a =
|
|
5165
|
+
})), a = Na(n), s = [];
|
|
5166
5166
|
for (const o of t.charts ?? []) {
|
|
5167
5167
|
const i = o.dataTable ? a.get(o.dataTable) : void 0, l = o.data ?? (i == null ? void 0 : i.rows) ?? [];
|
|
5168
5168
|
if (!l.length) {
|
|
@@ -5173,10 +5173,10 @@ function Ts(t) {
|
|
|
5173
5173
|
}
|
|
5174
5174
|
return s;
|
|
5175
5175
|
}
|
|
5176
|
-
function
|
|
5177
|
-
const n = `${
|
|
5176
|
+
function Is(t) {
|
|
5177
|
+
const n = `${Bs(t.metric)} by ${Ts(t.groupBy)}`, a = t.groupBy === "month" ? "helpers.monthKey" : t.groupBy === "quarter" ? "helpers.quarterKey" : "helpers.yearKey";
|
|
5178
5178
|
if (t.metric === "sales_revenue")
|
|
5179
|
-
return
|
|
5179
|
+
return yt({
|
|
5180
5180
|
title: n,
|
|
5181
5181
|
dataset: t.groupBy === "item" ? "sales_invoice_lines" : "sales_invoices",
|
|
5182
5182
|
requestName: "rows",
|
|
@@ -5193,7 +5193,7 @@ function Rs(t) {
|
|
|
5193
5193
|
chartType: t.groupBy === "customer" || t.groupBy === "item" ? "bar" : "line"
|
|
5194
5194
|
});
|
|
5195
5195
|
if (t.metric === "sales_returns")
|
|
5196
|
-
return
|
|
5196
|
+
return yt({
|
|
5197
5197
|
title: n,
|
|
5198
5198
|
dataset: "sales_invoices",
|
|
5199
5199
|
requestName: "rows",
|
|
@@ -5210,7 +5210,7 @@ function Rs(t) {
|
|
|
5210
5210
|
chartType: t.groupBy === "customer" ? "bar" : "line"
|
|
5211
5211
|
});
|
|
5212
5212
|
if (t.metric === "purchases")
|
|
5213
|
-
return
|
|
5213
|
+
return yt({
|
|
5214
5214
|
title: n,
|
|
5215
5215
|
dataset: t.groupBy === "item" ? "purchase_invoice_lines" : "purchase_invoices",
|
|
5216
5216
|
requestName: "rows",
|
|
@@ -5228,7 +5228,7 @@ function Rs(t) {
|
|
|
5228
5228
|
});
|
|
5229
5229
|
if (t.metric === "payments_received" || t.metric === "payments_made") {
|
|
5230
5230
|
const s = t.metric === "payments_received";
|
|
5231
|
-
return
|
|
5231
|
+
return yt({
|
|
5232
5232
|
title: n,
|
|
5233
5233
|
dataset: "payments",
|
|
5234
5234
|
requestName: "rows",
|
|
@@ -5248,7 +5248,7 @@ function Rs(t) {
|
|
|
5248
5248
|
}
|
|
5249
5249
|
if (t.metric === "outstanding_ar" || t.metric === "outstanding_ap") {
|
|
5250
5250
|
const s = t.metric === "outstanding_ar", o = s ? "ar_open_items" : "ap_open_items", i = s ? "customer" : "supplier", l = "outstanding_amount";
|
|
5251
|
-
return
|
|
5251
|
+
return yt({
|
|
5252
5252
|
title: n,
|
|
5253
5253
|
dataset: o,
|
|
5254
5254
|
requestName: "rows",
|
|
@@ -5264,7 +5264,7 @@ function Rs(t) {
|
|
|
5264
5264
|
chartType: "bar"
|
|
5265
5265
|
});
|
|
5266
5266
|
}
|
|
5267
|
-
return t.metric === "stock_value" ?
|
|
5267
|
+
return t.metric === "stock_value" ? yt({
|
|
5268
5268
|
title: n,
|
|
5269
5269
|
dataset: "stock_balances",
|
|
5270
5270
|
requestName: "rows",
|
|
@@ -5277,9 +5277,9 @@ function Rs(t) {
|
|
|
5277
5277
|
},
|
|
5278
5278
|
fields: [t.groupBy === "warehouse" ? "warehouse" : "item_code", "stock_value"],
|
|
5279
5279
|
chartType: "bar"
|
|
5280
|
-
}) : JSON.parse(
|
|
5280
|
+
}) : JSON.parse(xa);
|
|
5281
5281
|
}
|
|
5282
|
-
function
|
|
5282
|
+
function yt(t) {
|
|
5283
5283
|
const n = Object.fromEntries(Object.entries(t.filters).filter(([, s]) => s !== void 0)), a = ["month", "quarter", "year"].includes(t.groupBy) ? `${t.timeBucket}(row.${t.keyField})` : `row.${t.keyField} || "—"`;
|
|
5284
5284
|
return {
|
|
5285
5285
|
title: t.title,
|
|
@@ -5333,7 +5333,7 @@ return {
|
|
|
5333
5333
|
};`
|
|
5334
5334
|
};
|
|
5335
5335
|
}
|
|
5336
|
-
function
|
|
5336
|
+
function Bs(t) {
|
|
5337
5337
|
return {
|
|
5338
5338
|
sales_revenue: "Sales Revenue",
|
|
5339
5339
|
sales_returns: "Sales Returns",
|
|
@@ -5345,35 +5345,35 @@ function Is(t) {
|
|
|
5345
5345
|
stock_value: "Stock Value"
|
|
5346
5346
|
}[t] || "Analytics";
|
|
5347
5347
|
}
|
|
5348
|
-
function
|
|
5348
|
+
function Ht(t, n) {
|
|
5349
5349
|
var a, s;
|
|
5350
5350
|
return ((a = t == null ? void 0 : t.columns.find((o) => o.key === n)) == null ? void 0 : a.type) || ((s = t == null ? void 0 : t.columns.find((o) => o.key === n)) == null ? void 0 : s.format);
|
|
5351
5351
|
}
|
|
5352
5352
|
function Ct(t, n, a) {
|
|
5353
|
-
return n === "currency" ? qe($e(t), a) : n === "percent" ? `${($e(t) * 100).toFixed(1)}%` : n === "number" ?
|
|
5353
|
+
return n === "currency" ? qe($e(t), a) : n === "percent" ? `${($e(t) * 100).toFixed(1)}%` : n === "number" ? Zt($e(t)) : n === "date" ? Ft(String(t ?? "")) : typeof t == "number" ? Zt(t) : String(t ?? "");
|
|
5354
5354
|
}
|
|
5355
|
-
function
|
|
5355
|
+
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
|
|
5360
|
-
let
|
|
5361
|
-
function
|
|
5359
|
+
const qn = ["#3b82f6", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6", "#06b6d4"], Es = '12px -apple-system, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
|
|
5360
|
+
let Qt = null;
|
|
5361
|
+
function Ls(t, n = Es) {
|
|
5362
5362
|
if (typeof document > "u") return t.length * 7;
|
|
5363
|
-
|
|
5364
|
-
const a =
|
|
5363
|
+
Qt || (Qt = document.createElement("canvas"));
|
|
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 Os(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) => Ls(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 qs = ["USD", "EUR", "GBP", "CHF", "JPY", "CAD", "AUD", "CNY", "INR"];
|
|
5376
|
+
function zs() {
|
|
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 qs() {
|
|
|
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(Ms, { 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 qs() {
|
|
|
5441
5441
|
Ve,
|
|
5442
5442
|
{
|
|
5443
5443
|
label: "Currency",
|
|
5444
|
-
options:
|
|
5444
|
+
options: qs,
|
|
5445
5445
|
value: i,
|
|
5446
5446
|
onChange: (T) => l(T.target.value)
|
|
5447
5447
|
}
|
|
@@ -5536,7 +5536,7 @@ function qs() {
|
|
|
5536
5536
|
] }) })
|
|
5537
5537
|
] });
|
|
5538
5538
|
}
|
|
5539
|
-
function
|
|
5539
|
+
function Ms({ 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 zs({ 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 Fs = [
|
|
5581
5581
|
{
|
|
5582
5582
|
number: 1,
|
|
5583
5583
|
title: "Set Up Your Company",
|
|
@@ -5714,8 +5714,8 @@ const Ms = [
|
|
|
5714
5714
|
]
|
|
5715
5715
|
}
|
|
5716
5716
|
];
|
|
5717
|
-
function
|
|
5718
|
-
const t = Ee(), { sessions: n, createSession: a } =
|
|
5717
|
+
function wa() {
|
|
5718
|
+
const t = Ee(), { sessions: n, createSession: a } = ut();
|
|
5719
5719
|
return async (s) => {
|
|
5720
5720
|
var i;
|
|
5721
5721
|
let o = ((i = n[0]) == null ? void 0 : i.id) || "";
|
|
@@ -5729,8 +5729,8 @@ function Na() {
|
|
|
5729
5729
|
t(`/chat/${o}`, { state: { prefillMessage: s } });
|
|
5730
5730
|
};
|
|
5731
5731
|
}
|
|
5732
|
-
function
|
|
5733
|
-
const { t } = X(), n =
|
|
5732
|
+
function $s() {
|
|
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: "▶" }),
|
|
5736
5736
|
/* @__PURE__ */ r("div", { className: "flex-1 space-y-3", children: [
|
|
@@ -5765,8 +5765,8 @@ function Fs() {
|
|
|
5765
5765
|
] })
|
|
5766
5766
|
] }) });
|
|
5767
5767
|
}
|
|
5768
|
-
function
|
|
5769
|
-
const { t } = X(), n =
|
|
5768
|
+
function Us() {
|
|
5769
|
+
const { t } = X(), n = wa(), a = [
|
|
5770
5770
|
t("tutorial.caPrompt1"),
|
|
5771
5771
|
t("tutorial.caPrompt2"),
|
|
5772
5772
|
t("tutorial.caPrompt3"),
|
|
@@ -5824,7 +5824,7 @@ function $s() {
|
|
|
5824
5824
|
] })
|
|
5825
5825
|
] }) });
|
|
5826
5826
|
}
|
|
5827
|
-
function
|
|
5827
|
+
function Vs() {
|
|
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 Us() {
|
|
|
5895
5895
|
] })
|
|
5896
5896
|
] });
|
|
5897
5897
|
}
|
|
5898
|
-
function
|
|
5898
|
+
function Ks() {
|
|
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 Vs() {
|
|
|
5931
5931
|
] })
|
|
5932
5932
|
] });
|
|
5933
5933
|
}
|
|
5934
|
-
function
|
|
5934
|
+
function js() {
|
|
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 Ks() {
|
|
|
5955
5955
|
] }),
|
|
5956
5956
|
/* @__PURE__ */ e("p", { className: "mt-4 text-sm text-gray-500", children: t("tutorial.manualIntro") })
|
|
5957
5957
|
] }),
|
|
5958
|
-
/* @__PURE__ */ e(Fs, {}),
|
|
5959
5958
|
/* @__PURE__ */ e($s, {}),
|
|
5960
5959
|
/* @__PURE__ */ e(Us, {}),
|
|
5961
5960
|
/* @__PURE__ */ e(Vs, {}),
|
|
5962
|
-
|
|
5961
|
+
/* @__PURE__ */ e(Ks, {}),
|
|
5962
|
+
Fs.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,17 +6020,59 @@ function Ks() {
|
|
|
6020
6020
|
] }) })
|
|
6021
6021
|
] });
|
|
6022
6022
|
}
|
|
6023
|
-
const
|
|
6023
|
+
const Yt = 5, Gs = 10 * 1024 * 1024, Ws = /* @__PURE__ */ new Set([
|
|
6024
6024
|
"image/png",
|
|
6025
6025
|
"image/jpeg",
|
|
6026
6026
|
"image/gif",
|
|
6027
6027
|
"image/webp",
|
|
6028
|
-
"application/pdf"
|
|
6028
|
+
"application/pdf",
|
|
6029
|
+
// Spreadsheets
|
|
6030
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
6031
|
+
// xlsx
|
|
6032
|
+
"application/vnd.ms-excel",
|
|
6033
|
+
// xls
|
|
6034
|
+
"application/vnd.oasis.opendocument.spreadsheet",
|
|
6035
|
+
// ods
|
|
6036
|
+
// Documents
|
|
6037
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
6038
|
+
// docx
|
|
6039
|
+
"application/msword",
|
|
6040
|
+
// doc
|
|
6041
|
+
"application/vnd.oasis.opendocument.text",
|
|
6042
|
+
// odt
|
|
6043
|
+
// Presentations
|
|
6044
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
6045
|
+
// pptx
|
|
6046
|
+
"application/vnd.ms-powerpoint",
|
|
6047
|
+
// ppt
|
|
6048
|
+
"application/vnd.oasis.opendocument.presentation",
|
|
6049
|
+
// odp
|
|
6050
|
+
// Delimited / text
|
|
6051
|
+
"text/csv",
|
|
6052
|
+
"text/plain"
|
|
6053
|
+
]), Hs = /* @__PURE__ */ new Set([
|
|
6054
|
+
"png",
|
|
6055
|
+
"jpg",
|
|
6056
|
+
"jpeg",
|
|
6057
|
+
"gif",
|
|
6058
|
+
"webp",
|
|
6059
|
+
"pdf",
|
|
6060
|
+
"xlsx",
|
|
6061
|
+
"xls",
|
|
6062
|
+
"ods",
|
|
6063
|
+
"docx",
|
|
6064
|
+
"doc",
|
|
6065
|
+
"odt",
|
|
6066
|
+
"pptx",
|
|
6067
|
+
"ppt",
|
|
6068
|
+
"odp",
|
|
6069
|
+
"csv",
|
|
6070
|
+
"txt"
|
|
6029
6071
|
]);
|
|
6030
|
-
function
|
|
6072
|
+
function Qs(t) {
|
|
6031
6073
|
return new Promise((n) => window.setTimeout(n, t));
|
|
6032
6074
|
}
|
|
6033
|
-
function
|
|
6075
|
+
function Ys(t) {
|
|
6034
6076
|
return new Promise((n, a) => {
|
|
6035
6077
|
const s = new FileReader();
|
|
6036
6078
|
s.onloadend = () => {
|
|
@@ -6039,14 +6081,14 @@ function Hs(t) {
|
|
|
6039
6081
|
}, s.onerror = () => a(s.error ?? new Error("Could not read audio.")), s.readAsDataURL(t);
|
|
6040
6082
|
});
|
|
6041
6083
|
}
|
|
6042
|
-
function
|
|
6084
|
+
function zn(t) {
|
|
6043
6085
|
if (!t) return "";
|
|
6044
6086
|
const n = new Date(t);
|
|
6045
6087
|
if (isNaN(n.getTime())) return "";
|
|
6046
6088
|
const a = /* @__PURE__ */ new Date();
|
|
6047
6089
|
return n.getFullYear() === a.getFullYear() && n.getMonth() === a.getMonth() && n.getDate() === a.getDate() ? n.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) : n.getFullYear() === a.getFullYear() ? n.toLocaleDateString([], { day: "numeric", month: "short" }) : n.toLocaleDateString([], { day: "numeric", month: "short", year: "numeric" });
|
|
6048
6090
|
}
|
|
6049
|
-
function
|
|
6091
|
+
function Mn(t) {
|
|
6050
6092
|
if (!t) return "";
|
|
6051
6093
|
const n = new Date(t);
|
|
6052
6094
|
return isNaN(n.getTime()) ? "" : n.toLocaleString([], {
|
|
@@ -6059,8 +6101,8 @@ function zn(t) {
|
|
|
6059
6101
|
timeZoneName: "short"
|
|
6060
6102
|
});
|
|
6061
6103
|
}
|
|
6062
|
-
function
|
|
6063
|
-
const { t } = X(), { sessionId: n } =
|
|
6104
|
+
function Fn() {
|
|
6105
|
+
const { t } = X(), { sessionId: n } = dt(), a = Ee(), s = bt(), [o] = zt(), i = o.get("demo") === "1", [l, c] = w(""), [h, d] = w(""), [p, u] = w([]), [f, v] = w(""), [N, b] = w(!1), [C, S] = w("idle"), x = oe(null), y = oe(null), m = oe([]), {
|
|
6064
6106
|
connectionStatus: D,
|
|
6065
6107
|
connectionVersion: T,
|
|
6066
6108
|
createSession: U,
|
|
@@ -6076,9 +6118,9 @@ function Mn() {
|
|
|
6076
6118
|
isThinking: ee,
|
|
6077
6119
|
getDemoStatus: se,
|
|
6078
6120
|
getDemoTypingCue: P
|
|
6079
|
-
} =
|
|
6080
|
-
|
|
6081
|
-
|
|
6121
|
+
} = ut(), V = oe(null), ne = oe(null), H = oe(null), ce = oe(null), [Se, E] = w(0), ie = oe(!1), Le = oe(null), Te = oe(0), Ke = oe(!0), Fe = oe(null), vt = oe(!1), mt = oe(null), Je = A(n), De = D === "connected", Ie = ee(n), je = se(n), Qe = P(n), Oe = i || je === "running", pt = _(n), it = z(n), ht = Je[Je.length - 1], B = ht ? `${ht.type}:${ht.timestamp || ""}:${ht.content}` : "empty", K = Pe(() => {
|
|
6122
|
+
vt.current = !0, mt.current !== null && window.clearTimeout(mt.current), mt.current = window.setTimeout(() => {
|
|
6123
|
+
vt.current = !1, mt.current = null;
|
|
6082
6124
|
}, 600);
|
|
6083
6125
|
}, []), Y = Pe((k = "smooth") => {
|
|
6084
6126
|
const F = V.current;
|
|
@@ -6090,7 +6132,7 @@ function Mn() {
|
|
|
6090
6132
|
};
|
|
6091
6133
|
requestAnimationFrame(ae), window.setTimeout(ae, 120);
|
|
6092
6134
|
}, [Oe, Ie, K]);
|
|
6093
|
-
|
|
6135
|
+
hn(() => {
|
|
6094
6136
|
const k = V.current, F = Fe.current;
|
|
6095
6137
|
if (!k || F === null) return;
|
|
6096
6138
|
const ae = k.scrollHeight - F;
|
|
@@ -6103,29 +6145,29 @@ function Mn() {
|
|
|
6103
6145
|
let F = 0;
|
|
6104
6146
|
const ae = new ResizeObserver(() => {
|
|
6105
6147
|
Fe.current === null && (!Ke.current && !Oe && !Ie || (cancelAnimationFrame(F), F = requestAnimationFrame(() => {
|
|
6106
|
-
const
|
|
6107
|
-
if (!
|
|
6108
|
-
|
|
6148
|
+
const fe = V.current;
|
|
6149
|
+
if (!fe) return;
|
|
6150
|
+
fe.scrollHeight - fe.scrollTop - fe.clientHeight <= 120 && (K(), fe.scrollTo({ top: fe.scrollHeight, behavior: "auto" }));
|
|
6109
6151
|
})));
|
|
6110
6152
|
}), he = k.firstElementChild;
|
|
6111
6153
|
return he && ae.observe(he), ae.observe(k), () => {
|
|
6112
6154
|
ae.disconnect(), cancelAnimationFrame(F);
|
|
6113
6155
|
};
|
|
6114
|
-
}, [Oe, Ie, K]),
|
|
6156
|
+
}, [Oe, Ie, K]), hn(() => {
|
|
6115
6157
|
const k = ce.current;
|
|
6116
6158
|
if (!k || (E(k.offsetHeight), typeof ResizeObserver > "u")) return;
|
|
6117
6159
|
const F = new ResizeObserver(() => E(k.offsetHeight));
|
|
6118
6160
|
return F.observe(k), () => F.disconnect();
|
|
6119
6161
|
}, []);
|
|
6120
6162
|
const xe = Pe(() => {
|
|
6121
|
-
if (!n || it || !
|
|
6163
|
+
if (!n || it || !pt) return;
|
|
6122
6164
|
const k = V.current;
|
|
6123
6165
|
Fe.current = k ? k.scrollHeight : null, Ke.current = !1, W(n).catch(() => {
|
|
6124
6166
|
Fe.current = null;
|
|
6125
6167
|
});
|
|
6126
|
-
}, [n, it,
|
|
6168
|
+
}, [n, it, pt, W]), we = oe(null);
|
|
6127
6169
|
re(() => {
|
|
6128
|
-
d(""), Le.current = null, Te.current += 1, n &&
|
|
6170
|
+
d(""), Le.current = null, Te.current += 1, n && oa(n);
|
|
6129
6171
|
const k = s.state;
|
|
6130
6172
|
k != null && k.prefillMessage && we.current !== k ? (we.current = k, c(k.prefillMessage), window.setTimeout(() => {
|
|
6131
6173
|
var F;
|
|
@@ -6154,7 +6196,7 @@ function Mn() {
|
|
|
6154
6196
|
}, 50), ie.current = Ie;
|
|
6155
6197
|
}, [Ie, De]);
|
|
6156
6198
|
function ot(k) {
|
|
6157
|
-
if (
|
|
6199
|
+
if (vt.current) return;
|
|
6158
6200
|
const F = k.currentTarget, ae = F.scrollHeight - F.scrollTop - F.clientHeight;
|
|
6159
6201
|
Ke.current = ae < 80;
|
|
6160
6202
|
}
|
|
@@ -6173,50 +6215,51 @@ function Mn() {
|
|
|
6173
6215
|
re(() => {
|
|
6174
6216
|
if (!Qe || !n || Ze.current === Qe.seq) return;
|
|
6175
6217
|
Ze.current = Qe.seq;
|
|
6176
|
-
const k = n, F = Qe.content, ae = F.length > 0 ? Math.max(8, Qe.typingMs / F.length) : 0, he = Qe.seq,
|
|
6177
|
-
async function
|
|
6218
|
+
const k = n, F = Qe.content, ae = F.length > 0 ? Math.max(8, Qe.typingMs / F.length) : 0, he = Qe.seq, fe = ++Te.current;
|
|
6219
|
+
async function ft() {
|
|
6178
6220
|
c("");
|
|
6179
|
-
for (const
|
|
6180
|
-
if (
|
|
6181
|
-
c((Ge) => Ge +
|
|
6221
|
+
for (const et of F) {
|
|
6222
|
+
if (fe !== Te.current) return;
|
|
6223
|
+
c((Ge) => Ge + et), await Qs(ae);
|
|
6182
6224
|
}
|
|
6183
|
-
|
|
6225
|
+
fe === Te.current && j.current(k, he);
|
|
6184
6226
|
}
|
|
6185
|
-
|
|
6227
|
+
ft();
|
|
6186
6228
|
}, [Qe, n]), re(() => {
|
|
6187
6229
|
je === "complete" && (Te.current += 1, c(""));
|
|
6188
6230
|
}, [je]);
|
|
6189
|
-
const
|
|
6231
|
+
const ye = Pe((k) => {
|
|
6190
6232
|
if (!n) return;
|
|
6191
6233
|
v("");
|
|
6192
6234
|
const F = Array.from(k);
|
|
6193
6235
|
u((ae) => {
|
|
6194
6236
|
const he = [...ae];
|
|
6195
|
-
for (const
|
|
6196
|
-
if (he.length >=
|
|
6197
|
-
v(`Maximum ${
|
|
6237
|
+
for (const fe of F) {
|
|
6238
|
+
if (he.length >= Yt) {
|
|
6239
|
+
v(`Maximum ${Yt} attachments per message.`);
|
|
6198
6240
|
break;
|
|
6199
6241
|
}
|
|
6200
|
-
|
|
6201
|
-
|
|
6242
|
+
const ft = fe.name.includes(".") ? fe.name.split(".").pop().toLowerCase() : "";
|
|
6243
|
+
if (!Ws.has(fe.type) && !Hs.has(ft)) {
|
|
6244
|
+
v(`Unsupported file type: ${fe.type || fe.name}`);
|
|
6202
6245
|
continue;
|
|
6203
6246
|
}
|
|
6204
|
-
if (
|
|
6205
|
-
v(`"${
|
|
6247
|
+
if (fe.size > Gs) {
|
|
6248
|
+
v(`"${fe.name}" is too large (max 10 MB).`);
|
|
6206
6249
|
continue;
|
|
6207
6250
|
}
|
|
6208
|
-
const et = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
6209
|
-
he.push(
|
|
6251
|
+
const et = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`, Ge = fe.type.startsWith("image/") ? URL.createObjectURL(fe) : void 0, Ut = { localId: et, file: fe, previewUrl: Ge, uploading: !0 };
|
|
6252
|
+
he.push(Ut), I.uploadChatAttachment(n, fe).then((Nt) => {
|
|
6210
6253
|
u(
|
|
6211
6254
|
(At) => At.map(
|
|
6212
|
-
(wt) => wt.localId === et ? { ...wt, uploading: !1, uploadedId:
|
|
6255
|
+
(wt) => wt.localId === et ? { ...wt, uploading: !1, uploadedId: Nt.id } : wt
|
|
6213
6256
|
)
|
|
6214
6257
|
);
|
|
6215
|
-
}).catch((
|
|
6216
|
-
const At = (
|
|
6217
|
-
v(`"${
|
|
6258
|
+
}).catch((Nt) => {
|
|
6259
|
+
const At = (Nt == null ? void 0 : Nt.message) || "Upload failed";
|
|
6260
|
+
v(`"${fe.name}": ${At}`), u(
|
|
6218
6261
|
(wt) => wt.map(
|
|
6219
|
-
(
|
|
6262
|
+
(Vt) => Vt.localId === et ? { ...Vt, uploading: !1, error: At } : Vt
|
|
6220
6263
|
)
|
|
6221
6264
|
);
|
|
6222
6265
|
});
|
|
@@ -6234,7 +6277,7 @@ function Mn() {
|
|
|
6234
6277
|
const F = k.relatedTarget;
|
|
6235
6278
|
(!F || !k.currentTarget.contains(F)) && b(!1);
|
|
6236
6279
|
}, J = (k) => {
|
|
6237
|
-
k.preventDefault(), b(!1), k.dataTransfer.files && k.dataTransfer.files.length > 0 &&
|
|
6280
|
+
k.preventDefault(), b(!1), k.dataTransfer.files && k.dataTransfer.files.length > 0 && ye(k.dataTransfer.files);
|
|
6238
6281
|
}, Me = (k) => {
|
|
6239
6282
|
const F = [];
|
|
6240
6283
|
for (const ae of k.clipboardData.items)
|
|
@@ -6242,9 +6285,9 @@ function Mn() {
|
|
|
6242
6285
|
const he = ae.getAsFile();
|
|
6243
6286
|
he && F.push(he);
|
|
6244
6287
|
}
|
|
6245
|
-
F.length > 0 && (k.preventDefault(),
|
|
6288
|
+
F.length > 0 && (k.preventDefault(), ye(F));
|
|
6246
6289
|
}, ke = p.some((k) => k.uploading), pe = p.some((k) => k.error), ge = p.filter((k) => k.uploadedId && !k.error).map((k) => k.uploadedId);
|
|
6247
|
-
function
|
|
6290
|
+
function gt() {
|
|
6248
6291
|
const k = l.trim();
|
|
6249
6292
|
if (n && !(!k && ge.length === 0) && !ke && $(n, k, ge.length > 0 ? ge : void 0)) {
|
|
6250
6293
|
for (const F of p)
|
|
@@ -6252,8 +6295,8 @@ function Mn() {
|
|
|
6252
6295
|
u([]), v(""), c("");
|
|
6253
6296
|
}
|
|
6254
6297
|
}
|
|
6255
|
-
function
|
|
6256
|
-
k.key === "Enter" && !k.shiftKey && (k.preventDefault(),
|
|
6298
|
+
function xt(k) {
|
|
6299
|
+
k.key === "Enter" && !k.shiftKey && (k.preventDefault(), gt());
|
|
6257
6300
|
}
|
|
6258
6301
|
function Xe(k) {
|
|
6259
6302
|
const F = k.trim();
|
|
@@ -6262,7 +6305,7 @@ function Mn() {
|
|
|
6262
6305
|
ae && (ae.focus(), ae.style.height = "auto", ae.style.height = Math.min(Math.max(ae.scrollHeight, 48), 120) + "px");
|
|
6263
6306
|
}, 0));
|
|
6264
6307
|
}
|
|
6265
|
-
async function
|
|
6308
|
+
async function Ta() {
|
|
6266
6309
|
if (C !== "idle") return;
|
|
6267
6310
|
let k;
|
|
6268
6311
|
try {
|
|
@@ -6276,18 +6319,18 @@ function Mn() {
|
|
|
6276
6319
|
y.current = F, m.current = [], F.ondataavailable = (ae) => {
|
|
6277
6320
|
ae.data.size > 0 && m.current.push(ae.data);
|
|
6278
6321
|
}, F.onstop = async () => {
|
|
6279
|
-
var
|
|
6322
|
+
var et;
|
|
6280
6323
|
k.getTracks().forEach((Ge) => Ge.stop());
|
|
6281
6324
|
const ae = m.current;
|
|
6282
6325
|
if (m.current = [], y.current = null, ae.length === 0) {
|
|
6283
6326
|
S("idle");
|
|
6284
6327
|
return;
|
|
6285
6328
|
}
|
|
6286
|
-
const he = F.mimeType || ((
|
|
6329
|
+
const he = F.mimeType || ((et = ae[0]) == null ? void 0 : et.type) || "audio/webm", fe = new Blob(ae, { type: he }), ft = (he.split(";")[0].split("/")[1] || "webm").toLowerCase();
|
|
6287
6330
|
S("transcribing");
|
|
6288
6331
|
try {
|
|
6289
|
-
const Ge = await
|
|
6290
|
-
Xe(
|
|
6332
|
+
const Ge = await Ys(fe), Ut = await de(Ge, ft, n);
|
|
6333
|
+
Xe(Ut);
|
|
6291
6334
|
} catch (Ge) {
|
|
6292
6335
|
v(Ge instanceof Error ? Ge.message : t("chat.transcribeFailed"));
|
|
6293
6336
|
} finally {
|
|
@@ -6295,12 +6338,12 @@ function Mn() {
|
|
|
6295
6338
|
}
|
|
6296
6339
|
}, F.start(), S("recording");
|
|
6297
6340
|
}
|
|
6298
|
-
function
|
|
6341
|
+
function Ra() {
|
|
6299
6342
|
const k = y.current;
|
|
6300
6343
|
k && k.state !== "inactive" && k.stop();
|
|
6301
6344
|
}
|
|
6302
|
-
function
|
|
6303
|
-
C === "recording" ?
|
|
6345
|
+
function Ia() {
|
|
6346
|
+
C === "recording" ? Ra() : C === "idle" && Ta();
|
|
6304
6347
|
}
|
|
6305
6348
|
return n ? /* @__PURE__ */ r(
|
|
6306
6349
|
"div",
|
|
@@ -6323,11 +6366,11 @@ function Mn() {
|
|
|
6323
6366
|
className: "mx-auto max-w-3xl space-y-4",
|
|
6324
6367
|
style: { paddingBottom: (Se || 96) + 16 },
|
|
6325
6368
|
children: [
|
|
6326
|
-
(
|
|
6369
|
+
(pt || it) && Je.length > 0 && /* @__PURE__ */ e("div", { className: "flex justify-center", children: /* @__PURE__ */ e(
|
|
6327
6370
|
"button",
|
|
6328
6371
|
{
|
|
6329
6372
|
onClick: xe,
|
|
6330
|
-
disabled: it || !
|
|
6373
|
+
disabled: it || !pt,
|
|
6331
6374
|
className: "rounded-full bg-surface px-3 py-1 text-xs text-fg-muted ring-1 ring-line transition-colors hover:bg-surface-subtle hover:text-fg disabled:cursor-not-allowed disabled:opacity-60",
|
|
6332
6375
|
children: t(it ? "common.loading" : "chat.loadOlder")
|
|
6333
6376
|
}
|
|
@@ -6354,7 +6397,7 @@ function Mn() {
|
|
|
6354
6397
|
k
|
|
6355
6398
|
)) })
|
|
6356
6399
|
] }),
|
|
6357
|
-
Je.map((k, F) => /* @__PURE__ */ e(
|
|
6400
|
+
Je.map((k, F) => /* @__PURE__ */ e(Zs, { message: k }, F)),
|
|
6358
6401
|
/* @__PURE__ */ e("div", { ref: ne })
|
|
6359
6402
|
]
|
|
6360
6403
|
}
|
|
@@ -6396,11 +6439,11 @@ function Mn() {
|
|
|
6396
6439
|
{
|
|
6397
6440
|
ref: x,
|
|
6398
6441
|
type: "file",
|
|
6399
|
-
accept: "image/png,image/jpeg,image/gif,image/webp,application/pdf",
|
|
6442
|
+
accept: "image/png,image/jpeg,image/gif,image/webp,application/pdf,.xlsx,.xls,.ods,.docx,.doc,.odt,.pptx,.ppt,.odp,.csv,.txt,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel,application/vnd.oasis.opendocument.spreadsheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/msword,application/vnd.oasis.opendocument.text,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/vnd.ms-powerpoint,application/vnd.oasis.opendocument.presentation,text/csv,text/plain",
|
|
6400
6443
|
multiple: !0,
|
|
6401
6444
|
className: "hidden",
|
|
6402
6445
|
onChange: (k) => {
|
|
6403
|
-
k.target.files && k.target.files.length > 0 && (
|
|
6446
|
+
k.target.files && k.target.files.length > 0 && (ye(k.target.files), k.target.value = "");
|
|
6404
6447
|
}
|
|
6405
6448
|
}
|
|
6406
6449
|
),
|
|
@@ -6411,7 +6454,7 @@ function Mn() {
|
|
|
6411
6454
|
ref: H,
|
|
6412
6455
|
value: l,
|
|
6413
6456
|
onChange: (k) => c(k.target.value),
|
|
6414
|
-
onKeyDown:
|
|
6457
|
+
onKeyDown: xt,
|
|
6415
6458
|
onPaste: Me,
|
|
6416
6459
|
placeholder: t(Oe ? "chat.placeholderDemo" : De ? "chat.placeholderType" : "chat.placeholderConnecting"),
|
|
6417
6460
|
disabled: !De || !n || Ie || Oe,
|
|
@@ -6431,7 +6474,7 @@ function Mn() {
|
|
|
6431
6474
|
var k;
|
|
6432
6475
|
return (k = x.current) == null ? void 0 : k.click();
|
|
6433
6476
|
},
|
|
6434
|
-
disabled: !De || !n || Ie || Oe || p.length >=
|
|
6477
|
+
disabled: !De || !n || Ie || Oe || p.length >= Yt,
|
|
6435
6478
|
className: "flex h-11 w-11 shrink-0 items-center justify-center rounded-lg text-fg-muted transition-all hover:bg-surface-subtle hover:text-fg disabled:cursor-not-allowed disabled:opacity-40 md:h-10 md:w-10",
|
|
6436
6479
|
title: t("chat.attachTitle"),
|
|
6437
6480
|
children: /* @__PURE__ */ e("svg", { viewBox: "0 0 24 24", width: "20", height: "20", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ e("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48" }) })
|
|
@@ -6440,7 +6483,7 @@ function Mn() {
|
|
|
6440
6483
|
/* @__PURE__ */ e(
|
|
6441
6484
|
"button",
|
|
6442
6485
|
{
|
|
6443
|
-
onClick:
|
|
6486
|
+
onClick: Ia,
|
|
6444
6487
|
disabled: !De || !n || Ie || Oe || C === "transcribing",
|
|
6445
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"}`,
|
|
6446
6489
|
title: t(C === "recording" ? "chat.voiceStop" : C === "transcribing" ? "chat.voiceTranscribing" : "chat.voiceStart"),
|
|
@@ -6455,7 +6498,7 @@ function Mn() {
|
|
|
6455
6498
|
/* @__PURE__ */ e(
|
|
6456
6499
|
"button",
|
|
6457
6500
|
{
|
|
6458
|
-
onClick:
|
|
6501
|
+
onClick: gt,
|
|
6459
6502
|
disabled: !l.trim() && ge.length === 0 || !De || !n || Ie || Oe || ke || pe,
|
|
6460
6503
|
className: "flex h-11 w-11 shrink-0 items-center justify-center rounded-lg text-brand transition-all hover:bg-brand/10 active:translate-y-px disabled:cursor-not-allowed disabled:text-fg-muted disabled:active:translate-y-0 md:h-10 md:w-10",
|
|
6461
6504
|
children: /* @__PURE__ */ e(
|
|
@@ -6487,7 +6530,7 @@ function Mn() {
|
|
|
6487
6530
|
}
|
|
6488
6531
|
) : /* @__PURE__ */ e("div", { className: "flex h-full items-center justify-center text-fg-muted", children: t("chat.creating") });
|
|
6489
6532
|
}
|
|
6490
|
-
function
|
|
6533
|
+
function Js({ attachments: t }) {
|
|
6491
6534
|
return !t || t.length === 0 ? null : /* @__PURE__ */ e("div", { className: "mt-1 flex flex-wrap gap-1.5", children: t.map((n) => {
|
|
6492
6535
|
const a = I.getChatAttachmentUrl(n.id), s = n.mime_type.startsWith("image/");
|
|
6493
6536
|
return /* @__PURE__ */ r(
|
|
@@ -6507,14 +6550,14 @@ function Qs({ attachments: t }) {
|
|
|
6507
6550
|
);
|
|
6508
6551
|
}) });
|
|
6509
6552
|
}
|
|
6510
|
-
function
|
|
6553
|
+
function Zs({ message: t }) {
|
|
6511
6554
|
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: [
|
|
6512
6555
|
/* @__PURE__ */ e("div", { className: "whitespace-pre-wrap", children: t.content }),
|
|
6513
|
-
/* @__PURE__ */ e(
|
|
6514
|
-
t.timestamp && /* @__PURE__ */ e("div", { className: "mt-1 text-right text-[10px] text-brand-fg/70", title:
|
|
6556
|
+
/* @__PURE__ */ e(Js, { attachments: t.attachments }),
|
|
6557
|
+
t.timestamp && /* @__PURE__ */ e("div", { className: "mt-1 text-right text-[10px] text-brand-fg/70", title: Mn(t.timestamp), children: zn(t.timestamp) })
|
|
6515
6558
|
] }) }) : 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: [
|
|
6516
|
-
/* @__PURE__ */ e(
|
|
6517
|
-
t.timestamp && /* @__PURE__ */ e("div", { className: "mt-1 text-right text-[10px] text-fg-muted", title:
|
|
6559
|
+
/* @__PURE__ */ e(Xs, { content: t.content }),
|
|
6560
|
+
t.timestamp && /* @__PURE__ */ e("div", { className: "mt-1 text-right text-[10px] text-fg-muted", title: Mn(t.timestamp), children: zn(t.timestamp) })
|
|
6518
6561
|
] }) }) : 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: [
|
|
6519
6562
|
/* @__PURE__ */ e("span", { className: "inline-block h-1.5 w-1.5 animate-pulse rounded-full bg-brand" }),
|
|
6520
6563
|
t.content,
|
|
@@ -6553,7 +6596,7 @@ function Ys({ message: t }) {
|
|
|
6553
6596
|
}
|
|
6554
6597
|
) }) : 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;
|
|
6555
6598
|
}
|
|
6556
|
-
function
|
|
6599
|
+
function Xs({ content: t }) {
|
|
6557
6600
|
const n = t.split(`
|
|
6558
6601
|
`), a = [];
|
|
6559
6602
|
let s = !1, o = [];
|
|
@@ -6597,7 +6640,7 @@ function Js({ content: t }) {
|
|
|
6597
6640
|
);
|
|
6598
6641
|
}), /* @__PURE__ */ e("div", { children: a });
|
|
6599
6642
|
}
|
|
6600
|
-
function
|
|
6643
|
+
function ka(t, n, a) {
|
|
6601
6644
|
const s = t.startsWith("/") && !t.startsWith("/api/"), o = "font-medium text-brand underline decoration-brand/40 underline-offset-2 transition-colors hover:decoration-brand";
|
|
6602
6645
|
return s ? /* @__PURE__ */ e(ve, { to: t, className: o, children: n }, a) : /* @__PURE__ */ e(
|
|
6603
6646
|
"a",
|
|
@@ -6611,13 +6654,13 @@ function wa(t, n, a) {
|
|
|
6611
6654
|
a
|
|
6612
6655
|
);
|
|
6613
6656
|
}
|
|
6614
|
-
const
|
|
6657
|
+
const ei = /(https?:\/\/[^\s)\]}"'<>]+|\/(?:reports|app|masters|admin|chat|setup|tutorial)[^\s)\]}"'<>]*)/g;
|
|
6615
6658
|
function Ot(t) {
|
|
6616
6659
|
return t.split(/(\[[^\]]+\]\([^)]+\)|\*\*[^*]+?\*\*|`[^`]+`)/g).flatMap((a, s) => {
|
|
6617
6660
|
const o = a.match(/^\[([^\]]+)\]\(([^)]+)\)$/);
|
|
6618
6661
|
if (o) {
|
|
6619
6662
|
const [, i, l] = o;
|
|
6620
|
-
return
|
|
6663
|
+
return ka(l, Ot(i), s);
|
|
6621
6664
|
}
|
|
6622
6665
|
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(
|
|
6623
6666
|
"code",
|
|
@@ -6626,24 +6669,24 @@ function Ot(t) {
|
|
|
6626
6669
|
children: a.slice(1, -1)
|
|
6627
6670
|
},
|
|
6628
6671
|
s
|
|
6629
|
-
) :
|
|
6672
|
+
) : ti(a, `${s}`);
|
|
6630
6673
|
});
|
|
6631
6674
|
}
|
|
6632
|
-
function
|
|
6675
|
+
function ti(t, n) {
|
|
6633
6676
|
const a = [];
|
|
6634
6677
|
let s = 0, o;
|
|
6635
|
-
const i = new RegExp(
|
|
6678
|
+
const i = new RegExp(ei.source, "g");
|
|
6636
6679
|
let l = 0;
|
|
6637
6680
|
for (; (o = i.exec(t)) !== null; ) {
|
|
6638
6681
|
const c = o.index;
|
|
6639
6682
|
let h = o[0], d = "";
|
|
6640
6683
|
for (; h.length > 0 && /[.,;:!?]$/.test(h); )
|
|
6641
6684
|
d = h.slice(-1) + d, h = h.slice(0, -1);
|
|
6642
|
-
c > s && a.push(t.slice(s, c)), a.push(
|
|
6685
|
+
c > s && a.push(t.slice(s, c)), a.push(ka(h, h, `${n}-u${l}`)), d && a.push(d), s = c + o[0].length, l += 1;
|
|
6643
6686
|
}
|
|
6644
6687
|
return s < t.length && a.push(t.slice(s)), a.length > 0 ? a : [t];
|
|
6645
6688
|
}
|
|
6646
|
-
function
|
|
6689
|
+
function ni() {
|
|
6647
6690
|
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("");
|
|
6648
6691
|
re(() => {
|
|
6649
6692
|
a && a.role !== "public_manager" && t("/", { replace: !0 });
|
|
@@ -6743,8 +6786,8 @@ function ei() {
|
|
|
6743
6786
|
},
|
|
6744
6787
|
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",
|
|
6745
6788
|
children: [
|
|
6746
|
-
/* @__PURE__ */ e(
|
|
6747
|
-
i("login.continueWithProvider", { provider:
|
|
6789
|
+
/* @__PURE__ */ e(ri, { provider: $ }),
|
|
6790
|
+
i("login.continueWithProvider", { provider: ai($) })
|
|
6748
6791
|
]
|
|
6749
6792
|
},
|
|
6750
6793
|
$
|
|
@@ -6777,10 +6820,10 @@ function ei() {
|
|
|
6777
6820
|
] }) })
|
|
6778
6821
|
] }) });
|
|
6779
6822
|
}
|
|
6780
|
-
function
|
|
6823
|
+
function ai(t) {
|
|
6781
6824
|
return t.charAt(0).toUpperCase() + t.slice(1);
|
|
6782
6825
|
}
|
|
6783
|
-
function
|
|
6826
|
+
function ri({ provider: t }) {
|
|
6784
6827
|
return t === "google" ? /* @__PURE__ */ r("svg", { className: "h-4 w-4", viewBox: "0 0 48 48", "aria-hidden": "true", children: [
|
|
6785
6828
|
/* @__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" }),
|
|
6786
6829
|
/* @__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" }),
|
|
@@ -6788,7 +6831,7 @@ function ni({ provider: t }) {
|
|
|
6788
6831
|
/* @__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" })
|
|
6789
6832
|
] }) : 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;
|
|
6790
6833
|
}
|
|
6791
|
-
function
|
|
6834
|
+
function si() {
|
|
6792
6835
|
const t = Ee(), n = oe(!1), [a, s] = w("");
|
|
6793
6836
|
return re(() => {
|
|
6794
6837
|
n.current || (n.current = !0, I.createChatSession().then((o) => {
|
|
@@ -6811,17 +6854,17 @@ function ai() {
|
|
|
6811
6854
|
/* @__PURE__ */ e("p", { className: "text-sm text-fg-muted", children: "Starting live demo..." })
|
|
6812
6855
|
] }) }) });
|
|
6813
6856
|
}
|
|
6814
|
-
function
|
|
6857
|
+
function $n() {
|
|
6815
6858
|
return { account: "", debit: "", credit: "", party_type: "", party: "" };
|
|
6816
6859
|
}
|
|
6817
|
-
function
|
|
6860
|
+
function Un() {
|
|
6818
6861
|
return { item_code: "", qty: "", rate: "" };
|
|
6819
6862
|
}
|
|
6820
|
-
function
|
|
6863
|
+
function Vn() {
|
|
6821
6864
|
return { type: "sales", party: "", amount: "", due_date: "", remarks: "" };
|
|
6822
6865
|
}
|
|
6823
|
-
function
|
|
6824
|
-
const t = Ee(), n = He(), [a, s] = w(""), [o, i] = w((/* @__PURE__ */ new Date()).toISOString().split("T")[0]), [l, c] = w(""), [h, d] = w([
|
|
6866
|
+
function ii() {
|
|
6867
|
+
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({
|
|
6825
6868
|
mutationFn: () => I.importAccountBalances({
|
|
6826
6869
|
company: a,
|
|
6827
6870
|
posting_date: o,
|
|
@@ -6892,7 +6935,7 @@ function ri() {
|
|
|
6892
6935
|
/* @__PURE__ */ e("td", { className: "px-2 py-1", children: /* @__PURE__ */ e("input", { type: "number", value: m.credit, onChange: (T) => y(h, d, D, "credit", T.target.value), className: "w-24 rounded border border-gray-300 px-2 py-1.5 text-right text-sm", placeholder: "0.00" }) })
|
|
6893
6936
|
] }, D)) })
|
|
6894
6937
|
] }) }),
|
|
6895
|
-
/* @__PURE__ */ e("div", { className: "mt-2 flex gap-2", children: /* @__PURE__ */ e("button", { onClick: () => d([...h,
|
|
6938
|
+
/* @__PURE__ */ e("div", { className: "mt-2 flex gap-2", children: /* @__PURE__ */ e("button", { onClick: () => d([...h, $n()]), className: "text-xs text-blue-600 hover:text-blue-800", children: "+ Add Row" }) }),
|
|
6896
6939
|
/* @__PURE__ */ r("div", { className: "mt-3 flex items-center gap-3", children: [
|
|
6897
6940
|
/* @__PURE__ */ e(Q, { onClick: () => C.mutate(), disabled: !a || C.isPending, children: C.isPending ? "Importing..." : "Import Account Balances" }),
|
|
6898
6941
|
C.error && /* @__PURE__ */ e("span", { className: "text-xs text-red-600", children: C.error.message }),
|
|
@@ -6917,7 +6960,7 @@ function ri() {
|
|
|
6917
6960
|
/* @__PURE__ */ e("td", { className: "px-2 py-1", children: /* @__PURE__ */ e("input", { type: "number", value: m.rate, onChange: (T) => y(p, u, D, "rate", T.target.value), className: "w-24 rounded border border-gray-300 px-2 py-1.5 text-right text-sm", placeholder: "0.00" }) })
|
|
6918
6961
|
] }, D)) })
|
|
6919
6962
|
] }) }),
|
|
6920
|
-
/* @__PURE__ */ e("div", { className: "mt-2", children: /* @__PURE__ */ e("button", { onClick: () => u([...p,
|
|
6963
|
+
/* @__PURE__ */ e("div", { className: "mt-2", children: /* @__PURE__ */ e("button", { onClick: () => u([...p, Un()]), className: "text-xs text-blue-600 hover:text-blue-800", children: "+ Add Row" }) }),
|
|
6921
6964
|
/* @__PURE__ */ r("div", { className: "mt-3 flex items-center gap-3", children: [
|
|
6922
6965
|
/* @__PURE__ */ e(Q, { onClick: () => S.mutate(), disabled: !a || !l || S.isPending, children: S.isPending ? "Importing..." : "Import Stock Balances" }),
|
|
6923
6966
|
S.error && /* @__PURE__ */ e("span", { className: "text-xs text-red-600", children: S.error.message }),
|
|
@@ -6960,7 +7003,7 @@ function ri() {
|
|
|
6960
7003
|
/* @__PURE__ */ e("td", { className: "px-2 py-1", children: /* @__PURE__ */ e("input", { type: "text", value: m.remarks, onChange: (T) => y(f, v, D, "remarks", T.target.value), className: "w-full rounded border border-gray-300 px-2 py-1.5 text-sm", placeholder: "Old invoice ref" }) })
|
|
6961
7004
|
] }, D)) })
|
|
6962
7005
|
] }) }),
|
|
6963
|
-
/* @__PURE__ */ e("div", { className: "mt-2", children: /* @__PURE__ */ e("button", { onClick: () => v([...f,
|
|
7006
|
+
/* @__PURE__ */ e("div", { className: "mt-2", children: /* @__PURE__ */ e("button", { onClick: () => v([...f, Vn()]), className: "text-xs text-blue-600 hover:text-blue-800", children: "+ Add Row" }) }),
|
|
6964
7007
|
/* @__PURE__ */ r("div", { className: "mt-3 flex items-center gap-3", children: [
|
|
6965
7008
|
/* @__PURE__ */ e(Q, { onClick: () => x.mutate(), disabled: !a || x.isPending, children: x.isPending ? "Importing..." : "Import Outstanding Invoices" }),
|
|
6966
7009
|
x.error && /* @__PURE__ */ e("span", { className: "text-xs text-red-600", children: x.error.message }),
|
|
@@ -6986,7 +7029,7 @@ function ri() {
|
|
|
6986
7029
|
] })
|
|
6987
7030
|
] });
|
|
6988
7031
|
}
|
|
6989
|
-
function
|
|
7032
|
+
function oi() {
|
|
6990
7033
|
const { user: t } = st(), n = He(), { data: a, isLoading: s } = ue({
|
|
6991
7034
|
queryKey: ["auth-users"],
|
|
6992
7035
|
queryFn: () => I.authListUsers()
|
|
@@ -7007,7 +7050,7 @@ function si() {
|
|
|
7007
7050
|
}), N = me({
|
|
7008
7051
|
mutationFn: (m) => I.authRevokeInvite(m),
|
|
7009
7052
|
onSuccess: () => n.invalidateQueries({ queryKey: ["auth-invites"] })
|
|
7010
|
-
}), [b, C] = w(null), S =
|
|
7053
|
+
}), [b, C] = w(null), S = vr(), x = (m) => `${window.location.origin}/login?invite=${m}`, y = async (m) => {
|
|
7011
7054
|
try {
|
|
7012
7055
|
await navigator.clipboard.writeText(x(m)), C(m), setTimeout(() => C((D) => D === m ? null : D), 2e3);
|
|
7013
7056
|
} catch {
|
|
@@ -7147,98 +7190,98 @@ function si() {
|
|
|
7147
7190
|
] }) })
|
|
7148
7191
|
] });
|
|
7149
7192
|
}
|
|
7150
|
-
const ii = { 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" }, oi = { title: "Language", help: "Choose the language for the interface. Your choice is saved in this browser.", label: "Language" }, li = { back: "Back", logout: "Logout", openMenu: "Open menu", closeMenu: "Close menu", new: "New {{label}}" }, ci = { 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" }, di = { 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" } }, ui = { 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" } }, mi = { 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" } }, pi = { 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." } }, hi = { 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}}" }, gi = { 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" }, fi = { 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" }, yi = { 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}}." }, bi = { totalRevenue: "Total Revenue", outstandingReceivable: "Outstanding Receivable", outstandingPayable: "Outstanding Payable", totalStockValue: "Total Stock Value", recentDocuments: "Recent Documents", noRecentDocuments: "No recent documents" }, vi = { 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." }, xi = { "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" }, Ni = { "% 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" }, wi = { accounts: "accounts", items: "items", monthly_distribution: "monthly_distribution", payments: "payments", plans: "plans", references: "references", taxes: "taxes" }, ki = /* @__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?"}`), Ci = { 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." }, Si = { 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" } }, Di = {
|
|
7151
|
-
common:
|
|
7152
|
-
language:
|
|
7153
|
-
header:
|
|
7154
|
-
titles:
|
|
7155
|
-
doctypes:
|
|
7156
|
-
masters:
|
|
7157
|
-
nav:
|
|
7158
|
-
login:
|
|
7159
|
-
settings:
|
|
7160
|
-
status:
|
|
7161
|
-
reports:
|
|
7162
|
-
masterForm:
|
|
7163
|
-
dashboard:
|
|
7164
|
-
chat:
|
|
7165
|
-
conversions:
|
|
7166
|
-
fields:
|
|
7167
|
-
tables:
|
|
7168
|
-
tutorial:
|
|
7169
|
-
notesMarkup:
|
|
7170
|
-
coa:
|
|
7171
|
-
}, Ai = { 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" }, Pi = { title: "Sprache", help: "Wählen Sie die Sprache der Oberfläche. Ihre Auswahl wird in diesem Browser gespeichert.", label: "Sprache" }, _i = { back: "Zurück", logout: "Abmelden", openMenu: "Menü öffnen", closeMenu: "Menü schließen", new: "Neu: {{label}}" }, Ti = { 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" }, Ri = { 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" } }, Ii = { 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" } }, Bi = { 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" } }, Ei = { 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." } }, Li = { 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}}" }, Oi = { 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" }, qi = { 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" }, zi = { 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." }, Mi = { 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" }, Fi = { items: "Positionen", taxes: "Steuern", references: "Zahlungsreferenzen", accounts: "Kontobuchungen", payments: "Zahlungen", plans: "Planpositionen", monthly_distribution: "Monatliche Verteilung" }, $i = { "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" }, Ui = { totalRevenue: "Gesamtumsatz", outstandingReceivable: "Offene Forderungen", outstandingPayable: "Offene Verbindlichkeiten", totalStockValue: "Gesamter Lagerwert", recentDocuments: "Letzte Dokumente", noRecentDocuments: "Keine aktuellen Dokumente" }, Vi = { 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." }, Ki = /* @__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?"}'), ji = { 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." }, Gi = { 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" } }, Wi = {
|
|
7172
|
-
common:
|
|
7173
|
-
language:
|
|
7174
|
-
header:
|
|
7175
|
-
titles:
|
|
7176
|
-
doctypes:
|
|
7177
|
-
masters:
|
|
7178
|
-
nav:
|
|
7179
|
-
login:
|
|
7180
|
-
settings:
|
|
7181
|
-
status:
|
|
7182
|
-
reports:
|
|
7183
|
-
masterForm:
|
|
7184
|
-
fields:
|
|
7185
|
-
tables:
|
|
7186
|
-
conversions:
|
|
7187
|
-
dashboard:
|
|
7188
|
-
chat:
|
|
7189
|
-
tutorial:
|
|
7190
|
-
notesMarkup:
|
|
7191
|
-
coa:
|
|
7192
|
-
}, Hi = { 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" }, Qi = { title: "Langue", help: "Choisissez la langue de l'interface. Votre choix est enregistré dans ce navigateur.", label: "Langue" }, Yi = { back: "Retour", logout: "Déconnexion", openMenu: "Ouvrir le menu", closeMenu: "Fermer le menu", new: "Nouveau : {{label}}" }, Ji = { 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" }, Zi = { 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" } }, Xi = { 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" } }, eo = { 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" } }, to = { 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." } }, no = { 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}}" }, ao = { 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é" }, ro = { 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é" }, so = { 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}}." }, io = { 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é" }, oo = { 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" }, lo = { "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" }, co = { 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" }, uo = { 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." }, mo = /* @__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 ?"}`), po = { 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." }, ho = { 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" } }, go = {
|
|
7193
|
-
common:
|
|
7194
|
-
language:
|
|
7195
|
-
header:
|
|
7196
|
-
titles:
|
|
7197
|
-
doctypes:
|
|
7198
|
-
masters:
|
|
7199
|
-
nav:
|
|
7200
|
-
login:
|
|
7201
|
-
settings:
|
|
7202
|
-
status:
|
|
7203
|
-
reports:
|
|
7204
|
-
masterForm:
|
|
7205
|
-
fields:
|
|
7206
|
-
tables:
|
|
7207
|
-
conversions:
|
|
7208
|
-
dashboard:
|
|
7209
|
-
chat:
|
|
7210
|
-
tutorial:
|
|
7211
|
-
notesMarkup:
|
|
7212
|
-
coa:
|
|
7213
|
-
},
|
|
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: li,
|
|
7195
|
+
language: ci,
|
|
7196
|
+
header: di,
|
|
7197
|
+
titles: ui,
|
|
7198
|
+
doctypes: mi,
|
|
7199
|
+
masters: pi,
|
|
7200
|
+
nav: hi,
|
|
7201
|
+
login: gi,
|
|
7202
|
+
settings: fi,
|
|
7203
|
+
status: yi,
|
|
7204
|
+
reports: bi,
|
|
7205
|
+
masterForm: vi,
|
|
7206
|
+
dashboard: xi,
|
|
7207
|
+
chat: Ni,
|
|
7208
|
+
conversions: wi,
|
|
7209
|
+
fields: ki,
|
|
7210
|
+
tables: Ci,
|
|
7211
|
+
tutorial: Si,
|
|
7212
|
+
notesMarkup: Di,
|
|
7213
|
+
coa: Ai
|
|
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: _i,
|
|
7216
|
+
language: Ti,
|
|
7217
|
+
header: Ri,
|
|
7218
|
+
titles: Ii,
|
|
7219
|
+
doctypes: Bi,
|
|
7220
|
+
masters: Ei,
|
|
7221
|
+
nav: Li,
|
|
7222
|
+
login: Oi,
|
|
7223
|
+
settings: qi,
|
|
7224
|
+
status: zi,
|
|
7225
|
+
reports: Mi,
|
|
7226
|
+
masterForm: Fi,
|
|
7227
|
+
fields: $i,
|
|
7228
|
+
tables: Ui,
|
|
7229
|
+
conversions: Vi,
|
|
7230
|
+
dashboard: Ki,
|
|
7231
|
+
chat: ji,
|
|
7232
|
+
tutorial: Gi,
|
|
7233
|
+
notesMarkup: Wi,
|
|
7234
|
+
coa: Hi
|
|
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: Yi,
|
|
7237
|
+
language: Ji,
|
|
7238
|
+
header: Zi,
|
|
7239
|
+
titles: Xi,
|
|
7240
|
+
doctypes: eo,
|
|
7241
|
+
masters: to,
|
|
7242
|
+
nav: no,
|
|
7243
|
+
login: ao,
|
|
7244
|
+
settings: ro,
|
|
7245
|
+
status: so,
|
|
7246
|
+
reports: io,
|
|
7247
|
+
masterForm: oo,
|
|
7248
|
+
fields: lo,
|
|
7249
|
+
tables: co,
|
|
7250
|
+
conversions: uo,
|
|
7251
|
+
dashboard: mo,
|
|
7252
|
+
chat: po,
|
|
7253
|
+
tutorial: ho,
|
|
7254
|
+
notesMarkup: go,
|
|
7255
|
+
coa: fo
|
|
7256
|
+
}, Ca = [
|
|
7214
7257
|
{ code: "en", label: "English" },
|
|
7215
7258
|
{ code: "de", label: "Deutsch" },
|
|
7216
7259
|
{ code: "fr", label: "Français" }
|
|
7217
|
-
],
|
|
7218
|
-
function
|
|
7219
|
-
return !!t &&
|
|
7260
|
+
], Sa = "lambda-erp:language";
|
|
7261
|
+
function bo(t) {
|
|
7262
|
+
return !!t && Ca.some((n) => n.code === t);
|
|
7220
7263
|
}
|
|
7221
|
-
function
|
|
7264
|
+
function vo() {
|
|
7222
7265
|
try {
|
|
7223
|
-
const t = localStorage.getItem(
|
|
7224
|
-
if (
|
|
7266
|
+
const t = localStorage.getItem(Sa);
|
|
7267
|
+
if (bo(t)) return t;
|
|
7225
7268
|
} catch {
|
|
7226
7269
|
}
|
|
7227
7270
|
return "en";
|
|
7228
7271
|
}
|
|
7229
|
-
function
|
|
7272
|
+
function xo(t) {
|
|
7230
7273
|
try {
|
|
7231
|
-
localStorage.setItem(
|
|
7274
|
+
localStorage.setItem(Sa, t);
|
|
7232
7275
|
} catch {
|
|
7233
7276
|
}
|
|
7234
7277
|
}
|
|
7235
|
-
|
|
7278
|
+
na.use($a).init({
|
|
7236
7279
|
resources: {
|
|
7237
|
-
en: { translation:
|
|
7238
|
-
de: { translation:
|
|
7239
|
-
fr: { translation:
|
|
7280
|
+
en: { translation: Pi },
|
|
7281
|
+
de: { translation: Qi },
|
|
7282
|
+
fr: { translation: yo }
|
|
7240
7283
|
},
|
|
7241
|
-
lng:
|
|
7284
|
+
lng: vo(),
|
|
7242
7285
|
fallbackLng: "en",
|
|
7243
7286
|
// any key missing in de/fr falls back to the English value
|
|
7244
7287
|
interpolation: { escapeValue: !1 },
|
|
@@ -7246,21 +7289,21 @@ ta.use(Fa).init({
|
|
|
7246
7289
|
react: { useSuspense: !1 }
|
|
7247
7290
|
// resources are bundled synchronously — no Suspense needed
|
|
7248
7291
|
});
|
|
7249
|
-
|
|
7250
|
-
function
|
|
7292
|
+
na.on("languageChanged", xo);
|
|
7293
|
+
function No({ label: t }) {
|
|
7251
7294
|
var o;
|
|
7252
7295
|
const { t: n, i18n: a } = X(), s = ((o = a.language) == null ? void 0 : o.split("-")[0]) ?? "en";
|
|
7253
7296
|
return /* @__PURE__ */ e(
|
|
7254
7297
|
Ve,
|
|
7255
7298
|
{
|
|
7256
7299
|
label: t === null ? void 0 : t ?? n("language.label"),
|
|
7257
|
-
options:
|
|
7300
|
+
options: Ca.map((i) => ({ value: i.code, label: i.label })),
|
|
7258
7301
|
value: s,
|
|
7259
7302
|
onChange: (i) => a.changeLanguage(i.target.value)
|
|
7260
7303
|
}
|
|
7261
7304
|
);
|
|
7262
7305
|
}
|
|
7263
|
-
const
|
|
7306
|
+
const Kn = [
|
|
7264
7307
|
{ value: "1h", label: "Last 1 hour", hours: 1 },
|
|
7265
7308
|
{ value: "2h", label: "Last 2 hours", hours: 2 },
|
|
7266
7309
|
{ value: "4h", label: "Last 4 hours", hours: 4 },
|
|
@@ -7271,14 +7314,14 @@ const Vn = [
|
|
|
7271
7314
|
function We(t) {
|
|
7272
7315
|
return t === 0 ? "$0.00" : t < 0.01 ? `$${t.toFixed(4)}` : `$${t.toFixed(2)}`;
|
|
7273
7316
|
}
|
|
7274
|
-
function
|
|
7317
|
+
function wo({ demoActive: t }) {
|
|
7275
7318
|
var S, x;
|
|
7276
7319
|
const { t: n } = X(), [a, s] = w("1h"), { data: o, isLoading: i, isFetching: l, error: c, refetch: h, dataUpdatedAt: d } = ue({
|
|
7277
7320
|
queryKey: ["demo-spend"],
|
|
7278
7321
|
queryFn: () => I.getDemoSpend(),
|
|
7279
7322
|
// Refresh once a minute — demo spend changes slowly; no need to poll harder.
|
|
7280
7323
|
refetchInterval: 6e4
|
|
7281
|
-
}), p =
|
|
7324
|
+
}), p = Kn.find((y) => y.value === a), u = (S = o == null ? void 0 : o.windows) == null ? void 0 : S[a], f = ((x = o == null ? void 0 : o.caps) == null ? void 0 : x.global_hourly_usd) ?? 0, v = u ? u.demo_usd / p.hours : 0, N = u ? u.total_usd / p.hours : 0, b = f > 0 ? Math.min(100, v / f * 100) : 0, C = b >= 90 ? "bg-red-500" : b >= 60 ? "bg-amber-500" : "bg-emerald-500";
|
|
7282
7325
|
return /* @__PURE__ */ r(M, { title: n("settings.tokenSpendTitle"), children: [
|
|
7283
7326
|
/* @__PURE__ */ r("div", { className: "flex flex-wrap items-end justify-between gap-4", children: [
|
|
7284
7327
|
/* @__PURE__ */ r("div", { className: "max-w-lg text-sm text-gray-600", children: [
|
|
@@ -7297,7 +7340,7 @@ function xo({ demoActive: t }) {
|
|
|
7297
7340
|
Ve,
|
|
7298
7341
|
{
|
|
7299
7342
|
label: "Time range",
|
|
7300
|
-
options:
|
|
7343
|
+
options: Kn.map((y) => ({ value: y.value, label: y.label })),
|
|
7301
7344
|
value: a,
|
|
7302
7345
|
onChange: (y) => s(y.target.value)
|
|
7303
7346
|
}
|
|
@@ -7455,7 +7498,7 @@ function St({ label: t, value: n }) {
|
|
|
7455
7498
|
/* @__PURE__ */ e("div", { className: "mt-0.5 text-sm font-semibold tabular-nums text-gray-900", children: n })
|
|
7456
7499
|
] });
|
|
7457
7500
|
}
|
|
7458
|
-
function
|
|
7501
|
+
function ko() {
|
|
7459
7502
|
const { t } = X(), { user: n } = st(), [a, s] = w(""), [o, i] = w(""), [l, c] = w(""), [h, d] = w(""), [p, u] = w(!1), f = me({
|
|
7460
7503
|
mutationFn: () => I.authChangePassword(a, o),
|
|
7461
7504
|
onSuccess: () => {
|
|
@@ -7532,7 +7575,7 @@ function No() {
|
|
|
7532
7575
|
/* @__PURE__ */ e(Q, { type: "submit", disabled: f.isPending || !a || !o || !l, children: f.isPending ? t("settings.changingPassword") : t("settings.changePassword") })
|
|
7533
7576
|
] }) });
|
|
7534
7577
|
}
|
|
7535
|
-
function
|
|
7578
|
+
function Co() {
|
|
7536
7579
|
const { t } = X(), { user: n, refreshUser: a } = st(), [s, o] = w(""), [i, l] = w(""), [c, h] = w(""), [d, p] = w(!1), u = me({
|
|
7537
7580
|
mutationFn: () => I.authSetPassword(s),
|
|
7538
7581
|
onSuccess: async () => {
|
|
@@ -7598,7 +7641,7 @@ function wo() {
|
|
|
7598
7641
|
] })
|
|
7599
7642
|
] });
|
|
7600
7643
|
}
|
|
7601
|
-
function
|
|
7644
|
+
function So() {
|
|
7602
7645
|
const { t } = X(), { data: n } = ue({
|
|
7603
7646
|
queryKey: ["auth-setup-status"],
|
|
7604
7647
|
queryFn: () => I.authSetupStatus()
|
|
@@ -7632,10 +7675,10 @@ function ko() {
|
|
|
7632
7675
|
}) })
|
|
7633
7676
|
] });
|
|
7634
7677
|
}
|
|
7635
|
-
const
|
|
7636
|
-
function
|
|
7637
|
-
const { t: n } = X(), { user: a } = st(), s = He(), [o, i] = w(""), [l, c] = w(t in
|
|
7638
|
-
(g) =>
|
|
7678
|
+
const Jt = { viewer: 1, manager: 2, admin: 3 };
|
|
7679
|
+
function Da({ ownRole: t }) {
|
|
7680
|
+
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
|
+
(g) => Jt[g] <= (Jt[t] ?? 1)
|
|
7639
7682
|
), v = `${window.location.origin}/api/mcp`, N = h ? `claude mcp add --transport http --scope user lambda-erp ${v} \\
|
|
7640
7683
|
--header "Authorization: Bearer ${h}"` : "", b = h ? `# ~/.codex/config.toml
|
|
7641
7684
|
[mcp_servers.lambda-erp]
|
|
@@ -7808,7 +7851,7 @@ http_headers = { Authorization = "Bearer ${h}" }` : "", { data: C } = ue({
|
|
|
7808
7851
|
)
|
|
7809
7852
|
] });
|
|
7810
7853
|
}
|
|
7811
|
-
function
|
|
7854
|
+
function jn({
|
|
7812
7855
|
enabled: t,
|
|
7813
7856
|
onToggle: n,
|
|
7814
7857
|
body: a,
|
|
@@ -7831,7 +7874,7 @@ function Kn({
|
|
|
7831
7874
|
)
|
|
7832
7875
|
] });
|
|
7833
7876
|
}
|
|
7834
|
-
function
|
|
7877
|
+
function Do({
|
|
7835
7878
|
chatEnabled: t,
|
|
7836
7879
|
restEnabled: n,
|
|
7837
7880
|
onToggleChat: a,
|
|
@@ -7842,7 +7885,7 @@ function Co({
|
|
|
7842
7885
|
return /* @__PURE__ */ r(M, { title: i("settings.apiTitle"), children: [
|
|
7843
7886
|
/* @__PURE__ */ r("div", { className: "space-y-4", children: [
|
|
7844
7887
|
/* @__PURE__ */ e(
|
|
7845
|
-
|
|
7888
|
+
jn,
|
|
7846
7889
|
{
|
|
7847
7890
|
enabled: t,
|
|
7848
7891
|
onToggle: () => t ? c("chat") : a(),
|
|
@@ -7853,7 +7896,7 @@ function Co({
|
|
|
7853
7896
|
),
|
|
7854
7897
|
/* @__PURE__ */ e("div", { className: "border-t border-gray-100" }),
|
|
7855
7898
|
/* @__PURE__ */ e(
|
|
7856
|
-
|
|
7899
|
+
jn,
|
|
7857
7900
|
{
|
|
7858
7901
|
enabled: n,
|
|
7859
7902
|
onToggle: () => n ? c("rest") : s(),
|
|
@@ -7865,7 +7908,7 @@ function Co({
|
|
|
7865
7908
|
] }),
|
|
7866
7909
|
(t || n) && /* @__PURE__ */ r("div", { className: "mt-4 border-t border-gray-100 pt-4", children: [
|
|
7867
7910
|
/* @__PURE__ */ e("div", { className: "mb-2 text-xs font-medium text-gray-500", children: i("settings.chatApiKeysTitle") }),
|
|
7868
|
-
/* @__PURE__ */ e(
|
|
7911
|
+
/* @__PURE__ */ e(Da, { ownRole: o })
|
|
7869
7912
|
] }),
|
|
7870
7913
|
l && /* @__PURE__ */ e(
|
|
7871
7914
|
"div",
|
|
@@ -7903,7 +7946,7 @@ function Co({
|
|
|
7903
7946
|
)
|
|
7904
7947
|
] });
|
|
7905
7948
|
}
|
|
7906
|
-
function
|
|
7949
|
+
function Ao() {
|
|
7907
7950
|
const { user: t } = st(), { t: n } = X(), a = He(), s = (t == null ? void 0 : t.role) === "admin", { data: o, isLoading: i } = ue({
|
|
7908
7951
|
queryKey: ["settings"],
|
|
7909
7952
|
queryFn: () => I.getSettings()
|
|
@@ -7929,11 +7972,11 @@ function So() {
|
|
|
7929
7972
|
});
|
|
7930
7973
|
return i ? /* @__PURE__ */ e("p", { className: "text-gray-500", children: n("common.loading") }) : /* @__PURE__ */ r("div", { className: "space-y-6", children: [
|
|
7931
7974
|
/* @__PURE__ */ r(M, { title: n("language.title"), children: [
|
|
7932
|
-
/* @__PURE__ */ e("div", { className: "flex flex-wrap items-end gap-4", children: /* @__PURE__ */ e("div", { className: "w-64", children: /* @__PURE__ */ e(
|
|
7975
|
+
/* @__PURE__ */ e("div", { className: "flex flex-wrap items-end gap-4", children: /* @__PURE__ */ e("div", { className: "w-64", children: /* @__PURE__ */ e(No, {}) }) }),
|
|
7933
7976
|
/* @__PURE__ */ e("p", { className: "mt-2 text-xs text-gray-400", children: n("language.help") })
|
|
7934
7977
|
] }),
|
|
7935
|
-
(t == null ? void 0 : t.role) !== "public_manager" && ((t == null ? void 0 : t.has_password) === !1 ? /* @__PURE__ */ e(
|
|
7936
|
-
(t == null ? void 0 : t.role) !== "public_manager" && /* @__PURE__ */ e(
|
|
7978
|
+
(t == null ? void 0 : t.role) !== "public_manager" && ((t == null ? void 0 : t.has_password) === !1 ? /* @__PURE__ */ e(Co, {}) : /* @__PURE__ */ e(ko, {})),
|
|
7979
|
+
(t == null ? void 0 : t.role) !== "public_manager" && /* @__PURE__ */ e(So, {}),
|
|
7937
7980
|
/* @__PURE__ */ r(M, { title: n("settings.pdfTitle"), children: [
|
|
7938
7981
|
/* @__PURE__ */ e("div", { className: "flex flex-wrap items-end gap-4", children: s ? /* @__PURE__ */ e(
|
|
7939
7982
|
Ve,
|
|
@@ -7982,7 +8025,7 @@ function So() {
|
|
|
7982
8025
|
)
|
|
7983
8026
|
] }) }),
|
|
7984
8027
|
s && /* @__PURE__ */ e(
|
|
7985
|
-
|
|
8028
|
+
Do,
|
|
7986
8029
|
{
|
|
7987
8030
|
chatEnabled: (o == null ? void 0 : o.chat_api_enabled) === "1",
|
|
7988
8031
|
restEnabled: (o == null ? void 0 : o.rest_api_enabled) === "1",
|
|
@@ -7997,9 +8040,9 @@ function So() {
|
|
|
7997
8040
|
),
|
|
7998
8041
|
!s && (t == null ? void 0 : t.role) !== "public_manager" && /* @__PURE__ */ r(M, { title: n("settings.chatApiKeysTitle"), children: [
|
|
7999
8042
|
/* @__PURE__ */ e("p", { className: "mb-3 text-sm text-gray-700", children: n("settings.chatApiPersonal") }),
|
|
8000
|
-
/* @__PURE__ */ e(
|
|
8043
|
+
/* @__PURE__ */ e(Da, { ownRole: (t == null ? void 0 : t.role) ?? "viewer" })
|
|
8001
8044
|
] }),
|
|
8002
|
-
s && /* @__PURE__ */ e(
|
|
8045
|
+
s && /* @__PURE__ */ e(wo, { demoActive: !!(c != null && c.active) }),
|
|
8003
8046
|
s && /* @__PURE__ */ e(M, { title: n("settings.publicTitle"), children: c != null && c.active ? /* @__PURE__ */ r("div", { children: [
|
|
8004
8047
|
/* @__PURE__ */ r("div", { className: "flex items-center gap-2", children: [
|
|
8005
8048
|
/* @__PURE__ */ e("span", { className: "inline-block h-2 w-2 rounded-full bg-green-500" }),
|
|
@@ -8051,78 +8094,78 @@ function So() {
|
|
|
8051
8094
|
(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 }) })
|
|
8052
8095
|
] });
|
|
8053
8096
|
}
|
|
8054
|
-
const
|
|
8055
|
-
function
|
|
8056
|
-
|
|
8097
|
+
const Aa = {};
|
|
8098
|
+
function tl(t, n) {
|
|
8099
|
+
Aa[t] = n;
|
|
8057
8100
|
}
|
|
8058
|
-
function
|
|
8059
|
-
return
|
|
8101
|
+
function Po(t, n) {
|
|
8102
|
+
return Aa[t] ?? n;
|
|
8060
8103
|
}
|
|
8061
|
-
function
|
|
8062
|
-
const t =
|
|
8104
|
+
function _o() {
|
|
8105
|
+
const t = Po("Dashboard", Or);
|
|
8063
8106
|
return /* @__PURE__ */ e(t, {});
|
|
8064
8107
|
}
|
|
8065
|
-
const
|
|
8066
|
-
{ path: "/login", element: /* @__PURE__ */ e(
|
|
8067
|
-
{ path: "/demo", element: /* @__PURE__ */ e(
|
|
8068
|
-
],
|
|
8069
|
-
{ index: !0, element: /* @__PURE__ */ e(
|
|
8070
|
-
{ path: "setup", element: /* @__PURE__ */ e(
|
|
8071
|
-
{ path: "setup/opening-balances", element: /* @__PURE__ */ e(
|
|
8072
|
-
{ path: "tutorial", element: /* @__PURE__ */ e(
|
|
8073
|
-
{ path: "chat", element: /* @__PURE__ */ e(
|
|
8074
|
-
{ path: "chat/:sessionId", element: /* @__PURE__ */ e(
|
|
8108
|
+
const To = [
|
|
8109
|
+
{ path: "/login", element: /* @__PURE__ */ e(ni, {}) },
|
|
8110
|
+
{ path: "/demo", element: /* @__PURE__ */ e(si, {}) }
|
|
8111
|
+
], Ro = [
|
|
8112
|
+
{ index: !0, element: /* @__PURE__ */ e(_o, {}) },
|
|
8113
|
+
{ path: "setup", element: /* @__PURE__ */ e(zs, {}) },
|
|
8114
|
+
{ path: "setup/opening-balances", element: /* @__PURE__ */ e(ii, {}) },
|
|
8115
|
+
{ path: "tutorial", element: /* @__PURE__ */ e(js, {}) },
|
|
8116
|
+
{ path: "chat", element: /* @__PURE__ */ e(Fn, {}) },
|
|
8117
|
+
{ path: "chat/:sessionId", element: /* @__PURE__ */ e(Fn, {}) },
|
|
8075
8118
|
// Proposal (Sammelofferte) — a custom builder; the list reuses the generic
|
|
8076
8119
|
// DocumentList via the `proposal` doctype config. The static "proposal"
|
|
8077
8120
|
// segment outranks the ":doctype" wildcard below in react-router's matcher.
|
|
8078
|
-
{ path: "app/proposal/new", element: /* @__PURE__ */ e(
|
|
8079
|
-
{ path: "app/proposal/:name", element: /* @__PURE__ */ e(
|
|
8121
|
+
{ path: "app/proposal/new", element: /* @__PURE__ */ e(In, {}) },
|
|
8122
|
+
{ path: "app/proposal/:name", element: /* @__PURE__ */ e(In, {}) },
|
|
8080
8123
|
// Documents
|
|
8081
|
-
{ path: "app/:doctype", element: /* @__PURE__ */ e(
|
|
8082
|
-
{ path: "app/:doctype/new", element: /* @__PURE__ */ e(
|
|
8083
|
-
{ path: "app/:doctype/:name", element: /* @__PURE__ */ e(
|
|
8124
|
+
{ path: "app/:doctype", element: /* @__PURE__ */ e(ts, {}) },
|
|
8125
|
+
{ path: "app/:doctype/new", element: /* @__PURE__ */ e(An, {}) },
|
|
8126
|
+
{ path: "app/:doctype/:name", element: /* @__PURE__ */ e(An, {}) },
|
|
8084
8127
|
// Masters (reuse same routes - the components detect whether it's a doctype or master)
|
|
8085
|
-
{ path: "masters/:type", element: /* @__PURE__ */ e(
|
|
8086
|
-
{ path: "masters/:type/new", element: /* @__PURE__ */ e(
|
|
8087
|
-
{ path: "masters/:type/:name", element: /* @__PURE__ */ e(
|
|
8128
|
+
{ path: "masters/:type", element: /* @__PURE__ */ e(rs, {}) },
|
|
8129
|
+
{ path: "masters/:type/new", element: /* @__PURE__ */ e(En, {}) },
|
|
8130
|
+
{ path: "masters/:type/:name", element: /* @__PURE__ */ e(En, {}) },
|
|
8088
8131
|
// Reports
|
|
8089
|
-
{ path: "reports/chart-of-accounts", element: /* @__PURE__ */ e(
|
|
8090
|
-
{ path: "reports/trial-balance", element: /* @__PURE__ */ e(
|
|
8091
|
-
{ path: "reports/general-ledger", element: /* @__PURE__ */ e(
|
|
8092
|
-
{ path: "reports/stock-balance", element: /* @__PURE__ */ e(
|
|
8093
|
-
{ path: "reports/profit-and-loss", element: /* @__PURE__ */ e(
|
|
8094
|
-
{ path: "reports/balance-sheet", element: /* @__PURE__ */ e(
|
|
8095
|
-
{ path: "reports/ar-aging", element: /* @__PURE__ */ e(
|
|
8096
|
-
{ path: "reports/ap-aging", element: /* @__PURE__ */ e(
|
|
8097
|
-
{ path: "reports/analytics", element: /* @__PURE__ */ e(
|
|
8132
|
+
{ path: "reports/chart-of-accounts", element: /* @__PURE__ */ e(ys, {}) },
|
|
8133
|
+
{ path: "reports/trial-balance", element: /* @__PURE__ */ e(gs, {}) },
|
|
8134
|
+
{ path: "reports/general-ledger", element: /* @__PURE__ */ e(xs, {}) },
|
|
8135
|
+
{ path: "reports/stock-balance", element: /* @__PURE__ */ e(Ns, {}) },
|
|
8136
|
+
{ path: "reports/profit-and-loss", element: /* @__PURE__ */ e(ws, {}) },
|
|
8137
|
+
{ path: "reports/balance-sheet", element: /* @__PURE__ */ e(ks, {}) },
|
|
8138
|
+
{ path: "reports/ar-aging", element: /* @__PURE__ */ e(Cs, {}) },
|
|
8139
|
+
{ path: "reports/ap-aging", element: /* @__PURE__ */ e(Ss, {}) },
|
|
8140
|
+
{ path: "reports/analytics", element: /* @__PURE__ */ e(Ps, {}) },
|
|
8098
8141
|
// Admin
|
|
8099
|
-
{ path: "admin/users", element: /* @__PURE__ */ e(
|
|
8100
|
-
{ path: "admin/settings", element: /* @__PURE__ */ e(
|
|
8101
|
-
],
|
|
8102
|
-
function
|
|
8103
|
-
(n == null ? void 0 : n.area) === "top" ?
|
|
8104
|
-
}
|
|
8105
|
-
const
|
|
8106
|
-
function
|
|
8142
|
+
{ path: "admin/users", element: /* @__PURE__ */ e(oi, {}) },
|
|
8143
|
+
{ path: "admin/settings", element: /* @__PURE__ */ e(Ao, {}) }
|
|
8144
|
+
], Pa = [], _a = [];
|
|
8145
|
+
function Io(t, n) {
|
|
8146
|
+
(n == null ? void 0 : n.area) === "top" ? Pa.push(t) : _a.push(t);
|
|
8147
|
+
}
|
|
8148
|
+
const Gn = (t) => t.index ? "__index__" : t.path ?? "";
|
|
8149
|
+
function Wn(t, n) {
|
|
8107
8150
|
const a = [...t];
|
|
8108
8151
|
for (const s of n) {
|
|
8109
|
-
const o =
|
|
8152
|
+
const o = Gn(s), i = a.findIndex((l) => Gn(l) === o);
|
|
8110
8153
|
i >= 0 ? a[i] = s : a.push(s);
|
|
8111
8154
|
}
|
|
8112
8155
|
return a;
|
|
8113
8156
|
}
|
|
8114
|
-
function
|
|
8157
|
+
function Bo() {
|
|
8115
8158
|
return [
|
|
8116
|
-
...
|
|
8159
|
+
...Wn(To, Pa),
|
|
8117
8160
|
{
|
|
8118
8161
|
path: "/",
|
|
8119
|
-
element: /* @__PURE__ */ e(
|
|
8120
|
-
children:
|
|
8162
|
+
element: /* @__PURE__ */ e(Rr, { children: /* @__PURE__ */ e(_r, {}) }),
|
|
8163
|
+
children: Wn(Ro, _a)
|
|
8121
8164
|
}
|
|
8122
8165
|
];
|
|
8123
8166
|
}
|
|
8124
|
-
function
|
|
8125
|
-
const { name: s = "" } =
|
|
8167
|
+
function Eo({ slug: t, parentSlug: n, linkField: a }) {
|
|
8168
|
+
const { name: s = "" } = dt(), o = Ee();
|
|
8126
8169
|
return re(() => {
|
|
8127
8170
|
let i = !0;
|
|
8128
8171
|
return I.getDocument(t, s).then((l) => {
|
|
@@ -8136,7 +8179,7 @@ function Io({ slug: t, parentSlug: n, linkField: a }) {
|
|
|
8136
8179
|
};
|
|
8137
8180
|
}, [t, s, n, a, o]), /* @__PURE__ */ e("div", { className: "p-6 text-sm text-fg-muted", children: "…" });
|
|
8138
8181
|
}
|
|
8139
|
-
async function
|
|
8182
|
+
async function Lo() {
|
|
8140
8183
|
try {
|
|
8141
8184
|
const t = await L(
|
|
8142
8185
|
"/chat-doctypes",
|
|
@@ -8144,33 +8187,33 @@ async function Bo() {
|
|
|
8144
8187
|
);
|
|
8145
8188
|
for (const n of t.doctypes || []) {
|
|
8146
8189
|
const a = n.page;
|
|
8147
|
-
a && a.kind === "via" &&
|
|
8190
|
+
a && a.kind === "via" && Io({
|
|
8148
8191
|
path: `app/${n.slug}/:name`,
|
|
8149
|
-
element: /* @__PURE__ */ e(
|
|
8192
|
+
element: /* @__PURE__ */ e(Eo, { slug: n.slug, parentSlug: a.parent_slug, linkField: a.link_field })
|
|
8150
8193
|
});
|
|
8151
8194
|
}
|
|
8152
8195
|
} catch {
|
|
8153
8196
|
}
|
|
8154
8197
|
}
|
|
8155
|
-
function
|
|
8156
|
-
return new
|
|
8198
|
+
function Oo() {
|
|
8199
|
+
return new Oa({
|
|
8157
8200
|
defaultOptions: {
|
|
8158
8201
|
queries: { retry: 1, refetchOnWindowFocus: !1 }
|
|
8159
8202
|
}
|
|
8160
8203
|
});
|
|
8161
8204
|
}
|
|
8162
|
-
async function
|
|
8205
|
+
async function nl(t = {}) {
|
|
8163
8206
|
const n = t.rootElement ?? document.getElementById("root");
|
|
8164
8207
|
if (!n)
|
|
8165
8208
|
throw new Error('bootstrap: no mount element (pass rootElement or add <div id="root">)');
|
|
8166
|
-
const a = t.queryClient ??
|
|
8167
|
-
await
|
|
8168
|
-
const s =
|
|
8169
|
-
|
|
8170
|
-
/* @__PURE__ */ e(
|
|
8209
|
+
const a = t.queryClient ?? Oo();
|
|
8210
|
+
await Lo();
|
|
8211
|
+
const s = Ma(Bo());
|
|
8212
|
+
Ea(n).render(
|
|
8213
|
+
/* @__PURE__ */ e(Ba, { children: /* @__PURE__ */ e(La, { client: a, children: /* @__PURE__ */ e(mr, { children: /* @__PURE__ */ e(Fa, { router: s }) }) }) })
|
|
8171
8214
|
);
|
|
8172
8215
|
}
|
|
8173
|
-
function
|
|
8216
|
+
function al({
|
|
8174
8217
|
onConfirm: t,
|
|
8175
8218
|
children: n,
|
|
8176
8219
|
confirmLabel: a,
|
|
@@ -8238,37 +8281,37 @@ function tl({
|
|
|
8238
8281
|
}
|
|
8239
8282
|
export {
|
|
8240
8283
|
Ue as ApiError,
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8284
|
+
_r as AppShell,
|
|
8285
|
+
mr as AuthProvider,
|
|
8286
|
+
al as ConfirmButton,
|
|
8287
|
+
br as DialogProvider,
|
|
8288
|
+
ya as DocPager,
|
|
8289
|
+
Ca as SUPPORTED_LANGUAGES,
|
|
8247
8290
|
I as api,
|
|
8248
|
-
|
|
8249
|
-
|
|
8250
|
-
|
|
8251
|
-
|
|
8252
|
-
|
|
8291
|
+
nl as bootstrap,
|
|
8292
|
+
Bo as buildRoutes,
|
|
8293
|
+
Ho as configureApiBase,
|
|
8294
|
+
Zo as configureBranding,
|
|
8295
|
+
Oo as createAppQueryClient,
|
|
8253
8296
|
Ft as formatDate,
|
|
8254
|
-
|
|
8255
|
-
|
|
8256
|
-
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
|
|
8264
|
-
|
|
8265
|
-
|
|
8266
|
-
|
|
8297
|
+
el as getAllDoctypeConfigs,
|
|
8298
|
+
Nr as getBranding,
|
|
8299
|
+
Po as getComponent,
|
|
8300
|
+
fa as getDoctypeConfig,
|
|
8301
|
+
qr as getListContext,
|
|
8302
|
+
xr as getNavGroups,
|
|
8303
|
+
vo as getStoredLanguage,
|
|
8304
|
+
il as i18n,
|
|
8305
|
+
tl as registerComponent,
|
|
8306
|
+
Xo as registerDoctype,
|
|
8307
|
+
Yo as registerNavGroup,
|
|
8308
|
+
Jo as registerNavItem,
|
|
8309
|
+
Io as registerRoute,
|
|
8267
8310
|
L as request,
|
|
8268
|
-
|
|
8269
|
-
|
|
8311
|
+
Qo as setDateLocale,
|
|
8312
|
+
ga as setListContext,
|
|
8270
8313
|
st as useAuth,
|
|
8271
|
-
|
|
8272
|
-
|
|
8314
|
+
ua as useConfirm,
|
|
8315
|
+
vr as usePrompt
|
|
8273
8316
|
};
|
|
8274
8317
|
//# sourceMappingURL=index.js.map
|