@lambda-development/erp-core 0.3.3 → 0.4.0

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 CHANGED
@@ -1,20 +1,20 @@
1
1
  import { jsx as e, jsxs as r, Fragment as we } from "react/jsx-runtime";
2
- import { useState as C, useEffect as se, useCallback as Pe, useContext as Vn, createContext as Kn, useRef as te, useMemo as Se, useLayoutEffect as un, StrictMode as wa } from "react";
3
- import { createRoot as ka } from "react-dom/client";
4
- import { useQueryClient as We, useQuery as oe, useMutation as ie, QueryClientProvider as Ca, QueryClient as Sa } from "@tanstack/react-query";
5
- import { NavLink as Ot, useLocation as St, useNavigate as ze, Outlet as Da, Navigate as Aa, Link as be, useSearchParams as qt, useParams as bt, createBrowserRouter as Pa, RouterProvider as _a } from "react-router-dom";
6
- import { useTranslation as X, initReactI18next as Ta } from "react-i18next";
7
- import { BookOpen as Ra, ShoppingCart as jn, CreditCard as Ia, FileText as nn, Package as Gn, BarChart3 as Ba, Database as La, Settings as Ea, MessageCircle as Oa, ChevronDown as zt, ChevronRight as Mt, Plus as Wn, Trash2 as Hn, LineChart as qa, TrendingUp as za, ArrowDownRight as Ma, ArrowUpRight as Fa, Wallet as $a, Receipt as mn, Info as Ua } from "lucide-react";
8
- import { createColumnHelper as Qn, useReactTable as Yn, getCoreRowModel as Jn, flexRender as It } from "@tanstack/react-table";
9
- import { createPortal as Zn } from "react-dom";
10
- import { ResponsiveContainer as Va, LineChart as Ka, CartesianGrid as pn, XAxis as hn, YAxis as gn, Tooltip as Vt, Line as ja, PieChart as Ga, Pie as Wa, Cell as Ha, BarChart as Qa, Bar as Ya } from "recharts";
11
- import Xn from "i18next";
12
- import { default as zo } from "i18next";
2
+ import { useState as S, useEffect as se, useCallback as Pe, useContext as Kn, createContext as jn, useRef as te, useMemo as Ce, useLayoutEffect as un, StrictMode as ka } from "react";
3
+ import { createRoot as Sa } from "react-dom/client";
4
+ import { useQueryClient as We, useQuery as oe, useMutation as ie, QueryClientProvider as Ca, QueryClient as Da } from "@tanstack/react-query";
5
+ import { NavLink as Ot, useLocation as Ct, useNavigate as ze, Outlet as Aa, Navigate as Pa, Link as be, useSearchParams as qt, useParams as bt, createBrowserRouter as _a, RouterProvider as Ta } from "react-router-dom";
6
+ import { useTranslation as Z, initReactI18next as Ra } from "react-i18next";
7
+ import { BookOpen as Ia, ShoppingCart as Gn, CreditCard as Ba, FileText as nn, Package as Wn, BarChart3 as Ea, Database as La, Settings as Oa, MessageCircle as qa, ChevronDown as zt, ChevronRight as Mt, Plus as Hn, Trash2 as Qn, LineChart as za, TrendingUp as Ma, ArrowDownRight as Fa, ArrowUpRight as $a, Wallet as Ua, Receipt as mn, Info as Va } from "lucide-react";
8
+ import { createColumnHelper as Yn, useReactTable as Jn, getCoreRowModel as Zn, flexRender as It } from "@tanstack/react-table";
9
+ import { createPortal as Xn } from "react-dom";
10
+ import { ResponsiveContainer as Ka, LineChart as ja, CartesianGrid as pn, XAxis as hn, YAxis as gn, Tooltip as Vt, Line as Ga, PieChart as Wa, Pie as Ha, Cell as Qa, BarChart as Ya, Bar as Ja } from "recharts";
11
+ import ea from "i18next";
12
+ import { default as Mo } from "i18next";
13
13
  let ct = "/api";
14
- function Ao(t) {
14
+ function Po(t) {
15
15
  ct = t.replace(/\/+$/, "");
16
16
  }
17
- function Ja(t) {
17
+ function Za(t) {
18
18
  return new URL(`${ct}${t}`, window.location.origin).toString();
19
19
  }
20
20
  class $e extends Error {
@@ -22,7 +22,7 @@ class $e extends Error {
22
22
  super(a), this.status = n;
23
23
  }
24
24
  }
25
- function Za(t) {
25
+ function Xa(t) {
26
26
  if (!t) return "Request failed";
27
27
  if (typeof t == "string") return t;
28
28
  if (Array.isArray(t))
@@ -37,7 +37,7 @@ function Za(t) {
37
37
  }
38
38
  return String(t);
39
39
  }
40
- async function E(t, n) {
40
+ async function L(t, n) {
41
41
  const a = await fetch(`${ct}${t}`, {
42
42
  headers: { "Content-Type": "application/json" },
43
43
  credentials: "include",
@@ -47,7 +47,7 @@ async function E(t, n) {
47
47
  if (a.status === 401 && !t.startsWith("/auth/"))
48
48
  throw window.location.href = "/login", new $e(401, "Session expired");
49
49
  const s = await a.json().catch(() => ({ detail: a.statusText }));
50
- throw new $e(a.status, Za(s.detail));
50
+ throw new $e(a.status, Xa(s.detail));
51
51
  }
52
52
  return a.json();
53
53
  }
@@ -60,7 +60,7 @@ function Be(t) {
60
60
  }
61
61
  const I = {
62
62
  // Generic request (used by sidebar for chat sessions)
63
- request: E,
63
+ request: L,
64
64
  // Chat attachments
65
65
  uploadChatAttachment: async (t, n) => {
66
66
  const a = new FormData();
@@ -80,33 +80,33 @@ const I = {
80
80
  },
81
81
  getChatAttachmentUrl: (t) => `${ct}/chat/attachments/${encodeURIComponent(t)}`,
82
82
  // Chat
83
- createChatSession: () => E(
83
+ createChatSession: () => L(
84
84
  "/chat/sessions",
85
85
  { method: "POST" }
86
86
  ),
87
- getChatSession: (t) => E(
87
+ getChatSession: (t) => L(
88
88
  `/chat/sessions/${encodeURIComponent(t)}`
89
89
  ),
90
90
  // Documents
91
- listDocuments: (t, n) => E(
91
+ listDocuments: (t, n) => L(
92
92
  `/documents/${t}${Be(n)}`
93
93
  ),
94
- getDocument: (t, n) => E(`/documents/${t}/${encodeURIComponent(n)}`),
95
- createDocument: (t, n) => E(`/documents/${t}`, { method: "POST", body: JSON.stringify(n) }),
96
- updateDocument: (t, n, a) => E(`/documents/${t}/${encodeURIComponent(n)}`, {
94
+ getDocument: (t, n) => L(`/documents/${t}/${encodeURIComponent(n)}`),
95
+ createDocument: (t, n) => L(`/documents/${t}`, { method: "POST", body: JSON.stringify(n) }),
96
+ updateDocument: (t, n, a) => L(`/documents/${t}/${encodeURIComponent(n)}`, {
97
97
  method: "PUT",
98
98
  body: JSON.stringify(a)
99
99
  }),
100
- submitDocument: (t, n) => E(`/documents/${t}/${encodeURIComponent(n)}/submit`, { method: "POST" }),
101
- cancelDocument: (t, n) => E(`/documents/${t}/${encodeURIComponent(n)}/cancel`, { method: "POST" }),
102
- discardDocument: (t, n) => E(`/documents/${t}/${encodeURIComponent(n)}/discard`, { method: "POST" }),
103
- convertDocument: (t, n, a) => E(`/documents/${t}/${encodeURIComponent(n)}/convert`, {
100
+ submitDocument: (t, n) => L(`/documents/${t}/${encodeURIComponent(n)}/submit`, { method: "POST" }),
101
+ cancelDocument: (t, n) => L(`/documents/${t}/${encodeURIComponent(n)}/cancel`, { method: "POST" }),
102
+ discardDocument: (t, n) => L(`/documents/${t}/${encodeURIComponent(n)}/discard`, { method: "POST" }),
103
+ convertDocument: (t, n, a) => L(`/documents/${t}/${encodeURIComponent(n)}/convert`, {
104
104
  method: "POST",
105
105
  body: JSON.stringify({ target_doctype: a })
106
106
  }),
107
107
  // Proposal (Sammelofferte) extras — CRUD goes through the document methods
108
108
  // above (doctype "proposal"); these cover the appendix blob + cover default.
109
- getProposalCoverDefault: (t, n) => E(
109
+ getProposalCoverDefault: (t, n) => L(
110
110
  `/proposals/cover-default${Be({ company: t, customer: n })}`
111
111
  ),
112
112
  uploadProposalAppendix: async (t, n) => {
@@ -125,115 +125,115 @@ const I = {
125
125
  }
126
126
  return s.json();
127
127
  },
128
- deleteProposalAppendix: (t) => E(`/proposals/${encodeURIComponent(t)}/appendix`, { method: "DELETE" }),
128
+ deleteProposalAppendix: (t) => L(`/proposals/${encodeURIComponent(t)}/appendix`, { method: "DELETE" }),
129
129
  proposalPdfUrl: (t) => `${ct}/documents/proposal/${encodeURIComponent(t)}/pdf`,
130
130
  // Masters
131
- listMasters: (t, n) => E(
131
+ listMasters: (t, n) => L(
132
132
  `/masters/${t}${Be(n)}`
133
133
  ),
134
- searchMasters: (t, n) => E(`/masters/${t}/search?q=${encodeURIComponent(n)}`),
135
- searchDocuments: (t, n) => E(`/documents/${t}/search?q=${encodeURIComponent(n)}`),
134
+ searchMasters: (t, n) => L(`/masters/${t}/search?q=${encodeURIComponent(n)}`),
135
+ searchDocuments: (t, n) => L(`/documents/${t}/search?q=${encodeURIComponent(n)}`),
136
136
  searchLink: async (t, n) => {
137
137
  try {
138
- const a = await E(`/masters/${t}/search?q=${encodeURIComponent(n)}`);
138
+ const a = await L(`/masters/${t}/search?q=${encodeURIComponent(n)}`);
139
139
  if (a.length > 0) return a;
140
140
  } catch {
141
141
  }
142
- return E(`/documents/${t}/search?q=${encodeURIComponent(n)}`);
142
+ return L(`/documents/${t}/search?q=${encodeURIComponent(n)}`);
143
143
  },
144
- getMaster: (t, n) => E(`/masters/${t}/${encodeURIComponent(n)}`),
145
- currencies: (t) => E(
144
+ getMaster: (t, n) => L(`/masters/${t}/${encodeURIComponent(n)}`),
145
+ currencies: (t) => L(
146
146
  `/accounting/currencies${Be({ company: t })}`
147
147
  ),
148
- createMaster: (t, n) => E(`/masters/${t}`, { method: "POST", body: JSON.stringify(n) }),
149
- updateMaster: (t, n, a) => E(`/masters/${t}/${encodeURIComponent(n)}`, {
148
+ createMaster: (t, n) => L(`/masters/${t}`, { method: "POST", body: JSON.stringify(n) }),
149
+ updateMaster: (t, n, a) => L(`/masters/${t}/${encodeURIComponent(n)}`, {
150
150
  method: "PUT",
151
151
  body: JSON.stringify(a)
152
152
  }),
153
- deleteMaster: (t, n) => E(`/masters/${t}/${encodeURIComponent(n)}`, { method: "DELETE" }),
153
+ deleteMaster: (t, n) => L(`/masters/${t}/${encodeURIComponent(n)}`, { method: "DELETE" }),
154
154
  // Reports
155
- trialBalance: (t) => E(
155
+ trialBalance: (t) => L(
156
156
  `/reports/trial-balance${Be(t)}`
157
157
  ),
158
- chartOfAccounts: (t) => E(
158
+ chartOfAccounts: (t) => L(
159
159
  `/reports/chart-of-accounts${Be(t)}`
160
160
  ),
161
- generalLedger: (t) => E(`/reports/general-ledger${Be(t)}`),
162
- stockBalance: (t) => E(`/reports/stock-balance${Be(t)}`),
163
- dashboardSummary: (t) => E(`/reports/dashboard-summary${Be({ company: t })}`),
164
- profitAndLoss: (t) => E(`/reports/profit-and-loss${Be(t)}`),
165
- balanceSheet: (t) => E(`/reports/balance-sheet${Be(t)}`),
166
- arAging: (t) => E(`/reports/ar-aging${Be(t)}`),
167
- apAging: (t) => E(`/reports/ap-aging${Be(t)}`),
168
- analyticsMetrics: () => E("/reports/analytics/metrics"),
169
- analytics: (t) => E(`/reports/analytics${Be(t)}`),
170
- runtimeDatasets: () => E("/reports/runtime/datasets"),
171
- runtimeData: (t) => E("/reports/runtime/data", { method: "POST", body: JSON.stringify(t) }),
172
- createRuntimeDraft: (t) => E("/reports/runtime/drafts", { method: "POST", body: JSON.stringify(t) }),
173
- getRuntimeDraft: (t) => E(`/reports/runtime/drafts/${encodeURIComponent(t)}`),
174
- listRuntimeDrafts: () => E("/reports/runtime/drafts"),
175
- deleteRuntimeDraft: (t) => E(`/reports/runtime/drafts/${encodeURIComponent(t)}`, {
161
+ generalLedger: (t) => L(`/reports/general-ledger${Be(t)}`),
162
+ stockBalance: (t) => L(`/reports/stock-balance${Be(t)}`),
163
+ dashboardSummary: (t) => L(`/reports/dashboard-summary${Be({ company: t })}`),
164
+ profitAndLoss: (t) => L(`/reports/profit-and-loss${Be(t)}`),
165
+ balanceSheet: (t) => L(`/reports/balance-sheet${Be(t)}`),
166
+ arAging: (t) => L(`/reports/ar-aging${Be(t)}`),
167
+ apAging: (t) => L(`/reports/ap-aging${Be(t)}`),
168
+ analyticsMetrics: () => L("/reports/analytics/metrics"),
169
+ analytics: (t) => L(`/reports/analytics${Be(t)}`),
170
+ runtimeDatasets: () => L("/reports/runtime/datasets"),
171
+ runtimeData: (t) => L("/reports/runtime/data", { method: "POST", body: JSON.stringify(t) }),
172
+ createRuntimeDraft: (t) => L("/reports/runtime/drafts", { method: "POST", body: JSON.stringify(t) }),
173
+ getRuntimeDraft: (t) => L(`/reports/runtime/drafts/${encodeURIComponent(t)}`),
174
+ listRuntimeDrafts: () => L("/reports/runtime/drafts"),
175
+ deleteRuntimeDraft: (t) => L(`/reports/runtime/drafts/${encodeURIComponent(t)}`, {
176
176
  method: "DELETE"
177
177
  }),
178
178
  // Setup
179
- setupStatus: () => E("/setup/status"),
180
- createCompany: (t) => E("/setup/company", { method: "POST", body: JSON.stringify(t) }),
181
- seedDemo: () => E("/setup/seed-demo", { method: "POST" }),
182
- seedHistory: (t) => E(
179
+ setupStatus: () => L("/setup/status"),
180
+ createCompany: (t) => L("/setup/company", { method: "POST", body: JSON.stringify(t) }),
181
+ seedDemo: () => L("/setup/seed-demo", { method: "POST" }),
182
+ seedHistory: (t) => L(
183
183
  "/setup/seed-history",
184
184
  { method: "POST", body: JSON.stringify(t ?? {}) }
185
185
  ),
186
- importAccountBalances: (t) => E("/setup/opening-balances/accounts", { method: "POST", body: JSON.stringify(t) }),
187
- importStockBalances: (t) => E("/setup/opening-balances/stock", { method: "POST", body: JSON.stringify(t) }),
188
- importOutstandingInvoices: (t) => E("/setup/opening-balances/invoices", { method: "POST", body: JSON.stringify(t) }),
186
+ importAccountBalances: (t) => L("/setup/opening-balances/accounts", { method: "POST", body: JSON.stringify(t) }),
187
+ importStockBalances: (t) => L("/setup/opening-balances/stock", { method: "POST", body: JSON.stringify(t) }),
188
+ importOutstandingInvoices: (t) => L("/setup/opening-balances/invoices", { method: "POST", body: JSON.stringify(t) }),
189
189
  // Auth
190
- authSetupStatus: () => E("/auth/setup-status"),
190
+ authSetupStatus: () => L("/auth/setup-status"),
191
191
  // Social login is a full-page navigation, not a fetch — build the URL the
192
192
  // browser should be sent to. `link` starts a "link to my account" flow.
193
193
  oauthLoginUrl: (t, n) => {
194
194
  const a = new URLSearchParams();
195
195
  n != null && n.link && a.set("link", "1"), n != null && n.invite && a.set("invite", n.invite);
196
196
  const s = a.toString() ? `?${a.toString()}` : "";
197
- return Ja(`/auth/${encodeURIComponent(t)}/login${s}`);
197
+ return Za(`/auth/${encodeURIComponent(t)}/login${s}`);
198
198
  },
199
- oauthListIdentities: () => E("/auth/oauth/identities"),
200
- authRegister: (t) => E("/auth/register", { method: "POST", body: JSON.stringify(t) }),
201
- authLogin: (t, n) => E("/auth/login", { method: "POST", body: JSON.stringify({ email: t, password: n }) }),
202
- authLogout: () => E("/auth/logout", { method: "POST" }),
203
- authMe: () => E("/auth/me"),
204
- authChangePassword: (t, n) => E("/auth/change-password", {
199
+ oauthListIdentities: () => L("/auth/oauth/identities"),
200
+ authRegister: (t) => L("/auth/register", { method: "POST", body: JSON.stringify(t) }),
201
+ authLogin: (t, n) => L("/auth/login", { method: "POST", body: JSON.stringify({ email: t, password: n }) }),
202
+ authLogout: () => L("/auth/logout", { method: "POST" }),
203
+ authMe: () => L("/auth/me"),
204
+ authChangePassword: (t, n) => L("/auth/change-password", {
205
205
  method: "POST",
206
206
  body: JSON.stringify({ current_password: t, new_password: n })
207
207
  }),
208
- authSetPassword: (t) => E("/auth/set-password", {
208
+ authSetPassword: (t) => L("/auth/set-password", {
209
209
  method: "POST",
210
210
  body: JSON.stringify({ new_password: t })
211
211
  }),
212
- authInvite: (t, n) => E("/auth/invite", { method: "POST", body: JSON.stringify({ email: t, role: n }) }),
213
- authListUsers: () => E("/auth/users"),
214
- authChangeRole: (t, n) => E(`/auth/users/${encodeURIComponent(t)}/role`, { method: "PUT", body: JSON.stringify({ role: n }) }),
215
- authDisableUser: (t) => E(`/auth/users/${encodeURIComponent(t)}`, { method: "DELETE" }),
216
- authListInvites: () => E("/auth/invites"),
217
- authRevokeInvite: (t) => E(`/auth/invites/${encodeURIComponent(t)}`, { method: "DELETE" }),
218
- getPublicManagerStatus: () => E("/auth/public-manager"),
219
- createPublicManager: () => E("/auth/public-manager", { method: "POST" }),
220
- removePublicManager: () => E("/auth/public-manager", { method: "DELETE" }),
221
- getSettings: () => E("/auth/settings"),
222
- updateSettings: (t) => E("/auth/settings", { method: "PUT", body: JSON.stringify(t) }),
223
- getApiKeys: () => E("/auth/api-keys"),
224
- createApiKey: (t, n) => E("/auth/api-keys", { method: "POST", body: JSON.stringify({ name: t, role: n }) }),
225
- revokeApiKey: (t) => E(
212
+ authInvite: (t, n) => L("/auth/invite", { method: "POST", body: JSON.stringify({ email: t, role: n }) }),
213
+ authListUsers: () => L("/auth/users"),
214
+ authChangeRole: (t, n) => L(`/auth/users/${encodeURIComponent(t)}/role`, { method: "PUT", body: JSON.stringify({ role: n }) }),
215
+ authDisableUser: (t) => L(`/auth/users/${encodeURIComponent(t)}`, { method: "DELETE" }),
216
+ authListInvites: () => L("/auth/invites"),
217
+ authRevokeInvite: (t) => L(`/auth/invites/${encodeURIComponent(t)}`, { method: "DELETE" }),
218
+ getPublicManagerStatus: () => L("/auth/public-manager"),
219
+ createPublicManager: () => L("/auth/public-manager", { method: "POST" }),
220
+ removePublicManager: () => L("/auth/public-manager", { method: "DELETE" }),
221
+ getSettings: () => L("/auth/settings"),
222
+ updateSettings: (t) => L("/auth/settings", { method: "PUT", body: JSON.stringify(t) }),
223
+ getApiKeys: () => L("/auth/api-keys"),
224
+ createApiKey: (t, n) => L("/auth/api-keys", { method: "POST", body: JSON.stringify({ name: t, role: n }) }),
225
+ revokeApiKey: (t) => L(
226
226
  `/auth/api-keys/${encodeURIComponent(t)}/revoke`,
227
227
  { method: "POST" }
228
228
  ),
229
- deleteApiKey: (t) => E(
229
+ deleteApiKey: (t) => L(
230
230
  `/auth/api-keys/${encodeURIComponent(t)}`,
231
231
  { method: "DELETE" }
232
232
  ),
233
- getDemoSpend: () => E("/admin/demo-spend")
234
- }, ea = Kn(null);
235
- function Xa({ children: t }) {
236
- const [n, a] = C(null), [s, i] = C(!0);
233
+ getDemoSpend: () => L("/admin/demo-spend")
234
+ }, ta = jn(null);
235
+ function er({ children: t }) {
236
+ const [n, a] = S(null), [s, i] = S(!0);
237
237
  se(() => {
238
238
  I.authMe().then((m) => a(m)).catch(() => a(null)).finally(() => i(!1));
239
239
  }, []);
@@ -256,14 +256,14 @@ function Xa({ children: t }) {
256
256
  } catch {
257
257
  }
258
258
  }, []);
259
- return /* @__PURE__ */ e(ea.Provider, { value: { user: n, loading: s, login: o, register: l, logout: c, refreshUser: g }, children: t });
259
+ return /* @__PURE__ */ e(ta.Provider, { value: { user: n, loading: s, login: o, register: l, logout: c, refreshUser: g }, children: t });
260
260
  }
261
261
  function st() {
262
- const t = Vn(ea);
262
+ const t = Kn(ta);
263
263
  if (!t) throw new Error("useAuth must be used within AuthProvider");
264
264
  return t;
265
265
  }
266
- const ta = Kn(null), fn = {
266
+ const na = jn(null), fn = {
267
267
  quotation: { group: "Selling", item: "Quotation" },
268
268
  "sales-order": { group: "Selling", item: "Sales Order" },
269
269
  "sales-invoice": { group: "Selling", item: "Sales Invoice" },
@@ -289,7 +289,7 @@ const ta = Kn(null), fn = {
289
289
  function Kt(t) {
290
290
  return typeof t != "string" ? null : t.trim().toLowerCase().replace(/\s+/g, "-");
291
291
  }
292
- function er(t, n) {
292
+ function tr(t, n) {
293
293
  if (t === "create_custom_analytics_report" || t === "update_custom_analytics_report")
294
294
  return { group: "Custom Analytics", item: "" };
295
295
  if (!n) return null;
@@ -312,11 +312,11 @@ function bn(t) {
312
312
  attachments: t.attachments
313
313
  };
314
314
  }
315
- const na = "lambda-erp:known-chat-sessions";
315
+ const aa = "lambda-erp:known-chat-sessions";
316
316
  function an() {
317
317
  if (typeof localStorage > "u") return /* @__PURE__ */ new Set();
318
318
  try {
319
- const t = localStorage.getItem(na);
319
+ const t = localStorage.getItem(aa);
320
320
  if (!t) return /* @__PURE__ */ new Set();
321
321
  const n = JSON.parse(t);
322
322
  return new Set(Array.isArray(n) ? n.filter((a) => typeof a == "string") : []);
@@ -324,22 +324,22 @@ function an() {
324
324
  return /* @__PURE__ */ new Set();
325
325
  }
326
326
  }
327
- function aa(t) {
327
+ function ra(t) {
328
328
  if (!(typeof localStorage > "u"))
329
329
  try {
330
- localStorage.setItem(na, JSON.stringify([...t]));
330
+ localStorage.setItem(aa, JSON.stringify([...t]));
331
331
  } catch {
332
332
  }
333
333
  }
334
- function ra(t) {
334
+ function sa(t) {
335
335
  const n = an();
336
- n.has(t) || (n.add(t), aa(n));
336
+ n.has(t) || (n.add(t), ra(n));
337
337
  }
338
338
  function vn(t) {
339
339
  const n = an();
340
- n.delete(t) && aa(n);
340
+ n.delete(t) && ra(n);
341
341
  }
342
- function tr() {
342
+ function nr() {
343
343
  return typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID() : `req-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
344
344
  }
345
345
  function tt(t) {
@@ -347,8 +347,8 @@ function tt(t) {
347
347
  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();
348
348
  return Number.isNaN(a) ? 0 : a;
349
349
  }
350
- function nr({ children: t }) {
351
- const n = We(), [a, s] = C([]), [i, o] = C({}), [l, c] = C({}), [g, m] = C({}), [h, u] = C({}), [N, x] = C({}), [v, f] = C({}), [T, P] = C({}), [b, d] = C(null), [p, _] = C("connecting"), [y, B] = C(0), D = te(null), O = te(null), G = te(/* @__PURE__ */ new Map()), ee = te(null), S = te({}), w = te({}), q = te(null);
350
+ function ar({ children: t }) {
351
+ const n = We(), [a, s] = S([]), [i, o] = S({}), [l, c] = S({}), [g, m] = S({}), [h, u] = S({}), [N, x] = S({}), [v, f] = S({}), [T, P] = S({}), [b, d] = S(null), [p, _] = S("connecting"), [y, B] = S(0), D = te(null), O = te(null), G = te(/* @__PURE__ */ new Map()), ee = te(null), C = te({}), w = te({}), q = te(null);
352
352
  function A(R) {
353
353
  for (const V of G.current.values())
354
354
  V.reject(new Error(R));
@@ -376,27 +376,27 @@ function nr({ children: t }) {
376
376
  }
377
377
  function _e(R) {
378
378
  return [...R].sort((V, W) => {
379
- const ve = tt(S.current[V.id]) || tt(V.last_message_at || void 0) || tt(V.created_at);
380
- return (tt(S.current[W.id]) || tt(W.last_message_at || void 0) || tt(W.created_at)) - ve;
379
+ const ve = tt(C.current[V.id]) || tt(V.last_message_at || void 0) || tt(V.created_at);
380
+ return (tt(C.current[W.id]) || tt(W.last_message_at || void 0) || tt(W.created_at)) - ve;
381
381
  });
382
382
  }
383
383
  function pe(R) {
384
384
  s((V) => _e(R(V)));
385
385
  }
386
386
  function fe(R, V) {
387
- const W = V || (/* @__PURE__ */ new Date()).toISOString(), ve = S.current[R];
388
- tt(W) >= tt(ve) && (S.current = {
389
- ...S.current,
387
+ const W = V || (/* @__PURE__ */ new Date()).toISOString(), ve = C.current[R];
388
+ tt(W) >= tt(ve) && (C.current = {
389
+ ...C.current,
390
390
  [R]: W
391
391
  });
392
392
  }
393
393
  function Ue(R) {
394
- const V = { ...S.current };
394
+ const V = { ...C.current };
395
395
  for (const W of R)
396
396
  W.last_message_at && !V[W.id] && (V[W.id] = W.last_message_at);
397
- S.current = V;
397
+ C.current = V;
398
398
  }
399
- function L(R) {
399
+ function E(R) {
400
400
  const V = D.current;
401
401
  if (!V || V.readyState !== WebSocket.OPEN)
402
402
  throw new Error("Chat is disconnected.");
@@ -404,14 +404,14 @@ function nr({ children: t }) {
404
404
  }
405
405
  function ne(R, V, W) {
406
406
  return new Promise((ve, xe) => {
407
- const Ae = tr();
407
+ const Ae = nr();
408
408
  G.current.set(Ae, {
409
409
  expectedType: W,
410
410
  resolve: ve,
411
411
  reject: xe
412
412
  });
413
413
  try {
414
- L({ type: R, request_id: Ae, ...V });
414
+ E({ type: R, request_id: Ae, ...V });
415
415
  } catch (ot) {
416
416
  G.current.delete(Ae), xe(ot instanceof Error ? ot : new Error("Chat request failed."));
417
417
  }
@@ -466,38 +466,38 @@ function nr({ children: t }) {
466
466
  if (me === "session_created") {
467
467
  const F = K.session;
468
468
  if (!F) return;
469
- ra(F.id), Ue([F]), pe((j) => [F, ...j.filter((H) => H.id !== F.id)]);
469
+ sa(F.id), Ue([F]), pe((j) => [F, ...j.filter((Q) => Q.id !== F.id)]);
470
470
  return;
471
471
  }
472
472
  if (me === "session_deleted" && M) {
473
- vn(M), pe((j) => j.filter((H) => H.id !== M)), o((j) => {
474
- const H = { ...j };
475
- return delete H[M], H;
473
+ vn(M), pe((j) => j.filter((Q) => Q.id !== M)), o((j) => {
474
+ const Q = { ...j };
475
+ return delete Q[M], Q;
476
476
  }), x((j) => {
477
- const H = { ...j };
478
- return delete H[M], H;
477
+ const Q = { ...j };
478
+ return delete Q[M], Q;
479
479
  }), f((j) => {
480
- const H = { ...j };
481
- return delete H[M], H;
480
+ const Q = { ...j };
481
+ return delete Q[M], Q;
482
482
  }), P((j) => {
483
- const H = { ...j };
484
- return delete H[M], H;
483
+ const Q = { ...j };
484
+ return delete Q[M], Q;
485
485
  }), c((j) => {
486
- const H = { ...j };
487
- return delete H[M], H;
486
+ const Q = { ...j };
487
+ return delete Q[M], Q;
488
488
  }), m((j) => {
489
- const H = { ...j };
490
- return delete H[M], H;
489
+ const Q = { ...j };
490
+ return delete Q[M], Q;
491
491
  }), u((j) => {
492
- const H = { ...j };
493
- return delete H[M], H;
492
+ const Q = { ...j };
493
+ return delete Q[M], Q;
494
494
  });
495
- const F = { ...S.current };
496
- delete F[M], S.current = F;
495
+ const F = { ...C.current };
496
+ delete F[M], C.current = F;
497
497
  return;
498
498
  }
499
499
  if (me === "history_loaded" && M) {
500
- const F = Array.isArray(K.messages) ? K.messages.map(bn) : [], j = K.before_id != null, H = !!K.has_more, qe = typeof K.oldest_id == "number" ? K.oldest_id : null;
500
+ const F = Array.isArray(K.messages) ? K.messages.map(bn) : [], j = K.before_id != null, Q = !!K.has_more, qe = typeof K.oldest_id == "number" ? K.oldest_id : null;
501
501
  o((le) => {
502
502
  if (j) {
503
503
  const ue = le[M] ?? [], gt = new Set(
@@ -508,7 +508,7 @@ function nr({ children: t }) {
508
508
  return { ...le, [M]: [...xt, ...ue] };
509
509
  }
510
510
  return { ...le, [M]: F };
511
- }), c((le) => ({ ...le, [M]: H })), m((le) => ({ ...le, [M]: qe })), u((le) => ({ ...le, [M]: !1 }));
511
+ }), c((le) => ({ ...le, [M]: Q })), m((le) => ({ ...le, [M]: qe })), u((le) => ({ ...le, [M]: !1 }));
512
512
  const Ne = typeof K.title == "string" ? K.title : null;
513
513
  if (Ne && pe(
514
514
  (le) => le.map((ue) => ue.id === M ? { ...ue, title: Ne } : ue)
@@ -526,7 +526,7 @@ function nr({ children: t }) {
526
526
  const F = K.message;
527
527
  if (!F) return;
528
528
  fe(M, F.created_at), F.role === "user" && ce(M, null), z(M, (j) => [
529
- ...j.filter((H) => H.type !== "thinking"),
529
+ ...j.filter((Q) => Q.type !== "thinking"),
530
530
  bn(F)
531
531
  ]), pe((j) => j);
532
532
  return;
@@ -555,15 +555,15 @@ function nr({ children: t }) {
555
555
  if (me === "session_title_updated" && M) {
556
556
  const F = typeof K.title == "string" ? K.title : "";
557
557
  pe(
558
- (j) => j.map((H) => H.id === M ? { ...H, title: F } : H)
558
+ (j) => j.map((Q) => Q.id === M ? { ...Q, title: F } : Q)
559
559
  );
560
560
  return;
561
561
  }
562
562
  if (me === "thinking" && M) {
563
563
  Y(M, !0), z(M, (F) => {
564
- const j = F.find((H) => H.type === "thinking");
564
+ const j = F.find((Q) => Q.type === "thinking");
565
565
  return [
566
- ...F.filter((H) => H.type !== "thinking"),
566
+ ...F.filter((Q) => Q.type !== "thinking"),
567
567
  {
568
568
  type: "thinking",
569
569
  content: `Thinking (step ${K.iteration})...`,
@@ -614,11 +614,11 @@ function nr({ children: t }) {
614
614
  const F = w.current[M];
615
615
  if (F && F.tool === String(K.tool || "") && K.success)
616
616
  if (F.tool === "create_custom_analytics_report" || F.tool === "update_custom_analytics_report") {
617
- const H = typeof K.report_id == "string" ? K.report_id : void 0, qe = typeof ((ot = F.args) == null ? void 0 : ot.report_id) == "string" ? F.args.report_id : void 0;
618
- ge("Custom Analytics", H || qe || ""), n.invalidateQueries({ queryKey: ["runtime-drafts"] });
617
+ const Q = typeof K.report_id == "string" ? K.report_id : void 0, qe = typeof ((ot = F.args) == null ? void 0 : ot.report_id) == "string" ? F.args.report_id : void 0;
618
+ ge("Custom Analytics", Q || qe || ""), n.invalidateQueries({ queryKey: ["runtime-drafts"] });
619
619
  } else {
620
- const H = er(F.tool, F.args);
621
- H && ge(H.group, H.item);
620
+ const Q = tr(F.tool, F.args);
621
+ Q && ge(Q.group, Q.item);
622
622
  }
623
623
  w.current = {
624
624
  ...w.current,
@@ -685,7 +685,7 @@ function nr({ children: t }) {
685
685
  }
686
686
  function Ve(R, V) {
687
687
  try {
688
- L({ type: "demo_typing_done", session_id: R, seq: V });
688
+ E({ type: "demo_typing_done", session_id: R, seq: V });
689
689
  } catch {
690
690
  }
691
691
  }
@@ -724,7 +724,7 @@ function nr({ children: t }) {
724
724
  session_id: R,
725
725
  content: ve
726
726
  };
727
- return xe && (Ae.attachment_ids = W), L(Ae), !0;
727
+ return xe && (Ae.attachment_ids = W), E(Ae), !0;
728
728
  } catch {
729
729
  return Y(R, !1), !1;
730
730
  }
@@ -758,7 +758,7 @@ function nr({ children: t }) {
758
758
  return R ? T[R] ?? null : null;
759
759
  }
760
760
  return /* @__PURE__ */ e(
761
- ta.Provider,
761
+ na.Provider,
762
762
  {
763
763
  value: {
764
764
  sessions: a,
@@ -786,7 +786,7 @@ function nr({ children: t }) {
786
786
  );
787
787
  }
788
788
  function ut() {
789
- const t = Vn(ta);
789
+ const t = Kn(na);
790
790
  if (!t)
791
791
  throw new Error("useChat must be used within ChatProvider.");
792
792
  return t;
@@ -794,7 +794,7 @@ function ut() {
794
794
  const dt = [
795
795
  {
796
796
  label: "Introduction",
797
- icon: /* @__PURE__ */ e(Ra, { className: "h-4 w-4" }),
797
+ icon: /* @__PURE__ */ e(Ia, { className: "h-4 w-4" }),
798
798
  items: [
799
799
  { label: "Getting Started", path: "/tutorial" },
800
800
  { label: "Company Setup", path: "/setup" },
@@ -803,7 +803,7 @@ const dt = [
803
803
  },
804
804
  {
805
805
  label: "Selling",
806
- icon: /* @__PURE__ */ e(jn, { className: "h-4 w-4" }),
806
+ icon: /* @__PURE__ */ e(Gn, { className: "h-4 w-4" }),
807
807
  items: [
808
808
  { label: "Quotation", path: "/app/quotation" },
809
809
  { label: "Proposal", path: "/app/proposal" },
@@ -814,7 +814,7 @@ const dt = [
814
814
  },
815
815
  {
816
816
  label: "Buying",
817
- icon: /* @__PURE__ */ e(Ia, { className: "h-4 w-4" }),
817
+ icon: /* @__PURE__ */ e(Ba, { className: "h-4 w-4" }),
818
818
  items: [
819
819
  { label: "Purchase Order", path: "/app/purchase-order" },
820
820
  { label: "Purchase Invoice", path: "/app/purchase-invoice" }
@@ -834,7 +834,7 @@ const dt = [
834
834
  },
835
835
  {
836
836
  label: "Stock",
837
- icon: /* @__PURE__ */ e(Gn, { className: "h-4 w-4" }),
837
+ icon: /* @__PURE__ */ e(Wn, { className: "h-4 w-4" }),
838
838
  items: [
839
839
  { label: "Stock Entry", path: "/app/stock-entry" },
840
840
  { label: "Delivery Note", path: "/app/delivery-note" },
@@ -843,7 +843,7 @@ const dt = [
843
843
  },
844
844
  {
845
845
  label: "Reports",
846
- icon: /* @__PURE__ */ e(Ba, { className: "h-4 w-4" }),
846
+ icon: /* @__PURE__ */ e(Ea, { className: "h-4 w-4" }),
847
847
  items: [
848
848
  { label: "Trial Balance", path: "/reports/trial-balance" },
849
849
  { label: "Profit & Loss", path: "/reports/profit-and-loss" },
@@ -868,7 +868,7 @@ const dt = [
868
868
  },
869
869
  {
870
870
  label: "Settings",
871
- icon: /* @__PURE__ */ e(Ea, { className: "h-4 w-4" }),
871
+ icon: /* @__PURE__ */ e(Oa, { className: "h-4 w-4" }),
872
872
  items: [
873
873
  { label: "General", path: "/admin/settings" },
874
874
  { label: "Pricing Rule", path: "/app/pricing-rule" },
@@ -876,10 +876,10 @@ const dt = [
876
876
  ]
877
877
  }
878
878
  ];
879
- function ar() {
879
+ function rr() {
880
880
  return dt;
881
881
  }
882
- function Po(t, n) {
882
+ function _o(t, n) {
883
883
  const a = dt.findIndex((s) => s.label === t.label);
884
884
  if (a >= 0) {
885
885
  dt[a] = t;
@@ -887,25 +887,25 @@ function Po(t, n) {
887
887
  }
888
888
  (n == null ? void 0 : n.index) != null ? dt.splice(n.index, 0, t) : dt.push(t);
889
889
  }
890
- function _o(t, n) {
890
+ function To(t, n) {
891
891
  const a = dt.find((s) => s.label === t);
892
892
  a ? a.items.push(n) : dt.push({ label: t, icon: null, items: [n] });
893
893
  }
894
894
  let Jt = { appName: "Lambda ERP" };
895
- function To(t) {
895
+ function Ro(t) {
896
896
  if (Jt = { ...Jt, ...t }, !(typeof document > "u") && (t.appName && (document.title = t.appName), t.tokens)) {
897
897
  const n = document.documentElement;
898
898
  for (const [a, s] of Object.entries(t.tokens))
899
899
  n.style.setProperty(a.startsWith("--") ? a : `--${a}`, s);
900
900
  }
901
901
  }
902
- function rr() {
902
+ function sr() {
903
903
  return Jt;
904
904
  }
905
- function Le(...t) {
905
+ function Ee(...t) {
906
906
  return t.filter(Boolean).join(" ");
907
907
  }
908
- function Ee(t, n = "USD") {
908
+ function Le(t, n = "USD") {
909
909
  return new Intl.NumberFormat("en-US", {
910
910
  style: "currency",
911
911
  currency: n,
@@ -929,20 +929,20 @@ function Fe(t, n) {
929
929
  const a = parseFloat(String(t ?? 0)) || 0;
930
930
  return n !== void 0 ? parseFloat(a.toFixed(n)) : a;
931
931
  }
932
- const sa = "sidebar-collapsed";
932
+ const ia = "sidebar-collapsed";
933
933
  function jt() {
934
934
  try {
935
- const t = localStorage.getItem(sa);
935
+ const t = localStorage.getItem(ia);
936
936
  return t ? new Set(JSON.parse(t)) : /* @__PURE__ */ new Set();
937
937
  } catch {
938
938
  return /* @__PURE__ */ new Set();
939
939
  }
940
940
  }
941
941
  function xn(t) {
942
- localStorage.setItem(sa, JSON.stringify([...t]));
942
+ localStorage.setItem(ia, JSON.stringify([...t]));
943
943
  }
944
944
  function rn(t) {
945
- const [n, a] = C(() => !jt().has(t)), s = Pe(() => {
945
+ const [n, a] = S(() => !jt().has(t)), s = Pe(() => {
946
946
  a((o) => {
947
947
  const l = jt();
948
948
  return o ? l.add(t) : l.delete(t), xn(l), !o;
@@ -967,8 +967,8 @@ const sn = {
967
967
  Settings: "bg-purple-300 text-purple-950 ring-2 ring-inset ring-purple-100",
968
968
  "Custom Analytics": "bg-indigo-300 text-indigo-950 ring-2 ring-inset ring-indigo-100"
969
969
  };
970
- function sr() {
971
- const [t, n] = rn("chats"), a = St(), s = ze(), { t: i } = X(), { sessions: o, createSession: l, deleteSession: c } = ut(), g = async () => {
970
+ function ir() {
971
+ const [t, n] = rn("chats"), a = Ct(), s = ze(), { t: i } = Z(), { sessions: o, createSession: l, deleteSession: c } = ut(), g = async () => {
972
972
  try {
973
973
  const h = await l();
974
974
  s(`/chat/${h.id}`);
@@ -989,7 +989,7 @@ function sr() {
989
989
  onClick: n,
990
990
  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",
991
991
  children: [
992
- /* @__PURE__ */ e(Oa, { className: "h-4 w-4" }),
992
+ /* @__PURE__ */ e(qa, { className: "h-4 w-4" }),
993
993
  /* @__PURE__ */ e("span", { className: "flex-1 text-left", children: i("nav.chats") }),
994
994
  t ? /* @__PURE__ */ e(zt, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ e(Mt, { className: "h-3.5 w-3.5" })
995
995
  ]
@@ -1002,7 +1002,7 @@ function sr() {
1002
1002
  onClick: g,
1003
1003
  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",
1004
1004
  children: [
1005
- /* @__PURE__ */ e(Wn, { className: "h-3.5 w-3.5" }),
1005
+ /* @__PURE__ */ e(Hn, { className: "h-3.5 w-3.5" }),
1006
1006
  i("nav.newChat")
1007
1007
  ]
1008
1008
  }
@@ -1014,7 +1014,7 @@ function sr() {
1014
1014
  Ot,
1015
1015
  {
1016
1016
  to: `/chat/${h.id}`,
1017
- className: Le(
1017
+ className: Ee(
1018
1018
  "relative block truncate px-4 py-1.5 pl-10 pr-8 text-sm transition-colors",
1019
1019
  u ? "bg-surface-subtle font-medium text-fg" : "text-fg-muted hover:bg-surface-subtle hover:text-fg"
1020
1020
  ),
@@ -1028,7 +1028,7 @@ function sr() {
1028
1028
  onClick: (N) => m(N, h.id),
1029
1029
  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",
1030
1030
  title: i("nav.deleteChat"),
1031
- children: /* @__PURE__ */ e(Hn, { className: "h-3.5 w-3.5" })
1031
+ children: /* @__PURE__ */ e(Qn, { className: "h-3.5 w-3.5" })
1032
1032
  }
1033
1033
  )
1034
1034
  ] }, h.id);
@@ -1045,8 +1045,8 @@ function on() {
1045
1045
  }
1046
1046
  );
1047
1047
  }
1048
- function ir() {
1049
- const [t, n, a] = rn("custom-analytics"), s = St(), i = ze(), o = We(), { t: l } = X(), { navigationFlash: c, sessions: g, createSession: m } = ut(), h = (c == null ? void 0 : c.group) === "Custom Analytics", u = sn["Custom Analytics"], { data: N } = oe({
1048
+ function or() {
1049
+ const [t, n, a] = rn("custom-analytics"), s = Ct(), i = ze(), o = We(), { t: l } = Z(), { navigationFlash: c, sessions: g, createSession: m } = ut(), h = (c == null ? void 0 : c.group) === "Custom Analytics", u = sn["Custom Analytics"], { data: N } = oe({
1050
1050
  queryKey: ["runtime-drafts"],
1051
1051
  queryFn: () => I.listRuntimeDrafts(),
1052
1052
  staleTime: 3e4
@@ -1080,12 +1080,12 @@ function ir() {
1080
1080
  {
1081
1081
  type: "button",
1082
1082
  onClick: n,
1083
- className: Le(
1083
+ className: Ee(
1084
1084
  "flex w-full items-center gap-2 px-4 py-2 text-xs font-semibold uppercase tracking-wider text-fg-muted transition-all duration-300 hover:text-fg",
1085
1085
  h && u
1086
1086
  ),
1087
1087
  children: [
1088
- /* @__PURE__ */ e(qa, { className: "h-4 w-4" }),
1088
+ /* @__PURE__ */ e(za, { className: "h-4 w-4" }),
1089
1089
  /* @__PURE__ */ e("span", { className: "flex-1 text-left", children: l("nav.customAnalytics") }),
1090
1090
  t ? /* @__PURE__ */ e(zt, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ e(Mt, { className: "h-3.5 w-3.5" })
1091
1091
  ]
@@ -1098,7 +1098,7 @@ function ir() {
1098
1098
  onClick: T,
1099
1099
  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",
1100
1100
  children: [
1101
- /* @__PURE__ */ e(Wn, { className: "h-3.5 w-3.5" }),
1101
+ /* @__PURE__ */ e(Hn, { className: "h-3.5 w-3.5" }),
1102
1102
  l("nav.newAnalytics")
1103
1103
  ]
1104
1104
  }
@@ -1110,7 +1110,7 @@ function ir() {
1110
1110
  Ot,
1111
1111
  {
1112
1112
  to: b,
1113
- className: Le(
1113
+ className: Ee(
1114
1114
  "relative block truncate px-4 py-1.5 pl-10 pr-8 text-sm transition-all duration-300",
1115
1115
  !d && "text-fg-muted hover:bg-surface-subtle hover:text-fg",
1116
1116
  d && "bg-surface-subtle font-medium text-fg",
@@ -1127,7 +1127,7 @@ function ir() {
1127
1127
  onClick: (_) => f(_, P.id),
1128
1128
  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",
1129
1129
  title: l("nav.deleteReport"),
1130
- children: /* @__PURE__ */ e(Hn, { className: "h-3.5 w-3.5" })
1130
+ children: /* @__PURE__ */ e(Qn, { className: "h-3.5 w-3.5" })
1131
1131
  }
1132
1132
  )
1133
1133
  ] }, P.id);
@@ -1135,15 +1135,15 @@ function ir() {
1135
1135
  ] })
1136
1136
  ] });
1137
1137
  }
1138
- function or({ group: t }) {
1139
- const [n, a] = rn(t.label), { t: s } = X(), { navigationFlash: i } = ut(), o = (i == null ? void 0 : i.group) === t.label, l = sn[t.label] ?? "bg-blue-300 text-blue-950 ring-2 ring-inset ring-blue-100";
1138
+ function lr({ group: t }) {
1139
+ const [n, a] = rn(t.label), { t: s } = Z(), { navigationFlash: i } = ut(), o = (i == null ? void 0 : i.group) === t.label, l = sn[t.label] ?? "bg-blue-300 text-blue-950 ring-2 ring-inset ring-blue-100";
1140
1140
  return /* @__PURE__ */ r("div", { children: [
1141
1141
  /* @__PURE__ */ r(
1142
1142
  "button",
1143
1143
  {
1144
1144
  type: "button",
1145
1145
  onClick: a,
1146
- className: Le(
1146
+ className: Ee(
1147
1147
  "flex w-full items-center gap-2 px-4 py-2 text-xs font-semibold uppercase tracking-wider text-fg-muted transition-all duration-300 hover:text-fg",
1148
1148
  o && l
1149
1149
  ),
@@ -1163,7 +1163,7 @@ function or({ group: t }) {
1163
1163
  {
1164
1164
  to: c.path,
1165
1165
  end: g,
1166
- className: ({ isActive: m }) => Le(
1166
+ className: ({ isActive: m }) => Ee(
1167
1167
  "relative block px-4 py-1.5 pl-10 text-sm transition-all duration-300",
1168
1168
  !m && "text-fg-muted hover:bg-surface-subtle hover:text-fg",
1169
1169
  m && "bg-surface-subtle font-medium text-fg",
@@ -1178,10 +1178,10 @@ function or({ group: t }) {
1178
1178
  }) })
1179
1179
  ] });
1180
1180
  }
1181
- const lr = {
1181
+ const cr = {
1182
1182
  "/setup/opening-balances": "opening_balances_enabled"
1183
1183
  };
1184
- function cr({ isMobileOpen: t = !1, onClose: n }) {
1184
+ function dr({ isMobileOpen: t = !1, onClose: n }) {
1185
1185
  var c;
1186
1186
  const { data: a } = oe({
1187
1187
  queryKey: ["settings"],
@@ -1191,18 +1191,18 @@ function cr({ isMobileOpen: t = !1, onClose: n }) {
1191
1191
  queryKey: ["setup-status"],
1192
1192
  queryFn: () => I.setupStatus(),
1193
1193
  staleTime: 6e4
1194
- }), i = (c = s == null ? void 0 : s.companies) == null ? void 0 : c[0], o = (i == null ? void 0 : i.company_name) || (i == null ? void 0 : i.name) || rr().appName, l = Se(() => ar().map((m) => ({
1194
+ }), i = (c = s == null ? void 0 : s.companies) == null ? void 0 : c[0], o = (i == null ? void 0 : i.company_name) || (i == null ? void 0 : i.name) || sr().appName, l = Ce(() => rr().map((m) => ({
1195
1195
  ...m,
1196
1196
  items: m.items.filter((h) => {
1197
1197
  if (h.path === "/setup" && (s != null && s.setup_complete)) return !1;
1198
- const u = lr[h.path];
1198
+ const u = cr[h.path];
1199
1199
  return !u || !a ? !0 : a[u] !== "0";
1200
1200
  })
1201
1201
  })), [a, s]);
1202
1202
  return /* @__PURE__ */ r(
1203
1203
  "aside",
1204
1204
  {
1205
- className: Le(
1205
+ className: Ee(
1206
1206
  "fixed left-0 top-0 z-40 flex h-dvh w-64 flex-col border-r border-line bg-surface transition-transform duration-300 ease-out",
1207
1207
  "md:translate-x-0",
1208
1208
  t ? "translate-x-0 shadow-2xl" : "-translate-x-full"
@@ -1242,16 +1242,16 @@ function cr({ isMobileOpen: t = !1, onClose: n }) {
1242
1242
  )
1243
1243
  ] }),
1244
1244
  /* @__PURE__ */ r("nav", { className: "flex-1 overflow-y-auto py-3", children: [
1245
- /* @__PURE__ */ e(sr, {}),
1246
1245
  /* @__PURE__ */ e(ir, {}),
1247
- l.map((g) => /* @__PURE__ */ e(or, { group: g }, g.label))
1246
+ /* @__PURE__ */ e(or, {}),
1247
+ l.map((g) => /* @__PURE__ */ e(lr, { group: g }, g.label))
1248
1248
  ] })
1249
1249
  ]
1250
1250
  }
1251
1251
  );
1252
1252
  }
1253
1253
  const Nn = (t) => t.replace(/-/g, " ").replace(/\b\w/g, (n) => n.toUpperCase());
1254
- function dr(t, n) {
1254
+ function ur(t, n) {
1255
1255
  const a = t.split("/").filter(Boolean);
1256
1256
  if (a[0] === "setup") return n("titles.setup");
1257
1257
  if (a[0] === "tutorial") return n("titles.tutorial");
@@ -1270,17 +1270,17 @@ function dr(t, n) {
1270
1270
  }
1271
1271
  return n("titles.dashboard");
1272
1272
  }
1273
- function ur() {
1274
- return /* @__PURE__ */ e(nr, { children: /* @__PURE__ */ e(mr, {}) });
1275
- }
1276
1273
  function mr() {
1277
- const { pathname: t } = St(), { user: n, logout: a } = st(), { navigationFlash: s } = ut(), { t: i } = X(), o = dr(t, i), [l, c] = C(!1);
1274
+ return /* @__PURE__ */ e(ar, { children: /* @__PURE__ */ e(pr, {}) });
1275
+ }
1276
+ function pr() {
1277
+ const { pathname: t } = Ct(), { user: n, logout: a } = st(), { navigationFlash: s } = ut(), { t: i } = Z(), o = ur(t, i), [l, c] = S(!1);
1278
1278
  se(() => {
1279
1279
  c(!1);
1280
1280
  }, [t]);
1281
1281
  const g = s ? sn[s.group] : null;
1282
1282
  return /* @__PURE__ */ r("div", { className: "flex h-dvh bg-surface-muted", children: [
1283
- /* @__PURE__ */ e(cr, { isMobileOpen: l, onClose: () => c(!1) }),
1283
+ /* @__PURE__ */ e(dr, { isMobileOpen: l, onClose: () => c(!1) }),
1284
1284
  l && /* @__PURE__ */ e(
1285
1285
  "div",
1286
1286
  {
@@ -1296,7 +1296,7 @@ function mr() {
1296
1296
  "button",
1297
1297
  {
1298
1298
  onClick: () => c(!0),
1299
- className: Le(
1299
+ className: Ee(
1300
1300
  "rounded p-1 text-gray-500 transition-all duration-300 hover:bg-gray-100 hover:text-gray-900 md:hidden",
1301
1301
  g
1302
1302
  ),
@@ -1321,19 +1321,19 @@ function mr() {
1321
1321
  )
1322
1322
  ] })
1323
1323
  ] }),
1324
- /* @__PURE__ */ e("main", { className: "flex-1 overflow-auto p-4 md:p-6", children: /* @__PURE__ */ e(Da, {}) })
1324
+ /* @__PURE__ */ e("main", { className: "flex-1 overflow-auto p-4 md:p-6", children: /* @__PURE__ */ e(Aa, {}) })
1325
1325
  ] })
1326
1326
  ] });
1327
1327
  }
1328
- function pr({ children: t }) {
1328
+ function hr({ children: t }) {
1329
1329
  const { user: n, loading: a } = st();
1330
- 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(we, { children: t }) : /* @__PURE__ */ e(Aa, { to: "/login", replace: !0 });
1330
+ 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(we, { children: t }) : /* @__PURE__ */ e(Pa, { to: "/login", replace: !0 });
1331
1331
  }
1332
1332
  function $({ title: t, children: n, className: a, interactive: s }) {
1333
1333
  return /* @__PURE__ */ r(
1334
1334
  "div",
1335
1335
  {
1336
- className: Le(
1336
+ className: Ee(
1337
1337
  // Surface + 1px hairline ring + multi-layer soft shadow gives
1338
1338
  // the card depth on a tinted page background. The shadow is
1339
1339
  // closer in feel to Linear / Vercel than Tailwind's default
@@ -1350,7 +1350,7 @@ function $({ title: t, children: n, className: a, interactive: s }) {
1350
1350
  }
1351
1351
  );
1352
1352
  }
1353
- const hr = {
1353
+ const gr = {
1354
1354
  default: "bg-brand/10 text-brand ring-1 ring-inset ring-brand/20",
1355
1355
  success: "bg-emerald-50 text-emerald-700 ring-1 ring-inset ring-emerald-200",
1356
1356
  warning: "bg-amber-50 text-amber-700 ring-1 ring-inset ring-amber-200",
@@ -1361,9 +1361,9 @@ function Tt({ variant: t = "default", dot: n, children: a, className: s }) {
1361
1361
  return /* @__PURE__ */ r(
1362
1362
  "span",
1363
1363
  {
1364
- className: Le(
1364
+ className: Ee(
1365
1365
  "inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-xs font-medium",
1366
- hr[t],
1366
+ gr[t],
1367
1367
  s
1368
1368
  ),
1369
1369
  children: [
@@ -1373,7 +1373,7 @@ function Tt({ variant: t = "default", dot: n, children: a, className: s }) {
1373
1373
  }
1374
1374
  );
1375
1375
  }
1376
- const gr = {
1376
+ const fr = {
1377
1377
  Draft: "secondary",
1378
1378
  Open: "default",
1379
1379
  Submitted: "default",
@@ -1388,7 +1388,7 @@ const gr = {
1388
1388
  Overdue: "danger"
1389
1389
  };
1390
1390
  function ln({ status: t }) {
1391
- const { t: n } = X(), a = gr[t] ?? "secondary";
1391
+ const { t: n } = Z(), a = fr[t] ?? "secondary";
1392
1392
  return /* @__PURE__ */ e(Tt, { variant: a, children: n(`status.${t}`, { defaultValue: t }) });
1393
1393
  }
1394
1394
  function Oe(t) {
@@ -1411,7 +1411,7 @@ function At({ title: t, value: n, icon: a, tone: s }) {
1411
1411
  return /* @__PURE__ */ e($, { children: /* @__PURE__ */ r("div", { className: "flex items-start justify-between gap-4", children: [
1412
1412
  /* @__PURE__ */ r("div", { className: "min-w-0", children: [
1413
1413
  /* @__PURE__ */ e("p", { className: "text-sm font-medium text-fg-muted", children: t }),
1414
- /* @__PURE__ */ e("p", { className: "mt-1.5 text-2xl font-semibold tracking-tight tabular-nums text-fg", children: ((c) => Ee(c, o))(n ?? 0) })
1414
+ /* @__PURE__ */ e("p", { className: "mt-1.5 text-2xl font-semibold tracking-tight tabular-nums text-fg", children: ((c) => Le(c, o))(n ?? 0) })
1415
1415
  ] }),
1416
1416
  /* @__PURE__ */ e("div", { className: `shrink-0 rounded-lg p-2 ${i}`, children: /* @__PURE__ */ e(a, { className: "h-5 w-5", strokeWidth: 2 }) })
1417
1417
  ] }) });
@@ -1425,15 +1425,15 @@ function Pt() {
1425
1425
  /* @__PURE__ */ e("div", { className: "h-9 w-9 shrink-0 animate-pulse rounded-lg bg-surface-subtle" })
1426
1426
  ] }) });
1427
1427
  }
1428
- const fr = {
1428
+ const yr = {
1429
1429
  "Sales Invoice": mn,
1430
1430
  "Purchase Invoice": mn,
1431
- "Payment Entry": $a,
1432
- "Sales Order": jn,
1431
+ "Payment Entry": Ua,
1432
+ "Sales Order": Gn,
1433
1433
  Quotation: nn
1434
1434
  };
1435
- function yr({ doc: t }) {
1436
- const { t: n } = X(), a = t.doctype ?? t.type ?? "Document", s = t.creation ?? t.date, i = fr[a] ?? nn, l = `/app/${a.toLowerCase().replace(/\s+/g, "-")}/${encodeURIComponent(t.name)}`;
1435
+ function br({ doc: t }) {
1436
+ const { t: n } = Z(), a = t.doctype ?? t.type ?? "Document", s = t.creation ?? t.date, i = yr[a] ?? nn, l = `/app/${a.toLowerCase().replace(/\s+/g, "-")}/${encodeURIComponent(t.name)}`;
1437
1437
  return /* @__PURE__ */ r(
1438
1438
  be,
1439
1439
  {
@@ -1462,8 +1462,8 @@ function wt() {
1462
1462
  /* @__PURE__ */ e("div", { className: "hidden h-3 w-16 animate-pulse rounded bg-surface-subtle sm:block" })
1463
1463
  ] });
1464
1464
  }
1465
- function br() {
1466
- const { t } = X(), { data: n, isLoading: a } = oe({
1465
+ function vr() {
1466
+ const { t } = Z(), { data: n, isLoading: a } = oe({
1467
1467
  queryKey: ["dashboard-summary"],
1468
1468
  queryFn: () => I.dashboardSummary()
1469
1469
  });
@@ -1479,7 +1479,7 @@ function br() {
1479
1479
  {
1480
1480
  title: t("dashboard.totalRevenue"),
1481
1481
  value: n == null ? void 0 : n.total_revenue,
1482
- icon: za,
1482
+ icon: Ma,
1483
1483
  tone: "text-emerald-600 bg-emerald-500/10"
1484
1484
  }
1485
1485
  ),
@@ -1488,7 +1488,7 @@ function br() {
1488
1488
  {
1489
1489
  title: t("dashboard.outstandingReceivable"),
1490
1490
  value: n == null ? void 0 : n.outstanding_receivable,
1491
- icon: Ma,
1491
+ icon: Fa,
1492
1492
  tone: "text-sky-600 bg-sky-500/10"
1493
1493
  }
1494
1494
  ),
@@ -1497,7 +1497,7 @@ function br() {
1497
1497
  {
1498
1498
  title: t("dashboard.outstandingPayable"),
1499
1499
  value: n == null ? void 0 : n.outstanding_payable,
1500
- icon: Fa,
1500
+ icon: $a,
1501
1501
  tone: "text-amber-600 bg-amber-500/10"
1502
1502
  }
1503
1503
  ),
@@ -1506,7 +1506,7 @@ function br() {
1506
1506
  {
1507
1507
  title: t("dashboard.totalStockValue"),
1508
1508
  value: n == null ? void 0 : n.total_stock_value,
1509
- icon: Gn,
1509
+ icon: Wn,
1510
1510
  tone: "text-brand bg-brand/10"
1511
1511
  }
1512
1512
  )
@@ -1517,10 +1517,10 @@ function br() {
1517
1517
  /* @__PURE__ */ e(wt, {}),
1518
1518
  /* @__PURE__ */ e(wt, {}),
1519
1519
  /* @__PURE__ */ e(wt, {})
1520
- ] }) : n != null && n.recent_documents && n.recent_documents.length > 0 ? n.recent_documents.map((s, i) => /* @__PURE__ */ e(yr, { doc: s }, `${s.name}-${i}`)) : /* @__PURE__ */ e("div", { className: "px-3 py-10 text-center text-sm text-fg-muted", children: t("dashboard.noRecentDocuments") }) }) })
1520
+ ] }) : n != null && n.recent_documents && n.recent_documents.length > 0 ? n.recent_documents.map((s, i) => /* @__PURE__ */ e(br, { doc: s }, `${s.name}-${i}`)) : /* @__PURE__ */ e("div", { className: "px-3 py-10 text-center text-sm text-fg-muted", children: t("dashboard.noRecentDocuments") }) }) })
1521
1521
  ] });
1522
1522
  }
1523
- function vr(t, n) {
1523
+ function xr(t, n) {
1524
1524
  const { data: a, isLoading: s, error: i, refetch: o } = oe({
1525
1525
  queryKey: ["documents", t, n],
1526
1526
  queryFn: () => I.listDocuments(t, n),
@@ -1579,7 +1579,7 @@ const rt = [
1579
1579
  { name: "qty", label: "Qty", type: "number", required: !0 },
1580
1580
  { name: "rate", label: "Rate", type: "currency", required: !0 },
1581
1581
  { name: "amount", label: "Amount", type: "currency", readOnly: !0 }
1582
- ], xr = [
1582
+ ], Nr = [
1583
1583
  ...rt,
1584
1584
  {
1585
1585
  name: "frequency",
@@ -1626,7 +1626,7 @@ const rt = [
1626
1626
  { name: "remarks", label: "Notes / Terms", type: "textarea" }
1627
1627
  ],
1628
1628
  childTables: [
1629
- { key: "items", label: "Items", fields: xr },
1629
+ { key: "items", label: "Items", fields: Nr },
1630
1630
  { key: "taxes", label: "Taxes", fields: at }
1631
1631
  ],
1632
1632
  listColumns: ["name", "customer", "transaction_date", "grand_total", "status"],
@@ -2213,16 +2213,16 @@ const rt = [
2213
2213
  conversions: []
2214
2214
  }
2215
2215
  };
2216
- function ia(t) {
2216
+ function oa(t) {
2217
2217
  return cn[t];
2218
2218
  }
2219
- function Ro(t) {
2219
+ function Io(t) {
2220
2220
  cn[t.slug] = t;
2221
2221
  }
2222
- function Io() {
2222
+ function Bo() {
2223
2223
  return Object.values(cn);
2224
2224
  }
2225
- const Nr = {
2225
+ const wr = {
2226
2226
  // Primary: brand-coloured fill + a 1px inset top highlight for depth
2227
2227
  // (button-highlight shadow). On press, the button shifts down 1px —
2228
2228
  // tiny detail, large perceived "this is responsive".
@@ -2230,12 +2230,12 @@ const Nr = {
2230
2230
  secondary: "bg-surface text-fg ring-1 ring-line hover:bg-surface-subtle active:translate-y-px focus-visible:ring-fg/20",
2231
2231
  danger: "bg-red-600 text-white shadow-button-highlight hover:bg-red-700 active:translate-y-px focus-visible:ring-red-500/40",
2232
2232
  ghost: "bg-transparent text-fg-muted hover:bg-surface-subtle hover:text-fg focus-visible:ring-fg/20"
2233
- }, wr = {
2233
+ }, kr = {
2234
2234
  sm: "h-8 px-3 text-sm",
2235
2235
  md: "h-10 px-4 text-sm",
2236
2236
  lg: "h-11 px-5 text-sm"
2237
2237
  };
2238
- function Q({
2238
+ function H({
2239
2239
  variant: t = "primary",
2240
2240
  size: n = "md",
2241
2241
  disabled: a,
@@ -2250,7 +2250,7 @@ function Q({
2250
2250
  type: l,
2251
2251
  disabled: a,
2252
2252
  onClick: s,
2253
- className: Le(
2253
+ className: Ee(
2254
2254
  // Layout + base interaction. focus-visible (not :focus) so
2255
2255
  // mouse clicks don't leave a permanent ring; only keyboard
2256
2256
  // navigation gets the visible outline.
@@ -2258,8 +2258,8 @@ function Q({
2258
2258
  "transition-all duration-150",
2259
2259
  "focus-visible:outline-none focus-visible:ring-2",
2260
2260
  "disabled:cursor-not-allowed disabled:opacity-50 disabled:active:translate-y-0",
2261
- Nr[t],
2262
- wr[n],
2261
+ wr[t],
2262
+ kr[n],
2263
2263
  o
2264
2264
  ),
2265
2265
  children: i
@@ -2283,7 +2283,7 @@ function J({ label: t, hint: n, error: a, className: s, id: i, ...o }) {
2283
2283
  id: l,
2284
2284
  "aria-invalid": !!a || void 0,
2285
2285
  "aria-describedby": a || n ? `${l}-help` : void 0,
2286
- className: Le(
2286
+ className: Ee(
2287
2287
  // Bigger touch target (h-10) than the previous py-2 default;
2288
2288
  // brand-coloured halo on focus instead of a single hard ring.
2289
2289
  // text-sm is fine on desktop; the global media-query in
@@ -2303,7 +2303,7 @@ function J({ label: t, hint: n, error: a, className: s, id: i, ...o }) {
2303
2303
  "p",
2304
2304
  {
2305
2305
  id: `${l}-help`,
2306
- className: Le(
2306
+ className: Ee(
2307
2307
  "mt-1.5 text-xs",
2308
2308
  a ? "text-red-600" : "text-fg-muted"
2309
2309
  ),
@@ -2312,7 +2312,7 @@ function J({ label: t, hint: n, error: a, className: s, id: i, ...o }) {
2312
2312
  )
2313
2313
  ] });
2314
2314
  }
2315
- function kr(t) {
2315
+ function Sr(t) {
2316
2316
  return typeof t == "string" ? { value: t, label: t } : t;
2317
2317
  }
2318
2318
  function He({ label: t, options: n, value: a, onChange: s, className: i, required: o, disabled: l }) {
@@ -2334,7 +2334,7 @@ function He({ label: t, options: n, value: a, onChange: s, className: i, require
2334
2334
  onChange: s,
2335
2335
  required: o,
2336
2336
  disabled: l,
2337
- className: Le(
2337
+ className: Ee(
2338
2338
  // Same shape as the Input primitive: h-10, surface bg, line ring,
2339
2339
  // brand-tinted halo on focus.
2340
2340
  "block h-10 w-full rounded-lg bg-surface px-3 text-sm text-fg",
@@ -2346,7 +2346,7 @@ function He({ label: t, options: n, value: a, onChange: s, className: i, require
2346
2346
  children: [
2347
2347
  /* @__PURE__ */ e("option", { value: "", children: "Select..." }),
2348
2348
  n.map((g) => {
2349
- const { value: m, label: h } = kr(g);
2349
+ const { value: m, label: h } = Sr(g);
2350
2350
  return /* @__PURE__ */ e("option", { value: m, children: h }, m);
2351
2351
  })
2352
2352
  ]
@@ -2355,7 +2355,7 @@ function He({ label: t, options: n, value: a, onChange: s, className: i, require
2355
2355
  ] });
2356
2356
  }
2357
2357
  function Cr({ text: t }) {
2358
- const [n, a] = C(!1);
2358
+ const [n, a] = S(!1);
2359
2359
  return /* @__PURE__ */ r("span", { className: "relative ml-1 inline-flex", children: [
2360
2360
  /* @__PURE__ */ e(
2361
2361
  "button",
@@ -2374,8 +2374,8 @@ function Cr({ text: t }) {
2374
2374
  ] })
2375
2375
  ] });
2376
2376
  }
2377
- function Sr() {
2378
- const { t } = X(), [n, a] = C(!1), s = [
2377
+ function Dr() {
2378
+ const { t } = Z(), [n, a] = S(!1), s = [
2379
2379
  ["# Heading", t("notesMarkup.heading", { defaultValue: "bold heading" })],
2380
2380
  ["*italic* **bold**", t("notesMarkup.emphasis", { defaultValue: "italic / bold" })],
2381
2381
  ["---", t("notesMarkup.rule", { defaultValue: "horizontal divider line" })],
@@ -2400,7 +2400,7 @@ function Sr() {
2400
2400
  className: "inline-flex h-4 w-4 items-center justify-center rounded-full text-fg-muted hover:text-fg",
2401
2401
  onClick: () => a((i) => !i),
2402
2402
  "aria-label": t("notesMarkup.title", { defaultValue: "Formatting help" }),
2403
- children: /* @__PURE__ */ e(Ua, { className: "h-3.5 w-3.5" })
2403
+ children: /* @__PURE__ */ e(Va, { className: "h-3.5 w-3.5" })
2404
2404
  }
2405
2405
  ),
2406
2406
  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: [
@@ -2417,7 +2417,7 @@ function Sr() {
2417
2417
  }
2418
2418
  );
2419
2419
  }
2420
- function Dr(t, n = !0) {
2420
+ function Ar(t, n = !0) {
2421
2421
  const { data: a } = oe({
2422
2422
  queryKey: ["currencies", ""],
2423
2423
  queryFn: () => I.currencies(t),
@@ -2426,14 +2426,14 @@ function Dr(t, n = !0) {
2426
2426
  });
2427
2427
  return (a == null ? void 0 : a.currencies) ?? [];
2428
2428
  }
2429
- const Ar = /* @__PURE__ */ new Set([
2429
+ const Pr = /* @__PURE__ */ new Set([
2430
2430
  "customer",
2431
2431
  "supplier",
2432
2432
  "item",
2433
2433
  "warehouse"
2434
2434
  ]);
2435
2435
  function Xt(t, n) {
2436
- return !t || !n ? null : Ar.has(t) ? `/masters/${t}/${encodeURIComponent(n)}` : t === "account" ? `/reports/general-ledger?account=${encodeURIComponent(n)}` : null;
2436
+ return !t || !n ? null : Pr.has(t) ? `/masters/${t}/${encodeURIComponent(n)}` : t === "account" ? `/reports/general-ledger?account=${encodeURIComponent(n)}` : null;
2437
2437
  }
2438
2438
  function wn({ label: t, hint: n, extra: a }) {
2439
2439
  return /* @__PURE__ */ r("label", { className: "mb-1.5 block text-sm font-medium text-fg", children: [
@@ -2442,14 +2442,14 @@ function wn({ label: t, hint: n, extra: a }) {
2442
2442
  a
2443
2443
  ] });
2444
2444
  }
2445
- function Pr({
2445
+ function _r({
2446
2446
  field: t,
2447
2447
  value: n,
2448
2448
  onChange: a,
2449
2449
  disabled: s,
2450
2450
  hideLabel: i
2451
2451
  }) {
2452
- const [o, l] = C(n ?? ""), [c, g] = C(!1), m = te(null), [h, u] = C(null), { data: N } = oe({
2452
+ const [o, l] = S(n ?? ""), [c, g] = S(!1), m = te(null), [h, u] = S(null), { data: N } = oe({
2453
2453
  queryKey: ["link-search", t.linkDoctype, o],
2454
2454
  queryFn: () => I.searchLink(t.linkDoctype, o),
2455
2455
  enabled: !!t.linkDoctype && c
@@ -2484,7 +2484,7 @@ function Pr({
2484
2484
  onBlur: () => setTimeout(() => g(!1), 200)
2485
2485
  }
2486
2486
  ),
2487
- c && N && N.length > 0 && h && Zn(
2487
+ c && N && N.length > 0 && h && Xn(
2488
2488
  /* @__PURE__ */ e(
2489
2489
  "ul",
2490
2490
  {
@@ -2517,7 +2517,7 @@ function Rt({
2517
2517
  currency: l = "USD"
2518
2518
  }) {
2519
2519
  var x;
2520
- const { t: c } = X(), g = s || !!t.readOnly, m = () => o ? null : /* @__PURE__ */ e(wn, { label: c(`fields.${t.label}`, { defaultValue: t.label }), hint: t.hint }), h = t.type === "select" && t.optionsSource === "currency", u = Dr(void 0, h);
2520
+ const { t: c } = Z(), g = s || !!t.readOnly, m = () => o ? null : /* @__PURE__ */ e(wn, { label: c(`fields.${t.label}`, { defaultValue: t.label }), hint: t.hint }), h = t.type === "select" && t.optionsSource === "currency", u = Ar(void 0, h);
2521
2521
  if (g) {
2522
2522
  if (t.type === "link" && n) {
2523
2523
  const T = t.linkDoctypeField && i ? String(i[t.linkDoctypeField] ?? "").toLowerCase().replace(/\s+/g, "-") : t.linkDoctype, P = Xt(T, String(n));
@@ -2535,7 +2535,7 @@ function Rt({
2535
2535
  ] });
2536
2536
  }
2537
2537
  let v = n ?? "-";
2538
- t.type === "currency" && typeof n == "number" && (v = Ee(n, l));
2538
+ t.type === "currency" && typeof n == "number" && (v = Le(n, l));
2539
2539
  const f = [
2540
2540
  o ? "text-sm text-fg" : "py-2 text-sm text-fg",
2541
2541
  t.type === "textarea" ? "whitespace-pre-line" : ""
@@ -2550,7 +2550,7 @@ function Rt({
2550
2550
  return /* @__PURE__ */ r("div", { children: [
2551
2551
  /* @__PURE__ */ e(m, {}),
2552
2552
  /* @__PURE__ */ e(
2553
- Pr,
2553
+ _r,
2554
2554
  {
2555
2555
  field: v,
2556
2556
  value: n ?? "",
@@ -2583,7 +2583,7 @@ function Rt({
2583
2583
  {
2584
2584
  label: c(`fields.${t.label}`, { defaultValue: t.label }),
2585
2585
  hint: t.hint,
2586
- extra: v ? /* @__PURE__ */ e(Sr, {}) : void 0
2586
+ extra: v ? /* @__PURE__ */ e(Dr, {}) : void 0
2587
2587
  }
2588
2588
  ),
2589
2589
  /* @__PURE__ */ e(
@@ -2613,14 +2613,14 @@ function Rt({
2613
2613
  )
2614
2614
  ] });
2615
2615
  }
2616
- function _r({
2616
+ function Tr({
2617
2617
  tableDef: t,
2618
2618
  rows: n,
2619
2619
  onChange: a,
2620
2620
  readOnly: s,
2621
2621
  currency: i = "USD"
2622
2622
  }) {
2623
- const { t: o } = X(), l = (m, h, u) => {
2623
+ const { t: o } = Z(), l = (m, h, u) => {
2624
2624
  const N = n.map(
2625
2625
  (x, v) => v === m ? { ...x, [h]: u } : x
2626
2626
  );
@@ -2662,7 +2662,7 @@ function _r({
2662
2662
  }
2663
2663
  ) }, u.name)),
2664
2664
  !s && /* @__PURE__ */ e("td", { className: "px-2 py-1", children: /* @__PURE__ */ e(
2665
- Q,
2665
+ H,
2666
2666
  {
2667
2667
  variant: "ghost",
2668
2668
  size: "sm",
@@ -2672,10 +2672,10 @@ function _r({
2672
2672
  ) })
2673
2673
  ] }, h)) })
2674
2674
  ] }) }),
2675
- !s && /* @__PURE__ */ e("div", { className: "mt-2", children: /* @__PURE__ */ e(Q, { variant: "secondary", size: "sm", onClick: c, children: o("common.addRow") }) })
2675
+ !s && /* @__PURE__ */ e("div", { className: "mt-2", children: /* @__PURE__ */ e(H, { variant: "secondary", size: "sm", onClick: c, children: o("common.addRow") }) })
2676
2676
  ] });
2677
2677
  }
2678
- function Tr({
2678
+ function Rr({
2679
2679
  isNew: t,
2680
2680
  doctype: n,
2681
2681
  name: a,
@@ -2689,17 +2689,17 @@ function Tr({
2689
2689
  onConvert: h,
2690
2690
  onDiscard: u
2691
2691
  }) {
2692
- const { t: N } = X(), [x, v] = C(!1), [f, T] = C(!1);
2692
+ const { t: N } = Z(), [x, v] = S(!1), [f, T] = S(!1);
2693
2693
  if (!l) return null;
2694
2694
  const P = !t && n && a ? `/api/documents/${n}/${encodeURIComponent(a)}/pdf` : null, b = !t && l.canCancel && s === 1;
2695
2695
  return /* @__PURE__ */ r("div", { className: "flex flex-wrap items-center gap-2", children: [
2696
- P && /* @__PURE__ */ e(Q, { variant: "secondary", onClick: () => window.open(P, "_blank"), children: N("common.pdf") }),
2697
- s < 1 && !i && /* @__PURE__ */ e(Q, { onClick: c, disabled: o, children: N(o ? "common.saving" : "common.save") }),
2698
- !t && l.canSubmit && s === 0 && !i && /* @__PURE__ */ e(Q, { variant: "secondary", onClick: g, children: N("common.submit") }),
2696
+ P && /* @__PURE__ */ e(H, { variant: "secondary", onClick: () => window.open(P, "_blank"), children: N("common.pdf") }),
2697
+ s < 1 && !i && /* @__PURE__ */ e(H, { onClick: c, disabled: o, children: N(o ? "common.saving" : "common.save") }),
2698
+ !t && l.canSubmit && s === 0 && !i && /* @__PURE__ */ e(H, { variant: "secondary", onClick: g, children: N("common.submit") }),
2699
2699
  !t && l.canSubmit && s === 0 && !i && (f ? /* @__PURE__ */ r(we, { children: [
2700
- /* @__PURE__ */ e(Q, { variant: "secondary", onClick: () => T(!1), children: N("common.keepDraft") }),
2700
+ /* @__PURE__ */ e(H, { variant: "secondary", onClick: () => T(!1), children: N("common.keepDraft") }),
2701
2701
  /* @__PURE__ */ e(
2702
- Q,
2702
+ H,
2703
2703
  {
2704
2704
  variant: "danger",
2705
2705
  onClick: () => {
@@ -2708,10 +2708,10 @@ function Tr({
2708
2708
  children: N("common.discardDraftConfirm")
2709
2709
  }
2710
2710
  )
2711
- ] }) : /* @__PURE__ */ e(Q, { variant: "ghost", onClick: () => T(!0), children: N("common.discardDraft") })),
2712
- b && (x ? /* @__PURE__ */ e(Q, { variant: "secondary", onClick: () => v(!1), children: N("common.cancelDocAbort") }) : /* @__PURE__ */ e(Q, { variant: "danger", onClick: () => v(!0), children: N("common.cancelDoc") })),
2711
+ ] }) : /* @__PURE__ */ e(H, { variant: "ghost", onClick: () => T(!0), children: N("common.discardDraft") })),
2712
+ b && (x ? /* @__PURE__ */ e(H, { variant: "secondary", onClick: () => v(!1), children: N("common.cancelDocAbort") }) : /* @__PURE__ */ e(H, { variant: "danger", onClick: () => v(!0), children: N("common.cancelDoc") })),
2713
2713
  !t && s === 1 && !x && l.conversions.map((d) => /* @__PURE__ */ e(
2714
- Q,
2714
+ H,
2715
2715
  {
2716
2716
  variant: "secondary",
2717
2717
  onClick: () => h(d.targetDoctype),
@@ -2720,7 +2720,7 @@ function Tr({
2720
2720
  d.targetDoctype
2721
2721
  )),
2722
2722
  b && x && /* @__PURE__ */ e(
2723
- Q,
2723
+ H,
2724
2724
  {
2725
2725
  variant: "danger",
2726
2726
  className: "ml-auto",
@@ -2754,14 +2754,14 @@ function kn(t, n) {
2754
2754
  }
2755
2755
  return a;
2756
2756
  }
2757
- function Cn() {
2757
+ function Sn() {
2758
2758
  var Ue;
2759
- const { doctype: t, name: n } = bt(), a = ze(), s = We(), { t: i } = X(), o = ia(t ?? ""), l = !n, [c, g] = C({}), [m, h] = C(!1), { data: u, isLoading: N } = oe({
2759
+ const { doctype: t, name: n } = bt(), a = ze(), s = We(), { t: i } = Z(), o = oa(t ?? ""), l = !n, [c, g] = S({}), [m, h] = S(!1), { data: u, isLoading: N } = oe({
2760
2760
  queryKey: ["document", t, n],
2761
2761
  queryFn: () => I.getDocument(t, n),
2762
2762
  enabled: !!t && !!n && !l
2763
- }), x = Se(
2764
- () => !!(o != null && o.fields.some((L) => L.name === "currency")),
2763
+ }), x = Ce(
2764
+ () => !!(o != null && o.fields.some((E) => E.name === "currency")),
2765
2765
  [o]
2766
2766
  ), v = o == null ? void 0 : o.partyField, f = v ? c[v] : void 0, T = Oe(c.company), { data: P } = oe({
2767
2767
  queryKey: ["master", v, f],
@@ -2771,13 +2771,13 @@ function Cn() {
2771
2771
  });
2772
2772
  se(() => {
2773
2773
  if (!l || !x || m) return;
2774
- let L;
2774
+ let E;
2775
2775
  if (f) {
2776
2776
  if (!P) return;
2777
- L = P.default_currency || T;
2777
+ E = P.default_currency || T;
2778
2778
  } else
2779
- L = T;
2780
- L && L !== c.currency && g((ne) => ({ ...ne, currency: L }));
2779
+ E = T;
2780
+ E && E !== c.currency && g((ne) => ({ ...ne, currency: E }));
2781
2781
  }, [
2782
2782
  l,
2783
2783
  x,
@@ -2788,33 +2788,33 @@ function Cn() {
2788
2788
  c.currency
2789
2789
  ]), se(() => {
2790
2790
  if (l && o) {
2791
- const L = {};
2791
+ const E = {};
2792
2792
  o.fields.forEach((ne) => {
2793
- ne.type === "date" ? L[ne.name] = (/* @__PURE__ */ new Date()).toISOString().split("T")[0] : L[ne.name] = ne.default ?? "";
2793
+ ne.type === "date" ? E[ne.name] = (/* @__PURE__ */ new Date()).toISOString().split("T")[0] : E[ne.name] = ne.default ?? "";
2794
2794
  }), o.childTables.forEach((ne) => {
2795
- L[ne.key] = [];
2796
- }), L.docstatus = 0, g(L);
2795
+ E[ne.key] = [];
2796
+ }), E.docstatus = 0, g(E);
2797
2797
  } else u && g(u);
2798
2798
  }, [l, u, o]);
2799
2799
  const b = ie({
2800
- mutationFn: (L) => I.createDocument(t, L),
2801
- onSuccess: (L) => {
2802
- s.invalidateQueries({ queryKey: ["documents", t] }), a(`/app/${t}/${L.name}`, { replace: !0 });
2800
+ mutationFn: (E) => I.createDocument(t, E),
2801
+ onSuccess: (E) => {
2802
+ s.invalidateQueries({ queryKey: ["documents", t] }), a(`/app/${t}/${E.name}`, { replace: !0 });
2803
2803
  }
2804
2804
  }), d = ie({
2805
- mutationFn: (L) => I.updateDocument(t, n, L),
2806
- onSuccess: (L) => {
2807
- s.invalidateQueries({ queryKey: ["document", t, n] }), s.invalidateQueries({ queryKey: ["documents", t] }), g(L);
2805
+ mutationFn: (E) => I.updateDocument(t, n, E),
2806
+ onSuccess: (E) => {
2807
+ s.invalidateQueries({ queryKey: ["document", t, n] }), s.invalidateQueries({ queryKey: ["documents", t] }), g(E);
2808
2808
  }
2809
2809
  }), p = ie({
2810
2810
  mutationFn: () => I.submitDocument(t, n),
2811
- onSuccess: (L) => {
2812
- g(L), s.invalidateQueries({ queryKey: ["document", t, n] }), s.invalidateQueries({ queryKey: ["documents", t] });
2811
+ onSuccess: (E) => {
2812
+ g(E), s.invalidateQueries({ queryKey: ["document", t, n] }), s.invalidateQueries({ queryKey: ["documents", t] });
2813
2813
  }
2814
2814
  }), _ = ie({
2815
2815
  mutationFn: () => I.cancelDocument(t, n),
2816
- onSuccess: (L) => {
2817
- g(L), s.invalidateQueries({ queryKey: ["document", t, n] }), s.invalidateQueries({ queryKey: ["documents", t] });
2816
+ onSuccess: (E) => {
2817
+ g(E), s.invalidateQueries({ queryKey: ["document", t, n] }), s.invalidateQueries({ queryKey: ["documents", t] });
2818
2818
  }
2819
2819
  }), y = ie({
2820
2820
  mutationFn: () => I.discardDocument(t, n),
@@ -2822,23 +2822,23 @@ function Cn() {
2822
2822
  s.invalidateQueries({ queryKey: ["documents", t] }), a(`/app/${t}`, { replace: !0 });
2823
2823
  }
2824
2824
  }), B = ie({
2825
- mutationFn: (L) => I.convertDocument(t, n, L),
2826
- onSuccess: (L, ne) => {
2825
+ mutationFn: (E) => I.convertDocument(t, n, E),
2826
+ onSuccess: (E, ne) => {
2827
2827
  const Re = ne.toLowerCase().replace(/\s+/g, "-");
2828
- a(`/app/${Re}/${L.name}`);
2828
+ a(`/app/${Re}/${E.name}`);
2829
2829
  }
2830
2830
  }), D = Pe(
2831
- (L, ne) => {
2832
- L === "currency" && h(!0), g((Re) => {
2833
- const De = { ...Re, [L]: ne };
2834
- return L === "currency" && (De.conversion_rate = 0), kn(De, o);
2831
+ (E, ne) => {
2832
+ E === "currency" && h(!0), g((Re) => {
2833
+ const De = { ...Re, [E]: ne };
2834
+ return E === "currency" && (De.conversion_rate = 0), kn(De, o);
2835
2835
  });
2836
2836
  },
2837
2837
  [o]
2838
2838
  ), O = Pe(
2839
- (L, ne) => {
2839
+ (E, ne) => {
2840
2840
  g((Re) => {
2841
- const De = { ...Re, [L]: ne };
2841
+ const De = { ...Re, [E]: ne };
2842
2842
  return kn(De, o);
2843
2843
  });
2844
2844
  },
@@ -2847,10 +2847,10 @@ function Cn() {
2847
2847
  l ? b.mutate(c) : d.mutate(c);
2848
2848
  }, ee = () => {
2849
2849
  p.mutate();
2850
- }, S = () => {
2850
+ }, C = () => {
2851
2851
  _.mutate();
2852
- }, w = (L) => {
2853
- B.mutate(L);
2852
+ }, w = (E) => {
2853
+ B.mutate(E);
2854
2854
  }, q = () => {
2855
2855
  y.mutate();
2856
2856
  };
@@ -2861,7 +2861,7 @@ function Cn() {
2861
2861
  ] });
2862
2862
  if (!l && N)
2863
2863
  return /* @__PURE__ */ e("p", { className: "text-fg-muted", children: i("common.loading") });
2864
- const A = c.docstatus ?? 0, z = !!c.discarded, Y = A >= 1 || z, re = c.currency || T, ce = Fe(c.conversion_rate ?? 1), ge = o.fields.filter((L) => !L.readOnly), _e = ge.filter((L) => L.type !== "textarea"), pe = ge.filter((L) => L.type === "textarea"), fe = o.fields.filter((L) => L.readOnly);
2864
+ const A = c.docstatus ?? 0, z = !!c.discarded, Y = A >= 1 || z, re = c.currency || T, ce = Fe(c.conversion_rate ?? 1), ge = o.fields.filter((E) => !E.readOnly), _e = ge.filter((E) => E.type !== "textarea"), pe = ge.filter((E) => E.type === "textarea"), fe = o.fields.filter((E) => E.readOnly);
2865
2865
  return /* @__PURE__ */ r("div", { className: "space-y-6", children: [
2866
2866
  /* @__PURE__ */ r("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
2867
2867
  /* @__PURE__ */ r("div", { className: "flex items-center gap-3", children: [
@@ -2882,7 +2882,7 @@ function Cn() {
2882
2882
  )
2883
2883
  ] }),
2884
2884
  /* @__PURE__ */ e(
2885
- Tr,
2885
+ Rr,
2886
2886
  {
2887
2887
  isNew: l,
2888
2888
  doctype: t,
@@ -2893,7 +2893,7 @@ function Cn() {
2893
2893
  discarded: z,
2894
2894
  onSave: G,
2895
2895
  onSubmit: ee,
2896
- onCancel: S,
2896
+ onCancel: C,
2897
2897
  onConvert: w,
2898
2898
  onDiscard: q
2899
2899
  }
@@ -2901,68 +2901,68 @@ function Cn() {
2901
2901
  ] }),
2902
2902
  (b.error || d.error || p.error || _.error) && /* @__PURE__ */ e("div", { className: "rounded-lg bg-rose-50 p-4 text-sm text-rose-700 ring-1 ring-rose-200", children: ((Ue = b.error ?? d.error ?? p.error ?? _.error) == null ? void 0 : Ue.message) ?? i("common.errorOccurred") }),
2903
2903
  /* @__PURE__ */ r($, { children: [
2904
- /* @__PURE__ */ e("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: _e.map((L) => /* @__PURE__ */ e(
2904
+ /* @__PURE__ */ e("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: _e.map((E) => /* @__PURE__ */ e(
2905
2905
  Rt,
2906
2906
  {
2907
- field: L,
2908
- value: c[L.name],
2909
- onChange: (ne) => D(L.name, ne),
2907
+ field: E,
2908
+ value: c[E.name],
2909
+ onChange: (ne) => D(E.name, ne),
2910
2910
  readOnly: Y,
2911
2911
  rowData: c,
2912
2912
  currency: re
2913
2913
  },
2914
- L.name
2914
+ E.name
2915
2915
  )) }),
2916
- pe.length > 0 && /* @__PURE__ */ e("div", { className: "mt-4 space-y-4", children: pe.map((L) => /* @__PURE__ */ e(
2916
+ pe.length > 0 && /* @__PURE__ */ e("div", { className: "mt-4 space-y-4", children: pe.map((E) => /* @__PURE__ */ e(
2917
2917
  Rt,
2918
2918
  {
2919
- field: L,
2920
- value: c[L.name],
2921
- onChange: (ne) => D(L.name, ne),
2919
+ field: E,
2920
+ value: c[E.name],
2921
+ onChange: (ne) => D(E.name, ne),
2922
2922
  readOnly: Y,
2923
2923
  rowData: c,
2924
2924
  currency: re
2925
2925
  },
2926
- L.name
2926
+ E.name
2927
2927
  )) })
2928
2928
  ] }),
2929
- o.childTables.map((L) => /* @__PURE__ */ e(
2930
- _r,
2929
+ o.childTables.map((E) => /* @__PURE__ */ e(
2930
+ Tr,
2931
2931
  {
2932
- tableDef: L,
2933
- rows: c[L.key] ?? [],
2934
- onChange: (ne) => O(L.key, ne),
2932
+ tableDef: E,
2933
+ rows: c[E.key] ?? [],
2934
+ onChange: (ne) => O(E.key, ne),
2935
2935
  readOnly: Y,
2936
2936
  currency: re
2937
2937
  },
2938
- L.key
2938
+ E.key
2939
2939
  )),
2940
- fe.length > 0 && /* @__PURE__ */ e($, { title: i("common.totals"), children: /* @__PURE__ */ e("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-3", children: fe.map((L) => /* @__PURE__ */ e(
2940
+ fe.length > 0 && /* @__PURE__ */ e($, { title: i("common.totals"), children: /* @__PURE__ */ e("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-3", children: fe.map((E) => /* @__PURE__ */ e(
2941
2941
  Rt,
2942
2942
  {
2943
- field: L,
2944
- value: c[L.name],
2943
+ field: E,
2944
+ value: c[E.name],
2945
2945
  onChange: () => {
2946
2946
  },
2947
2947
  readOnly: !0,
2948
2948
  currency: re
2949
2949
  },
2950
- L.name
2950
+ E.name
2951
2951
  )) }) })
2952
2952
  ] });
2953
2953
  }
2954
2954
  function ye(t) {
2955
2955
  return t.toISOString().split("T")[0];
2956
2956
  }
2957
- function oa(t) {
2957
+ function la(t) {
2958
2958
  const n = new Date(t), a = n.getDay(), s = a === 0 ? 6 : a - 1;
2959
2959
  return n.setDate(n.getDate() - s), n;
2960
2960
  }
2961
- function Rr(t) {
2962
- const n = oa(t);
2961
+ function Ir(t) {
2962
+ const n = la(t);
2963
2963
  return n.setDate(n.getDate() + 6), n;
2964
2964
  }
2965
- function Sn(t) {
2965
+ function Cn(t) {
2966
2966
  return new Date(t.getFullYear(), t.getMonth(), 1);
2967
2967
  }
2968
2968
  function Bt(t) {
@@ -2979,10 +2979,10 @@ function tn(t) {
2979
2979
  function Dn(t) {
2980
2980
  return new Date(t.getFullYear(), 0, 1);
2981
2981
  }
2982
- function Lt(t) {
2982
+ function Et(t) {
2983
2983
  return new Date(t.getFullYear(), 11, 31);
2984
2984
  }
2985
- const Ir = [
2985
+ const Br = [
2986
2986
  {
2987
2987
  label: "Today",
2988
2988
  range: () => {
@@ -2992,11 +2992,11 @@ const Ir = [
2992
2992
  },
2993
2993
  {
2994
2994
  label: "This Week",
2995
- range: () => [ye(oa(/* @__PURE__ */ new Date())), ye(Rr(/* @__PURE__ */ new Date()))]
2995
+ range: () => [ye(la(/* @__PURE__ */ new Date())), ye(Ir(/* @__PURE__ */ new Date()))]
2996
2996
  },
2997
2997
  {
2998
2998
  label: "This Month",
2999
- range: () => [ye(Sn(/* @__PURE__ */ new Date())), ye(Bt(/* @__PURE__ */ new Date()))]
2999
+ range: () => [ye(Cn(/* @__PURE__ */ new Date())), ye(Bt(/* @__PURE__ */ new Date()))]
3000
3000
  },
3001
3001
  {
3002
3002
  label: "This Quarter",
@@ -3004,13 +3004,13 @@ const Ir = [
3004
3004
  },
3005
3005
  {
3006
3006
  label: "This Year",
3007
- range: () => [ye(Dn(/* @__PURE__ */ new Date())), ye(Lt(/* @__PURE__ */ new Date()))]
3007
+ range: () => [ye(Dn(/* @__PURE__ */ new Date())), ye(Et(/* @__PURE__ */ new Date()))]
3008
3008
  },
3009
3009
  {
3010
3010
  label: "Last Month",
3011
3011
  range: () => {
3012
3012
  const t = /* @__PURE__ */ new Date(), n = new Date(t.getFullYear(), t.getMonth() - 1, 1);
3013
- return [ye(Sn(n)), ye(Bt(n))];
3013
+ return [ye(Cn(n)), ye(Bt(n))];
3014
3014
  }
3015
3015
  },
3016
3016
  {
@@ -3024,12 +3024,12 @@ const Ir = [
3024
3024
  label: "Last Year",
3025
3025
  range: () => {
3026
3026
  const t = new Date((/* @__PURE__ */ new Date()).getFullYear() - 1, 6, 1);
3027
- return [ye(Dn(t)), ye(Lt(t))];
3027
+ return [ye(Dn(t)), ye(Et(t))];
3028
3028
  }
3029
3029
  }
3030
3030
  ];
3031
3031
  function $t({ onSelect: t }) {
3032
- return /* @__PURE__ */ e("div", { className: "flex flex-wrap gap-1.5", children: Ir.map((n) => /* @__PURE__ */ e(
3032
+ return /* @__PURE__ */ e("div", { className: "flex flex-wrap gap-1.5", children: Br.map((n) => /* @__PURE__ */ e(
3033
3033
  "button",
3034
3034
  {
3035
3035
  type: "button",
@@ -3052,8 +3052,8 @@ function dn({ onSelect: t }) {
3052
3052
  return ye(Bt(new Date(a.getFullYear(), a.getMonth() - 1, 1)));
3053
3053
  } },
3054
3054
  { label: "End of This Quarter", value: () => ye(tn(/* @__PURE__ */ new Date())) },
3055
- { label: "End of This Year", value: () => ye(Lt(/* @__PURE__ */ new Date())) },
3056
- { label: "End of Last Year", value: () => ye(Lt(new Date((/* @__PURE__ */ new Date()).getFullYear() - 1, 0, 1))) }
3055
+ { label: "End of This Year", value: () => ye(Et(/* @__PURE__ */ new Date())) },
3056
+ { label: "End of Last Year", value: () => ye(Et(new Date((/* @__PURE__ */ new Date()).getFullYear() - 1, 0, 1))) }
3057
3057
  ].map((a) => /* @__PURE__ */ e(
3058
3058
  "button",
3059
3059
  {
@@ -3065,14 +3065,14 @@ function dn({ onSelect: t }) {
3065
3065
  a.label
3066
3066
  )) });
3067
3067
  }
3068
- const Br = ["All", "Draft", "Submitted", "Cancelled"], Lr = /* @__PURE__ */ new Set([
3068
+ const Er = ["All", "Draft", "Submitted", "Cancelled"], Lr = /* @__PURE__ */ new Set([
3069
3069
  "grand_total",
3070
3070
  "outstanding_amount",
3071
3071
  "paid_amount",
3072
3072
  "total_debit",
3073
3073
  "total_amount",
3074
3074
  "net_total"
3075
- ]), Er = /* @__PURE__ */ new Set([
3075
+ ]), Or = /* @__PURE__ */ new Set([
3076
3076
  "transaction_date",
3077
3077
  "posting_date",
3078
3078
  "due_date",
@@ -3089,25 +3089,25 @@ const Br = ["All", "Draft", "Submitted", "Cancelled"], Lr = /* @__PURE__ */ new
3089
3089
  account: "account",
3090
3090
  cost_center: "cost-center"
3091
3091
  };
3092
- function Or(t) {
3092
+ function qr(t) {
3093
3093
  if (typeof t != "string") return null;
3094
3094
  const n = t.toLowerCase();
3095
3095
  return n === "customer" ? "customer" : n === "supplier" ? "supplier" : null;
3096
3096
  }
3097
- const qr = ["25", "50", "100", "200"];
3098
- function zr() {
3099
- const { t } = X(), n = Oe(), { doctype: a } = bt(), s = ia(a ?? ""), [i] = ae("status", "All"), [o] = ae("from", ""), [l] = ae("to", ""), [c] = ae("discarded", ""), [g] = ae("per_page", 50), [m] = ae("page", 1), h = m - 1, u = Ye(), N = (S) => u({ page: S === 0 ? null : S + 1 }), x = (S) => u({ status: S === "All" ? null : S, page: null }), v = (S) => u({ from: S || null, page: null }), f = (S) => u({ to: S || null, page: null }), T = (S) => u({ discarded: S ? "1" : null, page: null }), P = (S) => u({ per_page: S, page: null }), b = Se(() => {
3100
- const S = {};
3101
- return i !== "All" && (S.status = i), o && (S.from_date = o), l && (S.to_date = l), c && (S.include_discarded = "true"), S.limit = g, S.offset = h * g, S;
3102
- }, [i, o, l, c, g, h]), { data: d, isLoading: p } = vr(a ?? "", b), _ = (d == null ? void 0 : d.rows) ?? [], y = (d == null ? void 0 : d.total) ?? 0, B = Math.max(1, Math.ceil(y / g)), D = y === 0 ? 0 : h * g + 1, O = Math.min(y, (h + 1) * g), G = Se(() => {
3097
+ const zr = ["25", "50", "100", "200"];
3098
+ function Mr() {
3099
+ const { t } = Z(), n = Oe(), { doctype: a } = bt(), s = oa(a ?? ""), [i] = ae("status", "All"), [o] = ae("from", ""), [l] = ae("to", ""), [c] = ae("discarded", ""), [g] = ae("per_page", 50), [m] = ae("page", 1), h = m - 1, u = Ye(), N = (C) => u({ page: C === 0 ? null : C + 1 }), x = (C) => u({ status: C === "All" ? null : C, page: null }), v = (C) => u({ from: C || null, page: null }), f = (C) => u({ to: C || null, page: null }), T = (C) => u({ discarded: C ? "1" : null, page: null }), P = (C) => u({ per_page: C, page: null }), b = Ce(() => {
3100
+ const C = {};
3101
+ return i !== "All" && (C.status = i), o && (C.from_date = o), l && (C.to_date = l), c && (C.include_discarded = "true"), C.limit = g, C.offset = h * g, C;
3102
+ }, [i, o, l, c, g, h]), { data: d, isLoading: p } = xr(a ?? "", b), _ = (d == null ? void 0 : d.rows) ?? [], y = (d == null ? void 0 : d.total) ?? 0, B = Math.max(1, Math.ceil(y / g)), D = y === 0 ? 0 : h * g + 1, O = Math.min(y, (h + 1) * g), G = Ce(() => {
3103
3103
  if (!s) return [];
3104
- const S = Qn(), w = (q) => {
3104
+ const C = Yn(), w = (q) => {
3105
3105
  const A = q.split("_").map((z) => z.charAt(0).toUpperCase() + z.slice(1)).join(" ");
3106
3106
  return t(`fields.${A}`, { defaultValue: A });
3107
3107
  };
3108
3108
  return s.listColumns.map((q) => {
3109
3109
  if (q === "name")
3110
- return S.accessor("name", {
3110
+ return C.accessor("name", {
3111
3111
  header: t("fields.Name", { defaultValue: "Name" }),
3112
3112
  cell: (A) => /* @__PURE__ */ e(
3113
3113
  be,
@@ -3119,25 +3119,25 @@ function zr() {
3119
3119
  )
3120
3120
  });
3121
3121
  if (q === "status")
3122
- return S.accessor("status", {
3122
+ return C.accessor("status", {
3123
3123
  header: t("fields.Status", { defaultValue: "Status" }),
3124
3124
  cell: (A) => /* @__PURE__ */ e(ln, { status: A.getValue() })
3125
3125
  });
3126
3126
  if (Lr.has(q))
3127
- return S.accessor(q, {
3127
+ return C.accessor(q, {
3128
3128
  header: w(q),
3129
3129
  cell: (A) => {
3130
3130
  var z;
3131
- return Ee(A.getValue(), ((z = A.row.original) == null ? void 0 : z.currency) || n);
3131
+ return Le(A.getValue(), ((z = A.row.original) == null ? void 0 : z.currency) || n);
3132
3132
  }
3133
3133
  });
3134
3134
  if (q === "party")
3135
- return S.accessor("party", {
3135
+ return C.accessor("party", {
3136
3136
  header: t("fields.Party", { defaultValue: "Party" }),
3137
3137
  cell: (A) => {
3138
3138
  const z = A.getValue();
3139
3139
  if (!z) return "-";
3140
- const Y = Or(A.row.original.party_type), re = Y ? Xt(Y, String(z)) : null;
3140
+ const Y = qr(A.row.original.party_type), re = Y ? Xt(Y, String(z)) : null;
3141
3141
  return re ? /* @__PURE__ */ e(
3142
3142
  be,
3143
3143
  {
@@ -3151,7 +3151,7 @@ function zr() {
3151
3151
  });
3152
3152
  if (An[q]) {
3153
3153
  const A = An[q];
3154
- return S.accessor(q, {
3154
+ return C.accessor(q, {
3155
3155
  header: w(q),
3156
3156
  cell: (z) => {
3157
3157
  const Y = z.getValue();
@@ -3169,31 +3169,31 @@ function zr() {
3169
3169
  }
3170
3170
  });
3171
3171
  }
3172
- return Er.has(q) ? S.accessor(q, {
3172
+ return Or.has(q) ? C.accessor(q, {
3173
3173
  header: w(q),
3174
3174
  cell: (A) => Ft(A.getValue())
3175
- }) : S.accessor(q, {
3175
+ }) : C.accessor(q, {
3176
3176
  header: w(q)
3177
3177
  });
3178
3178
  });
3179
- }, [s, t, n]), ee = Yn({
3179
+ }, [s, t, n]), ee = Jn({
3180
3180
  data: _,
3181
3181
  columns: G,
3182
- getCoreRowModel: Jn()
3182
+ getCoreRowModel: Zn()
3183
3183
  });
3184
3184
  return s ? /* @__PURE__ */ r("div", { className: "space-y-4", children: [
3185
- /* @__PURE__ */ e("div", { className: "flex items-center justify-end", children: /* @__PURE__ */ e(be, { to: `/app/${s.slug}/new`, children: /* @__PURE__ */ e(Q, { children: t("common.new") }) }) }),
3185
+ /* @__PURE__ */ e("div", { className: "flex items-center justify-end", children: /* @__PURE__ */ e(be, { to: `/app/${s.slug}/new`, children: /* @__PURE__ */ e(H, { children: t("common.new") }) }) }),
3186
3186
  /* @__PURE__ */ r("div", { className: "flex flex-wrap items-end gap-4", children: [
3187
3187
  /* @__PURE__ */ e(
3188
3188
  He,
3189
3189
  {
3190
3190
  label: t("fields.Status", { defaultValue: "Status" }),
3191
- options: Br.map((S) => ({
3192
- value: S,
3193
- label: S === "All" ? t("common.all") : t(`status.${S}`, { defaultValue: S })
3191
+ options: Er.map((C) => ({
3192
+ value: C,
3193
+ label: C === "All" ? t("common.all") : t(`status.${C}`, { defaultValue: C })
3194
3194
  })),
3195
3195
  value: i,
3196
- onChange: (S) => x(S.target.value)
3196
+ onChange: (C) => x(C.target.value)
3197
3197
  }
3198
3198
  ),
3199
3199
  /* @__PURE__ */ e(
@@ -3202,7 +3202,7 @@ function zr() {
3202
3202
  label: t("fields.From Date", { defaultValue: "From Date" }),
3203
3203
  type: "date",
3204
3204
  value: o,
3205
- onChange: (S) => v(S.target.value)
3205
+ onChange: (C) => v(C.target.value)
3206
3206
  }
3207
3207
  ),
3208
3208
  /* @__PURE__ */ e(
@@ -3211,7 +3211,7 @@ function zr() {
3211
3211
  label: t("fields.To Date", { defaultValue: "To Date" }),
3212
3212
  type: "date",
3213
3213
  value: l,
3214
- onChange: (S) => f(S.target.value)
3214
+ onChange: (C) => f(C.target.value)
3215
3215
  }
3216
3216
  ),
3217
3217
  /* @__PURE__ */ r("label", { className: "flex h-10 items-center gap-2 text-sm text-fg-muted", children: [
@@ -3221,16 +3221,16 @@ function zr() {
3221
3221
  type: "checkbox",
3222
3222
  className: "h-4 w-4 rounded border-line text-brand focus:ring-brand/30",
3223
3223
  checked: !!c,
3224
- onChange: (S) => T(S.target.checked)
3224
+ onChange: (C) => T(C.target.checked)
3225
3225
  }
3226
3226
  ),
3227
3227
  t("common.showDiscarded")
3228
3228
  ] })
3229
3229
  ] }),
3230
- /* @__PURE__ */ e($t, { onSelect: (S, w) => u({ from: S, to: w, page: null }) }),
3230
+ /* @__PURE__ */ e($t, { onSelect: (C, w) => u({ from: C, to: w, page: null }) }),
3231
3231
  p ? /* @__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(we, { children: [
3232
3232
  /* @__PURE__ */ e("div", { className: "overflow-x-auto rounded-xl bg-surface ring-1 ring-line shadow-card", children: /* @__PURE__ */ r("table", { className: "min-w-full divide-y divide-line text-sm", children: [
3233
- /* @__PURE__ */ e("thead", { className: "bg-surface-subtle", children: ee.getHeaderGroups().map((S) => /* @__PURE__ */ e("tr", { children: S.headers.map((w) => /* @__PURE__ */ e(
3233
+ /* @__PURE__ */ e("thead", { className: "bg-surface-subtle", children: ee.getHeaderGroups().map((C) => /* @__PURE__ */ e("tr", { children: C.headers.map((w) => /* @__PURE__ */ e(
3234
3234
  "th",
3235
3235
  {
3236
3236
  className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wide text-fg-muted",
@@ -3240,11 +3240,11 @@ function zr() {
3240
3240
  )
3241
3241
  },
3242
3242
  w.id
3243
- )) }, S.id)) }),
3244
- /* @__PURE__ */ e("tbody", { className: "divide-y divide-line", children: ee.getRowModel().rows.map((S) => /* @__PURE__ */ e("tr", { className: "transition-colors hover:bg-surface-subtle", children: S.getVisibleCells().map((w) => /* @__PURE__ */ e("td", { className: "px-4 py-2.5 text-fg", children: It(
3243
+ )) }, C.id)) }),
3244
+ /* @__PURE__ */ e("tbody", { className: "divide-y divide-line", children: ee.getRowModel().rows.map((C) => /* @__PURE__ */ e("tr", { className: "transition-colors hover:bg-surface-subtle", children: C.getVisibleCells().map((w) => /* @__PURE__ */ e("td", { className: "px-4 py-2.5 text-fg", children: It(
3245
3245
  w.column.columnDef.cell,
3246
3246
  w.getContext()
3247
- ) }, w.id)) }, S.id)) })
3247
+ ) }, w.id)) }, C.id)) })
3248
3248
  ] }) }),
3249
3249
  /* @__PURE__ */ r("div", { className: "flex flex-wrap items-center justify-between gap-3 text-sm text-fg-muted", children: [
3250
3250
  /* @__PURE__ */ r("div", { children: [
@@ -3267,9 +3267,9 @@ function zr() {
3267
3267
  "select",
3268
3268
  {
3269
3269
  value: g,
3270
- onChange: (S) => P(Number(S.target.value)),
3270
+ onChange: (C) => P(Number(C.target.value)),
3271
3271
  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",
3272
- children: qr.map((S) => /* @__PURE__ */ e("option", { value: S, children: S }, S))
3272
+ children: zr.map((C) => /* @__PURE__ */ e("option", { value: C, children: C }, C))
3273
3273
  }
3274
3274
  )
3275
3275
  ] }),
@@ -3308,14 +3308,14 @@ function zr() {
3308
3308
  a
3309
3309
  ] });
3310
3310
  }
3311
- function Ce({
3311
+ function Se({
3312
3312
  label: t,
3313
3313
  value: n,
3314
3314
  onChange: a,
3315
3315
  linkDoctype: s,
3316
3316
  readOnly: i
3317
3317
  }) {
3318
- const [o, l] = C(n ?? ""), [c, g] = C([]), [m, h] = C(!1), [u, N] = C(!1), [x, v] = C({}), f = te(null), T = te(null), P = te(null), b = te(null), d = te(!1);
3318
+ const [o, l] = S(n ?? ""), [c, g] = S([]), [m, h] = S(!1), [u, N] = S(!1), [x, v] = S({}), f = te(null), T = te(null), P = te(null), b = te(null), d = te(!1);
3319
3319
  se(() => {
3320
3320
  l(n ?? "");
3321
3321
  }, [n]);
@@ -3362,9 +3362,9 @@ function Ce({
3362
3362
  };
3363
3363
  return se(() => {
3364
3364
  const O = (G) => {
3365
- var S, w;
3365
+ var C, w;
3366
3366
  const ee = G.target;
3367
- (S = T.current) != null && S.contains(ee) || (w = P.current) != null && w.contains(ee) || h(!1);
3367
+ (C = T.current) != null && C.contains(ee) || (w = P.current) != null && w.contains(ee) || h(!1);
3368
3368
  };
3369
3369
  return document.addEventListener("mousedown", O), () => document.removeEventListener("mousedown", O);
3370
3370
  }, []), i ? /* @__PURE__ */ r("div", { children: [
@@ -3384,13 +3384,13 @@ function Ce({
3384
3384
  },
3385
3385
  onBlur: D,
3386
3386
  placeholder: `Search ${s}...`,
3387
- className: Le(
3387
+ className: Ee(
3388
3388
  "block h-9 w-full rounded-lg bg-surface px-3 text-sm text-fg ring-1 ring-line transition-all placeholder:text-fg-muted/70 focus:outline-none focus:ring-2 focus:ring-brand/30",
3389
3389
  u && "bg-surface-subtle"
3390
3390
  )
3391
3391
  }
3392
3392
  ),
3393
- m && c.length > 0 && Zn(
3393
+ m && c.length > 0 && Xn(
3394
3394
  /* @__PURE__ */ e("div", { ref: P, style: x, className: "max-h-48 overflow-y-auto rounded-lg bg-surface ring-1 ring-line shadow-card-hover", children: c.map((O, G) => {
3395
3395
  const ee = O.name ?? O.id ?? String(O);
3396
3396
  return /* @__PURE__ */ e(
@@ -3416,9 +3416,9 @@ const _t = () => ({
3416
3416
  position_title: "",
3417
3417
  position_blurb: "",
3418
3418
  is_recommended: 0
3419
- }), Mr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
3419
+ }), Fr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
3420
3420
  function Pn() {
3421
- const { name: t } = bt(), n = !t, a = ze(), s = We(), { t: i } = X(), o = (w, q) => i(w, { defaultValue: q }), [l, c] = C({
3421
+ const { name: t } = bt(), n = !t, a = ze(), s = We(), { t: i } = Z(), o = (w, q) => i(w, { defaultValue: q }), [l, c] = S({
3422
3422
  title: "Offerte",
3423
3423
  customer: "",
3424
3424
  company: "",
@@ -3426,7 +3426,7 @@ function Pn() {
3426
3426
  partner_name: "",
3427
3427
  partner_email: "",
3428
3428
  cover_letter: ""
3429
- }), [g, m] = C([_t()]), [h, u] = C(null), [N, x] = C(!1), [v, f] = C(null), T = te(null), P = (w, q) => c((A) => ({ ...A, [w]: q })), { data: b } = oe({
3429
+ }), [g, m] = S([_t()]), [h, u] = S(null), [N, x] = S(!1), [v, f] = S(null), T = te(null), P = (w, q) => c((A) => ({ ...A, [w]: q })), { data: b } = oe({
3430
3430
  queryKey: ["document", "proposal", t],
3431
3431
  queryFn: () => I.getDocument("proposal", t),
3432
3432
  enabled: !n
@@ -3489,7 +3489,7 @@ function Pn() {
3489
3489
  x(!1);
3490
3490
  }
3491
3491
  }
3492
- }, S = async () => {
3492
+ }, C = async () => {
3493
3493
  if (!n) {
3494
3494
  x(!0);
3495
3495
  try {
@@ -3509,7 +3509,7 @@ function Pn() {
3509
3509
  ] }),
3510
3510
  /* @__PURE__ */ r("div", { className: "flex gap-2", children: [
3511
3511
  !n && /* @__PURE__ */ e(
3512
- Q,
3512
+ H,
3513
3513
  {
3514
3514
  variant: "danger",
3515
3515
  disabled: y.isPending,
@@ -3519,8 +3519,8 @@ function Pn() {
3519
3519
  children: y.isPending ? o("common.discarding", "Discarding…") : o("common.discard", "Discard")
3520
3520
  }
3521
3521
  ),
3522
- !n && /* @__PURE__ */ e(Q, { variant: "secondary", onClick: () => window.open(I.proposalPdfUrl(t), "_blank"), children: o("common.pdf", "PDF") }),
3523
- /* @__PURE__ */ e(Q, { onClick: () => _.mutate(), disabled: _.isPending, children: _.isPending ? o("common.saving", "Saving…") : o("common.save", "Save") })
3522
+ !n && /* @__PURE__ */ e(H, { variant: "secondary", onClick: () => window.open(I.proposalPdfUrl(t), "_blank"), children: o("common.pdf", "PDF") }),
3523
+ /* @__PURE__ */ e(H, { onClick: () => _.mutate(), disabled: _.isPending, children: _.isPending ? o("common.saving", "Saving…") : o("common.save", "Save") })
3524
3524
  ] })
3525
3525
  ] }),
3526
3526
  v && /* @__PURE__ */ e("div", { className: "rounded-lg bg-red-50 px-4 py-2 text-sm text-red-700 ring-1 ring-red-200", children: v }),
@@ -3528,8 +3528,8 @@ function Pn() {
3528
3528
  /* @__PURE__ */ r("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
3529
3529
  /* @__PURE__ */ e(J, { label: o("fields.Title", "Title"), value: l.title, onChange: (w) => P("title", w.target.value) }),
3530
3530
  /* @__PURE__ */ e(J, { label: o("fields.Date", "Date"), type: "date", value: l.proposal_date, onChange: (w) => P("proposal_date", w.target.value) }),
3531
- /* @__PURE__ */ e(Ce, { label: o("fields.Customer", "Customer"), value: l.customer, onChange: (w) => P("customer", w), linkDoctype: "customer", readOnly: !1 }),
3532
- /* @__PURE__ */ e(Ce, { label: o("fields.Company", "Company"), value: l.company, onChange: (w) => P("company", w), linkDoctype: "company", readOnly: !1 }),
3531
+ /* @__PURE__ */ e(Se, { label: o("fields.Customer", "Customer"), value: l.customer, onChange: (w) => P("customer", w), linkDoctype: "customer", readOnly: !1 }),
3532
+ /* @__PURE__ */ e(Se, { label: o("fields.Company", "Company"), value: l.company, onChange: (w) => P("company", w), linkDoctype: "company", readOnly: !1 }),
3533
3533
  /* @__PURE__ */ e(J, { label: o("fields.Partner", "Account Manager"), value: l.partner_name, onChange: (w) => P("partner_name", w.target.value) }),
3534
3534
  /* @__PURE__ */ e(J, { label: o("fields.Partner Email", "Account Manager Email"), value: l.partner_email, onChange: (w) => P("partner_email", w.target.value) })
3535
3535
  ] }),
@@ -3552,12 +3552,12 @@ function Pn() {
3552
3552
  /* @__PURE__ */ r($, { className: "space-y-4 p-5", children: [
3553
3553
  /* @__PURE__ */ r("div", { className: "flex items-center justify-between", children: [
3554
3554
  /* @__PURE__ */ e("h2", { className: "font-semibold text-fg", children: o("proposal.offers", "Offers") }),
3555
- /* @__PURE__ */ e(Q, { size: "sm", variant: "secondary", onClick: D, children: o("proposal.addOffer", "Add offer") })
3555
+ /* @__PURE__ */ e(H, { size: "sm", variant: "secondary", onClick: D, children: o("proposal.addOffer", "Add offer") })
3556
3556
  ] }),
3557
3557
  g.map((w, q) => /* @__PURE__ */ r("div", { className: "rounded-lg p-3 ring-1 ring-line", children: [
3558
3558
  /* @__PURE__ */ r("div", { className: "mb-2 flex items-center gap-2", children: [
3559
- /* @__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: Mr[q] ?? q + 1 }),
3560
- /* @__PURE__ */ e("div", { className: "flex-1", children: /* @__PURE__ */ e(Ce, { label: "", value: w.quotation, onChange: (A) => B(q, { quotation: A }), linkDoctype: "quotation", readOnly: !1 }) }),
3559
+ /* @__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: Fr[q] ?? q + 1 }),
3560
+ /* @__PURE__ */ e("div", { className: "flex-1", children: /* @__PURE__ */ e(Se, { label: "", value: w.quotation, onChange: (A) => B(q, { quotation: A }), linkDoctype: "quotation", readOnly: !1 }) }),
3561
3561
  /* @__PURE__ */ e("button", { type: "button", onClick: () => G(q, -1), disabled: q === 0, className: "px-1 text-fg-muted disabled:opacity-30", children: "↑" }),
3562
3562
  /* @__PURE__ */ e("button", { type: "button", onClick: () => G(q, 1), disabled: q === g.length - 1, className: "px-1 text-fg-muted disabled:opacity-30", children: "↓" }),
3563
3563
  /* @__PURE__ */ e("button", { type: "button", onClick: () => O(q), className: "px-1 text-red-500 hover:text-red-700", children: "✕" })
@@ -3579,10 +3579,10 @@ function Pn() {
3579
3579
  "📎 ",
3580
3580
  h
3581
3581
  ] }),
3582
- /* @__PURE__ */ e("button", { type: "button", onClick: S, disabled: N, className: "text-red-500 hover:underline", children: o("common.remove", "Remove") })
3582
+ /* @__PURE__ */ e("button", { type: "button", onClick: C, disabled: N, className: "text-red-500 hover:underline", children: o("common.remove", "Remove") })
3583
3583
  ] }) : /* @__PURE__ */ r("div", { children: [
3584
3584
  /* @__PURE__ */ e("input", { ref: T, type: "file", accept: "application/pdf", onChange: ee, className: "hidden" }),
3585
- /* @__PURE__ */ e(Q, { size: "sm", variant: "secondary", disabled: N, onClick: () => {
3585
+ /* @__PURE__ */ e(H, { size: "sm", variant: "secondary", disabled: N, onClick: () => {
3586
3586
  var w;
3587
3587
  return (w = T.current) == null ? void 0 : w.click();
3588
3588
  }, children: N ? o("common.uploading", "Uploading…") : o("proposal.uploadAppendix", "Upload appendix PDF") }),
@@ -3591,10 +3591,10 @@ function Pn() {
3591
3591
  ] })
3592
3592
  ] });
3593
3593
  }
3594
- const Fr = ["25", "50", "100", "200"];
3595
- function $r() {
3594
+ const $r = ["25", "50", "100", "200"];
3595
+ function Ur() {
3596
3596
  var d;
3597
- const { type: t } = bt(), n = ze(), s = (d = St().state) == null ? void 0 : d.notice, [i] = ae("per_page", 50), [o] = ae("page", 1), l = o - 1, c = Ye(), g = (p) => c({ page: p === 0 ? null : p + 1 }), m = (p) => c({ per_page: p, page: null }), { data: h, isLoading: u } = oe({
3597
+ const { type: t } = bt(), n = ze(), s = (d = Ct().state) == null ? void 0 : d.notice, [i] = ae("per_page", 50), [o] = ae("page", 1), l = o - 1, c = Ye(), g = (p) => c({ page: p === 0 ? null : p + 1 }), m = (p) => c({ per_page: p, page: null }), { data: h, isLoading: u } = oe({
3598
3598
  queryKey: ["masters", t, l, i],
3599
3599
  queryFn: () => I.listMasters(t, {
3600
3600
  include_disabled: 1,
@@ -3602,9 +3602,9 @@ function $r() {
3602
3602
  offset: l * i
3603
3603
  }),
3604
3604
  enabled: !!t
3605
- }), N = (h == null ? void 0 : h.rows) ?? [], x = (h == null ? void 0 : h.total) ?? 0, v = Math.max(1, Math.ceil(x / i)), f = x === 0 ? 0 : l * i + 1, T = Math.min(x, (l + 1) * i), P = Se(() => {
3605
+ }), N = (h == null ? void 0 : h.rows) ?? [], x = (h == null ? void 0 : h.total) ?? 0, v = Math.max(1, Math.ceil(x / i)), f = x === 0 ? 0 : l * i + 1, T = Math.min(x, (l + 1) * i), P = Ce(() => {
3606
3606
  if (!N || N.length === 0) return [];
3607
- const p = Qn();
3607
+ const p = Yn();
3608
3608
  return Object.keys(N[0]).map(
3609
3609
  (y) => p.accessor(y, {
3610
3610
  header: y.split("_").map((B) => B.charAt(0).toUpperCase() + B.slice(1)).join(" "),
@@ -3625,14 +3625,14 @@ function $r() {
3625
3625
  }
3626
3626
  })
3627
3627
  );
3628
- }, [N, t]), b = Yn({
3628
+ }, [N, t]), b = Jn({
3629
3629
  data: N,
3630
3630
  columns: P,
3631
- getCoreRowModel: Jn()
3631
+ getCoreRowModel: Zn()
3632
3632
  });
3633
3633
  return /* @__PURE__ */ r("div", { className: "space-y-4", children: [
3634
3634
  s && /* @__PURE__ */ e("div", { className: "rounded-md bg-amber-50 px-4 py-3 text-sm text-amber-800", children: s }),
3635
- /* @__PURE__ */ e("div", { className: "flex items-center justify-end", children: /* @__PURE__ */ e(be, { to: `/masters/${t}/new`, children: /* @__PURE__ */ e(Q, { children: "New" }) }) }),
3635
+ /* @__PURE__ */ e("div", { className: "flex items-center justify-end", children: /* @__PURE__ */ e(be, { to: `/masters/${t}/new`, children: /* @__PURE__ */ e(H, { children: "New" }) }) }),
3636
3636
  u ? /* @__PURE__ */ e("p", { className: "text-fg-muted", children: "Loading..." }) : N.length === 0 ? /* @__PURE__ */ e("p", { className: "py-8 text-center text-fg-muted", children: "No records found" }) : /* @__PURE__ */ r(we, { children: [
3637
3637
  /* @__PURE__ */ e("div", { className: "overflow-x-auto rounded-xl bg-surface ring-1 ring-line shadow-card", children: /* @__PURE__ */ r("table", { className: "min-w-full divide-y divide-line text-sm", children: [
3638
3638
  /* @__PURE__ */ e("thead", { className: "bg-surface-subtle", children: b.getHeaderGroups().map((p) => /* @__PURE__ */ e("tr", { children: p.headers.map((_) => /* @__PURE__ */ e(
@@ -3680,7 +3680,7 @@ function $r() {
3680
3680
  value: i,
3681
3681
  onChange: (p) => m(Number(p.target.value)),
3682
3682
  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",
3683
- children: Fr.map((p) => /* @__PURE__ */ e("option", { value: p, children: p }, p))
3683
+ children: $r.map((p) => /* @__PURE__ */ e("option", { value: p, children: p }, p))
3684
3684
  }
3685
3685
  )
3686
3686
  ] }),
@@ -3714,7 +3714,7 @@ function $r() {
3714
3714
  ] })
3715
3715
  ] });
3716
3716
  }
3717
- const Ur = {
3717
+ const Vr = {
3718
3718
  customer: [
3719
3719
  { name: "name", label: "ID", type: "text", required: !0 },
3720
3720
  { name: "customer_name", label: "Customer Name", type: "text", required: !0 },
@@ -3777,7 +3777,7 @@ const Ur = {
3777
3777
  { name: "tax_id", label: "Tax ID", type: "text" },
3778
3778
  { name: "iban", label: "IBAN", type: "text" }
3779
3779
  ]
3780
- }, Vr = {
3780
+ }, Kr = {
3781
3781
  customer: "Customer",
3782
3782
  supplier: "Supplier",
3783
3783
  item: "Item",
@@ -3786,7 +3786,7 @@ const Ur = {
3786
3786
  }, _n = /* @__PURE__ */ new Set(["customer", "supplier", "item", "warehouse"]);
3787
3787
  function Tn() {
3788
3788
  var B;
3789
- const { type: t, name: n } = bt(), a = ze(), s = We(), { t: i } = X(), o = !n || n === "new", l = Vr[t ?? ""] ?? t ?? "", c = i(`masters.${t}.one`, { defaultValue: l }), g = Ur[t ?? ""] ?? [], m = (D) => i(`fields.${D.label}`, { defaultValue: D.label }), [h, u] = C({}), { data: N, isLoading: x } = oe({
3789
+ const { type: t, name: n } = bt(), a = ze(), s = We(), { t: i } = Z(), o = !n || n === "new", l = Kr[t ?? ""] ?? t ?? "", c = i(`masters.${t}.one`, { defaultValue: l }), g = Vr[t ?? ""] ?? [], m = (D) => i(`fields.${D.label}`, { defaultValue: D.label }), [h, u] = S({}), { data: N, isLoading: x } = oe({
3790
3790
  queryKey: ["master", t, n],
3791
3791
  queryFn: () => I.getMaster(t, n),
3792
3792
  enabled: !!t && !!n && !o
@@ -3852,9 +3852,9 @@ function Tn() {
3852
3852
  });
3853
3853
  return /* @__PURE__ */ r("div", { className: "space-y-6", children: [
3854
3854
  /* @__PURE__ */ e("div", { className: "flex items-center justify-end", children: /* @__PURE__ */ r("div", { className: "flex gap-2", children: [
3855
- /* @__PURE__ */ e(Q, { onClick: b, disabled: _ || y.length > 0, children: i(_ ? "common.saving" : "common.save") }),
3855
+ /* @__PURE__ */ e(H, { onClick: b, disabled: _ || y.length > 0, children: i(_ ? "common.saving" : "common.save") }),
3856
3856
  !o && /* @__PURE__ */ e(
3857
- Q,
3857
+ H,
3858
3858
  {
3859
3859
  variant: "danger",
3860
3860
  onClick: d,
@@ -3898,12 +3898,12 @@ function Tn() {
3898
3898
  }
3899
3899
  )
3900
3900
  ] }, D.name);
3901
- const S = D.type === "number" || D.type === "currency" ? "number" : D.type === "date" ? "date" : "text";
3901
+ const C = D.type === "number" || D.type === "currency" ? "number" : D.type === "date" ? "date" : "text";
3902
3902
  return /* @__PURE__ */ e(
3903
3903
  J,
3904
3904
  {
3905
3905
  label: m(D),
3906
- type: S,
3906
+ type: C,
3907
3907
  step: D.type === "currency" ? "0.01" : void 0,
3908
3908
  required: ee,
3909
3909
  readOnly: G,
@@ -3911,7 +3911,7 @@ function Tn() {
3911
3911
  value: h[D.name] ?? "",
3912
3912
  onChange: (w) => p(
3913
3913
  D.name,
3914
- S === "number" ? parseFloat(w.target.value) || 0 : w.target.value
3914
+ C === "number" ? parseFloat(w.target.value) || 0 : w.target.value
3915
3915
  )
3916
3916
  },
3917
3917
  D.name
@@ -3919,67 +3919,67 @@ function Tn() {
3919
3919
  }) }) })
3920
3920
  ] });
3921
3921
  }
3922
- function Kr(t) {
3922
+ function jr(t) {
3923
3923
  const { data: n, isLoading: a, error: s, refetch: i } = oe({
3924
3924
  queryKey: ["report", "trial-balance", t],
3925
3925
  queryFn: () => I.trialBalance(t)
3926
3926
  });
3927
3927
  return { data: n, isLoading: a, error: s, refetch: i };
3928
3928
  }
3929
- function jr(t) {
3929
+ function Gr(t) {
3930
3930
  const { data: n, isLoading: a, error: s, refetch: i } = oe({
3931
3931
  queryKey: ["report", "chart-of-accounts", t],
3932
3932
  queryFn: () => I.chartOfAccounts(t)
3933
3933
  });
3934
3934
  return { data: n, isLoading: a, error: s, refetch: i };
3935
3935
  }
3936
- function Gr(t) {
3936
+ function Wr(t) {
3937
3937
  const { data: n, isLoading: a, error: s, refetch: i } = oe({
3938
3938
  queryKey: ["report", "general-ledger", t],
3939
3939
  queryFn: () => I.generalLedger(t)
3940
3940
  });
3941
3941
  return { data: n, isLoading: a, error: s, refetch: i };
3942
3942
  }
3943
- function Wr(t) {
3943
+ function Hr(t) {
3944
3944
  const { data: n, isLoading: a, error: s, refetch: i } = oe({
3945
3945
  queryKey: ["report", "stock-balance", t],
3946
3946
  queryFn: () => I.stockBalance(t)
3947
3947
  });
3948
3948
  return { data: n, isLoading: a, error: s, refetch: i };
3949
3949
  }
3950
- function Hr(t) {
3950
+ function Qr(t) {
3951
3951
  const { data: n, isLoading: a, error: s, refetch: i } = oe({
3952
3952
  queryKey: ["report", "profit-and-loss", t],
3953
3953
  queryFn: () => I.profitAndLoss(t)
3954
3954
  });
3955
3955
  return { data: n, isLoading: a, error: s, refetch: i };
3956
3956
  }
3957
- function Qr(t) {
3957
+ function Yr(t) {
3958
3958
  const { data: n, isLoading: a, error: s, refetch: i } = oe({
3959
3959
  queryKey: ["report", "balance-sheet", t],
3960
3960
  queryFn: () => I.balanceSheet(t)
3961
3961
  });
3962
3962
  return { data: n, isLoading: a, error: s, refetch: i };
3963
3963
  }
3964
- function Yr(t) {
3964
+ function Jr(t) {
3965
3965
  const { data: n, isLoading: a, error: s, refetch: i } = oe({
3966
3966
  queryKey: ["report", "ar-aging", t],
3967
3967
  queryFn: () => I.arAging(t)
3968
3968
  });
3969
3969
  return { data: n, isLoading: a, error: s, refetch: i };
3970
3970
  }
3971
- function Jr(t) {
3971
+ function Zr(t) {
3972
3972
  const { data: n, isLoading: a, error: s, refetch: i } = oe({
3973
3973
  queryKey: ["report", "ap-aging", t],
3974
3974
  queryFn: () => I.apAging(t)
3975
3975
  });
3976
3976
  return { data: n, isLoading: a, error: s, refetch: i };
3977
3977
  }
3978
- function Zr() {
3979
- const { t } = X(), [n] = ae("company", ""), [a] = ae("from", ""), [s] = ae("to", ""), i = Ye(), [o, l] = C(n), [c, g] = C(a), [m, h] = C(s), u = Oe(o), N = (d) => Ee(d, u), x = Se(() => {
3978
+ function Xr() {
3979
+ const { t } = Z(), [n] = ae("company", ""), [a] = ae("from", ""), [s] = ae("to", ""), i = Ye(), [o, l] = S(n), [c, g] = S(a), [m, h] = S(s), u = Oe(o), N = (d) => Le(d, u), x = Ce(() => {
3980
3980
  const d = {};
3981
3981
  return n && (d.company = n), a && (d.from_date = a), s && (d.to_date = s), d;
3982
- }, [n, a, s]), { data: v, isLoading: f, refetch: T } = Kr(x), P = () => {
3982
+ }, [n, a, s]), { data: v, isLoading: f, refetch: T } = jr(x), P = () => {
3983
3983
  i({
3984
3984
  company: o || null,
3985
3985
  from: c || null,
@@ -3989,7 +3989,7 @@ function Zr() {
3989
3989
  return /* @__PURE__ */ r("div", { className: "space-y-4", children: [
3990
3990
  /* @__PURE__ */ r("div", { className: "flex flex-wrap items-end gap-4", children: [
3991
3991
  /* @__PURE__ */ e(
3992
- Ce,
3992
+ Se,
3993
3993
  {
3994
3994
  label: t("fields.Company", { defaultValue: "Company" }),
3995
3995
  value: o,
@@ -4016,7 +4016,7 @@ function Zr() {
4016
4016
  onChange: (d) => h(d.target.value)
4017
4017
  }
4018
4018
  ),
4019
- /* @__PURE__ */ e(Q, { onClick: P, children: t("common.apply") })
4019
+ /* @__PURE__ */ e(H, { onClick: P, children: t("common.apply") })
4020
4020
  ] }),
4021
4021
  /* @__PURE__ */ e($t, { onSelect: (d, p) => {
4022
4022
  g(d), h(p), i({ from: d, to: p });
@@ -4052,17 +4052,17 @@ function Zr() {
4052
4052
  ] })
4053
4053
  ] });
4054
4054
  }
4055
- const Xr = ["Asset", "Liability", "Equity", "Income", "Expense"];
4056
- function es() {
4057
- const { t } = X(), n = (/* @__PURE__ */ new Date()).getFullYear(), [a, s] = C(String(n)), [i, o] = C(/* @__PURE__ */ new Set()), l = Se(() => {
4055
+ const es = ["Asset", "Liability", "Equity", "Income", "Expense"];
4056
+ function ts() {
4057
+ const { t } = Z(), n = (/* @__PURE__ */ new Date()).getFullYear(), [a, s] = S(String(n)), [i, o] = S(/* @__PURE__ */ new Set()), l = Ce(() => {
4058
4058
  const b = [];
4059
4059
  for (let d = n; d >= n - 6; d--)
4060
4060
  b.push({ value: String(d), label: String(d) });
4061
4061
  return b.push({ value: "all", label: t("coa.allTime", { defaultValue: "All time" }) }), b;
4062
- }, [n, t]), c = Se(() => {
4062
+ }, [n, t]), c = Ce(() => {
4063
4063
  const b = {};
4064
4064
  return a !== "all" && (b.from_date = `${a}-01-01`, b.to_date = `${a}-12-31`), b;
4065
- }, [a]), { data: g, isLoading: m } = jr(c), h = Oe(""), u = (b) => Ee(b, h), N = (g == null ? void 0 : g.accounts) ?? [], { childrenOf: x, rootsByType: v } = Se(() => {
4065
+ }, [a]), { data: g, isLoading: m } = Gr(c), h = Oe(""), u = (b) => Le(b, h), N = (g == null ? void 0 : g.accounts) ?? [], { childrenOf: x, rootsByType: v } = Ce(() => {
4066
4066
  const b = new Map(N.map((_) => [_.name, _])), d = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map();
4067
4067
  for (const _ of N)
4068
4068
  if (_.parent_account && b.has(_.parent_account)) {
@@ -4132,21 +4132,21 @@ function es() {
4132
4132
  ] }),
4133
4133
  m && /* @__PURE__ */ e($, { children: /* @__PURE__ */ e("p", { className: "text-sm text-fg-muted", children: t("common.loading", { defaultValue: "Loading…" }) }) }),
4134
4134
  !m && N.length === 0 && /* @__PURE__ */ e($, { children: /* @__PURE__ */ e("p", { className: "text-sm text-fg-muted", children: t("coa.empty", { defaultValue: "No accounts found. Complete the company setup first." }) }) }),
4135
- !m && Xr.filter((b) => (v.get(b) ?? []).length > 0).map((b) => /* @__PURE__ */ r($, { children: [
4135
+ !m && es.filter((b) => (v.get(b) ?? []).length > 0).map((b) => /* @__PURE__ */ r($, { children: [
4136
4136
  /* @__PURE__ */ e("h3", { className: "mb-2 px-2 text-xs font-semibold uppercase tracking-wider text-fg-muted", children: t(`coa.rootType.${b}`, { defaultValue: b }) }),
4137
4137
  /* @__PURE__ */ e("div", { children: (v.get(b) ?? []).map((d) => P(d, 0)) })
4138
4138
  ] }, b))
4139
4139
  ] });
4140
4140
  }
4141
- function ts(t) {
4141
+ function ns(t) {
4142
4142
  return t.toLowerCase().replace(/\s+/g, "-");
4143
4143
  }
4144
- const ns = ["25", "50", "100", "200"];
4145
- function as() {
4146
- const { t } = X(), [n] = ae("account", ""), [a] = ae("party", ""), [s] = ae("from", ""), [i] = ae("to", ""), [o] = ae("per_page", 50), [l] = ae("page", 1), c = l - 1, g = Ye(), m = (A) => g({ page: A === 0 ? null : A + 1 }), h = (A) => g({ per_page: A, page: null }), [u, N] = C(n), [x, v] = C(a), [f, T] = C(s), [P, b] = C(i), d = Oe(), p = (A) => Ee(A, d), _ = Se(() => {
4144
+ const as = ["25", "50", "100", "200"];
4145
+ function rs() {
4146
+ const { t } = Z(), [n] = ae("account", ""), [a] = ae("party", ""), [s] = ae("from", ""), [i] = ae("to", ""), [o] = ae("per_page", 50), [l] = ae("page", 1), c = l - 1, g = Ye(), m = (A) => g({ page: A === 0 ? null : A + 1 }), h = (A) => g({ per_page: A, page: null }), [u, N] = S(n), [x, v] = S(a), [f, T] = S(s), [P, b] = S(i), d = Oe(), p = (A) => Le(A, d), _ = Ce(() => {
4147
4147
  const A = {};
4148
4148
  return n && (A.account = n), a && (A.party = a), s && (A.from_date = s), i && (A.to_date = i), A.limit = String(o), A.offset = String(c * o), A;
4149
- }, [n, a, s, i, o, c]), { data: y, isLoading: B, refetch: D } = Gr(_), O = (y == null ? void 0 : y.rows) ?? [], G = (y == null ? void 0 : y.total) ?? 0, ee = Math.max(1, Math.ceil(G / o)), S = G === 0 ? 0 : c * o + 1, w = Math.min(G, (c + 1) * o), q = () => {
4149
+ }, [n, a, s, i, o, c]), { data: y, isLoading: B, refetch: D } = Wr(_), O = (y == null ? void 0 : y.rows) ?? [], G = (y == null ? void 0 : y.total) ?? 0, ee = Math.max(1, Math.ceil(G / o)), C = G === 0 ? 0 : c * o + 1, w = Math.min(G, (c + 1) * o), q = () => {
4150
4150
  g({
4151
4151
  account: u || null,
4152
4152
  party: x || null,
@@ -4158,7 +4158,7 @@ function as() {
4158
4158
  return /* @__PURE__ */ r("div", { className: "space-y-4", children: [
4159
4159
  /* @__PURE__ */ r("div", { className: "flex flex-wrap items-end gap-4", children: [
4160
4160
  /* @__PURE__ */ e(
4161
- Ce,
4161
+ Se,
4162
4162
  {
4163
4163
  label: t("fields.Account", { defaultValue: "Account" }),
4164
4164
  value: u,
@@ -4168,7 +4168,7 @@ function as() {
4168
4168
  }
4169
4169
  ),
4170
4170
  /* @__PURE__ */ e(
4171
- Ce,
4171
+ Se,
4172
4172
  {
4173
4173
  label: t("fields.Party", { defaultValue: "Party" }),
4174
4174
  value: x,
@@ -4195,7 +4195,7 @@ function as() {
4195
4195
  onChange: (A) => b(A.target.value)
4196
4196
  }
4197
4197
  ),
4198
- /* @__PURE__ */ e(Q, { onClick: q, children: t("common.apply") })
4198
+ /* @__PURE__ */ e(H, { onClick: q, children: t("common.apply") })
4199
4199
  ] }),
4200
4200
  /* @__PURE__ */ e($t, { onSelect: (A, z) => {
4201
4201
  T(A), b(z), g({ from: A, to: z, page: null });
@@ -4223,7 +4223,7 @@ function as() {
4223
4223
  /* @__PURE__ */ e("td", { className: "px-4 py-2", children: A.voucher_type && A.voucher_no ? /* @__PURE__ */ e(
4224
4224
  be,
4225
4225
  {
4226
- to: `/app/${ts(A.voucher_type)}/${A.voucher_no}`,
4226
+ to: `/app/${ns(A.voucher_type)}/${A.voucher_no}`,
4227
4227
  className: "font-medium text-blue-600 hover:text-blue-800",
4228
4228
  children: A.voucher_no
4229
4229
  }
@@ -4235,7 +4235,7 @@ function as() {
4235
4235
  t("common.showing"),
4236
4236
  " ",
4237
4237
  /* @__PURE__ */ r("span", { className: "font-medium text-gray-900", children: [
4238
- S,
4238
+ C,
4239
4239
  "–",
4240
4240
  w
4241
4241
  ] }),
@@ -4253,7 +4253,7 @@ function as() {
4253
4253
  value: o,
4254
4254
  onChange: (A) => h(Number(A.target.value)),
4255
4255
  className: "rounded border border-gray-300 bg-white px-2 py-1 text-sm",
4256
- children: ns.map((A) => /* @__PURE__ */ e("option", { value: A, children: A }, A))
4256
+ children: as.map((A) => /* @__PURE__ */ e("option", { value: A, children: A }, A))
4257
4257
  }
4258
4258
  )
4259
4259
  ] }),
@@ -4289,11 +4289,11 @@ function as() {
4289
4289
  ] })
4290
4290
  ] });
4291
4291
  }
4292
- function rs() {
4293
- const { t } = X(), [n] = ae("item_code", ""), [a] = ae("warehouse", ""), s = Ye(), [i, o] = C(n), [l, c] = C(a), g = Oe(), m = (f) => Ee(f, g), h = Se(() => {
4292
+ function ss() {
4293
+ const { t } = Z(), [n] = ae("item_code", ""), [a] = ae("warehouse", ""), s = Ye(), [i, o] = S(n), [l, c] = S(a), g = Oe(), m = (f) => Le(f, g), h = Ce(() => {
4294
4294
  const f = {};
4295
4295
  return n && (f.item_code = n), a && (f.warehouse = a), f;
4296
- }, [n, a]), { data: u, isLoading: N, refetch: x } = Wr(h), v = () => {
4296
+ }, [n, a]), { data: u, isLoading: N, refetch: x } = Hr(h), v = () => {
4297
4297
  s({
4298
4298
  item_code: i || null,
4299
4299
  warehouse: l || null
@@ -4302,7 +4302,7 @@ function rs() {
4302
4302
  return /* @__PURE__ */ r("div", { className: "space-y-4", children: [
4303
4303
  /* @__PURE__ */ r("div", { className: "flex flex-wrap items-end gap-4", children: [
4304
4304
  /* @__PURE__ */ e(
4305
- Ce,
4305
+ Se,
4306
4306
  {
4307
4307
  label: t("fields.Item Code", { defaultValue: "Item Code" }),
4308
4308
  value: i,
@@ -4312,7 +4312,7 @@ function rs() {
4312
4312
  }
4313
4313
  ),
4314
4314
  /* @__PURE__ */ e(
4315
- Ce,
4315
+ Se,
4316
4316
  {
4317
4317
  label: t("fields.Warehouse", { defaultValue: "Warehouse" }),
4318
4318
  value: l,
@@ -4321,7 +4321,7 @@ function rs() {
4321
4321
  readOnly: !1
4322
4322
  }
4323
4323
  ),
4324
- /* @__PURE__ */ e(Q, { onClick: v, children: t("common.apply") })
4324
+ /* @__PURE__ */ e(H, { onClick: v, children: t("common.apply") })
4325
4325
  ] }),
4326
4326
  N ? /* @__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.noStockData") }) : /* @__PURE__ */ e($, { children: /* @__PURE__ */ e("div", { className: "overflow-x-auto", children: /* @__PURE__ */ r("table", { className: "min-w-full divide-y divide-gray-200 text-sm", children: [
4327
4327
  /* @__PURE__ */ e("thead", { className: "bg-gray-50", children: /* @__PURE__ */ r("tr", { children: [
@@ -4343,11 +4343,11 @@ function rs() {
4343
4343
  ] }) }) })
4344
4344
  ] });
4345
4345
  }
4346
- function ss() {
4347
- const { t } = X(), [n] = ae("company", ""), [a] = ae("from", ""), [s] = ae("to", ""), i = Ye(), [o, l] = C(n), c = Oe(o), g = (d) => Ee(d, c), [m, h] = C(a), [u, N] = C(s), x = Se(() => {
4346
+ function is() {
4347
+ const { t } = Z(), [n] = ae("company", ""), [a] = ae("from", ""), [s] = ae("to", ""), i = Ye(), [o, l] = S(n), c = Oe(o), g = (d) => Le(d, c), [m, h] = S(a), [u, N] = S(s), x = Ce(() => {
4348
4348
  const d = {};
4349
4349
  return n && (d.company = n), a && (d.from_date = a), s && (d.to_date = s), d;
4350
- }, [n, a, s]), { data: v, isLoading: f, refetch: T } = Hr(x), P = () => {
4350
+ }, [n, a, s]), { data: v, isLoading: f, refetch: T } = Qr(x), P = () => {
4351
4351
  i({
4352
4352
  company: o || null,
4353
4353
  from: m || null,
@@ -4356,10 +4356,10 @@ function ss() {
4356
4356
  }, b = v && (v.income && v.income.length > 0 || v.expense && v.expense.length > 0);
4357
4357
  return /* @__PURE__ */ r("div", { className: "space-y-4", children: [
4358
4358
  /* @__PURE__ */ r("div", { className: "flex flex-wrap items-end gap-4", children: [
4359
- /* @__PURE__ */ e(Ce, { label: t("fields.Company", { defaultValue: "Company" }), value: o, onChange: l, linkDoctype: "company", readOnly: !1 }),
4359
+ /* @__PURE__ */ e(Se, { label: t("fields.Company", { defaultValue: "Company" }), value: o, onChange: l, linkDoctype: "company", readOnly: !1 }),
4360
4360
  /* @__PURE__ */ e(J, { label: t("fields.From Date", { defaultValue: "From Date" }), type: "date", value: m, onChange: (d) => h(d.target.value) }),
4361
4361
  /* @__PURE__ */ e(J, { label: t("fields.To Date", { defaultValue: "To Date" }), type: "date", value: u, onChange: (d) => N(d.target.value) }),
4362
- /* @__PURE__ */ e(Q, { onClick: P, children: t("common.apply") })
4362
+ /* @__PURE__ */ e(H, { onClick: P, children: t("common.apply") })
4363
4363
  ] }),
4364
4364
  /* @__PURE__ */ e($t, { onSelect: (d, p) => {
4365
4365
  h(d), N(p), i({ from: d, to: p });
@@ -4408,7 +4408,7 @@ function ss() {
4408
4408
  ] });
4409
4409
  }
4410
4410
  function Gt({ title: t, rows: n, total: a, totalLabel: s, currency: i }) {
4411
- const { t: o } = X(), l = (c) => Ee(c, i);
4411
+ const { t: o } = Z(), l = (c) => Le(c, i);
4412
4412
  return /* @__PURE__ */ r($, { children: [
4413
4413
  /* @__PURE__ */ e("h3", { className: "mb-3 text-base font-semibold text-gray-800", children: t }),
4414
4414
  /* @__PURE__ */ r("table", { className: "min-w-full divide-y divide-gray-200 text-sm", children: [
@@ -4427,19 +4427,19 @@ function Gt({ title: t, rows: n, total: a, totalLabel: s, currency: i }) {
4427
4427
  ] })
4428
4428
  ] });
4429
4429
  }
4430
- function is() {
4430
+ function os() {
4431
4431
  var P, b, d;
4432
- const { t } = X(), [n] = ae("company", ""), [a] = ae("as_of_date", ""), s = Ye(), [i, o] = C(n), [l, c] = C(a), g = Oe(i), m = (p) => Ee(p, g), h = Se(() => {
4432
+ const { t } = Z(), [n] = ae("company", ""), [a] = ae("as_of_date", ""), s = Ye(), [i, o] = S(n), [l, c] = S(a), g = Oe(i), m = (p) => Le(p, g), h = Ce(() => {
4433
4433
  const p = {};
4434
4434
  return n && (p.company = n), a && (p.as_of_date = a), p;
4435
- }, [n, a]), { data: u, isLoading: N, refetch: x } = Qr(h), v = () => {
4435
+ }, [n, a]), { data: u, isLoading: N, refetch: x } = Yr(h), v = () => {
4436
4436
  s({ company: i || null, as_of_date: l || null }), x();
4437
4437
  }, f = u && (((P = u.assets) == null ? void 0 : P.length) > 0 || ((b = u.liabilities) == null ? void 0 : b.length) > 0 || ((d = u.equity) == null ? void 0 : d.length) > 0), T = u ? Math.abs(u.total_assets - u.total_liabilities_and_equity) < 0.01 : !1;
4438
4438
  return /* @__PURE__ */ r("div", { className: "space-y-4", children: [
4439
4439
  /* @__PURE__ */ r("div", { className: "flex flex-wrap items-end gap-4", children: [
4440
- /* @__PURE__ */ e(Ce, { label: t("fields.Company", { defaultValue: "Company" }), value: i, onChange: o, linkDoctype: "company", readOnly: !1 }),
4440
+ /* @__PURE__ */ e(Se, { label: t("fields.Company", { defaultValue: "Company" }), value: i, onChange: o, linkDoctype: "company", readOnly: !1 }),
4441
4441
  /* @__PURE__ */ e(J, { label: t("fields.As of Date", { defaultValue: "As of Date" }), type: "date", value: l, onChange: (p) => c(p.target.value) }),
4442
- /* @__PURE__ */ e(Q, { onClick: v, children: t("common.apply") })
4442
+ /* @__PURE__ */ e(H, { onClick: v, children: t("common.apply") })
4443
4443
  ] }),
4444
4444
  /* @__PURE__ */ e(dn, { onSelect: (p) => {
4445
4445
  c(p), s({ as_of_date: p });
@@ -4466,18 +4466,18 @@ function is() {
4466
4466
  ] }) : /* @__PURE__ */ e("p", { className: "py-8 text-center text-gray-400", children: t("reports.noData") })
4467
4467
  ] });
4468
4468
  }
4469
- function os() {
4470
- const { t } = X(), [n] = ae("company", ""), [a] = ae("as_of_date", ""), s = Ye(), [i, o] = C(n), [l, c] = C(a), g = Oe(i), m = (f) => Ee(f, g), h = Se(() => {
4469
+ function ls() {
4470
+ const { t } = Z(), [n] = ae("company", ""), [a] = ae("as_of_date", ""), s = Ye(), [i, o] = S(n), [l, c] = S(a), g = Oe(i), m = (f) => Le(f, g), h = Ce(() => {
4471
4471
  const f = {};
4472
4472
  return n && (f.company = n), a && (f.as_of_date = a), f;
4473
- }, [n, a]), { data: u, isLoading: N, refetch: x } = Yr(h), v = () => {
4473
+ }, [n, a]), { data: u, isLoading: N, refetch: x } = Jr(h), v = () => {
4474
4474
  s({ company: i || null, as_of_date: l || null }), x();
4475
4475
  };
4476
4476
  return /* @__PURE__ */ r("div", { className: "space-y-4", children: [
4477
4477
  /* @__PURE__ */ r("div", { className: "flex flex-wrap items-end gap-4", children: [
4478
- /* @__PURE__ */ e(Ce, { label: t("fields.Company", { defaultValue: "Company" }), value: i, onChange: o, linkDoctype: "company", readOnly: !1 }),
4478
+ /* @__PURE__ */ e(Se, { label: t("fields.Company", { defaultValue: "Company" }), value: i, onChange: o, linkDoctype: "company", readOnly: !1 }),
4479
4479
  /* @__PURE__ */ e(J, { label: t("fields.As of Date", { defaultValue: "As of Date" }), type: "date", value: l, onChange: (f) => c(f.target.value) }),
4480
- /* @__PURE__ */ e(Q, { onClick: v, children: t("common.apply") })
4480
+ /* @__PURE__ */ e(H, { onClick: v, children: t("common.apply") })
4481
4481
  ] }),
4482
4482
  /* @__PURE__ */ e(dn, { onSelect: (f) => {
4483
4483
  c(f), s({ as_of_date: f });
@@ -4524,18 +4524,18 @@ function os() {
4524
4524
  ] }) }) })
4525
4525
  ] });
4526
4526
  }
4527
- function ls() {
4528
- const { t } = X(), [n] = ae("company", ""), [a] = ae("as_of_date", ""), s = Ye(), [i, o] = C(n), [l, c] = C(a), g = Oe(i), m = (f) => Ee(f, g), h = Se(() => {
4527
+ function cs() {
4528
+ const { t } = Z(), [n] = ae("company", ""), [a] = ae("as_of_date", ""), s = Ye(), [i, o] = S(n), [l, c] = S(a), g = Oe(i), m = (f) => Le(f, g), h = Ce(() => {
4529
4529
  const f = {};
4530
4530
  return n && (f.company = n), a && (f.as_of_date = a), f;
4531
- }, [n, a]), { data: u, isLoading: N, refetch: x } = Jr(h), v = () => {
4531
+ }, [n, a]), { data: u, isLoading: N, refetch: x } = Zr(h), v = () => {
4532
4532
  s({ company: i || null, as_of_date: l || null }), x();
4533
4533
  };
4534
4534
  return /* @__PURE__ */ r("div", { className: "space-y-4", children: [
4535
4535
  /* @__PURE__ */ r("div", { className: "flex flex-wrap items-end gap-4", children: [
4536
- /* @__PURE__ */ e(Ce, { label: t("fields.Company", { defaultValue: "Company" }), value: i, onChange: o, linkDoctype: "company", readOnly: !1 }),
4536
+ /* @__PURE__ */ e(Se, { label: t("fields.Company", { defaultValue: "Company" }), value: i, onChange: o, linkDoctype: "company", readOnly: !1 }),
4537
4537
  /* @__PURE__ */ e(J, { label: t("fields.As of Date", { defaultValue: "As of Date" }), type: "date", value: l, onChange: (f) => c(f.target.value) }),
4538
- /* @__PURE__ */ e(Q, { onClick: v, children: t("common.apply") })
4538
+ /* @__PURE__ */ e(H, { onClick: v, children: t("common.apply") })
4539
4539
  ] }),
4540
4540
  /* @__PURE__ */ e(dn, { onSelect: (f) => {
4541
4541
  c(f), s({ as_of_date: f });
@@ -4582,8 +4582,8 @@ function ls() {
4582
4582
  ] }) }) })
4583
4583
  ] });
4584
4584
  }
4585
- const la = '(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', Rn = typeof self < "u" && self.Blob && new Blob([la], { type: "text/javascript;charset=utf-8" });
4586
- function cs(t) {
4585
+ const ca = '(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', Rn = typeof self < "u" && self.Blob && new Blob([ca], { type: "text/javascript;charset=utf-8" });
4586
+ function ds(t) {
4587
4587
  let n;
4588
4588
  try {
4589
4589
  if (n = Rn && (self.URL || self.webkitURL).createObjectURL(Rn), !n) throw "";
@@ -4595,7 +4595,7 @@ function cs(t) {
4595
4595
  }), a;
4596
4596
  } catch {
4597
4597
  return new Worker(
4598
- "data:text/javascript;charset=utf-8," + encodeURIComponent(la),
4598
+ "data:text/javascript;charset=utf-8," + encodeURIComponent(ca),
4599
4599
  {
4600
4600
  name: t == null ? void 0 : t.name
4601
4601
  }
@@ -4604,7 +4604,7 @@ function cs(t) {
4604
4604
  n && (self.URL || self.webkitURL).revokeObjectURL(n);
4605
4605
  }
4606
4606
  }
4607
- function ds() {
4607
+ function us() {
4608
4608
  const t = /* @__PURE__ */ new Date(), n = t.toISOString().slice(0, 10), a = new Date(t);
4609
4609
  a.setMonth(a.getMonth() - 12);
4610
4610
  const s = a.toISOString().slice(0, 10);
@@ -4675,15 +4675,15 @@ return {
4675
4675
  2
4676
4676
  );
4677
4677
  }
4678
- const ca = ds();
4679
- function us() {
4680
- const t = ze(), { sessions: n, createSession: a } = ut(), [s] = ae("report_id", ""), [i] = ae("metric", ""), [o] = ae("group_by", ""), [l] = ae("from", ""), [c] = ae("to", ""), [g] = ae("company", ""), [m, h] = C(ca), [u, N] = C([]), [x, v] = C(null), [f, T] = C(""), [P, b] = C(!1), [d, p] = C(!1), [_, y] = C(""), B = te(null), D = te(""), O = te(""), G = te(0), ee = Se(() => !i || !o ? "" : JSON.stringify(gs({
4678
+ const da = us();
4679
+ function ms() {
4680
+ const t = ze(), { sessions: n, createSession: a } = ut(), [s] = ae("report_id", ""), [i] = ae("metric", ""), [o] = ae("group_by", ""), [l] = ae("from", ""), [c] = ae("to", ""), [g] = ae("company", ""), [m, h] = S(da), [u, N] = S([]), [x, v] = S(null), [f, T] = S(""), [P, b] = S(!1), [d, p] = S(!1), [_, y] = S(""), B = te(null), D = te(""), O = te(""), G = te(0), ee = Ce(() => !i || !o ? "" : JSON.stringify(fs({
4681
4681
  metric: i,
4682
4682
  groupBy: o,
4683
4683
  fromDate: l || void 0,
4684
4684
  toDate: c || void 0,
4685
4685
  company: g || void 0
4686
- }), null, 2), [i, o, l, c, g]), S = async (z) => {
4686
+ }), null, 2), [i, o, l, c, g]), C = async (z) => {
4687
4687
  var ce;
4688
4688
  const Y = ++G.current, re = () => G.current === Y;
4689
4689
  T(""), b(!0);
@@ -4691,15 +4691,15 @@ function us() {
4691
4691
  const _e = JSON.parse(z ?? m), pe = await I.runtimeData({ requests: _e.data_requests || [] });
4692
4692
  if (!re()) return;
4693
4693
  N(pe.datasets), (ce = B.current) == null || ce.terminate();
4694
- const fe = new cs();
4694
+ const fe = new ds();
4695
4695
  B.current = fe;
4696
- const Ue = await new Promise((L, ne) => {
4696
+ const Ue = await new Promise((E, ne) => {
4697
4697
  const Re = window.setTimeout(() => {
4698
4698
  fe.terminate(), ne(new Error("Report runtime exceeded 4 seconds"));
4699
4699
  }, 4e3);
4700
4700
  fe.onmessage = (De) => {
4701
4701
  var Ve, Me;
4702
- window.clearTimeout(Re), fe.terminate(), B.current === fe && (B.current = null), (Ve = De.data) != null && Ve.ok ? L(De.data.output) : ne(new Error(((Me = De.data) == null ? void 0 : Me.error) || "Runtime failed"));
4702
+ window.clearTimeout(Re), fe.terminate(), B.current === fe && (B.current = null), (Ve = De.data) != null && Ve.ok ? E(De.data.output) : ne(new Error(((Me = De.data) == null ? void 0 : Me.error) || "Runtime failed"));
4703
4703
  }, fe.postMessage({
4704
4704
  datasets: pe.datasets,
4705
4705
  params: {},
@@ -4720,18 +4720,18 @@ function us() {
4720
4720
  return s ? D.current === s ? void 0 : (p(!0), T(""), I.getRuntimeDraft(s).then((Y) => {
4721
4721
  if (z) return;
4722
4722
  const re = JSON.stringify(Y.definition, null, 2);
4723
- return D.current = s, O.current = re, y(Y.source_chat_session_id || ""), h(re), S(re);
4723
+ return D.current = s, O.current = re, y(Y.source_chat_session_id || ""), h(re), C(re);
4724
4724
  }).catch((Y) => {
4725
4725
  z || (v(null), T(Y instanceof Error ? Y.message : String(Y)));
4726
4726
  }).finally(() => {
4727
4727
  z || p(!1);
4728
4728
  }), () => {
4729
4729
  z = !0;
4730
- }) : (D.current = "", O.current = "", y(""), ee && (O.current = ee, h(ee), S(ee)), () => {
4730
+ }) : (D.current = "", O.current = "", y(""), ee && (O.current = ee, h(ee), C(ee)), () => {
4731
4731
  z = !0;
4732
4732
  });
4733
4733
  }, [s, ee]);
4734
- const w = !!(!s && ee), q = Se(() => hs(x), [x]), A = async () => {
4734
+ const w = !!(!s && ee), q = Ce(() => gs(x), [x]), A = async () => {
4735
4735
  var pe;
4736
4736
  const z = m.trim() !== O.current.trim(), Y = s || "unsaved-runtime-report", re = u.map((fe) => ({
4737
4737
  name: fe.name,
@@ -4779,11 +4779,11 @@ function us() {
4779
4779
  "Loaded draft: ",
4780
4780
  s
4781
4781
  ] }) : w ? /* @__PURE__ */ e("div", { className: "text-xs text-gray-500", children: "Loaded runtime report from legacy URL filters." }) : null,
4782
- s ? /* @__PURE__ */ e(Q, { variant: "secondary", onClick: () => void A(), children: "Fix In Chat" }) : null,
4783
- /* @__PURE__ */ e(Q, { onClick: () => void S(), disabled: P, children: P ? "Running..." : "Run Report" })
4782
+ s ? /* @__PURE__ */ e(H, { variant: "secondary", onClick: () => void A(), children: "Fix In Chat" }) : null,
4783
+ /* @__PURE__ */ e(H, { onClick: () => void C(), disabled: P, children: P ? "Running..." : "Run Report" })
4784
4784
  ] })
4785
4785
  ] }) }),
4786
- d ? /* @__PURE__ */ e($, { children: /* @__PURE__ */ e("p", { className: "text-sm text-gray-600", children: "Loading draft..." }) }) : f ? /* @__PURE__ */ e($, { children: /* @__PURE__ */ e("p", { className: "text-sm text-red-600", children: f }) }) : x ? /* @__PURE__ */ e(ms, { output: x }) : /* @__PURE__ */ e($, { 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." }) }),
4786
+ d ? /* @__PURE__ */ e($, { children: /* @__PURE__ */ e("p", { className: "text-sm text-gray-600", children: "Loading draft..." }) }) : f ? /* @__PURE__ */ e($, { children: /* @__PURE__ */ e("p", { className: "text-sm text-red-600", children: f }) }) : x ? /* @__PURE__ */ e(ps, { output: x }) : /* @__PURE__ */ e($, { 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." }) }),
4787
4787
  u.length > 0 && /* @__PURE__ */ e($, { 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: [
4788
4788
  /* @__PURE__ */ r("div", { className: "flex items-baseline justify-between gap-4", children: [
4789
4789
  /* @__PURE__ */ r("div", { children: [
@@ -4812,12 +4812,12 @@ function us() {
4812
4812
  ] })
4813
4813
  ] });
4814
4814
  }
4815
- function ms({ output: t }) {
4815
+ function ps({ output: t }) {
4816
4816
  var i, o;
4817
4817
  const n = Oe(), a = (t.tables ?? []).map((l, c) => ({
4818
4818
  ...l,
4819
4819
  id: l.id || `table_${c + 1}`
4820
- })), s = da(a);
4820
+ })), s = ua(a);
4821
4821
  return /* @__PURE__ */ r("div", { className: "space-y-4", children: [
4822
4822
  /* @__PURE__ */ r($, { children: [
4823
4823
  /* @__PURE__ */ e("div", { className: "flex items-baseline justify-between gap-4", children: /* @__PURE__ */ r("div", { children: [
@@ -4833,10 +4833,10 @@ function ms({ output: t }) {
4833
4833
  const g = l.dataTable ? s.get(l.dataTable) : void 0, m = l.data ?? (g == null ? void 0 : g.rows) ?? [];
4834
4834
  if (!m.length)
4835
4835
  return /* @__PURE__ */ e($, { title: l.title, children: /* @__PURE__ */ e("p", { className: "text-sm text-red-600", children: "Chart has no usable data." }) }, l.id || `chart_${c + 1}`);
4836
- const h = l.type === "pie" ? [] : m.map((x) => String(x[l.x] ?? "")), u = vs(h), N = Math.max(320, 200 + u.axisHeight);
4836
+ const h = l.type === "pie" ? [] : m.map((x) => String(x[l.x] ?? "")), u = xs(h), N = Math.max(320, 200 + u.axisHeight);
4837
4837
  return /* @__PURE__ */ r($, { children: [
4838
4838
  /* @__PURE__ */ e("div", { className: "pb-3 text-sm font-semibold text-gray-700", children: l.title }),
4839
- /* @__PURE__ */ e("div", { style: { height: N }, className: "w-full", children: /* @__PURE__ */ e(Va, { width: "100%", height: "100%", children: l.type === "line" ? /* @__PURE__ */ r(Ka, { data: m, margin: { top: 10, right: 20, left: 0, bottom: 0 }, children: [
4839
+ /* @__PURE__ */ e("div", { style: { height: N }, className: "w-full", children: /* @__PURE__ */ e(Ka, { width: "100%", height: "100%", children: l.type === "line" ? /* @__PURE__ */ r(ja, { data: m, margin: { top: 10, right: 20, left: 0, bottom: 0 }, children: [
4840
4840
  /* @__PURE__ */ e(pn, { strokeDasharray: "3 3", stroke: "#f3f4f6" }),
4841
4841
  /* @__PURE__ */ e(
4842
4842
  hn,
@@ -4851,11 +4851,11 @@ function ms({ output: t }) {
4851
4851
  ),
4852
4852
  /* @__PURE__ */ e(gn, { tick: { fill: "#6b7280", fontSize: 12 }, tickFormatter: In }),
4853
4853
  /* @__PURE__ */ e(Vt, { formatter: (x) => kt(x, Wt(g, l.y), n) }),
4854
- /* @__PURE__ */ e(ja, { type: "monotone", dataKey: l.y, stroke: "#3b82f6", strokeWidth: 2, dot: { r: 3 } })
4855
- ] }) : l.type === "pie" ? /* @__PURE__ */ r(Ga, { children: [
4854
+ /* @__PURE__ */ e(Ga, { type: "monotone", dataKey: l.y, stroke: "#3b82f6", strokeWidth: 2, dot: { r: 3 } })
4855
+ ] }) : l.type === "pie" ? /* @__PURE__ */ r(Wa, { children: [
4856
4856
  /* @__PURE__ */ e(Vt, { formatter: (x) => kt(x, Wt(g, l.y), n) }),
4857
- /* @__PURE__ */ e(Wa, { data: m, dataKey: l.y, nameKey: l.x, outerRadius: 110, children: m.map((x, v) => /* @__PURE__ */ e(Ha, { fill: Bn[v % Bn.length] }, v)) })
4858
- ] }) : /* @__PURE__ */ r(Qa, { data: m, margin: { top: 10, right: 20, left: 0, bottom: 0 }, children: [
4857
+ /* @__PURE__ */ e(Ha, { data: m, dataKey: l.y, nameKey: l.x, outerRadius: 110, children: m.map((x, v) => /* @__PURE__ */ e(Qa, { fill: Bn[v % Bn.length] }, v)) })
4858
+ ] }) : /* @__PURE__ */ r(Ya, { data: m, margin: { top: 10, right: 20, left: 0, bottom: 0 }, children: [
4859
4859
  /* @__PURE__ */ e(pn, { strokeDasharray: "3 3", stroke: "#f3f4f6" }),
4860
4860
  /* @__PURE__ */ e(
4861
4861
  hn,
@@ -4870,7 +4870,7 @@ function ms({ output: t }) {
4870
4870
  ),
4871
4871
  /* @__PURE__ */ e(gn, { tick: { fill: "#6b7280", fontSize: 12 }, tickFormatter: In }),
4872
4872
  /* @__PURE__ */ e(Vt, { formatter: (x) => kt(x, Wt(g, l.y), n) }),
4873
- /* @__PURE__ */ e(Ya, { dataKey: l.y, fill: "#3b82f6", radius: [4, 4, 0, 0] })
4873
+ /* @__PURE__ */ e(Ja, { dataKey: l.y, fill: "#3b82f6", radius: [4, 4, 0, 0] })
4874
4874
  ] }) }) })
4875
4875
  ] }, l.id || `chart_${c + 1}`);
4876
4876
  }),
@@ -4880,21 +4880,21 @@ function ms({ output: t }) {
4880
4880
  ] }) }) }, l.id))
4881
4881
  ] });
4882
4882
  }
4883
- function ps(t) {
4883
+ function hs(t) {
4884
4884
  return t.replace(/_/g, " ").replace(/\b\w/g, (n) => n.toUpperCase());
4885
4885
  }
4886
- function da(t) {
4886
+ function ua(t) {
4887
4887
  const n = /* @__PURE__ */ new Map();
4888
4888
  for (const a of t)
4889
4889
  n.set(a.id, a), a.title && n.set(a.title, a);
4890
4890
  return n;
4891
4891
  }
4892
- function hs(t) {
4892
+ function gs(t) {
4893
4893
  if (!t) return [];
4894
4894
  const n = (t.tables ?? []).map((i, o) => ({
4895
4895
  ...i,
4896
4896
  id: i.id || `table_${o + 1}`
4897
- })), a = da(n), s = [];
4897
+ })), a = ua(n), s = [];
4898
4898
  for (const i of t.charts ?? []) {
4899
4899
  const o = i.dataTable ? a.get(i.dataTable) : void 0, l = i.data ?? (o == null ? void 0 : o.rows) ?? [];
4900
4900
  if (!l.length) {
@@ -4905,8 +4905,8 @@ function hs(t) {
4905
4905
  }
4906
4906
  return s;
4907
4907
  }
4908
- function gs(t) {
4909
- const n = `${fs(t.metric)} by ${ps(t.groupBy)}`, a = t.groupBy === "month" ? "helpers.monthKey" : t.groupBy === "quarter" ? "helpers.quarterKey" : "helpers.yearKey";
4908
+ function fs(t) {
4909
+ const n = `${ys(t.metric)} by ${hs(t.groupBy)}`, a = t.groupBy === "month" ? "helpers.monthKey" : t.groupBy === "quarter" ? "helpers.quarterKey" : "helpers.yearKey";
4910
4910
  if (t.metric === "sales_revenue")
4911
4911
  return yt({
4912
4912
  title: n,
@@ -5009,7 +5009,7 @@ function gs(t) {
5009
5009
  },
5010
5010
  fields: [t.groupBy === "warehouse" ? "warehouse" : "item_code", "stock_value"],
5011
5011
  chartType: "bar"
5012
- }) : JSON.parse(ca);
5012
+ }) : JSON.parse(da);
5013
5013
  }
5014
5014
  function yt(t) {
5015
5015
  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} || "—"`;
@@ -5065,7 +5065,7 @@ return {
5065
5065
  };`
5066
5066
  };
5067
5067
  }
5068
- function fs(t) {
5068
+ function ys(t) {
5069
5069
  return {
5070
5070
  sales_revenue: "Sales Revenue",
5071
5071
  sales_returns: "Sales Returns",
@@ -5082,34 +5082,34 @@ function Wt(t, n) {
5082
5082
  return ((a = t == null ? void 0 : t.columns.find((i) => i.key === n)) == null ? void 0 : a.type) || ((s = t == null ? void 0 : t.columns.find((i) => i.key === n)) == null ? void 0 : s.format);
5083
5083
  }
5084
5084
  function kt(t, n, a) {
5085
- return n === "currency" ? Ee(Fe(t), a) : n === "percent" ? `${(Fe(t) * 100).toFixed(1)}%` : n === "number" ? Zt(Fe(t)) : n === "date" ? Ft(String(t ?? "")) : typeof t == "number" ? Zt(t) : String(t ?? "");
5085
+ return n === "currency" ? Le(Fe(t), a) : n === "percent" ? `${(Fe(t) * 100).toFixed(1)}%` : n === "number" ? Zt(Fe(t)) : n === "date" ? Ft(String(t ?? "")) : typeof t == "number" ? Zt(t) : String(t ?? "");
5086
5086
  }
5087
5087
  function In(t) {
5088
5088
  const n = Math.abs(t);
5089
5089
  return n >= 1e6 ? `${(t / 1e6).toFixed(1)}M` : n >= 1e3 ? `${(t / 1e3).toFixed(0)}k` : String(t);
5090
5090
  }
5091
- const Bn = ["#3b82f6", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6", "#06b6d4"], ys = '12px -apple-system, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
5091
+ const Bn = ["#3b82f6", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6", "#06b6d4"], bs = '12px -apple-system, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
5092
5092
  let Ht = null;
5093
- function bs(t, n = ys) {
5093
+ function vs(t, n = bs) {
5094
5094
  if (typeof document > "u") return t.length * 7;
5095
5095
  Ht || (Ht = document.createElement("canvas"));
5096
5096
  const a = Ht.getContext("2d");
5097
5097
  return a ? (a.font = n, a.measureText(t).width) : t.length * 7;
5098
5098
  }
5099
- function vs(t) {
5099
+ function xs(t) {
5100
5100
  if (!t.length) return { angle: 0, axisHeight: 30, maxWidth: 0 };
5101
- const n = t.map((c) => bs(c)), a = Math.max(1, ...n);
5101
+ const n = t.map((c) => vs(c)), a = Math.max(1, ...n);
5102
5102
  let s = 0;
5103
5103
  a > 55 && (s = -30), a > 110 && (s = -45), a > 200 && (s = -60), a > 300 && (s = -90);
5104
5104
  const i = Math.abs(s) * Math.PI / 180, o = s === 0 ? 20 : Math.abs(s) === 90 ? a : Math.ceil(a * Math.sin(i)), l = Math.min(280, Math.max(30, o + 18));
5105
5105
  return { angle: s, axisHeight: l, maxWidth: a };
5106
5106
  }
5107
- const xs = ["USD", "EUR", "GBP", "CHF", "JPY", "CAD", "AUD", "CNY", "INR"];
5108
- function Ns() {
5107
+ const Ns = ["USD", "EUR", "GBP", "CHF", "JPY", "CAD", "AUD", "CNY", "INR"];
5108
+ function ws() {
5109
5109
  const t = We(), { data: n, isLoading: a } = oe({
5110
5110
  queryKey: ["setup-status"],
5111
5111
  queryFn: () => I.setupStatus()
5112
- }), [s, i] = C(""), [o, l] = C("USD"), [c, g] = C({
5112
+ }), [s, i] = S(""), [o, l] = S("USD"), [c, g] = S({
5113
5113
  address: "",
5114
5114
  city: "",
5115
5115
  zip_code: "",
@@ -5117,7 +5117,7 @@ function Ns() {
5117
5117
  email: "",
5118
5118
  phone: "",
5119
5119
  tax_id: ""
5120
- }), m = (y) => (B) => g((D) => ({ ...D, [y]: B.target.value })), [h, u] = C("quick"), [N, x] = C(!1), [v, f] = C(null), T = ie({
5120
+ }), m = (y) => (B) => g((D) => ({ ...D, [y]: B.target.value })), [h, u] = S("quick"), [N, x] = S(!1), [v, f] = S(null), T = ie({
5121
5121
  mutationFn: () => I.createCompany({ name: s, currency: o, ...c })
5122
5122
  }), P = ie({
5123
5123
  mutationFn: () => I.seedDemo()
@@ -5138,7 +5138,7 @@ function Ns() {
5138
5138
  return /* @__PURE__ */ e("p", { className: "text-gray-500", children: "Loading..." });
5139
5139
  if (n != null && n.setup_complete && !N)
5140
5140
  return /* @__PURE__ */ r("div", { className: "space-y-6", children: [
5141
- /* @__PURE__ */ e($, { title: "Companies", children: n.companies && n.companies.length > 0 ? /* @__PURE__ */ e("ul", { className: "divide-y divide-gray-100", children: n.companies.map((y, B) => /* @__PURE__ */ e("li", { className: "py-3", children: /* @__PURE__ */ e(ws, { company: y }) }, B)) }) : /* @__PURE__ */ e("p", { className: "text-gray-400", children: "No companies found" }) }),
5141
+ /* @__PURE__ */ e($, { title: "Companies", children: n.companies && n.companies.length > 0 ? /* @__PURE__ */ e("ul", { className: "divide-y divide-gray-100", children: n.companies.map((y, B) => /* @__PURE__ */ e("li", { className: "py-3", children: /* @__PURE__ */ e(ks, { company: y }) }, B)) }) : /* @__PURE__ */ e("p", { className: "text-gray-400", children: "No companies found" }) }),
5142
5142
  /* @__PURE__ */ e(be, { to: "/", className: "text-blue-600 hover:text-blue-800 text-sm font-medium", children: "Go to Dashboard" })
5143
5143
  ] });
5144
5144
  if (N)
@@ -5152,7 +5152,7 @@ function Ns() {
5152
5152
  /* @__PURE__ */ e("span", { className: "font-mono text-gray-900", children: B.toLocaleString() })
5153
5153
  ] }, y)) })
5154
5154
  ] }),
5155
- /* @__PURE__ */ e("div", { className: "mt-6", children: /* @__PURE__ */ e(be, { to: "/", children: /* @__PURE__ */ e(Q, { children: "Go to Dashboard" }) }) })
5155
+ /* @__PURE__ */ e("div", { className: "mt-6", children: /* @__PURE__ */ e(be, { to: "/", children: /* @__PURE__ */ e(H, { children: "Go to Dashboard" }) }) })
5156
5156
  ] }) }) });
5157
5157
  const p = T.isPending || P.isPending || b.isPending, _ = T.error ?? P.error ?? b.error;
5158
5158
  return /* @__PURE__ */ r("div", { className: "mx-auto max-w-lg space-y-6", children: [
@@ -5173,7 +5173,7 @@ function Ns() {
5173
5173
  He,
5174
5174
  {
5175
5175
  label: "Currency",
5176
- options: xs,
5176
+ options: Ns,
5177
5177
  value: o,
5178
5178
  onChange: (y) => l(y.target.value)
5179
5179
  }
@@ -5258,7 +5258,7 @@ function Ns() {
5258
5258
  ] })
5259
5259
  ] }),
5260
5260
  /* @__PURE__ */ e("div", { className: "pt-2", children: /* @__PURE__ */ e(
5261
- Q,
5261
+ H,
5262
5262
  {
5263
5263
  onClick: d,
5264
5264
  disabled: p || !s.trim(),
@@ -5268,7 +5268,7 @@ function Ns() {
5268
5268
  ] }) })
5269
5269
  ] });
5270
5270
  }
5271
- function ws({ company: t }) {
5271
+ function ks({ company: t }) {
5272
5272
  const n = [
5273
5273
  [t.city, t.zip_code].filter(Boolean).join(" "),
5274
5274
  t.country
@@ -5309,7 +5309,7 @@ function ws({ company: t }) {
5309
5309
  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 })
5310
5310
  ] });
5311
5311
  }
5312
- const ks = [
5312
+ const Ss = [
5313
5313
  {
5314
5314
  number: 1,
5315
5315
  title: "Set Up Your Company",
@@ -5446,7 +5446,7 @@ const ks = [
5446
5446
  ]
5447
5447
  }
5448
5448
  ];
5449
- function ua() {
5449
+ function ma() {
5450
5450
  const t = ze(), { sessions: n, createSession: a } = ut();
5451
5451
  return async (s) => {
5452
5452
  var o;
@@ -5462,7 +5462,7 @@ function ua() {
5462
5462
  };
5463
5463
  }
5464
5464
  function Cs() {
5465
- const { t } = X(), n = ua();
5465
+ const { t } = Z(), n = ma();
5466
5466
  return /* @__PURE__ */ e($, { className: "border-emerald-200 bg-gradient-to-br from-emerald-50 to-white", children: /* @__PURE__ */ r("div", { className: "flex flex-col gap-4 md:flex-row md:items-start", children: [
5467
5467
  /* @__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: "▶" }),
5468
5468
  /* @__PURE__ */ r("div", { className: "flex-1 space-y-3", children: [
@@ -5497,8 +5497,8 @@ function Cs() {
5497
5497
  ] })
5498
5498
  ] }) });
5499
5499
  }
5500
- function Ss() {
5501
- const { t } = X(), n = ua(), a = [
5500
+ function Ds() {
5501
+ const { t } = Z(), n = ma(), a = [
5502
5502
  t("tutorial.caPrompt1"),
5503
5503
  t("tutorial.caPrompt2"),
5504
5504
  t("tutorial.caPrompt3"),
@@ -5556,8 +5556,8 @@ function Ss() {
5556
5556
  ] })
5557
5557
  ] }) });
5558
5558
  }
5559
- function Ds() {
5560
- const { t } = X(), n = (a) => t(`tutorial.chips.${a}`, { defaultValue: a });
5559
+ function As() {
5560
+ const { t } = Z(), n = (a) => t(`tutorial.chips.${a}`, { defaultValue: a });
5561
5561
  return /* @__PURE__ */ r($, { children: [
5562
5562
  /* @__PURE__ */ e("h3", { className: "text-base font-semibold text-gray-900 mb-3", children: t("tutorial.flowTitle") }),
5563
5563
  /* @__PURE__ */ r("div", { className: "space-y-4 text-sm text-gray-600", children: [
@@ -5627,8 +5627,8 @@ function Ds() {
5627
5627
  ] })
5628
5628
  ] });
5629
5629
  }
5630
- function As() {
5631
- const { t } = X(), n = (a) => t(`tutorial.chips.${a}`, { defaultValue: a });
5630
+ function Ps() {
5631
+ const { t } = Z(), n = (a) => t(`tutorial.chips.${a}`, { defaultValue: a });
5632
5632
  return /* @__PURE__ */ r($, { children: [
5633
5633
  /* @__PURE__ */ e("h3", { className: "text-base font-semibold text-gray-900 mb-3", children: t("tutorial.lifecycleTitle") }),
5634
5634
  /* @__PURE__ */ r("div", { className: "space-y-2 text-sm text-gray-600", children: [
@@ -5663,8 +5663,8 @@ function As() {
5663
5663
  ] })
5664
5664
  ] });
5665
5665
  }
5666
- function Ps() {
5667
- const { t } = X();
5666
+ function _s() {
5667
+ const { t } = Z();
5668
5668
  return /* @__PURE__ */ r("div", { className: "mx-auto max-w-3xl space-y-6", children: [
5669
5669
  /* @__PURE__ */ r("div", { children: [
5670
5670
  /* @__PURE__ */ e("h2", { className: "text-xl font-semibold text-gray-900", children: t("tutorial.pageTitle") }),
@@ -5688,10 +5688,10 @@ function Ps() {
5688
5688
  /* @__PURE__ */ e("p", { className: "mt-4 text-sm text-gray-500", children: t("tutorial.manualIntro") })
5689
5689
  ] }),
5690
5690
  /* @__PURE__ */ e(Cs, {}),
5691
- /* @__PURE__ */ e(Ss, {}),
5692
5691
  /* @__PURE__ */ e(Ds, {}),
5693
5692
  /* @__PURE__ */ e(As, {}),
5694
- ks.map((n) => {
5693
+ /* @__PURE__ */ e(Ps, {}),
5694
+ Ss.map((n) => {
5695
5695
  var a;
5696
5696
  return /* @__PURE__ */ e($, { children: /* @__PURE__ */ r("div", { className: "flex gap-4", children: [
5697
5697
  /* @__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 }),
@@ -5752,17 +5752,17 @@ function Ps() {
5752
5752
  ] }) })
5753
5753
  ] });
5754
5754
  }
5755
- const Qt = 5, _s = 10 * 1024 * 1024, Ts = /* @__PURE__ */ new Set([
5755
+ const Qt = 5, Ts = 10 * 1024 * 1024, Rs = /* @__PURE__ */ new Set([
5756
5756
  "image/png",
5757
5757
  "image/jpeg",
5758
5758
  "image/gif",
5759
5759
  "image/webp",
5760
5760
  "application/pdf"
5761
5761
  ]);
5762
- function Rs(t) {
5762
+ function Is(t) {
5763
5763
  return new Promise((n) => window.setTimeout(n, t));
5764
5764
  }
5765
- function Is(t) {
5765
+ function Bs(t) {
5766
5766
  return new Promise((n, a) => {
5767
5767
  const s = new FileReader();
5768
5768
  s.onloadend = () => {
@@ -5771,14 +5771,14 @@ function Is(t) {
5771
5771
  }, s.onerror = () => a(s.error ?? new Error("Could not read audio.")), s.readAsDataURL(t);
5772
5772
  });
5773
5773
  }
5774
- function Ln(t) {
5774
+ function En(t) {
5775
5775
  if (!t) return "";
5776
5776
  const n = new Date(t);
5777
5777
  if (isNaN(n.getTime())) return "";
5778
5778
  const a = /* @__PURE__ */ new Date();
5779
5779
  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" });
5780
5780
  }
5781
- function En(t) {
5781
+ function Ln(t) {
5782
5782
  if (!t) return "";
5783
5783
  const n = new Date(t);
5784
5784
  return isNaN(n.getTime()) ? "" : n.toLocaleString([], {
@@ -5792,7 +5792,7 @@ function En(t) {
5792
5792
  });
5793
5793
  }
5794
5794
  function On() {
5795
- const { t } = X(), { sessionId: n } = bt(), a = ze(), s = St(), [i] = qt(), o = i.get("demo") === "1", [l, c] = C(""), [g, m] = C(""), [h, u] = C([]), [N, x] = C(""), [v, f] = C(!1), [T, P] = C("idle"), b = te(null), d = te(null), p = te([]), {
5795
+ const { t } = Z(), { sessionId: n } = bt(), a = ze(), s = Ct(), [i] = qt(), o = i.get("demo") === "1", [l, c] = S(""), [g, m] = S(""), [h, u] = S([]), [N, x] = S(""), [v, f] = S(!1), [T, P] = S("idle"), b = te(null), d = te(null), p = te([]), {
5796
5796
  connectionStatus: _,
5797
5797
  connectionVersion: y,
5798
5798
  createSession: B,
@@ -5800,7 +5800,7 @@ function On() {
5800
5800
  completeDemoTyping: O,
5801
5801
  loadHistory: G,
5802
5802
  loadMoreHistory: ee,
5803
- sendMessage: S,
5803
+ sendMessage: C,
5804
5804
  transcribeAudio: w,
5805
5805
  getMessages: q,
5806
5806
  hasMoreHistory: A,
@@ -5808,7 +5808,7 @@ function On() {
5808
5808
  isThinking: Y,
5809
5809
  getDemoStatus: re,
5810
5810
  getDemoTypingCue: ce
5811
- } = ut(), ge = te(null), _e = te(null), pe = te(null), fe = te(null), [Ue, L] = C(0), ne = te(!1), Re = te(null), De = te(0), Ve = te(!0), Me = te(null), vt = te(!1), mt = te(null), Je = q(n), ke = _ === "connected", Te = Y(n), Ke = re(n), Qe = ce(n), Ie = o || Ke === "running", pt = A(n), it = z(n), ht = Je[Je.length - 1], R = ht ? `${ht.type}:${ht.timestamp || ""}:${ht.content}` : "empty", V = Pe(() => {
5811
+ } = ut(), ge = te(null), _e = te(null), pe = te(null), fe = te(null), [Ue, E] = S(0), ne = te(!1), Re = te(null), De = te(0), Ve = te(!0), Me = te(null), vt = te(!1), mt = te(null), Je = q(n), ke = _ === "connected", Te = Y(n), Ke = re(n), Qe = ce(n), Ie = o || Ke === "running", pt = A(n), it = z(n), ht = Je[Je.length - 1], R = ht ? `${ht.type}:${ht.timestamp || ""}:${ht.content}` : "empty", V = Pe(() => {
5812
5812
  vt.current = !0, mt.current !== null && window.clearTimeout(mt.current), mt.current = window.setTimeout(() => {
5813
5813
  vt.current = !1, mt.current = null;
5814
5814
  }, 600);
@@ -5816,37 +5816,37 @@ function On() {
5816
5816
  const U = ge.current;
5817
5817
  if (!U) return;
5818
5818
  V(), U.scrollTo({ top: U.scrollHeight, behavior: k });
5819
- const Z = () => {
5819
+ const X = () => {
5820
5820
  const de = ge.current;
5821
5821
  de && (!Ve.current && !Ie && !Te || de.scrollTop + de.clientHeight >= de.scrollHeight - 2 || (V(), de.scrollTo({ top: de.scrollHeight, behavior: "auto" })));
5822
5822
  };
5823
- requestAnimationFrame(Z), window.setTimeout(Z, 120);
5823
+ requestAnimationFrame(X), window.setTimeout(X, 120);
5824
5824
  }, [Ie, Te, V]);
5825
5825
  un(() => {
5826
5826
  const k = ge.current, U = Me.current;
5827
5827
  if (!k || U === null) return;
5828
- const Z = k.scrollHeight - U;
5829
- Z > 0 && (k.scrollTop = k.scrollTop + Z), Me.current = null;
5828
+ const X = k.scrollHeight - U;
5829
+ X > 0 && (k.scrollTop = k.scrollTop + X), Me.current = null;
5830
5830
  }, [Je.length]), se(() => {
5831
5831
  Me.current === null && (!Ve.current && !Ie && !Te || W(Ie ? "auto" : "smooth"));
5832
5832
  }, [R, Ie, Te, W]), se(() => {
5833
5833
  const k = ge.current;
5834
5834
  if (!k || typeof ResizeObserver > "u") return;
5835
5835
  let U = 0;
5836
- const Z = new ResizeObserver(() => {
5836
+ const X = new ResizeObserver(() => {
5837
5837
  Me.current === null && (!Ve.current && !Ie && !Te || (cancelAnimationFrame(U), U = requestAnimationFrame(() => {
5838
5838
  const he = ge.current;
5839
5839
  if (!he) return;
5840
5840
  he.scrollHeight - he.scrollTop - he.clientHeight <= 120 && (V(), he.scrollTo({ top: he.scrollHeight, behavior: "auto" }));
5841
5841
  })));
5842
5842
  }), de = k.firstElementChild;
5843
- return de && Z.observe(de), Z.observe(k), () => {
5844
- Z.disconnect(), cancelAnimationFrame(U);
5843
+ return de && X.observe(de), X.observe(k), () => {
5844
+ X.disconnect(), cancelAnimationFrame(U);
5845
5845
  };
5846
5846
  }, [Ie, Te, V]), un(() => {
5847
5847
  const k = fe.current;
5848
- if (!k || (L(k.offsetHeight), typeof ResizeObserver > "u")) return;
5849
- const U = new ResizeObserver(() => L(k.offsetHeight));
5848
+ if (!k || (E(k.offsetHeight), typeof ResizeObserver > "u")) return;
5849
+ const U = new ResizeObserver(() => E(k.offsetHeight));
5850
5850
  return U.observe(k), () => U.disconnect();
5851
5851
  }, []);
5852
5852
  const ve = Pe(() => {
@@ -5857,7 +5857,7 @@ function On() {
5857
5857
  });
5858
5858
  }, [n, it, pt, ee]), xe = te(null);
5859
5859
  se(() => {
5860
- m(""), Re.current = null, De.current += 1, n && ra(n);
5860
+ m(""), Re.current = null, De.current += 1, n && sa(n);
5861
5861
  const k = s.state;
5862
5862
  k != null && k.prefillMessage && xe.current !== k ? (xe.current = k, c(k.prefillMessage), window.setTimeout(() => {
5863
5863
  var U;
@@ -5887,8 +5887,8 @@ function On() {
5887
5887
  }, [Te, ke]);
5888
5888
  function ot(k) {
5889
5889
  if (vt.current) return;
5890
- const U = k.currentTarget, Z = U.scrollHeight - U.scrollTop - U.clientHeight;
5891
- Ve.current = Z < 80;
5890
+ const U = k.currentTarget, X = U.scrollHeight - U.scrollTop - U.clientHeight;
5891
+ Ve.current = X < 80;
5892
5892
  }
5893
5893
  se(() => {
5894
5894
  !n || !ke || !o || Re.current !== n && (Re.current = n, m(""), D(n).catch((k) => {
@@ -5905,12 +5905,12 @@ function On() {
5905
5905
  se(() => {
5906
5906
  if (!Qe || !n || Ze.current === Qe.seq) return;
5907
5907
  Ze.current = Qe.seq;
5908
- const k = n, U = Qe.content, Z = U.length > 0 ? Math.max(8, Qe.typingMs / U.length) : 0, de = Qe.seq, he = ++De.current;
5908
+ const k = n, U = Qe.content, X = U.length > 0 ? Math.max(8, Qe.typingMs / U.length) : 0, de = Qe.seq, he = ++De.current;
5909
5909
  async function et() {
5910
5910
  c("");
5911
5911
  for (const ft of U) {
5912
5912
  if (he !== De.current) return;
5913
- c((je) => je + ft), await Rs(Z);
5913
+ c((je) => je + ft), await Is(X);
5914
5914
  }
5915
5915
  he === De.current && K.current(k, de);
5916
5916
  }
@@ -5922,18 +5922,18 @@ function On() {
5922
5922
  if (!n) return;
5923
5923
  x("");
5924
5924
  const U = Array.from(k);
5925
- u((Z) => {
5926
- const de = [...Z];
5925
+ u((X) => {
5926
+ const de = [...X];
5927
5927
  for (const he of U) {
5928
5928
  if (de.length >= Qt) {
5929
5929
  x(`Maximum ${Qt} attachments per message.`);
5930
5930
  break;
5931
5931
  }
5932
- if (!Ts.has(he.type)) {
5932
+ if (!Rs.has(he.type)) {
5933
5933
  x(`Unsupported file type: ${he.type || he.name}`);
5934
5934
  continue;
5935
5935
  }
5936
- if (he.size > _s) {
5936
+ if (he.size > Ts) {
5937
5937
  x(`"${he.name}" is too large (max 10 MB).`);
5938
5938
  continue;
5939
5939
  }
@@ -5957,28 +5957,28 @@ function On() {
5957
5957
  });
5958
5958
  }, [n]), M = (k) => {
5959
5959
  u((U) => {
5960
- const Z = U.find((de) => de.localId === k);
5961
- return Z != null && Z.previewUrl && URL.revokeObjectURL(Z.previewUrl), U.filter((de) => de.localId !== k);
5960
+ const X = U.find((de) => de.localId === k);
5961
+ return X != null && X.previewUrl && URL.revokeObjectURL(X.previewUrl), U.filter((de) => de.localId !== k);
5962
5962
  });
5963
5963
  }, F = (k) => {
5964
5964
  k.dataTransfer.types.includes("Files") && (k.preventDefault(), f(!0));
5965
5965
  }, j = (k) => {
5966
5966
  const U = k.relatedTarget;
5967
5967
  (!U || !k.currentTarget.contains(U)) && f(!1);
5968
- }, H = (k) => {
5968
+ }, Q = (k) => {
5969
5969
  k.preventDefault(), f(!1), k.dataTransfer.files && k.dataTransfer.files.length > 0 && me(k.dataTransfer.files);
5970
5970
  }, qe = (k) => {
5971
5971
  const U = [];
5972
- for (const Z of k.clipboardData.items)
5973
- if (Z.kind === "file") {
5974
- const de = Z.getAsFile();
5972
+ for (const X of k.clipboardData.items)
5973
+ if (X.kind === "file") {
5974
+ const de = X.getAsFile();
5975
5975
  de && U.push(de);
5976
5976
  }
5977
5977
  U.length > 0 && (k.preventDefault(), me(U));
5978
5978
  }, Ne = h.some((k) => k.uploading), le = h.some((k) => k.error), ue = h.filter((k) => k.uploadedId && !k.error).map((k) => k.uploadedId);
5979
5979
  function gt() {
5980
5980
  const k = l.trim();
5981
- if (n && !(!k && ue.length === 0) && !Ne && S(n, k, ue.length > 0 ? ue : void 0)) {
5981
+ if (n && !(!k && ue.length === 0) && !Ne && C(n, k, ue.length > 0 ? ue : void 0)) {
5982
5982
  for (const U of h)
5983
5983
  U.previewUrl && URL.revokeObjectURL(U.previewUrl);
5984
5984
  u([]), x(""), c("");
@@ -5989,12 +5989,12 @@ function On() {
5989
5989
  }
5990
5990
  function Xe(k) {
5991
5991
  const U = k.trim();
5992
- U && (c((Z) => Z.trim() ? `${Z.trim()} ${U}` : U), window.setTimeout(() => {
5993
- const Z = pe.current;
5994
- Z && (Z.focus(), Z.style.height = "auto", Z.style.height = Math.min(Math.max(Z.scrollHeight, 48), 120) + "px");
5992
+ U && (c((X) => X.trim() ? `${X.trim()} ${U}` : U), window.setTimeout(() => {
5993
+ const X = pe.current;
5994
+ X && (X.focus(), X.style.height = "auto", X.style.height = Math.min(Math.max(X.scrollHeight, 48), 120) + "px");
5995
5995
  }, 0));
5996
5996
  }
5997
- async function va() {
5997
+ async function xa() {
5998
5998
  if (T !== "idle") return;
5999
5999
  let k;
6000
6000
  try {
@@ -6005,20 +6005,20 @@ function On() {
6005
6005
  }
6006
6006
  x("");
6007
6007
  const U = new MediaRecorder(k);
6008
- d.current = U, p.current = [], U.ondataavailable = (Z) => {
6009
- Z.data.size > 0 && p.current.push(Z.data);
6008
+ d.current = U, p.current = [], U.ondataavailable = (X) => {
6009
+ X.data.size > 0 && p.current.push(X.data);
6010
6010
  }, U.onstop = async () => {
6011
6011
  var ft;
6012
6012
  k.getTracks().forEach((je) => je.stop());
6013
- const Z = p.current;
6014
- if (p.current = [], d.current = null, Z.length === 0) {
6013
+ const X = p.current;
6014
+ if (p.current = [], d.current = null, X.length === 0) {
6015
6015
  P("idle");
6016
6016
  return;
6017
6017
  }
6018
- const de = U.mimeType || ((ft = Z[0]) == null ? void 0 : ft.type) || "audio/webm", he = new Blob(Z, { type: de }), et = (de.split(";")[0].split("/")[1] || "webm").toLowerCase();
6018
+ const de = U.mimeType || ((ft = X[0]) == null ? void 0 : ft.type) || "audio/webm", he = new Blob(X, { type: de }), et = (de.split(";")[0].split("/")[1] || "webm").toLowerCase();
6019
6019
  P("transcribing");
6020
6020
  try {
6021
- const je = await Is(he), lt = await w(je, et, n);
6021
+ const je = await Bs(he), lt = await w(je, et, n);
6022
6022
  Xe(lt);
6023
6023
  } catch (je) {
6024
6024
  x(je instanceof Error ? je.message : t("chat.transcribeFailed"));
@@ -6027,12 +6027,12 @@ function On() {
6027
6027
  }
6028
6028
  }, U.start(), P("recording");
6029
6029
  }
6030
- function xa() {
6030
+ function Na() {
6031
6031
  const k = d.current;
6032
6032
  k && k.state !== "inactive" && k.stop();
6033
6033
  }
6034
- function Na() {
6035
- T === "recording" ? xa() : T === "idle" && va();
6034
+ function wa() {
6035
+ T === "recording" ? Na() : T === "idle" && xa();
6036
6036
  }
6037
6037
  return n ? /* @__PURE__ */ r(
6038
6038
  "div",
@@ -6040,7 +6040,7 @@ function On() {
6040
6040
  className: "relative -m-4 h-[calc(100%+2rem)] overflow-hidden md:-m-6 md:h-[calc(100%+3rem)]",
6041
6041
  onDragOver: F,
6042
6042
  onDragLeave: j,
6043
- onDrop: H,
6043
+ onDrop: Q,
6044
6044
  children: [
6045
6045
  v && /* @__PURE__ */ e("div", { className: "pointer-events-none absolute inset-3 z-50 flex items-center justify-center rounded-lg border-2 border-dashed border-brand bg-brand/5 text-sm font-medium text-brand", children: t("chat.dropToAttach") }),
6046
6046
  /* @__PURE__ */ e(
@@ -6172,7 +6172,7 @@ function On() {
6172
6172
  /* @__PURE__ */ e(
6173
6173
  "button",
6174
6174
  {
6175
- onClick: Na,
6175
+ onClick: wa,
6176
6176
  disabled: !ke || !n || Te || Ie || T === "transcribing",
6177
6177
  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 ${T === "recording" ? "bg-rose-500/10 text-rose-600 hover:bg-rose-500/20" : "text-fg-muted hover:bg-surface-subtle hover:text-fg"}`,
6178
6178
  title: t(T === "recording" ? "chat.voiceStop" : T === "transcribing" ? "chat.voiceTranscribing" : "chat.voiceStart"),
@@ -6219,7 +6219,7 @@ function On() {
6219
6219
  }
6220
6220
  ) : /* @__PURE__ */ e("div", { className: "flex h-full items-center justify-center text-fg-muted", children: t("chat.creating") });
6221
6221
  }
6222
- function Bs({ attachments: t }) {
6222
+ function Es({ attachments: t }) {
6223
6223
  return !t || t.length === 0 ? null : /* @__PURE__ */ e("div", { className: "mt-1 flex flex-wrap gap-1.5", children: t.map((n) => {
6224
6224
  const a = I.getChatAttachmentUrl(n.id), s = n.mime_type.startsWith("image/");
6225
6225
  return /* @__PURE__ */ r(
@@ -6242,11 +6242,11 @@ function Bs({ attachments: t }) {
6242
6242
  function Ls({ message: t }) {
6243
6243
  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: [
6244
6244
  /* @__PURE__ */ e("div", { className: "whitespace-pre-wrap", children: t.content }),
6245
- /* @__PURE__ */ e(Bs, { attachments: t.attachments }),
6246
- t.timestamp && /* @__PURE__ */ e("div", { className: "mt-1 text-right text-[10px] text-brand-fg/70", title: En(t.timestamp), children: Ln(t.timestamp) })
6245
+ /* @__PURE__ */ e(Es, { attachments: t.attachments }),
6246
+ t.timestamp && /* @__PURE__ */ e("div", { className: "mt-1 text-right text-[10px] text-brand-fg/70", title: Ln(t.timestamp), children: En(t.timestamp) })
6247
6247
  ] }) }) : 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: [
6248
- /* @__PURE__ */ e(Es, { content: t.content }),
6249
- t.timestamp && /* @__PURE__ */ e("div", { className: "mt-1 text-right text-[10px] text-fg-muted", title: En(t.timestamp), children: Ln(t.timestamp) })
6248
+ /* @__PURE__ */ e(Os, { content: t.content }),
6249
+ t.timestamp && /* @__PURE__ */ e("div", { className: "mt-1 text-right text-[10px] text-fg-muted", title: Ln(t.timestamp), children: En(t.timestamp) })
6250
6250
  ] }) }) : 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: [
6251
6251
  /* @__PURE__ */ e("span", { className: "inline-block h-1.5 w-1.5 animate-pulse rounded-full bg-brand" }),
6252
6252
  t.content,
@@ -6285,7 +6285,7 @@ function Ls({ message: t }) {
6285
6285
  }
6286
6286
  ) }) : 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;
6287
6287
  }
6288
- function Es({ content: t }) {
6288
+ function Os({ content: t }) {
6289
6289
  const n = t.split(`
6290
6290
  `), a = [];
6291
6291
  let s = !1, i = [];
@@ -6321,15 +6321,15 @@ function Es({ content: t }) {
6321
6321
  a.push(
6322
6322
  /* @__PURE__ */ r("div", { className: "ml-3 flex gap-1", children: [
6323
6323
  /* @__PURE__ */ e("span", { className: "text-fg-muted", children: "•" }),
6324
- /* @__PURE__ */ e("span", { children: Et(c) })
6324
+ /* @__PURE__ */ e("span", { children: Lt(c) })
6325
6325
  ] }, l)
6326
6326
  );
6327
6327
  } else o.trim() === "" ? a.push(/* @__PURE__ */ e("div", { className: "h-2" }, l)) : a.push(
6328
- /* @__PURE__ */ e("p", { className: "leading-relaxed", children: Et(o) }, l)
6328
+ /* @__PURE__ */ e("p", { className: "leading-relaxed", children: Lt(o) }, l)
6329
6329
  );
6330
6330
  }), /* @__PURE__ */ e("div", { children: a });
6331
6331
  }
6332
- function ma(t, n, a) {
6332
+ function pa(t, n, a) {
6333
6333
  const s = t.startsWith("/") && !t.startsWith("/api/"), i = "font-medium text-brand underline decoration-brand/40 underline-offset-2 transition-colors hover:decoration-brand";
6334
6334
  return s ? /* @__PURE__ */ e(be, { to: t, className: i, children: n }, a) : /* @__PURE__ */ e(
6335
6335
  "a",
@@ -6343,53 +6343,53 @@ function ma(t, n, a) {
6343
6343
  a
6344
6344
  );
6345
6345
  }
6346
- const Os = /(https?:\/\/[^\s)\]}"'<>]+|\/(?:reports|app|masters|admin|chat|setup|tutorial)[^\s)\]}"'<>]*)/g;
6347
- function Et(t) {
6346
+ const qs = /(https?:\/\/[^\s)\]}"'<>]+|\/(?:reports|app|masters|admin|chat|setup|tutorial)[^\s)\]}"'<>]*)/g;
6347
+ function Lt(t) {
6348
6348
  return t.split(/(\[[^\]]+\]\([^)]+\)|\*\*[^*]+?\*\*|`[^`]+`)/g).flatMap((a, s) => {
6349
6349
  const i = a.match(/^\[([^\]]+)\]\(([^)]+)\)$/);
6350
6350
  if (i) {
6351
6351
  const [, o, l] = i;
6352
- return ma(l, Et(o), s);
6352
+ return pa(l, Lt(o), s);
6353
6353
  }
6354
- return a.startsWith("**") && a.endsWith("**") && a.length > 4 ? /* @__PURE__ */ e("strong", { className: "font-semibold", children: Et(a.slice(2, -2)) }, s) : a.startsWith("`") && a.endsWith("`") ? /* @__PURE__ */ e(
6354
+ return a.startsWith("**") && a.endsWith("**") && a.length > 4 ? /* @__PURE__ */ e("strong", { className: "font-semibold", children: Lt(a.slice(2, -2)) }, s) : a.startsWith("`") && a.endsWith("`") ? /* @__PURE__ */ e(
6355
6355
  "code",
6356
6356
  {
6357
6357
  className: "rounded bg-gray-200 px-1 py-0.5 text-xs font-mono",
6358
6358
  children: a.slice(1, -1)
6359
6359
  },
6360
6360
  s
6361
- ) : qs(a, `${s}`);
6361
+ ) : zs(a, `${s}`);
6362
6362
  });
6363
6363
  }
6364
- function qs(t, n) {
6364
+ function zs(t, n) {
6365
6365
  const a = [];
6366
6366
  let s = 0, i;
6367
- const o = new RegExp(Os.source, "g");
6367
+ const o = new RegExp(qs.source, "g");
6368
6368
  let l = 0;
6369
6369
  for (; (i = o.exec(t)) !== null; ) {
6370
6370
  const c = i.index;
6371
6371
  let g = i[0], m = "";
6372
6372
  for (; g.length > 0 && /[.,;:!?]$/.test(g); )
6373
6373
  m = g.slice(-1) + m, g = g.slice(0, -1);
6374
- c > s && a.push(t.slice(s, c)), a.push(ma(g, g, `${n}-u${l}`)), m && a.push(m), s = c + i[0].length, l += 1;
6374
+ c > s && a.push(t.slice(s, c)), a.push(pa(g, g, `${n}-u${l}`)), m && a.push(m), s = c + i[0].length, l += 1;
6375
6375
  }
6376
6376
  return s < t.length && a.push(t.slice(s)), a.length > 0 ? a : [t];
6377
6377
  }
6378
- function zs() {
6379
- const t = ze(), [n] = qt(), { user: a, login: s, register: i } = st(), { t: o } = X(), l = n.get("invite") || "", [c, g] = C(l ? "register" : "login"), [m, h] = C(!1), [u, N] = C(!1), [x, v] = C([]), [f, T] = C(!0), [P, b] = C(""), [d, p] = C(""), [_, y] = C(""), [B, D] = C(""), [O, G] = C("");
6378
+ function Ms() {
6379
+ const t = ze(), [n] = qt(), { user: a, login: s, register: i } = st(), { t: o } = Z(), l = n.get("invite") || "", [c, g] = S(l ? "register" : "login"), [m, h] = S(!1), [u, N] = S(!1), [x, v] = S([]), [f, T] = S(!0), [P, b] = S(""), [d, p] = S(""), [_, y] = S(""), [B, D] = S(""), [O, G] = S("");
6380
6380
  se(() => {
6381
6381
  a && a.role !== "public_manager" && t("/", { replace: !0 });
6382
6382
  }, [a, t]), se(() => {
6383
- I.authSetupStatus().then((S) => {
6384
- h(S.registration_open), N(S.first_run), v(S.oauth_providers ?? []), S.first_run && g("register");
6383
+ I.authSetupStatus().then((C) => {
6384
+ h(C.registration_open), N(C.first_run), v(C.oauth_providers ?? []), C.first_run && g("register");
6385
6385
  }).catch(() => {
6386
6386
  }).finally(() => T(!1));
6387
6387
  }, []), se(() => {
6388
- const S = n.get("oauth_error");
6389
- S && b(o(`login.oauthError.${S}`, { defaultValue: o("login.oauthError.generic") }));
6388
+ const C = n.get("oauth_error");
6389
+ C && b(o(`login.oauthError.${C}`, { defaultValue: o("login.oauthError.generic") }));
6390
6390
  }, [n, o]);
6391
- const ee = async (S) => {
6392
- if (S.preventDefault(), b(""), c === "register") {
6391
+ const ee = async (C) => {
6392
+ if (C.preventDefault(), b(""), c === "register") {
6393
6393
  if (B !== O) {
6394
6394
  b(o("login.passwordsNoMatch"));
6395
6395
  return;
@@ -6424,7 +6424,7 @@ function zs() {
6424
6424
  {
6425
6425
  label: o("login.fullName"),
6426
6426
  value: _,
6427
- onChange: (S) => y(S.target.value),
6427
+ onChange: (C) => y(C.target.value),
6428
6428
  required: !0
6429
6429
  }
6430
6430
  ),
@@ -6434,7 +6434,7 @@ function zs() {
6434
6434
  label: o("login.email"),
6435
6435
  type: "email",
6436
6436
  value: d,
6437
- onChange: (S) => p(S.target.value),
6437
+ onChange: (C) => p(C.target.value),
6438
6438
  required: !0
6439
6439
  }
6440
6440
  ),
@@ -6444,7 +6444,7 @@ function zs() {
6444
6444
  label: o("login.password"),
6445
6445
  type: "password",
6446
6446
  value: B,
6447
- onChange: (S) => D(S.target.value),
6447
+ onChange: (C) => D(C.target.value),
6448
6448
  required: !0
6449
6449
  }
6450
6450
  ),
@@ -6454,11 +6454,11 @@ function zs() {
6454
6454
  label: o("login.confirmPassword"),
6455
6455
  type: "password",
6456
6456
  value: O,
6457
- onChange: (S) => G(S.target.value),
6457
+ onChange: (C) => G(C.target.value),
6458
6458
  required: !0
6459
6459
  }
6460
6460
  ),
6461
- /* @__PURE__ */ e(Q, { type: "submit", className: "w-full", children: o(c === "register" ? u ? "login.createAdmin" : "login.register" : "login.signIn") })
6461
+ /* @__PURE__ */ e(H, { type: "submit", className: "w-full", children: o(c === "register" ? u ? "login.createAdmin" : "login.register" : "login.signIn") })
6462
6462
  ] }),
6463
6463
  x.length > 0 && /* @__PURE__ */ r("div", { className: "mt-4 space-y-3", children: [
6464
6464
  /* @__PURE__ */ r("div", { className: "flex items-center gap-3", children: [
@@ -6466,20 +6466,20 @@ function zs() {
6466
6466
  /* @__PURE__ */ e("span", { className: "text-xs uppercase tracking-wide text-fg-muted", children: o("login.orContinueWith") }),
6467
6467
  /* @__PURE__ */ e("div", { className: "h-px flex-1 bg-border" })
6468
6468
  ] }),
6469
- /* @__PURE__ */ e("div", { className: "space-y-2", children: x.map((S) => /* @__PURE__ */ r(
6469
+ /* @__PURE__ */ e("div", { className: "space-y-2", children: x.map((C) => /* @__PURE__ */ r(
6470
6470
  "button",
6471
6471
  {
6472
6472
  type: "button",
6473
6473
  onClick: () => {
6474
- window.location.href = I.oauthLoginUrl(S, { invite: l || void 0 });
6474
+ window.location.href = I.oauthLoginUrl(C, { invite: l || void 0 });
6475
6475
  },
6476
6476
  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",
6477
6477
  children: [
6478
- /* @__PURE__ */ e(Fs, { provider: S }),
6479
- o("login.continueWithProvider", { provider: Ms(S) })
6478
+ /* @__PURE__ */ e($s, { provider: C }),
6479
+ o("login.continueWithProvider", { provider: Fs(C) })
6480
6480
  ]
6481
6481
  },
6482
- S
6482
+ C
6483
6483
  )) })
6484
6484
  ] })
6485
6485
  ] }),
@@ -6489,7 +6489,7 @@ function zs() {
6489
6489
  /* @__PURE__ */ e("p", { className: "mt-1 text-sm text-fg-muted", children: o("login.browsingBody") })
6490
6490
  ] }),
6491
6491
  /* @__PURE__ */ e(
6492
- Q,
6492
+ H,
6493
6493
  {
6494
6494
  type: "button",
6495
6495
  className: "w-full",
@@ -6509,10 +6509,10 @@ function zs() {
6509
6509
  ] }) })
6510
6510
  ] }) });
6511
6511
  }
6512
- function Ms(t) {
6512
+ function Fs(t) {
6513
6513
  return t.charAt(0).toUpperCase() + t.slice(1);
6514
6514
  }
6515
- function Fs({ provider: t }) {
6515
+ function $s({ provider: t }) {
6516
6516
  return t === "google" ? /* @__PURE__ */ r("svg", { className: "h-4 w-4", viewBox: "0 0 48 48", "aria-hidden": "true", children: [
6517
6517
  /* @__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" }),
6518
6518
  /* @__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" }),
@@ -6520,8 +6520,8 @@ function Fs({ provider: t }) {
6520
6520
  /* @__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" })
6521
6521
  ] }) : 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;
6522
6522
  }
6523
- function $s() {
6524
- const t = ze(), n = te(!1), [a, s] = C("");
6523
+ function Us() {
6524
+ const t = ze(), n = te(!1), [a, s] = S("");
6525
6525
  return se(() => {
6526
6526
  n.current || (n.current = !0, I.createChatSession().then((i) => {
6527
6527
  t(`/chat/${i.id}?demo=1`, { replace: !0 });
@@ -6552,8 +6552,8 @@ function zn() {
6552
6552
  function Mn() {
6553
6553
  return { type: "sales", party: "", amount: "", due_date: "", remarks: "" };
6554
6554
  }
6555
- function Us() {
6556
- const t = ze(), n = We(), [a, s] = C(""), [i, o] = C((/* @__PURE__ */ new Date()).toISOString().split("T")[0]), [l, c] = C(""), [g, m] = C([qn()]), [h, u] = C([zn()]), [N, x] = C([Mn()]), [v, f] = C({}), T = ie({
6555
+ function Vs() {
6556
+ const t = ze(), n = We(), [a, s] = S(""), [i, o] = S((/* @__PURE__ */ new Date()).toISOString().split("T")[0]), [l, c] = S(""), [g, m] = S([qn()]), [h, u] = S([zn()]), [N, x] = S([Mn()]), [v, f] = S({}), T = ie({
6557
6557
  mutationFn: () => I.importAccountBalances({
6558
6558
  company: a,
6559
6559
  posting_date: i,
@@ -6599,7 +6599,7 @@ function Us() {
6599
6599
  return /* @__PURE__ */ r("div", { className: "space-y-6", children: [
6600
6600
  /* @__PURE__ */ e("p", { className: "text-sm text-gray-500", children: "Import balances from your previous system. Each section creates the appropriate documents (Journal Entry, Stock Entry, or Invoices) and submits them automatically." }),
6601
6601
  /* @__PURE__ */ e($, { title: "Common Settings", children: /* @__PURE__ */ r("div", { className: "flex flex-wrap items-end gap-4", children: [
6602
- /* @__PURE__ */ e(Ce, { label: "Company", value: a, onChange: s, linkDoctype: "company", readOnly: !1 }),
6602
+ /* @__PURE__ */ e(Se, { label: "Company", value: a, onChange: s, linkDoctype: "company", readOnly: !1 }),
6603
6603
  /* @__PURE__ */ e(J, { label: "As-of Date", type: "date", value: i, onChange: (p) => o(p.target.value) })
6604
6604
  ] }) }),
6605
6605
  /* @__PURE__ */ r($, { title: "1. Account Balances", children: [
@@ -6613,20 +6613,20 @@ function Us() {
6613
6613
  /* @__PURE__ */ e("th", { className: "px-2 py-2 text-right font-medium text-gray-500", children: "Credit" })
6614
6614
  ] }) }),
6615
6615
  /* @__PURE__ */ e("tbody", { children: g.map((p, _) => /* @__PURE__ */ r("tr", { children: [
6616
- /* @__PURE__ */ e("td", { className: "px-2 py-1", children: /* @__PURE__ */ e(Ce, { value: p.account, onChange: (y) => d(g, m, _, "account", y), linkDoctype: "account", readOnly: !1, label: "" }) }),
6616
+ /* @__PURE__ */ e("td", { className: "px-2 py-1", children: /* @__PURE__ */ e(Se, { value: p.account, onChange: (y) => d(g, m, _, "account", y), linkDoctype: "account", readOnly: !1, label: "" }) }),
6617
6617
  /* @__PURE__ */ e("td", { className: "px-2 py-1", children: /* @__PURE__ */ r("select", { value: p.party_type, onChange: (y) => d(g, m, _, "party_type", y.target.value), className: "w-full rounded border border-gray-300 px-2 py-1.5 text-sm", children: [
6618
6618
  /* @__PURE__ */ e("option", { value: "", children: "—" }),
6619
6619
  /* @__PURE__ */ e("option", { value: "Customer", children: "Customer" }),
6620
6620
  /* @__PURE__ */ e("option", { value: "Supplier", children: "Supplier" })
6621
6621
  ] }) }),
6622
- /* @__PURE__ */ e("td", { className: "px-2 py-1", children: p.party_type ? /* @__PURE__ */ e(Ce, { label: "", value: p.party, onChange: (y) => d(g, m, _, "party", y), linkDoctype: p.party_type.toLowerCase(), readOnly: !1 }) : /* @__PURE__ */ e("span", { className: "text-gray-300 text-xs", children: "set party type first" }) }),
6622
+ /* @__PURE__ */ e("td", { className: "px-2 py-1", children: p.party_type ? /* @__PURE__ */ e(Se, { label: "", value: p.party, onChange: (y) => d(g, m, _, "party", y), linkDoctype: p.party_type.toLowerCase(), readOnly: !1 }) : /* @__PURE__ */ e("span", { className: "text-gray-300 text-xs", children: "set party type first" }) }),
6623
6623
  /* @__PURE__ */ e("td", { className: "px-2 py-1", children: /* @__PURE__ */ e("input", { type: "number", value: p.debit, onChange: (y) => d(g, m, _, "debit", y.target.value), className: "w-24 rounded border border-gray-300 px-2 py-1.5 text-right text-sm", placeholder: "0.00" }) }),
6624
6624
  /* @__PURE__ */ e("td", { className: "px-2 py-1", children: /* @__PURE__ */ e("input", { type: "number", value: p.credit, onChange: (y) => d(g, m, _, "credit", y.target.value), className: "w-24 rounded border border-gray-300 px-2 py-1.5 text-right text-sm", placeholder: "0.00" }) })
6625
6625
  ] }, _)) })
6626
6626
  ] }) }),
6627
6627
  /* @__PURE__ */ e("div", { className: "mt-2 flex gap-2", children: /* @__PURE__ */ e("button", { onClick: () => m([...g, qn()]), className: "text-xs text-blue-600 hover:text-blue-800", children: "+ Add Row" }) }),
6628
6628
  /* @__PURE__ */ r("div", { className: "mt-3 flex items-center gap-3", children: [
6629
- /* @__PURE__ */ e(Q, { onClick: () => T.mutate(), disabled: !a || T.isPending, children: T.isPending ? "Importing..." : "Import Account Balances" }),
6629
+ /* @__PURE__ */ e(H, { onClick: () => T.mutate(), disabled: !a || T.isPending, children: T.isPending ? "Importing..." : "Import Account Balances" }),
6630
6630
  T.error && /* @__PURE__ */ e("span", { className: "text-xs text-red-600", children: T.error.message }),
6631
6631
  v.accounts && /* @__PURE__ */ r("span", { className: "text-xs text-green-600", children: [
6632
6632
  "Created ",
@@ -6636,7 +6636,7 @@ function Us() {
6636
6636
  ] }),
6637
6637
  /* @__PURE__ */ r($, { title: "2. Stock Balances", children: [
6638
6638
  /* @__PURE__ */ e("p", { className: "mb-3 text-xs text-gray-500", children: "Enter your current inventory. Creates a Stock Entry (Opening Stock) — posts Dr Stock In Hand / Cr Opening Balance Equity so the P&L isn't distorted by day-one inventory." }),
6639
- /* @__PURE__ */ e("div", { className: "mb-3", children: /* @__PURE__ */ e(Ce, { label: "Warehouse", value: l, onChange: c, linkDoctype: "warehouse", readOnly: !1 }) }),
6639
+ /* @__PURE__ */ e("div", { className: "mb-3", children: /* @__PURE__ */ e(Se, { label: "Warehouse", value: l, onChange: c, linkDoctype: "warehouse", readOnly: !1 }) }),
6640
6640
  /* @__PURE__ */ e("div", { children: /* @__PURE__ */ r("table", { className: "min-w-full text-sm", children: [
6641
6641
  /* @__PURE__ */ e("thead", { className: "bg-gray-50", children: /* @__PURE__ */ r("tr", { children: [
6642
6642
  /* @__PURE__ */ e("th", { className: "px-2 py-2 text-left font-medium text-gray-500", children: "Item" }),
@@ -6644,14 +6644,14 @@ function Us() {
6644
6644
  /* @__PURE__ */ e("th", { className: "px-2 py-2 text-right font-medium text-gray-500", children: "Rate" })
6645
6645
  ] }) }),
6646
6646
  /* @__PURE__ */ e("tbody", { children: h.map((p, _) => /* @__PURE__ */ r("tr", { children: [
6647
- /* @__PURE__ */ e("td", { className: "px-2 py-1", children: /* @__PURE__ */ e(Ce, { label: "", value: p.item_code, onChange: (y) => d(h, u, _, "item_code", y), linkDoctype: "item", readOnly: !1 }) }),
6647
+ /* @__PURE__ */ e("td", { className: "px-2 py-1", children: /* @__PURE__ */ e(Se, { label: "", value: p.item_code, onChange: (y) => d(h, u, _, "item_code", y), linkDoctype: "item", readOnly: !1 }) }),
6648
6648
  /* @__PURE__ */ e("td", { className: "px-2 py-1", children: /* @__PURE__ */ e("input", { type: "number", value: p.qty, onChange: (y) => d(h, u, _, "qty", y.target.value), className: "w-24 rounded border border-gray-300 px-2 py-1.5 text-right text-sm", placeholder: "0" }) }),
6649
6649
  /* @__PURE__ */ e("td", { className: "px-2 py-1", children: /* @__PURE__ */ e("input", { type: "number", value: p.rate, onChange: (y) => d(h, u, _, "rate", y.target.value), className: "w-24 rounded border border-gray-300 px-2 py-1.5 text-right text-sm", placeholder: "0.00" }) })
6650
6650
  ] }, _)) })
6651
6651
  ] }) }),
6652
6652
  /* @__PURE__ */ e("div", { className: "mt-2", children: /* @__PURE__ */ e("button", { onClick: () => u([...h, zn()]), className: "text-xs text-blue-600 hover:text-blue-800", children: "+ Add Row" }) }),
6653
6653
  /* @__PURE__ */ r("div", { className: "mt-3 flex items-center gap-3", children: [
6654
- /* @__PURE__ */ e(Q, { onClick: () => P.mutate(), disabled: !a || !l || P.isPending, children: P.isPending ? "Importing..." : "Import Stock Balances" }),
6654
+ /* @__PURE__ */ e(H, { onClick: () => P.mutate(), disabled: !a || !l || P.isPending, children: P.isPending ? "Importing..." : "Import Stock Balances" }),
6655
6655
  P.error && /* @__PURE__ */ e("span", { className: "text-xs text-red-600", children: P.error.message }),
6656
6656
  v.stock && /* @__PURE__ */ r("span", { className: "text-xs text-green-600", children: [
6657
6657
  "Created ",
@@ -6678,7 +6678,7 @@ function Us() {
6678
6678
  /* @__PURE__ */ e("option", { value: "purchase", children: "Purchase (AP)" })
6679
6679
  ] }) }),
6680
6680
  /* @__PURE__ */ e("td", { className: "px-2 py-1", children: /* @__PURE__ */ e(
6681
- Ce,
6681
+ Se,
6682
6682
  {
6683
6683
  label: "",
6684
6684
  value: p.party,
@@ -6694,7 +6694,7 @@ function Us() {
6694
6694
  ] }) }),
6695
6695
  /* @__PURE__ */ e("div", { className: "mt-2", children: /* @__PURE__ */ e("button", { onClick: () => x([...N, Mn()]), className: "text-xs text-blue-600 hover:text-blue-800", children: "+ Add Row" }) }),
6696
6696
  /* @__PURE__ */ r("div", { className: "mt-3 flex items-center gap-3", children: [
6697
- /* @__PURE__ */ e(Q, { onClick: () => b.mutate(), disabled: !a || b.isPending, children: b.isPending ? "Importing..." : "Import Outstanding Invoices" }),
6697
+ /* @__PURE__ */ e(H, { onClick: () => b.mutate(), disabled: !a || b.isPending, children: b.isPending ? "Importing..." : "Import Outstanding Invoices" }),
6698
6698
  b.error && /* @__PURE__ */ e("span", { className: "text-xs text-red-600", children: b.error.message }),
6699
6699
  v.invoices && /* @__PURE__ */ r("span", { className: "text-xs text-green-600", children: [
6700
6700
  "Created ",
@@ -6718,14 +6718,14 @@ function Us() {
6718
6718
  ] })
6719
6719
  ] });
6720
6720
  }
6721
- function Vs() {
6721
+ function Ks() {
6722
6722
  const { user: t } = st(), n = We(), { data: a, isLoading: s } = oe({
6723
6723
  queryKey: ["auth-users"],
6724
6724
  queryFn: () => I.authListUsers()
6725
6725
  }), { data: i } = oe({
6726
6726
  queryKey: ["auth-invites"],
6727
6727
  queryFn: () => I.authListInvites()
6728
- }), [o, l] = C(""), [c, g] = C("viewer"), [m, h] = C(null), u = ie({
6728
+ }), [o, l] = S(""), [c, g] = S("viewer"), [m, h] = S(null), u = ie({
6729
6729
  mutationFn: () => I.authInvite(o, c),
6730
6730
  onSuccess: (d) => {
6731
6731
  h(d), l(""), n.invalidateQueries({ queryKey: ["auth-invites"] });
@@ -6739,7 +6739,7 @@ function Vs() {
6739
6739
  }), v = ie({
6740
6740
  mutationFn: (d) => I.authRevokeInvite(d),
6741
6741
  onSuccess: () => n.invalidateQueries({ queryKey: ["auth-invites"] })
6742
- }), [f, T] = C(null), P = (d) => `${window.location.origin}/login?invite=${d}`, b = async (d) => {
6742
+ }), [f, T] = S(null), P = (d) => `${window.location.origin}/login?invite=${d}`, b = async (d) => {
6743
6743
  try {
6744
6744
  await navigator.clipboard.writeText(P(d)), T(d), setTimeout(() => T((p) => p === d ? null : p), 2e3);
6745
6745
  } catch {
@@ -6783,7 +6783,7 @@ function Vs() {
6783
6783
  }
6784
6784
  ),
6785
6785
  /* @__PURE__ */ e(
6786
- Q,
6786
+ H,
6787
6787
  {
6788
6788
  onClick: () => u.mutate(),
6789
6789
  disabled: !o.trim() || u.isPending,
@@ -6819,7 +6819,7 @@ function Vs() {
6819
6819
  /* @__PURE__ */ e("td", { className: "px-4 py-2 text-gray-500", children: (p = d.creation) == null ? void 0 : p.split("T")[0] }),
6820
6820
  /* @__PURE__ */ e("td", { className: "px-4 py-2 text-right", children: /* @__PURE__ */ r("div", { className: "flex items-center justify-end gap-2", children: [
6821
6821
  /* @__PURE__ */ e(
6822
- Q,
6822
+ H,
6823
6823
  {
6824
6824
  variant: "secondary",
6825
6825
  size: "sm",
@@ -6828,7 +6828,7 @@ function Vs() {
6828
6828
  }
6829
6829
  ),
6830
6830
  /* @__PURE__ */ e(
6831
- Q,
6831
+ H,
6832
6832
  {
6833
6833
  variant: "danger",
6834
6834
  size: "sm",
@@ -6879,98 +6879,98 @@ function Vs() {
6879
6879
  ] }) })
6880
6880
  ] });
6881
6881
  }
6882
- const Ks = { 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" }, js = { title: "Language", help: "Choose the language for the interface. Your choice is saved in this browser.", label: "Language" }, Gs = { logout: "Logout", openMenu: "Open menu", closeMenu: "Close menu", new: "New {{label}}" }, Ws = { 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" }, Hs = { 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" } }, Qs = { 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" } }, Ys = { 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" } }, Js = { 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." } }, Zs = { 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", 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.", 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." }, Xs = { 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" }, ei = { 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" }, ti = { required: "Required: {{fields}}", deleteConfirm: "Delete this {{label}}?", disabledNotice: "This {{label}} is disabled. It remains in the system because other records still reference it.", disabledOnDelete: "{{label}} {{name}} was disabled instead of deleted because it is referenced by {{reason}}." }, ni = { totalRevenue: "Total Revenue", outstandingReceivable: "Outstanding Receivable", outstandingPayable: "Outstanding Payable", totalStockValue: "Total Stock Value", recentDocuments: "Recent Documents", noRecentDocuments: "No recent documents" }, ai = { 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." }, ri = { "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" }, si = { "% 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" }, ii = { accounts: "accounts", items: "items", monthly_distribution: "monthly_distribution", payments: "payments", plans: "plans", references: "references", taxes: "taxes" }, oi = /* @__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?"}`), li = { 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." }, ci = { 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 = {
6883
- common: Ks,
6884
- language: js,
6885
- header: Gs,
6886
- titles: Ws,
6887
- doctypes: Hs,
6888
- masters: Qs,
6889
- nav: Ys,
6890
- login: Js,
6891
- settings: Zs,
6892
- status: Xs,
6893
- reports: ei,
6894
- masterForm: ti,
6895
- dashboard: ni,
6896
- chat: ai,
6897
- conversions: ri,
6898
- fields: si,
6899
- tables: ii,
6900
- tutorial: oi,
6901
- notesMarkup: li,
6902
- coa: ci
6903
- }, ui = { 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" }, mi = { title: "Sprache", help: "Wählen Sie die Sprache der Oberfläche. Ihre Auswahl wird in diesem Browser gespeichert.", label: "Sprache" }, pi = { logout: "Abmelden", openMenu: "Menü öffnen", closeMenu: "Menü schließen", new: "Neu: {{label}}" }, hi = { 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" }, gi = { 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" } }, fi = { 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" } }, yi = { 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" } }, bi = { 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." } }, vi = { 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", 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.", 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." }, xi = { 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" }, Ni = { 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" }, wi = { 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." }, ki = { 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" }, Ci = { items: "Positionen", taxes: "Steuern", references: "Zahlungsreferenzen", accounts: "Kontobuchungen", payments: "Zahlungen", plans: "Planpositionen", monthly_distribution: "Monatliche Verteilung" }, Si = { "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" }, Di = { totalRevenue: "Gesamtumsatz", outstandingReceivable: "Offene Forderungen", outstandingPayable: "Offene Verbindlichkeiten", totalStockValue: "Gesamter Lagerwert", recentDocuments: "Letzte Dokumente", noRecentDocuments: "Keine aktuellen Dokumente" }, Ai = { 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." }, Pi = /* @__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?"}'), _i = { 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." }, Ti = { 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" } }, Ri = {
6904
- common: ui,
6905
- language: mi,
6906
- header: pi,
6907
- titles: hi,
6908
- doctypes: gi,
6909
- masters: fi,
6910
- nav: yi,
6911
- login: bi,
6912
- settings: vi,
6913
- status: xi,
6914
- reports: Ni,
6915
- masterForm: wi,
6916
- fields: ki,
6882
+ const js = { 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" }, Gs = { title: "Language", help: "Choose the language for the interface. Your choice is saved in this browser.", label: "Language" }, Ws = { logout: "Logout", openMenu: "Open menu", closeMenu: "Close menu", new: "New {{label}}" }, Hs = { 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" }, Qs = { 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" } }, Ys = { 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" } }, Js = { 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" } }, Zs = { 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." } }, Xs = { 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." }, ei = { 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" }, ti = { 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" }, ni = { 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}}." }, ai = { totalRevenue: "Total Revenue", outstandingReceivable: "Outstanding Receivable", outstandingPayable: "Outstanding Payable", totalStockValue: "Total Stock Value", recentDocuments: "Recent Documents", noRecentDocuments: "No recent documents" }, ri = { 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." }, si = { "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" }, ii = { "% 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" }, oi = { accounts: "accounts", items: "items", monthly_distribution: "monthly_distribution", payments: "payments", plans: "plans", references: "references", taxes: "taxes" }, li = /* @__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." }, di = { 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" } }, ui = {
6883
+ common: js,
6884
+ language: Gs,
6885
+ header: Ws,
6886
+ titles: Hs,
6887
+ doctypes: Qs,
6888
+ masters: Ys,
6889
+ nav: Js,
6890
+ login: Zs,
6891
+ settings: Xs,
6892
+ status: ei,
6893
+ reports: ti,
6894
+ masterForm: ni,
6895
+ dashboard: ai,
6896
+ chat: ri,
6897
+ conversions: si,
6898
+ fields: ii,
6899
+ tables: oi,
6900
+ tutorial: li,
6901
+ notesMarkup: ci,
6902
+ coa: di
6903
+ }, mi = { 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" }, hi = { logout: "Abmelden", openMenu: "Menü öffnen", closeMenu: "Menü schließen", new: "Neu: {{label}}" }, gi = { 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" }, fi = { 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" } }, yi = { 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" } }, vi = { 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." } }, xi = { 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." }, Ni = { 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" }, wi = { 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" }, ki = { 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." }, Si = { 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" }, Ci = { items: "Positionen", taxes: "Steuern", references: "Zahlungsreferenzen", accounts: "Kontobuchungen", payments: "Zahlungen", plans: "Planpositionen", monthly_distribution: "Monatliche Verteilung" }, Di = { "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" }, Ai = { totalRevenue: "Gesamtumsatz", outstandingReceivable: "Offene Forderungen", outstandingPayable: "Offene Verbindlichkeiten", totalStockValue: "Gesamter Lagerwert", recentDocuments: "Letzte Dokumente", noRecentDocuments: "Keine aktuellen Dokumente" }, Pi = { 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." }, _i = /* @__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?"}'), Ti = { 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." }, Ri = { 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" } }, Ii = {
6904
+ common: mi,
6905
+ language: pi,
6906
+ header: hi,
6907
+ titles: gi,
6908
+ doctypes: fi,
6909
+ masters: yi,
6910
+ nav: bi,
6911
+ login: vi,
6912
+ settings: xi,
6913
+ status: Ni,
6914
+ reports: wi,
6915
+ masterForm: ki,
6916
+ fields: Si,
6917
6917
  tables: Ci,
6918
- conversions: Si,
6919
- dashboard: Di,
6920
- chat: Ai,
6921
- tutorial: Pi,
6922
- notesMarkup: _i,
6923
- coa: Ti
6924
- }, Ii = { 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" }, Bi = { title: "Langue", help: "Choisissez la langue de l'interface. Votre choix est enregistré dans ce navigateur.", label: "Langue" }, Li = { logout: "Déconnexion", openMenu: "Ouvrir le menu", closeMenu: "Fermer le menu", new: "Nouveau : {{label}}" }, Ei = { 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" }, Oi = { 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" } }, qi = { 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" } }, zi = { 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" } }, Mi = { 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." } }, Fi = { 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", 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.", 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." }, $i = { 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é" }, Ui = { 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é" }, Vi = { 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}}." }, Ki = { 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é" }, ji = { 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" }, Gi = { "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" }, Wi = { 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" }, Hi = { 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." }, Qi = /* @__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 ?"}`), Yi = { 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." }, Ji = { 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" } }, Zi = {
6925
- common: Ii,
6926
- language: Bi,
6918
+ conversions: Di,
6919
+ dashboard: Ai,
6920
+ chat: Pi,
6921
+ tutorial: _i,
6922
+ notesMarkup: Ti,
6923
+ coa: Ri
6924
+ }, Bi = { 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" }, Ei = { title: "Langue", help: "Choisissez la langue de l'interface. Votre choix est enregistré dans ce navigateur.", label: "Langue" }, Li = { logout: "Déconnexion", openMenu: "Ouvrir le menu", closeMenu: "Fermer le menu", new: "Nouveau : {{label}}" }, Oi = { 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" }, qi = { 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" } }, zi = { 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" } }, Mi = { 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" } }, Fi = { 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." } }, $i = { 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." }, Ui = { 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é" }, Vi = { 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é" }, Ki = { 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}}." }, ji = { 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é" }, Gi = { 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" }, Wi = { "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" }, Hi = { 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" }, Qi = { 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." }, Yi = /* @__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 ?"}`), Ji = { 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." }, Zi = { 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" } }, Xi = {
6925
+ common: Bi,
6926
+ language: Ei,
6927
6927
  header: Li,
6928
- titles: Ei,
6929
- doctypes: Oi,
6930
- masters: qi,
6931
- nav: zi,
6932
- login: Mi,
6933
- settings: Fi,
6934
- status: $i,
6935
- reports: Ui,
6936
- masterForm: Vi,
6937
- fields: Ki,
6938
- tables: ji,
6939
- conversions: Gi,
6940
- dashboard: Wi,
6941
- chat: Hi,
6942
- tutorial: Qi,
6943
- notesMarkup: Yi,
6944
- coa: Ji
6945
- }, pa = [
6928
+ titles: Oi,
6929
+ doctypes: qi,
6930
+ masters: zi,
6931
+ nav: Mi,
6932
+ login: Fi,
6933
+ settings: $i,
6934
+ status: Ui,
6935
+ reports: Vi,
6936
+ masterForm: Ki,
6937
+ fields: ji,
6938
+ tables: Gi,
6939
+ conversions: Wi,
6940
+ dashboard: Hi,
6941
+ chat: Qi,
6942
+ tutorial: Yi,
6943
+ notesMarkup: Ji,
6944
+ coa: Zi
6945
+ }, ha = [
6946
6946
  { code: "en", label: "English" },
6947
6947
  { code: "de", label: "Deutsch" },
6948
6948
  { code: "fr", label: "Français" }
6949
- ], ha = "lambda-erp:language";
6950
- function Xi(t) {
6951
- return !!t && pa.some((n) => n.code === t);
6949
+ ], ga = "lambda-erp:language";
6950
+ function eo(t) {
6951
+ return !!t && ha.some((n) => n.code === t);
6952
6952
  }
6953
- function eo() {
6953
+ function to() {
6954
6954
  try {
6955
- const t = localStorage.getItem(ha);
6956
- if (Xi(t)) return t;
6955
+ const t = localStorage.getItem(ga);
6956
+ if (eo(t)) return t;
6957
6957
  } catch {
6958
6958
  }
6959
6959
  return "en";
6960
6960
  }
6961
- function to(t) {
6961
+ function no(t) {
6962
6962
  try {
6963
- localStorage.setItem(ha, t);
6963
+ localStorage.setItem(ga, t);
6964
6964
  } catch {
6965
6965
  }
6966
6966
  }
6967
- Xn.use(Ta).init({
6967
+ ea.use(Ra).init({
6968
6968
  resources: {
6969
- en: { translation: di },
6970
- de: { translation: Ri },
6971
- fr: { translation: Zi }
6969
+ en: { translation: ui },
6970
+ de: { translation: Ii },
6971
+ fr: { translation: Xi }
6972
6972
  },
6973
- lng: eo(),
6973
+ lng: to(),
6974
6974
  fallbackLng: "en",
6975
6975
  // any key missing in de/fr falls back to the English value
6976
6976
  interpolation: { escapeValue: !1 },
@@ -6978,15 +6978,15 @@ Xn.use(Ta).init({
6978
6978
  react: { useSuspense: !1 }
6979
6979
  // resources are bundled synchronously — no Suspense needed
6980
6980
  });
6981
- Xn.on("languageChanged", to);
6982
- function no({ label: t }) {
6981
+ ea.on("languageChanged", no);
6982
+ function ao({ label: t }) {
6983
6983
  var i;
6984
- const { t: n, i18n: a } = X(), s = ((i = a.language) == null ? void 0 : i.split("-")[0]) ?? "en";
6984
+ const { t: n, i18n: a } = Z(), s = ((i = a.language) == null ? void 0 : i.split("-")[0]) ?? "en";
6985
6985
  return /* @__PURE__ */ e(
6986
6986
  He,
6987
6987
  {
6988
6988
  label: t === null ? void 0 : t ?? n("language.label"),
6989
- options: pa.map((o) => ({ value: o.code, label: o.label })),
6989
+ options: ha.map((o) => ({ value: o.code, label: o.label })),
6990
6990
  value: s,
6991
6991
  onChange: (o) => a.changeLanguage(o.target.value)
6992
6992
  }
@@ -7003,9 +7003,9 @@ const Fn = [
7003
7003
  function Ge(t) {
7004
7004
  return t === 0 ? "$0.00" : t < 0.01 ? `$${t.toFixed(4)}` : `$${t.toFixed(2)}`;
7005
7005
  }
7006
- function ao({ demoActive: t }) {
7006
+ function ro({ demoActive: t }) {
7007
7007
  var P, b;
7008
- const { t: n } = X(), [a, s] = C("1h"), { data: i, isLoading: o, isFetching: l, error: c, refetch: g, dataUpdatedAt: m } = oe({
7008
+ const { t: n } = Z(), [a, s] = S("1h"), { data: i, isLoading: o, isFetching: l, error: c, refetch: g, dataUpdatedAt: m } = oe({
7009
7009
  queryKey: ["demo-spend"],
7010
7010
  queryFn: () => I.getDemoSpend(),
7011
7011
  // Refresh once a minute — demo spend changes slowly; no need to poll harder.
@@ -7131,11 +7131,11 @@ function ao({ demoActive: t }) {
7131
7131
  ] })
7132
7132
  ),
7133
7133
  /* @__PURE__ */ r("div", { className: "grid grid-cols-2 gap-3 sm:grid-cols-4", children: [
7134
- t ? /* @__PURE__ */ e(Ct, { label: "Demo spend", value: Ge(u.demo_usd) }) : /* @__PURE__ */ e(Ct, { label: "Cost", value: Ge(u.total_usd) }),
7135
- /* @__PURE__ */ e(Ct, { label: "Calls", value: u.call_count.toLocaleString() }),
7136
- /* @__PURE__ */ e(Ct, { label: "Unique IPs", value: u.unique_ips.toLocaleString() }),
7134
+ t ? /* @__PURE__ */ e(St, { label: "Demo spend", value: Ge(u.demo_usd) }) : /* @__PURE__ */ e(St, { label: "Cost", value: Ge(u.total_usd) }),
7135
+ /* @__PURE__ */ e(St, { label: "Calls", value: u.call_count.toLocaleString() }),
7136
+ /* @__PURE__ */ e(St, { label: "Unique IPs", value: u.unique_ips.toLocaleString() }),
7137
7137
  /* @__PURE__ */ e(
7138
- Ct,
7138
+ St,
7139
7139
  {
7140
7140
  label: "Tokens (in/out)",
7141
7141
  value: `${u.prompt_tokens.toLocaleString()} / ${u.completion_tokens.toLocaleString()}`
@@ -7181,14 +7181,14 @@ function ao({ demoActive: t }) {
7181
7181
  ] })
7182
7182
  ] });
7183
7183
  }
7184
- function Ct({ label: t, value: n }) {
7184
+ function St({ label: t, value: n }) {
7185
7185
  return /* @__PURE__ */ r("div", { className: "rounded-md bg-gray-50 px-3 py-2", children: [
7186
7186
  /* @__PURE__ */ e("div", { className: "text-xs font-medium uppercase tracking-wide text-gray-500", children: t }),
7187
7187
  /* @__PURE__ */ e("div", { className: "mt-0.5 text-sm font-semibold tabular-nums text-gray-900", children: n })
7188
7188
  ] });
7189
7189
  }
7190
- function ro() {
7191
- const { t } = X(), { user: n } = st(), [a, s] = C(""), [i, o] = C(""), [l, c] = C(""), [g, m] = C(""), [h, u] = C(!1), N = ie({
7190
+ function so() {
7191
+ const { t } = Z(), { user: n } = st(), [a, s] = S(""), [i, o] = S(""), [l, c] = S(""), [g, m] = S(""), [h, u] = S(!1), N = ie({
7192
7192
  mutationFn: () => I.authChangePassword(a, i),
7193
7193
  onSuccess: () => {
7194
7194
  u(!0), m(""), s(""), o(""), c(""), setTimeout(() => u(!1), 4e3);
@@ -7261,11 +7261,11 @@ function ro() {
7261
7261
  ),
7262
7262
  g && /* @__PURE__ */ e("p", { className: "text-sm text-red-600", children: g }),
7263
7263
  h && /* @__PURE__ */ e("p", { className: "text-sm text-green-700", children: t("settings.passwordChanged") }),
7264
- /* @__PURE__ */ e(Q, { type: "submit", disabled: N.isPending || !a || !i || !l, children: N.isPending ? t("settings.changingPassword") : t("settings.changePassword") })
7264
+ /* @__PURE__ */ e(H, { type: "submit", disabled: N.isPending || !a || !i || !l, children: N.isPending ? t("settings.changingPassword") : t("settings.changePassword") })
7265
7265
  ] }) });
7266
7266
  }
7267
- function so() {
7268
- const { t } = X(), { user: n, refreshUser: a } = st(), [s, i] = C(""), [o, l] = C(""), [c, g] = C(""), [m, h] = C(!1), u = ie({
7267
+ function io() {
7268
+ const { t } = Z(), { user: n, refreshUser: a } = st(), [s, i] = S(""), [o, l] = S(""), [c, g] = S(""), [m, h] = S(!1), u = ie({
7269
7269
  mutationFn: () => I.authSetPassword(s),
7270
7270
  onSuccess: async () => {
7271
7271
  h(!0), g(""), i(""), l(""), await a();
@@ -7326,12 +7326,12 @@ function so() {
7326
7326
  ),
7327
7327
  c && /* @__PURE__ */ e("p", { className: "text-sm text-red-600", children: c }),
7328
7328
  m && /* @__PURE__ */ e("p", { className: "text-sm text-green-700", children: t("settings.passwordSet") }),
7329
- /* @__PURE__ */ e(Q, { type: "submit", disabled: u.isPending || !s || !o, children: u.isPending ? t("settings.changingPassword") : t("settings.setPassword") })
7329
+ /* @__PURE__ */ e(H, { type: "submit", disabled: u.isPending || !s || !o, children: u.isPending ? t("settings.changingPassword") : t("settings.setPassword") })
7330
7330
  ] })
7331
7331
  ] });
7332
7332
  }
7333
- function io() {
7334
- const { t } = X(), { data: n } = oe({
7333
+ function oo() {
7334
+ const { t } = Z(), { data: n } = oe({
7335
7335
  queryKey: ["auth-setup-status"],
7336
7336
  queryFn: () => I.authSetupStatus()
7337
7337
  }), { data: a } = oe({
@@ -7365,8 +7365,8 @@ function io() {
7365
7365
  ] });
7366
7366
  }
7367
7367
  const Yt = { viewer: 1, manager: 2, admin: 3 };
7368
- function ga({ ownRole: t }) {
7369
- const { t: n } = X(), { user: a } = st(), s = We(), [i, o] = C(""), [l, c] = C(t in Yt ? t : "viewer"), [g, m] = C(null), [h, u] = C(null), N = ["viewer", "manager", "admin"].filter(
7368
+ function fa({ ownRole: t }) {
7369
+ const { t: n } = Z(), { user: a } = st(), s = We(), [i, o] = S(""), [l, c] = S(t in Yt ? t : "viewer"), [g, m] = S(null), [h, u] = S(null), N = ["viewer", "manager", "admin"].filter(
7370
7370
  (y) => Yt[y] <= (Yt[t] ?? 1)
7371
7371
  ), { data: x } = oe({
7372
7372
  queryKey: ["api-keys"],
@@ -7382,7 +7382,7 @@ function ga({ ownRole: t }) {
7382
7382
  }), T = ie({
7383
7383
  mutationFn: (y) => I.deleteApiKey(y),
7384
7384
  onSuccess: () => s.invalidateQueries({ queryKey: ["api-keys"] })
7385
- }), P = (y) => y.is_mine ?? y.user === (a == null ? void 0 : a.name), b = (y) => y.owner_full_name || y.owner_email || y.user || n("settings.chatApiUnknownUser"), d = Se(() => {
7385
+ }), P = (y) => y.is_mine ?? y.user === (a == null ? void 0 : a.name), b = (y) => y.owner_full_name || y.owner_email || y.user || n("settings.chatApiUnknownUser"), d = Ce(() => {
7386
7386
  const y = /* @__PURE__ */ new Map();
7387
7387
  for (const B of x ?? []) {
7388
7388
  const D = B.is_mine ?? B.user === (a == null ? void 0 : a.name), O = D ? "__me__" : B.user ?? "__unknown__";
@@ -7480,7 +7480,7 @@ function ga({ ownRole: t }) {
7480
7480
  onChange: (y) => c(y.target.value)
7481
7481
  }
7482
7482
  ),
7483
- /* @__PURE__ */ e(Q, { onClick: () => v.mutate(), disabled: !i.trim() || v.isPending, children: n("settings.chatApiCreate") })
7483
+ /* @__PURE__ */ e(H, { onClick: () => v.mutate(), disabled: !i.trim() || v.isPending, children: n("settings.chatApiCreate") })
7484
7484
  ] }),
7485
7485
  /* @__PURE__ */ e("p", { className: "mt-2 text-xs text-fg-muted", children: n("settings.chatApiWarn") }),
7486
7486
  h && /* @__PURE__ */ e(
@@ -7502,9 +7502,9 @@ function ga({ ownRole: t }) {
7502
7502
  { name: h.owner, key: h.keyName }
7503
7503
  ) }),
7504
7504
  /* @__PURE__ */ r("div", { className: "mt-4 flex justify-end gap-2", children: [
7505
- /* @__PURE__ */ e(Q, { variant: "secondary", size: "sm", onClick: () => u(null), children: n("common.cancel") }),
7505
+ /* @__PURE__ */ e(H, { variant: "secondary", size: "sm", onClick: () => u(null), children: n("common.cancel") }),
7506
7506
  /* @__PURE__ */ e(
7507
- Q,
7507
+ H,
7508
7508
  {
7509
7509
  variant: "danger",
7510
7510
  size: "sm",
@@ -7522,35 +7522,103 @@ function ga({ ownRole: t }) {
7522
7522
  )
7523
7523
  ] });
7524
7524
  }
7525
- function oo({
7525
+ function $n({
7526
7526
  enabled: t,
7527
7527
  onToggle: n,
7528
- ownRole: a
7528
+ body: a,
7529
+ statusOn: s,
7530
+ statusOff: i
7529
7531
  }) {
7530
- const { t: s } = X();
7531
- return /* @__PURE__ */ r($, { title: s("settings.chatApiTitle"), children: [
7532
- /* @__PURE__ */ r("div", { className: "flex items-center justify-between", children: [
7533
- /* @__PURE__ */ r("div", { children: [
7534
- /* @__PURE__ */ e("p", { className: "text-sm text-gray-700", children: s("settings.chatApiBody") }),
7535
- /* @__PURE__ */ e("p", { className: "mt-1 text-xs text-gray-400", children: s(t ? "settings.chatApiEnabled" : "settings.chatApiDisabled") })
7536
- ] }),
7532
+ const { t: o } = Z();
7533
+ return /* @__PURE__ */ r("div", { className: "flex items-center justify-between", children: [
7534
+ /* @__PURE__ */ r("div", { children: [
7535
+ /* @__PURE__ */ e("p", { className: "text-sm text-gray-700", children: a }),
7536
+ /* @__PURE__ */ e("p", { className: "mt-1 text-xs text-gray-400", children: t ? s : i })
7537
+ ] }),
7538
+ /* @__PURE__ */ e(
7539
+ "button",
7540
+ {
7541
+ onClick: n,
7542
+ className: `ml-4 shrink-0 rounded-full px-4 py-1.5 text-sm font-medium ${t ? "bg-red-50 text-red-700 hover:bg-red-100" : "bg-green-50 text-green-700 hover:bg-green-100"}`,
7543
+ children: o(t ? "common.disable" : "common.enable")
7544
+ }
7545
+ )
7546
+ ] });
7547
+ }
7548
+ function lo({
7549
+ chatEnabled: t,
7550
+ restEnabled: n,
7551
+ onToggleChat: a,
7552
+ onToggleRest: s,
7553
+ ownRole: i
7554
+ }) {
7555
+ const { t: o } = Z(), [l, c] = S(null);
7556
+ return /* @__PURE__ */ r($, { title: o("settings.apiTitle"), children: [
7557
+ /* @__PURE__ */ r("div", { className: "space-y-4", children: [
7537
7558
  /* @__PURE__ */ e(
7538
- "button",
7559
+ $n,
7539
7560
  {
7540
- onClick: n,
7541
- className: `ml-4 shrink-0 rounded-full px-4 py-1.5 text-sm font-medium ${t ? "bg-red-50 text-red-700 hover:bg-red-100" : "bg-green-50 text-green-700 hover:bg-green-100"}`,
7542
- children: s(t ? "common.disable" : "common.enable")
7561
+ enabled: t,
7562
+ onToggle: () => t ? c("chat") : a(),
7563
+ body: o("settings.chatApiBody"),
7564
+ statusOn: o("settings.chatApiEnabled"),
7565
+ statusOff: o("settings.chatApiDisabled")
7566
+ }
7567
+ ),
7568
+ /* @__PURE__ */ e("div", { className: "border-t border-gray-100" }),
7569
+ /* @__PURE__ */ e(
7570
+ $n,
7571
+ {
7572
+ enabled: n,
7573
+ onToggle: () => n ? c("rest") : s(),
7574
+ body: o("settings.restApiBody"),
7575
+ statusOn: o("settings.restApiEnabled"),
7576
+ statusOff: o("settings.restApiDisabled")
7543
7577
  }
7544
7578
  )
7545
7579
  ] }),
7546
- t && /* @__PURE__ */ r("div", { className: "mt-4 border-t border-gray-100 pt-4", children: [
7547
- /* @__PURE__ */ e("div", { className: "mb-2 text-xs font-medium text-gray-500", children: s("settings.chatApiKeysTitle") }),
7548
- /* @__PURE__ */ e(ga, { ownRole: a })
7549
- ] })
7580
+ (t || n) && /* @__PURE__ */ r("div", { className: "mt-4 border-t border-gray-100 pt-4", children: [
7581
+ /* @__PURE__ */ e("div", { className: "mb-2 text-xs font-medium text-gray-500", children: o("settings.chatApiKeysTitle") }),
7582
+ /* @__PURE__ */ e(fa, { ownRole: i })
7583
+ ] }),
7584
+ l && /* @__PURE__ */ e(
7585
+ "div",
7586
+ {
7587
+ className: "fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4",
7588
+ onClick: () => c(null),
7589
+ children: /* @__PURE__ */ r(
7590
+ "div",
7591
+ {
7592
+ className: "w-full max-w-md rounded-xl border border-line bg-surface p-6 shadow-xl",
7593
+ role: "dialog",
7594
+ "aria-modal": "true",
7595
+ onClick: (g) => g.stopPropagation(),
7596
+ children: [
7597
+ /* @__PURE__ */ e("h3", { className: "text-base font-semibold text-fg", children: o(l === "chat" ? "settings.chatApiDeactivateTitle" : "settings.restApiDeactivateTitle") }),
7598
+ /* @__PURE__ */ e("p", { className: "mt-3 text-sm text-fg-muted", children: o(l === "chat" ? "settings.chatApiDeactivateBody" : "settings.restApiDeactivateBody") }),
7599
+ /* @__PURE__ */ r("div", { className: "mt-6 flex justify-end gap-2", children: [
7600
+ /* @__PURE__ */ e(H, { variant: "secondary", size: "sm", onClick: () => c(null), children: o("common.cancel") }),
7601
+ /* @__PURE__ */ e(
7602
+ H,
7603
+ {
7604
+ variant: "danger",
7605
+ size: "sm",
7606
+ onClick: () => {
7607
+ l === "chat" ? a() : s(), c(null);
7608
+ },
7609
+ children: o("settings.chatApiDeactivateConfirm")
7610
+ }
7611
+ )
7612
+ ] })
7613
+ ]
7614
+ }
7615
+ )
7616
+ }
7617
+ )
7550
7618
  ] });
7551
7619
  }
7552
- function lo() {
7553
- const { user: t } = st(), { t: n } = X(), a = We(), s = (t == null ? void 0 : t.role) === "admin", { data: i, isLoading: o } = oe({
7620
+ function co() {
7621
+ const { user: t } = st(), { t: n } = Z(), a = We(), s = (t == null ? void 0 : t.role) === "admin", { data: i, isLoading: o } = oe({
7554
7622
  queryKey: ["settings"],
7555
7623
  queryFn: () => I.getSettings()
7556
7624
  }), l = ie({
@@ -7559,7 +7627,7 @@ function lo() {
7559
7627
  }), { data: c } = oe({
7560
7628
  queryKey: ["public-manager"],
7561
7629
  queryFn: () => I.getPublicManagerStatus()
7562
- }), [g, m] = C(!1), h = ie({
7630
+ }), [g, m] = S(!1), h = ie({
7563
7631
  mutationFn: () => I.createPublicManager(),
7564
7632
  onSuccess: () => {
7565
7633
  a.invalidateQueries({ queryKey: ["public-manager"] }), m(!1);
@@ -7570,11 +7638,11 @@ function lo() {
7570
7638
  });
7571
7639
  return o ? /* @__PURE__ */ e("p", { className: "text-gray-500", children: n("common.loading") }) : /* @__PURE__ */ r("div", { className: "space-y-6", children: [
7572
7640
  /* @__PURE__ */ r($, { title: n("language.title"), children: [
7573
- /* @__PURE__ */ e("div", { className: "flex flex-wrap items-end gap-4", children: /* @__PURE__ */ e("div", { className: "w-64", children: /* @__PURE__ */ e(no, {}) }) }),
7641
+ /* @__PURE__ */ e("div", { className: "flex flex-wrap items-end gap-4", children: /* @__PURE__ */ e("div", { className: "w-64", children: /* @__PURE__ */ e(ao, {}) }) }),
7574
7642
  /* @__PURE__ */ e("p", { className: "mt-2 text-xs text-gray-400", children: n("language.help") })
7575
7643
  ] }),
7576
- (t == null ? void 0 : t.role) !== "public_manager" && ((t == null ? void 0 : t.has_password) === !1 ? /* @__PURE__ */ e(so, {}) : /* @__PURE__ */ e(ro, {})),
7577
- (t == null ? void 0 : t.role) !== "public_manager" && /* @__PURE__ */ e(io, {}),
7644
+ (t == null ? void 0 : t.role) !== "public_manager" && ((t == null ? void 0 : t.has_password) === !1 ? /* @__PURE__ */ e(io, {}) : /* @__PURE__ */ e(so, {})),
7645
+ (t == null ? void 0 : t.role) !== "public_manager" && /* @__PURE__ */ e(oo, {}),
7578
7646
  /* @__PURE__ */ r($, { title: n("settings.pdfTitle"), children: [
7579
7647
  /* @__PURE__ */ e("div", { className: "flex flex-wrap items-end gap-4", children: s ? /* @__PURE__ */ e(
7580
7648
  He,
@@ -7623,20 +7691,24 @@ function lo() {
7623
7691
  )
7624
7692
  ] }) }),
7625
7693
  s && /* @__PURE__ */ e(
7626
- oo,
7694
+ lo,
7627
7695
  {
7628
- enabled: (i == null ? void 0 : i.chat_api_enabled) === "1",
7696
+ chatEnabled: (i == null ? void 0 : i.chat_api_enabled) === "1",
7697
+ restEnabled: (i == null ? void 0 : i.rest_api_enabled) === "1",
7629
7698
  ownRole: (t == null ? void 0 : t.role) ?? "viewer",
7630
- onToggle: () => l.mutate({
7699
+ onToggleChat: () => l.mutate({
7631
7700
  chat_api_enabled: (i == null ? void 0 : i.chat_api_enabled) === "1" ? "0" : "1"
7701
+ }),
7702
+ onToggleRest: () => l.mutate({
7703
+ rest_api_enabled: (i == null ? void 0 : i.rest_api_enabled) === "1" ? "0" : "1"
7632
7704
  })
7633
7705
  }
7634
7706
  ),
7635
7707
  !s && (t == null ? void 0 : t.role) !== "public_manager" && /* @__PURE__ */ r($, { title: n("settings.chatApiKeysTitle"), children: [
7636
7708
  /* @__PURE__ */ e("p", { className: "mb-3 text-sm text-gray-700", children: n("settings.chatApiPersonal") }),
7637
- /* @__PURE__ */ e(ga, { ownRole: (t == null ? void 0 : t.role) ?? "viewer" })
7709
+ /* @__PURE__ */ e(fa, { ownRole: (t == null ? void 0 : t.role) ?? "viewer" })
7638
7710
  ] }),
7639
- s && /* @__PURE__ */ e(ao, { demoActive: !!(c != null && c.active) }),
7711
+ s && /* @__PURE__ */ e(ro, { demoActive: !!(c != null && c.active) }),
7640
7712
  s && /* @__PURE__ */ e($, { title: n("settings.publicTitle"), children: c != null && c.active ? /* @__PURE__ */ r("div", { children: [
7641
7713
  /* @__PURE__ */ r("div", { className: "flex items-center gap-2", children: [
7642
7714
  /* @__PURE__ */ e("span", { className: "inline-block h-2 w-2 rounded-full bg-green-500" }),
@@ -7687,25 +7759,25 @@ function lo() {
7687
7759
  ] }) })
7688
7760
  ] });
7689
7761
  }
7690
- const fa = {};
7691
- function Bo(t, n) {
7692
- fa[t] = n;
7762
+ const ya = {};
7763
+ function Eo(t, n) {
7764
+ ya[t] = n;
7693
7765
  }
7694
- function co(t, n) {
7695
- return fa[t] ?? n;
7766
+ function uo(t, n) {
7767
+ return ya[t] ?? n;
7696
7768
  }
7697
- function uo() {
7698
- const t = co("Dashboard", br);
7769
+ function mo() {
7770
+ const t = uo("Dashboard", vr);
7699
7771
  return /* @__PURE__ */ e(t, {});
7700
7772
  }
7701
- const mo = [
7702
- { path: "/login", element: /* @__PURE__ */ e(zs, {}) },
7703
- { path: "/demo", element: /* @__PURE__ */ e($s, {}) }
7704
- ], po = [
7705
- { index: !0, element: /* @__PURE__ */ e(uo, {}) },
7706
- { path: "setup", element: /* @__PURE__ */ e(Ns, {}) },
7707
- { path: "setup/opening-balances", element: /* @__PURE__ */ e(Us, {}) },
7708
- { path: "tutorial", element: /* @__PURE__ */ e(Ps, {}) },
7773
+ const po = [
7774
+ { path: "/login", element: /* @__PURE__ */ e(Ms, {}) },
7775
+ { path: "/demo", element: /* @__PURE__ */ e(Us, {}) }
7776
+ ], ho = [
7777
+ { index: !0, element: /* @__PURE__ */ e(mo, {}) },
7778
+ { path: "setup", element: /* @__PURE__ */ e(ws, {}) },
7779
+ { path: "setup/opening-balances", element: /* @__PURE__ */ e(Vs, {}) },
7780
+ { path: "tutorial", element: /* @__PURE__ */ e(_s, {}) },
7709
7781
  { path: "chat", element: /* @__PURE__ */ e(On, {}) },
7710
7782
  { path: "chat/:sessionId", element: /* @__PURE__ */ e(On, {}) },
7711
7783
  // Proposal (Sammelofferte) — a custom builder; the list reuses the generic
@@ -7714,89 +7786,89 @@ const mo = [
7714
7786
  { path: "app/proposal/new", element: /* @__PURE__ */ e(Pn, {}) },
7715
7787
  { path: "app/proposal/:name", element: /* @__PURE__ */ e(Pn, {}) },
7716
7788
  // Documents
7717
- { path: "app/:doctype", element: /* @__PURE__ */ e(zr, {}) },
7718
- { path: "app/:doctype/new", element: /* @__PURE__ */ e(Cn, {}) },
7719
- { path: "app/:doctype/:name", element: /* @__PURE__ */ e(Cn, {}) },
7789
+ { path: "app/:doctype", element: /* @__PURE__ */ e(Mr, {}) },
7790
+ { path: "app/:doctype/new", element: /* @__PURE__ */ e(Sn, {}) },
7791
+ { path: "app/:doctype/:name", element: /* @__PURE__ */ e(Sn, {}) },
7720
7792
  // Masters (reuse same routes - the components detect whether it's a doctype or master)
7721
- { path: "masters/:type", element: /* @__PURE__ */ e($r, {}) },
7793
+ { path: "masters/:type", element: /* @__PURE__ */ e(Ur, {}) },
7722
7794
  { path: "masters/:type/new", element: /* @__PURE__ */ e(Tn, {}) },
7723
7795
  { path: "masters/:type/:name", element: /* @__PURE__ */ e(Tn, {}) },
7724
7796
  // Reports
7725
- { path: "reports/chart-of-accounts", element: /* @__PURE__ */ e(es, {}) },
7726
- { path: "reports/trial-balance", element: /* @__PURE__ */ e(Zr, {}) },
7727
- { path: "reports/general-ledger", element: /* @__PURE__ */ e(as, {}) },
7728
- { path: "reports/stock-balance", element: /* @__PURE__ */ e(rs, {}) },
7729
- { path: "reports/profit-and-loss", element: /* @__PURE__ */ e(ss, {}) },
7730
- { path: "reports/balance-sheet", element: /* @__PURE__ */ e(is, {}) },
7731
- { path: "reports/ar-aging", element: /* @__PURE__ */ e(os, {}) },
7732
- { path: "reports/ap-aging", element: /* @__PURE__ */ e(ls, {}) },
7733
- { path: "reports/analytics", element: /* @__PURE__ */ e(us, {}) },
7797
+ { path: "reports/chart-of-accounts", element: /* @__PURE__ */ e(ts, {}) },
7798
+ { path: "reports/trial-balance", element: /* @__PURE__ */ e(Xr, {}) },
7799
+ { path: "reports/general-ledger", element: /* @__PURE__ */ e(rs, {}) },
7800
+ { path: "reports/stock-balance", element: /* @__PURE__ */ e(ss, {}) },
7801
+ { path: "reports/profit-and-loss", element: /* @__PURE__ */ e(is, {}) },
7802
+ { path: "reports/balance-sheet", element: /* @__PURE__ */ e(os, {}) },
7803
+ { path: "reports/ar-aging", element: /* @__PURE__ */ e(ls, {}) },
7804
+ { path: "reports/ap-aging", element: /* @__PURE__ */ e(cs, {}) },
7805
+ { path: "reports/analytics", element: /* @__PURE__ */ e(ms, {}) },
7734
7806
  // Admin
7735
- { path: "admin/users", element: /* @__PURE__ */ e(Vs, {}) },
7736
- { path: "admin/settings", element: /* @__PURE__ */ e(lo, {}) }
7737
- ], ya = [], ba = [];
7807
+ { path: "admin/users", element: /* @__PURE__ */ e(Ks, {}) },
7808
+ { path: "admin/settings", element: /* @__PURE__ */ e(co, {}) }
7809
+ ], ba = [], va = [];
7738
7810
  function Lo(t, n) {
7739
- (n == null ? void 0 : n.area) === "top" ? ya.push(t) : ba.push(t);
7811
+ (n == null ? void 0 : n.area) === "top" ? ba.push(t) : va.push(t);
7740
7812
  }
7741
- const $n = (t) => t.index ? "__index__" : t.path ?? "";
7742
- function Un(t, n) {
7813
+ const Un = (t) => t.index ? "__index__" : t.path ?? "";
7814
+ function Vn(t, n) {
7743
7815
  const a = [...t];
7744
7816
  for (const s of n) {
7745
- const i = $n(s), o = a.findIndex((l) => $n(l) === i);
7817
+ const i = Un(s), o = a.findIndex((l) => Un(l) === i);
7746
7818
  o >= 0 ? a[o] = s : a.push(s);
7747
7819
  }
7748
7820
  return a;
7749
7821
  }
7750
- function ho() {
7822
+ function go() {
7751
7823
  return [
7752
- ...Un(mo, ya),
7824
+ ...Vn(po, ba),
7753
7825
  {
7754
7826
  path: "/",
7755
- element: /* @__PURE__ */ e(pr, { children: /* @__PURE__ */ e(ur, {}) }),
7756
- children: Un(po, ba)
7827
+ element: /* @__PURE__ */ e(hr, { children: /* @__PURE__ */ e(mr, {}) }),
7828
+ children: Vn(ho, va)
7757
7829
  }
7758
7830
  ];
7759
7831
  }
7760
- function go() {
7761
- return new Sa({
7832
+ function fo() {
7833
+ return new Da({
7762
7834
  defaultOptions: {
7763
7835
  queries: { retry: 1, refetchOnWindowFocus: !1 }
7764
7836
  }
7765
7837
  });
7766
7838
  }
7767
- function Eo(t = {}) {
7839
+ function Oo(t = {}) {
7768
7840
  const n = t.rootElement ?? document.getElementById("root");
7769
7841
  if (!n)
7770
7842
  throw new Error('bootstrap: no mount element (pass rootElement or add <div id="root">)');
7771
- const a = t.queryClient ?? go(), s = Pa(ho());
7772
- ka(n).render(
7773
- /* @__PURE__ */ e(wa, { children: /* @__PURE__ */ e(Ca, { client: a, children: /* @__PURE__ */ e(Xa, { children: /* @__PURE__ */ e(_a, { router: s }) }) }) })
7843
+ const a = t.queryClient ?? fo(), s = _a(go());
7844
+ Sa(n).render(
7845
+ /* @__PURE__ */ e(ka, { children: /* @__PURE__ */ e(Ca, { client: a, children: /* @__PURE__ */ e(er, { children: /* @__PURE__ */ e(Ta, { router: s }) }) }) })
7774
7846
  );
7775
7847
  }
7776
7848
  export {
7777
7849
  $e as ApiError,
7778
- ur as AppShell,
7779
- Xa as AuthProvider,
7780
- pa as SUPPORTED_LANGUAGES,
7850
+ mr as AppShell,
7851
+ er as AuthProvider,
7852
+ ha as SUPPORTED_LANGUAGES,
7781
7853
  I as api,
7782
- Eo as bootstrap,
7783
- ho as buildRoutes,
7784
- Ao as configureApiBase,
7785
- To as configureBranding,
7786
- go as createAppQueryClient,
7787
- Io as getAllDoctypeConfigs,
7788
- rr as getBranding,
7789
- co as getComponent,
7790
- ia as getDoctypeConfig,
7791
- ar as getNavGroups,
7792
- eo as getStoredLanguage,
7793
- zo as i18n,
7794
- Bo as registerComponent,
7795
- Ro as registerDoctype,
7796
- Po as registerNavGroup,
7797
- _o as registerNavItem,
7854
+ Oo as bootstrap,
7855
+ go as buildRoutes,
7856
+ Po as configureApiBase,
7857
+ Ro as configureBranding,
7858
+ fo as createAppQueryClient,
7859
+ Bo as getAllDoctypeConfigs,
7860
+ sr as getBranding,
7861
+ uo as getComponent,
7862
+ oa as getDoctypeConfig,
7863
+ rr as getNavGroups,
7864
+ to as getStoredLanguage,
7865
+ Mo as i18n,
7866
+ Eo as registerComponent,
7867
+ Io as registerDoctype,
7868
+ _o as registerNavGroup,
7869
+ To as registerNavItem,
7798
7870
  Lo as registerRoute,
7799
- E as request,
7871
+ L as request,
7800
7872
  st as useAuth
7801
7873
  };
7802
7874
  //# sourceMappingURL=index.js.map