@fayz-ai/plugin-financial 0.19.0 → 0.19.1
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/components/InstallmentRow.d.ts +42 -0
- package/dist/components/InstallmentRow.d.ts.map +1 -0
- package/dist/components/InstallmentSource.d.ts.map +1 -1
- package/dist/components/InstallmentStatusBadge.d.ts +6 -0
- package/dist/components/InstallmentStatusBadge.d.ts.map +1 -0
- package/dist/components/InvoiceAttachmentsModal.d.ts +12 -0
- package/dist/components/InvoiceAttachmentsModal.d.ts.map +1 -0
- package/dist/components/PaymentFields.d.ts.map +1 -1
- package/dist/components/PaymentIcons.d.ts +12 -0
- package/dist/components/PaymentIcons.d.ts.map +1 -0
- package/dist/components/PaymentReceiptModal.d.ts.map +1 -1
- package/dist/data/supabase.d.ts.map +1 -1
- package/dist/data/types.d.ts +2 -0
- package/dist/data/types.d.ts.map +1 -1
- package/dist/index.js +887 -571
- package/dist/index.js.map +1 -1
- package/dist/lib/settlements.d.ts +6 -0
- package/dist/lib/settlements.d.ts.map +1 -1
- package/dist/locales/en.d.ts.map +1 -1
- package/dist/locales/pt-BR.d.ts.map +1 -1
- package/dist/migrations/index.d.ts +1 -0
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/views/FinancialPage.d.ts.map +1 -1
- package/dist/views/GapScreens.d.ts +0 -2
- package/dist/views/GapScreens.d.ts.map +1 -1
- package/dist/views/InvoiceDetailView.d.ts.map +1 -1
- package/dist/views/InvoiceFormView.d.ts.map +1 -1
- package/dist/views/InvoiceListView.d.ts.map +1 -1
- package/dist/views/cardChip.d.ts +1 -1
- package/dist/views/cardChip.d.ts.map +1 -1
- package/package.json +4 -4
- package/dist/components/AttachmentViewer.d.ts +0 -8
- package/dist/components/AttachmentViewer.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import
|
|
1
|
+
import * as React25 from 'react';
|
|
2
|
+
import React25__default, { useState, useEffect, useMemo, useRef, useCallback } from 'react';
|
|
3
3
|
import { recordRailFields, RECORD_GROUP, activeFacet, createConnectionStore, connectionSettings, connectionStatus, settingsStatus, connectionRuns, registerTranslations, getSupabaseClientOptional, createSafeDataProvider, registerMessageDefaults, reportDataError, useTranslation, createPendingCommand, useUnitMode, useActiveUnitId, useDataChanged, countByTenant, tl, resolveDataProvider, getActiveTenantId, emitDataChanged, exportCSV } from '@fayz-ai/core';
|
|
4
|
-
import { INLINE_LINK_TONE, SearchSelect, ModalTask, toast, Button, useInModalTaskHost, useSaveBar,
|
|
4
|
+
import { INLINE_LINK_TONE, SearchSelect, ModalTask, toast, Button, useInModalTaskHost, useSaveBar, tourAnchor, DatePicker, SubpageHeader, defineKpiWidget, defineChartWidget, defineCustomWidget, defineTableWidget, Modal, ModalContent, ModalHeader, ModalTitle, ModalDescription, ModalBody, DataTable, Card, CardContent, Skeleton, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, MultiSelect, PageTransition, ModulePage, Badge, TooltipProvider, ConfirmDialog, CurrencyInput, Input, PageHeaderActions, Hint, ModalFooter, PageTabs, Tooltip, TooltipTrigger, TooltipContent, Checkbox, Popover, PopoverTrigger, PopoverContent, DashboardCanvas, ComingSoon, StatTiles, ListView, DateRangeControl, FilterPanel, FilterPanelField, SegmentedControl, RequiredFilter, FilterMenuRow, ModalFlow, Switch, WizardSteps, KpiCard, ChartWidget, CardHeader, CardTitle, TableWidget, useDashboardNavigate, GoldCard } from '@fayz-ai/ui';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
|
-
import { createPluginContext, fayzConnectorOAuth, formatCurrency, RightRailPage, createCrudPage, PluginSettingsPanel, dedup, useUnitFilter, useLimitGuard, usePermissionOptional, useLookupCreate, OrderFormSkeleton, OrderFormBlock, OrderFormView, OrderFormItemsCard, OrderFormItemRow, OrderFormAddItemStep, useUnitStore, OrderDetailSkeleton, PageActions, OrderDetailBlock, OrderDetailView, PersonLink, useTenantPluginSettings, useModuleNavigation, usePluginOnboardingGate, useModuleNavAccess, PluginOnboardingGateSkeleton, ModuleActionBar, SettingsGroup, ToggleRow, createArchetypeLookup, invalidateLimit, useAgentSurface, parseViewId, EntitlementGate, UpgradePrompt, useChatStore, adminNavigateTo, revealPage, useAuth, GetStarted, resolveEntityRoute, PermissionGate, createOneShotAsk,
|
|
7
|
-
import { Landmark, CircleDollarSign, FileText, TriangleAlert, Loader2, Check, X, MoreVertical, Ban,
|
|
6
|
+
import { createPluginContext, fayzConnectorOAuth, formatCurrency, RightRailPage, createCrudPage, PluginSettingsPanel, dedup, useUnitFilter, useLimitGuard, usePermissionOptional, useLookupCreate, OrderFormSkeleton, OrderFormBlock, OrderFormView, OrderFormItemsCard, OrderFormItemRow, OrderFormAddItemStep, useUnitStore, OrderDetailSkeleton, PageActions, OrderDetailBlock, OrderDetailView, PersonLink, useTenantPluginSettings, useModuleNavigation, usePluginOnboardingGate, useModuleNavAccess, PluginOnboardingGateSkeleton, ModuleActionBar, SettingsGroup, ToggleRow, createArchetypeLookup, invalidateLimit, useAgentSurface, parseViewId, EntitlementGate, UpgradePrompt, useChatStore, adminNavigateTo, revealPage, useAuth, GetStarted, resolveEntityRoute, PermissionGate, createOneShotAsk, askAI, requestChatUpload, toInlineFile, shrinkForVision } from '@fayz-ai/admin';
|
|
7
|
+
import { Landmark, CircleDollarSign, FileText, TriangleAlert, Loader2, Check, X, MoreVertical, Ban, CircleDashed, CircleAlert, CircleCheckBig, CircleEllipsis, Pencil, Receipt, Gift, Briefcase, Package, CalendarDays, ExternalLink, DollarSign, LayoutList, Layers, Paperclip, Ticket, FileCheck, ArrowRightLeft, CreditCard, QrCode, Banknote, Undo2, Wallet, Plus, AlertTriangle, Filter, TrendingUp, Copy, Trash2, Search, ChevronsUpDown, ChevronsDownUp, ChevronRight, Building2, ChevronDown, Image, UploadCloud, Calendar, User, Unlink, Eye, Inbox, Clock, ClipboardCheck, BookOpen, Info, FolderOpen, Folder, RotateCcw, ArrowLeft, ChevronLeft, Calculator, Square, Play, ChevronUp, Printer, CalendarClock, BadgeCheck, Target, Settings, ArrowRight, Users, RefreshCw, Download, Camera, Sparkles, Link2, FileSearch, CheckCheck, Pause, ShoppingCart, Car, Home, Utensils, Zap, Film, HeartPulse, Dumbbell, Music, ShoppingBag, FileDown, ArrowUpRight, ArrowDownRight, EyeOff } from 'lucide-react';
|
|
8
8
|
import { createPortal } from 'react-dom';
|
|
9
9
|
import { createStore as createStore$1 } from 'zustand/vanilla';
|
|
10
10
|
import { useStore } from 'zustand';
|
|
@@ -105,22 +105,6 @@ function PettyCashView() {
|
|
|
105
105
|
}
|
|
106
106
|
);
|
|
107
107
|
}
|
|
108
|
-
function DigitizeExpenseView() {
|
|
109
|
-
return /* @__PURE__ */ jsx(
|
|
110
|
-
ComingSoon,
|
|
111
|
-
{
|
|
112
|
-
title: "Digitalizar Despesa",
|
|
113
|
-
summary: "Fotografar o boleto ou a nota e deixar a m\xE1quina ler valor, vencimento e fornecedor \u2014 em vez de digitar os quatro campos de novo.",
|
|
114
|
-
v1Path: "Financeiro \u2192 Contas a Pagar \u2192 Digitalizar Despesa",
|
|
115
|
-
measured: "1.436 anexos de conta no V1, 55 da Artorius. A Laissa anexa comprovante 25 vezes por m\xEAs \u2014 mas digita os campos \xE0 m\xE3o todas elas.",
|
|
116
|
-
missing: [
|
|
117
|
-
"Ler o comprovante e PR\xC9-PREENCHER o formul\xE1rio, deixando o usu\xE1rio confirmar \u2014 n\xE3o gravar sozinho",
|
|
118
|
-
"Guardar o arquivo junto do t\xEDtulo, que \xE9 o que a contabilidade pede depois",
|
|
119
|
-
"A Entrada de Notas j\xE1 faz isto para XML de NF-e; aqui \xE9 o mesmo trabalho para o que chega em papel"
|
|
120
|
-
]
|
|
121
|
-
}
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
108
|
function ImportPayrollView() {
|
|
125
109
|
return /* @__PURE__ */ jsx(
|
|
126
110
|
ComingSoon,
|
|
@@ -924,9 +908,9 @@ function startReceiptCapture(labels) {
|
|
|
924
908
|
});
|
|
925
909
|
}
|
|
926
910
|
function ReceiptAgentSurface({ onOpenDraft }) {
|
|
927
|
-
const live =
|
|
911
|
+
const live = React25.useRef(onOpenDraft);
|
|
928
912
|
live.current = onOpenDraft;
|
|
929
|
-
const contribution =
|
|
913
|
+
const contribution = React25.useMemo(() => ({
|
|
930
914
|
id: "financial.payables.receipt",
|
|
931
915
|
pluginId: "financial",
|
|
932
916
|
role: "finance",
|
|
@@ -1277,22 +1261,22 @@ function searchBrBanks(query) {
|
|
|
1277
1261
|
(b) => qd && qd === q && (b.code.startsWith(qd) || b.code.replace(/^0+/, "").startsWith(qd)) || norm(b.name).includes(q) || b.aliases?.some((a) => norm(a).includes(q))
|
|
1278
1262
|
);
|
|
1279
1263
|
}
|
|
1280
|
-
function BankLogo({ bank, size = 20 }) {
|
|
1264
|
+
function BankLogo({ bank, size: size2 = 20 }) {
|
|
1281
1265
|
const [broken, setBroken] = useState(false);
|
|
1282
1266
|
if (!bank?.logo || broken) {
|
|
1283
|
-
return /* @__PURE__ */ jsx(Landmark, { className: "text-muted-foreground", style: { width:
|
|
1267
|
+
return /* @__PURE__ */ jsx(Landmark, { className: "text-muted-foreground", style: { width: size2 * 0.8, height: size2 * 0.8 }, "aria-hidden": true });
|
|
1284
1268
|
}
|
|
1285
1269
|
return /* @__PURE__ */ jsx(
|
|
1286
1270
|
"img",
|
|
1287
1271
|
{
|
|
1288
1272
|
src: bank.logo,
|
|
1289
1273
|
alt: "",
|
|
1290
|
-
width:
|
|
1291
|
-
height:
|
|
1274
|
+
width: size2,
|
|
1275
|
+
height: size2,
|
|
1292
1276
|
loading: "lazy",
|
|
1293
1277
|
onError: () => setBroken(true),
|
|
1294
1278
|
className: "shrink-0 object-contain",
|
|
1295
|
-
style: { width:
|
|
1279
|
+
style: { width: size2, height: size2 }
|
|
1296
1280
|
}
|
|
1297
1281
|
);
|
|
1298
1282
|
}
|
|
@@ -1420,22 +1404,22 @@ function lineFromInvoice(invoice, payee) {
|
|
|
1420
1404
|
var openAmount = (invoice) => Math.max(0, invoice.totalAmount - invoice.paidAmount);
|
|
1421
1405
|
function CnabRemittanceModal({ invoices, bankAccounts, provider, onClose }) {
|
|
1422
1406
|
const { currency } = useFinancialConfig();
|
|
1423
|
-
const [step, setStep] =
|
|
1424
|
-
const [bankAccountId, setBankAccountId] =
|
|
1425
|
-
const [draft, setDraft] =
|
|
1426
|
-
const [context, setContext] =
|
|
1427
|
-
const [companyName, setCompanyName] =
|
|
1428
|
-
const [companyDocument, setCompanyDocument] =
|
|
1429
|
-
const [lines, setLines] =
|
|
1430
|
-
const [companyUnsaved, setCompanyUnsaved] =
|
|
1431
|
-
const [loadingContext, setLoadingContext] =
|
|
1432
|
-
const [busy, setBusy] =
|
|
1433
|
-
const [error, setError] =
|
|
1407
|
+
const [step, setStep] = React25__default.useState(0);
|
|
1408
|
+
const [bankAccountId, setBankAccountId] = React25__default.useState("");
|
|
1409
|
+
const [draft, setDraft] = React25__default.useState(null);
|
|
1410
|
+
const [context, setContext] = React25__default.useState(null);
|
|
1411
|
+
const [companyName, setCompanyName] = React25__default.useState("");
|
|
1412
|
+
const [companyDocument, setCompanyDocument] = React25__default.useState("");
|
|
1413
|
+
const [lines, setLines] = React25__default.useState([]);
|
|
1414
|
+
const [companyUnsaved, setCompanyUnsaved] = React25__default.useState(false);
|
|
1415
|
+
const [loadingContext, setLoadingContext] = React25__default.useState(false);
|
|
1416
|
+
const [busy, setBusy] = React25__default.useState(false);
|
|
1417
|
+
const [error, setError] = React25__default.useState("");
|
|
1434
1418
|
const eligibleAccounts2 = bankAccounts.filter((account2) => account2.accountType === "bank" && account2.isActive);
|
|
1435
1419
|
const total = invoices.reduce((sum, invoice) => sum + openAmount(invoice), 0);
|
|
1436
1420
|
const account = eligibleAccounts2.find((candidate) => candidate.id === bankAccountId);
|
|
1437
1421
|
const missingBankData = draft ? missingFields(draft, companyDocument) : [];
|
|
1438
|
-
const items =
|
|
1422
|
+
const items = React25__default.useMemo(() => lines.map((line) => ({
|
|
1439
1423
|
reference: line.invoice.id,
|
|
1440
1424
|
amount: openAmount(line.invoice),
|
|
1441
1425
|
paymentDate: line.paymentDate,
|
|
@@ -1460,8 +1444,8 @@ function CnabRemittanceModal({ invoices, bankAccounts, provider, onClose }) {
|
|
|
1460
1444
|
postalCode: line.payee.postalCode
|
|
1461
1445
|
}
|
|
1462
1446
|
})), [lines]);
|
|
1463
|
-
const gaps =
|
|
1464
|
-
const batches =
|
|
1447
|
+
const gaps = React25__default.useMemo(() => cnabPayeeGaps(items), [items]);
|
|
1448
|
+
const batches = React25__default.useMemo(() => {
|
|
1465
1449
|
const grouped = /* @__PURE__ */ new Map();
|
|
1466
1450
|
for (const line of lines) {
|
|
1467
1451
|
const current = grouped.get(line.paymentForm) ?? { count: 0, total: 0 };
|
|
@@ -1877,97 +1861,182 @@ function Field({ label, value, onChange, required, placeholder, className = "" }
|
|
|
1877
1861
|
/* @__PURE__ */ jsx("input", { value, onChange: (event) => onChange(event.target.value), placeholder, className: "h-9 w-full rounded-input border bg-background px-3 text-sm outline-none focus:border-primary focus:ring-2 focus:ring-primary/15" })
|
|
1878
1862
|
] });
|
|
1879
1863
|
}
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1864
|
+
var ACCEPT = "image/*,application/pdf";
|
|
1865
|
+
var MAX_BYTES = 15 * 1024 * 1024;
|
|
1866
|
+
function size(bytes) {
|
|
1867
|
+
if (!bytes) return "";
|
|
1868
|
+
return bytes < 1024 * 1024 ? `${Math.max(1, Math.round(bytes / 1024))} KB` : `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
1869
|
+
}
|
|
1870
|
+
function InvoiceAttachmentsModal({ invoiceId, onClose, onChanged }) {
|
|
1871
|
+
const provider = useFinancialProvider();
|
|
1872
|
+
const inputRef = useRef(null);
|
|
1873
|
+
const [items, setItems] = useState(null);
|
|
1874
|
+
const [uploading, setUploading] = useState(0);
|
|
1875
|
+
const [over, setOver] = useState(false);
|
|
1876
|
+
const [preview, setPreview] = useState(null);
|
|
1877
|
+
async function load() {
|
|
1878
|
+
try {
|
|
1879
|
+
setItems(await (provider.getInvoiceAttachments?.(invoiceId) ?? Promise.resolve([])));
|
|
1880
|
+
} catch (e) {
|
|
1881
|
+
setItems([]);
|
|
1882
|
+
toast.error(e?.message ?? String(e));
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
useEffect(() => {
|
|
1886
|
+
void load();
|
|
1887
|
+
}, [invoiceId]);
|
|
1888
|
+
async function upload(files) {
|
|
1889
|
+
const list = Array.from(files);
|
|
1890
|
+
if (!list.length || !provider.addInvoiceAttachment) return;
|
|
1891
|
+
const invalid = list.filter((f) => !(f.type.startsWith("image/") || f.type === "application/pdf") || f.size > MAX_BYTES);
|
|
1892
|
+
if (invalid.length) toast.error("Envie imagem ou PDF de at\xE9 15 MB.");
|
|
1893
|
+
const ok = list.filter((f) => !invalid.includes(f));
|
|
1894
|
+
if (!ok.length) return;
|
|
1895
|
+
setUploading((n) => n + ok.length);
|
|
1896
|
+
for (const file of ok) {
|
|
1897
|
+
try {
|
|
1898
|
+
await provider.addInvoiceAttachment(invoiceId, file);
|
|
1899
|
+
} catch (e) {
|
|
1900
|
+
toast.error(`${file.name}: ${e?.message ?? String(e)}`);
|
|
1901
|
+
} finally {
|
|
1902
|
+
setUploading((n) => n - 1);
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
await load();
|
|
1906
|
+
onChanged?.();
|
|
1907
|
+
}
|
|
1908
|
+
return /* @__PURE__ */ jsx(Modal, { open: true, onOpenChange: (o) => {
|
|
1909
|
+
if (!o) onClose();
|
|
1910
|
+
}, children: /* @__PURE__ */ jsx(ModalContent, { size: preview !== null ? "3xl" : "sm", children: preview !== null && items?.[preview] ? /* @__PURE__ */ jsx(
|
|
1911
|
+
AttachmentPreview,
|
|
1912
|
+
{
|
|
1913
|
+
items,
|
|
1914
|
+
index: preview,
|
|
1915
|
+
onIndex: setPreview,
|
|
1916
|
+
onBack: () => setPreview(null)
|
|
1917
|
+
}
|
|
1918
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1919
|
+
/* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsxs(ModalTitle, { className: "flex items-center gap-2", children: [
|
|
1920
|
+
/* @__PURE__ */ jsx(Paperclip, { className: "h-4 w-4 text-muted-foreground", "aria-hidden": true }),
|
|
1921
|
+
"Anexos da conta"
|
|
1922
|
+
] }) }),
|
|
1923
|
+
/* @__PURE__ */ jsxs(ModalBody, { className: "space-y-3", children: [
|
|
1924
|
+
items === null ? /* @__PURE__ */ jsx("ul", { className: "divide-y rounded-card border", "aria-busy": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-3 px-3 py-2.5", children: [
|
|
1925
|
+
/* @__PURE__ */ jsx("div", { className: "h-4 w-4 shrink-0 animate-pulse rounded bg-muted" }),
|
|
1926
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-1.5", children: [
|
|
1927
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-2/3 animate-pulse rounded bg-muted" }),
|
|
1928
|
+
/* @__PURE__ */ jsx("div", { className: "h-2.5 w-1/3 animate-pulse rounded bg-muted" })
|
|
1929
|
+
] })
|
|
1930
|
+
] }, i)) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-card bg-muted/40 px-4 py-5 text-center", children: [
|
|
1931
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Nenhum anexo ainda" }),
|
|
1932
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: "Guarde aqui o boleto, a nota ou o comprovante de pagamento \u2014 fica tudo junto da conta." })
|
|
1933
|
+
] }) : /* @__PURE__ */ jsx("ul", { className: "divide-y rounded-card border", children: items.map((a, i) => {
|
|
1934
|
+
const Icon = (a.mimeType ?? "").startsWith("image/") ? Image : FileText;
|
|
1935
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
|
|
1936
|
+
"button",
|
|
1898
1937
|
{
|
|
1899
|
-
|
|
1900
|
-
onClick: (
|
|
1938
|
+
type: "button",
|
|
1939
|
+
onClick: () => setPreview(i),
|
|
1940
|
+
className: "flex w-full items-center gap-3 px-3 py-2 text-left transition-colors hover:bg-muted/40",
|
|
1901
1941
|
children: [
|
|
1902
|
-
/* @__PURE__ */
|
|
1903
|
-
|
|
1904
|
-
/* @__PURE__ */
|
|
1905
|
-
|
|
1906
|
-
/* @__PURE__ */ jsxs("p", { className: "text-[11px] opacity-60", children: [
|
|
1907
|
-
attachments.length > 1 ? `${index + 1} de ${attachments.length}` : null,
|
|
1908
|
-
doc.fileSize ? `${attachments.length > 1 ? " \xB7 " : ""}${Math.round(doc.fileSize / 1024)} KB` : null
|
|
1909
|
-
] })
|
|
1910
|
-
] }),
|
|
1911
|
-
doc.url ? /* @__PURE__ */ jsxs(
|
|
1912
|
-
"a",
|
|
1913
|
-
{
|
|
1914
|
-
href: doc.url,
|
|
1915
|
-
target: "_blank",
|
|
1916
|
-
rel: "noreferrer",
|
|
1917
|
-
className: "inline-flex shrink-0 items-center gap-1 rounded-lg border border-white/20 px-2.5 py-1.5 text-xs font-medium text-white hover:bg-white/10",
|
|
1918
|
-
children: [
|
|
1919
|
-
/* @__PURE__ */ jsx(ExternalLink, { className: "h-3.5 w-3.5", "aria-hidden": true }),
|
|
1920
|
-
" Abrir"
|
|
1921
|
-
]
|
|
1922
|
-
}
|
|
1923
|
-
) : null,
|
|
1924
|
-
/* @__PURE__ */ jsx(
|
|
1925
|
-
"button",
|
|
1926
|
-
{
|
|
1927
|
-
type: "button",
|
|
1928
|
-
onClick: () => onClose(),
|
|
1929
|
-
"aria-label": "Fechar",
|
|
1930
|
-
className: "shrink-0 rounded-lg border border-white/20 px-2.5 py-1.5 text-xs font-medium text-white hover:bg-white/10",
|
|
1931
|
-
children: "Fechar"
|
|
1932
|
-
}
|
|
1933
|
-
)
|
|
1942
|
+
/* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 shrink-0 text-muted-foreground", "aria-hidden": true }),
|
|
1943
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1944
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm", children: a.fileName }),
|
|
1945
|
+
/* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: a.pending ? "Arquivo ainda n\xE3o dispon\xEDvel" : [size(a.fileSize), a.createdAt?.slice(0, 10).split("-").reverse().join("/")].filter(Boolean).join(" \xB7 ") })
|
|
1934
1946
|
] }),
|
|
1935
|
-
/* @__PURE__ */ jsx(
|
|
1936
|
-
"O registro deste anexo atravessou, o arquivo ainda n\xE3o. Ele continua no V1 \u2014 procure por ",
|
|
1937
|
-
/* @__PURE__ */ jsx("span", { className: "font-mono text-xs", children: doc.fileName }),
|
|
1938
|
-
"."
|
|
1939
|
-
] }) : ehImagem ? /* @__PURE__ */ jsx("img", { src: doc.url, alt: doc.fileName, className: "max-h-full max-w-full object-contain" }) : ehPdf ? /* @__PURE__ */ jsx("iframe", { src: doc.url, title: doc.fileName, className: "h-full w-full rounded-xl bg-white" }) : /* @__PURE__ */ jsxs("p", { className: "p-8 text-center text-sm text-white/70", children: [
|
|
1940
|
-
"Este tipo de arquivo n\xE3o tem pr\xE9-visualiza\xE7\xE3o. Use ",
|
|
1941
|
-
/* @__PURE__ */ jsx("strong", { children: "Abrir" }),
|
|
1942
|
-
"."
|
|
1943
|
-
] }) }),
|
|
1944
|
-
attachments.length > 1 && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2", children: [
|
|
1945
|
-
/* @__PURE__ */ jsx(
|
|
1946
|
-
"button",
|
|
1947
|
-
{
|
|
1948
|
-
type: "button",
|
|
1949
|
-
onClick: () => irPara(-1),
|
|
1950
|
-
className: "rounded-lg border border-white/20 px-3 py-1.5 text-xs font-medium text-white hover:bg-white/10",
|
|
1951
|
-
children: "Anterior"
|
|
1952
|
-
}
|
|
1953
|
-
),
|
|
1954
|
-
/* @__PURE__ */ jsx(
|
|
1955
|
-
"button",
|
|
1956
|
-
{
|
|
1957
|
-
type: "button",
|
|
1958
|
-
onClick: () => irPara(1),
|
|
1959
|
-
className: "rounded-lg border border-white/20 px-3 py-1.5 text-xs font-medium text-white hover:bg-white/10",
|
|
1960
|
-
children: "Pr\xF3ximo"
|
|
1961
|
-
}
|
|
1962
|
-
)
|
|
1963
|
-
] })
|
|
1947
|
+
/* @__PURE__ */ jsx(ChevronRight, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": true })
|
|
1964
1948
|
]
|
|
1965
1949
|
}
|
|
1966
|
-
)
|
|
1967
|
-
}
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1950
|
+
) }, a.id);
|
|
1951
|
+
}) }),
|
|
1952
|
+
provider.addInvoiceAttachment && /* @__PURE__ */ jsxs(
|
|
1953
|
+
"button",
|
|
1954
|
+
{
|
|
1955
|
+
type: "button",
|
|
1956
|
+
onClick: () => inputRef.current?.click(),
|
|
1957
|
+
onDragOver: (e) => {
|
|
1958
|
+
e.preventDefault();
|
|
1959
|
+
setOver(true);
|
|
1960
|
+
},
|
|
1961
|
+
onDragLeave: () => setOver(false),
|
|
1962
|
+
onDrop: (e) => {
|
|
1963
|
+
e.preventDefault();
|
|
1964
|
+
setOver(false);
|
|
1965
|
+
void upload(e.dataTransfer.files);
|
|
1966
|
+
},
|
|
1967
|
+
disabled: uploading > 0,
|
|
1968
|
+
className: `flex w-full flex-col items-center gap-1 rounded-card border-2 border-dashed px-4 py-5 text-center transition-colors ${over ? "border-primary bg-primary/5" : "border-border hover:bg-muted/40"}`,
|
|
1969
|
+
children: [
|
|
1970
|
+
uploading > 0 ? /* @__PURE__ */ jsx(Loader2, { className: "h-5 w-5 animate-spin text-muted-foreground" }) : /* @__PURE__ */ jsx(UploadCloud, { className: "h-5 w-5 text-muted-foreground", "aria-hidden": true }),
|
|
1971
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: uploading > 0 ? "Enviando\u2026" : "Solte arquivos aqui ou clique para escolher" }),
|
|
1972
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] text-muted-foreground", children: "Imagem ou PDF, at\xE9 15 MB" })
|
|
1973
|
+
]
|
|
1974
|
+
}
|
|
1975
|
+
),
|
|
1976
|
+
/* @__PURE__ */ jsx(
|
|
1977
|
+
"input",
|
|
1978
|
+
{
|
|
1979
|
+
ref: inputRef,
|
|
1980
|
+
type: "file",
|
|
1981
|
+
accept: ACCEPT,
|
|
1982
|
+
multiple: true,
|
|
1983
|
+
className: "hidden",
|
|
1984
|
+
onChange: (e) => {
|
|
1985
|
+
const f = e.target.files;
|
|
1986
|
+
if (f) void upload(f);
|
|
1987
|
+
e.target.value = "";
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
)
|
|
1991
|
+
] })
|
|
1992
|
+
] }) }) });
|
|
1993
|
+
}
|
|
1994
|
+
function AttachmentPreview({ items, index, onIndex, onBack }) {
|
|
1995
|
+
const doc = items[index];
|
|
1996
|
+
const isImage = (doc.mimeType ?? "").startsWith("image/");
|
|
1997
|
+
const isPdf = doc.mimeType === "application/pdf";
|
|
1998
|
+
const go = (d) => onIndex((index + d + items.length) % items.length);
|
|
1999
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2000
|
+
/* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pr-8", children: [
|
|
2001
|
+
/* @__PURE__ */ jsxs(
|
|
2002
|
+
"button",
|
|
2003
|
+
{
|
|
2004
|
+
type: "button",
|
|
2005
|
+
onClick: onBack,
|
|
2006
|
+
className: "inline-flex shrink-0 items-center gap-1 rounded-md px-1.5 py-1 text-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
2007
|
+
children: [
|
|
2008
|
+
/* @__PURE__ */ jsx(ArrowLeft, { className: "h-4 w-4", "aria-hidden": true }),
|
|
2009
|
+
" Voltar"
|
|
2010
|
+
]
|
|
2011
|
+
}
|
|
2012
|
+
),
|
|
2013
|
+
/* @__PURE__ */ jsx(ModalTitle, { className: "min-w-0 flex-1 truncate text-sm font-medium", title: doc.fileName, children: doc.fileName }),
|
|
2014
|
+
items.length > 1 && /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2015
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => go(-1), "aria-label": "Anterior", className: "rounded-md p-1 hover:bg-muted", children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" }) }),
|
|
2016
|
+
index + 1,
|
|
2017
|
+
" de ",
|
|
2018
|
+
items.length,
|
|
2019
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => go(1), "aria-label": "Pr\xF3ximo", className: "rounded-md p-1 hover:bg-muted", children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" }) })
|
|
2020
|
+
] }),
|
|
2021
|
+
doc.url && /* @__PURE__ */ jsx(
|
|
2022
|
+
"a",
|
|
2023
|
+
{
|
|
2024
|
+
href: doc.url,
|
|
2025
|
+
target: "_blank",
|
|
2026
|
+
rel: "noreferrer",
|
|
2027
|
+
"aria-label": "Abrir em nova aba",
|
|
2028
|
+
className: "shrink-0 rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
2029
|
+
children: /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4" })
|
|
2030
|
+
}
|
|
2031
|
+
)
|
|
2032
|
+
] }) }),
|
|
2033
|
+
/* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsx("div", { className: "flex h-[65vh] items-center justify-center overflow-hidden rounded-card bg-muted/40", children: doc.pending || !doc.url ? /* @__PURE__ */ jsxs("p", { className: "max-w-sm p-8 text-center text-sm text-muted-foreground", children: [
|
|
2034
|
+
"O registro deste anexo atravessou, o arquivo ainda n\xE3o. Ele continua no V1 \u2014 procure por",
|
|
2035
|
+
" ",
|
|
2036
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono text-xs", children: doc.fileName }),
|
|
2037
|
+
"."
|
|
2038
|
+
] }) : isImage ? /* @__PURE__ */ jsx("img", { src: doc.url, alt: doc.fileName, className: "max-h-full max-w-full object-contain" }) : isPdf ? /* @__PURE__ */ jsx("iframe", { src: doc.url, title: doc.fileName, className: "h-full w-full bg-white" }) : /* @__PURE__ */ jsx("p", { className: "p-8 text-center text-sm text-muted-foreground", children: "Este tipo de arquivo n\xE3o tem pr\xE9-visualiza\xE7\xE3o. Use o bot\xE3o de abrir." }) }) })
|
|
2039
|
+
] });
|
|
1971
2040
|
}
|
|
1972
2041
|
var KIND_LABELS = {
|
|
1973
2042
|
supplier: "Fornecedor",
|
|
@@ -1994,7 +2063,7 @@ function FinancialCounterpartySearchSelect({
|
|
|
1994
2063
|
onEdit,
|
|
1995
2064
|
disabled
|
|
1996
2065
|
}) {
|
|
1997
|
-
const search =
|
|
2066
|
+
const search = React25.useCallback(async (query) => {
|
|
1998
2067
|
const results = await lookup.search(query);
|
|
1999
2068
|
return results.map((result) => ({
|
|
2000
2069
|
id: result.id,
|
|
@@ -2197,7 +2266,7 @@ function useInvoiceColumns(currency, paymentMethods2, paymentMethodTypes, bankAc
|
|
|
2197
2266
|
},
|
|
2198
2267
|
children: [
|
|
2199
2268
|
/* @__PURE__ */ jsx(Paperclip, { className: "h-4 w-4", "aria-hidden": true }),
|
|
2200
|
-
n >
|
|
2269
|
+
n > 0 && /* @__PURE__ */ jsx("span", { className: "absolute -right-0.5 -top-0.5 flex h-4 min-w-4 items-center justify-center rounded-full bg-primary px-1 text-[10px] font-semibold leading-none text-primary-foreground tabular-nums", children: n })
|
|
2201
2270
|
]
|
|
2202
2271
|
}
|
|
2203
2272
|
) });
|
|
@@ -2345,13 +2414,8 @@ function InvoiceListView({ direction, onNew, onNewReceipt, onEdit }) {
|
|
|
2345
2414
|
}).finally(() => setConsolidating(null));
|
|
2346
2415
|
}, [provider, t2, fetchInvoices, query, onEdit]);
|
|
2347
2416
|
const filtered = invoices.filter((inv) => inv.direction === direction);
|
|
2348
|
-
const [
|
|
2349
|
-
const openAttachments = useCallback((invoiceId) =>
|
|
2350
|
-
if (!provider.getInvoiceAttachments) return;
|
|
2351
|
-
provider.getInvoiceAttachments(invoiceId).then((attachments) => {
|
|
2352
|
-
if (attachments.length) setViewer({ attachments, index: 0 });
|
|
2353
|
-
}).catch(() => toast.error("N\xE3o foi poss\xEDvel abrir os anexos"));
|
|
2354
|
-
}, [provider]);
|
|
2417
|
+
const [attachmentsOf, setAttachmentsOf] = useState(null);
|
|
2418
|
+
const openAttachments = useCallback((invoiceId) => setAttachmentsOf(invoiceId), []);
|
|
2355
2419
|
const columns = useInvoiceColumns(currency, paymentMethods2, paymentMethodTypes, bankAccounts, consolidar, consolidating, openAttachments);
|
|
2356
2420
|
const contactLookup = useMemo(() => createFinancialCounterpartyLookup(direction), [direction]);
|
|
2357
2421
|
const tags = useMemo(
|
|
@@ -2695,7 +2759,9 @@ function InvoiceListView({ direction, onNew, onNewReceipt, onEdit }) {
|
|
|
2695
2759
|
},
|
|
2696
2760
|
...onNewReceiptGated ? [{
|
|
2697
2761
|
id: "receipt",
|
|
2698
|
-
|
|
2762
|
+
// Same flow for payables and receivables: the photo is the request and
|
|
2763
|
+
// the assistant returns the form filled in.
|
|
2764
|
+
label: t2(direction === "debit" ? "financial.quickTx.digitizeExpense" : "financial.quickTx.digitizeReceipt"),
|
|
2699
2765
|
description: t2("financial.quickTx.receiptCapture"),
|
|
2700
2766
|
icon: Camera,
|
|
2701
2767
|
intent: "secondary",
|
|
@@ -2705,10 +2771,20 @@ function InvoiceListView({ direction, onNew, onNewReceipt, onEdit }) {
|
|
|
2705
2771
|
// preenchido. Ver receipt-agent.ts.
|
|
2706
2772
|
onSelect: () => startReceiptCapture({
|
|
2707
2773
|
ask: t2("financial.receipt.ask"),
|
|
2708
|
-
uploadLabel: t2("financial.quickTx.
|
|
2774
|
+
uploadLabel: t2(direction === "debit" ? "financial.quickTx.digitizeExpense" : "financial.quickTx.digitizeReceipt"),
|
|
2709
2775
|
uploadHint: t2("financial.quickTx.receiptCapture"),
|
|
2710
2776
|
prompt: t2("financial.receipt.prompt")
|
|
2711
2777
|
})
|
|
2778
|
+
}] : [],
|
|
2779
|
+
...direction === "debit" ? [{
|
|
2780
|
+
id: "payroll",
|
|
2781
|
+
label: t2("financial.invoice.importPayroll"),
|
|
2782
|
+
description: t2("financial.invoice.importPayrollSoon"),
|
|
2783
|
+
icon: Users,
|
|
2784
|
+
intent: "secondary",
|
|
2785
|
+
disabled: true,
|
|
2786
|
+
onSelect: () => {
|
|
2787
|
+
}
|
|
2712
2788
|
}] : []
|
|
2713
2789
|
] : [];
|
|
2714
2790
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
@@ -2738,13 +2814,14 @@ function InvoiceListView({ direction, onNew, onNewReceipt, onEdit }) {
|
|
|
2738
2814
|
onEmptyAction: onNewGated
|
|
2739
2815
|
}
|
|
2740
2816
|
),
|
|
2741
|
-
|
|
2742
|
-
|
|
2817
|
+
attachmentsOf && /* @__PURE__ */ jsx(
|
|
2818
|
+
InvoiceAttachmentsModal,
|
|
2743
2819
|
{
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2820
|
+
invoiceId: attachmentsOf,
|
|
2821
|
+
onClose: () => setAttachmentsOf(null),
|
|
2822
|
+
onChanged: () => {
|
|
2823
|
+
void fetchInvoices(query);
|
|
2824
|
+
}
|
|
2748
2825
|
}
|
|
2749
2826
|
),
|
|
2750
2827
|
filtered.length > 0 && !invoicesLoading && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-6 rounded-lg border bg-muted/30 px-5 py-3 text-sm", children: [
|
|
@@ -3825,9 +3902,9 @@ var SUBMIT_DRAFT = {
|
|
|
3825
3902
|
parameters: { type: "object", properties: {} }
|
|
3826
3903
|
};
|
|
3827
3904
|
function PayableDraftSurface({ config, draft }) {
|
|
3828
|
-
const live =
|
|
3905
|
+
const live = React25.useRef(draft);
|
|
3829
3906
|
live.current = draft;
|
|
3830
|
-
const lookup =
|
|
3907
|
+
const lookup = React25.useMemo(
|
|
3831
3908
|
() => config.contactLookup ?? createArchetypeLookup({
|
|
3832
3909
|
archetype: "person",
|
|
3833
3910
|
kind: "supplier",
|
|
@@ -3836,7 +3913,7 @@ function PayableDraftSurface({ config, draft }) {
|
|
|
3836
3913
|
}),
|
|
3837
3914
|
[config.contactLookup]
|
|
3838
3915
|
);
|
|
3839
|
-
|
|
3916
|
+
React25.useEffect(() => {
|
|
3840
3917
|
liveDraft = {
|
|
3841
3918
|
describe: () => live.current.describe(),
|
|
3842
3919
|
setSupplier: (name, id) => live.current.setSupplier(name, id),
|
|
@@ -3847,7 +3924,7 @@ function PayableDraftSurface({ config, draft }) {
|
|
|
3847
3924
|
liveDraft = null;
|
|
3848
3925
|
};
|
|
3849
3926
|
}, []);
|
|
3850
|
-
const contribution =
|
|
3927
|
+
const contribution = React25.useMemo(() => ({
|
|
3851
3928
|
id: "financial.payables.draft",
|
|
3852
3929
|
pluginId: "financial",
|
|
3853
3930
|
role: "finance",
|
|
@@ -3922,7 +3999,7 @@ function PayableDraftSurface({ config, draft }) {
|
|
|
3922
3999
|
}
|
|
3923
4000
|
function createFinancialAgentMount(deps) {
|
|
3924
4001
|
const FinancialAgentMount = () => {
|
|
3925
|
-
const contribution =
|
|
4002
|
+
const contribution = React25.useMemo(() => ({
|
|
3926
4003
|
id: "financial.payables.global",
|
|
3927
4004
|
pluginId: "financial",
|
|
3928
4005
|
role: "finance",
|
|
@@ -4017,13 +4094,24 @@ function CardVisual({
|
|
|
4017
4094
|
lastFour: lastFour2,
|
|
4018
4095
|
color,
|
|
4019
4096
|
brandId,
|
|
4020
|
-
size = "sm"
|
|
4097
|
+
size: size2 = "sm"
|
|
4021
4098
|
}) {
|
|
4022
4099
|
const brand = useBrandName(brandId);
|
|
4023
4100
|
const last = (lastFour2 ?? "").trim();
|
|
4024
4101
|
if (!last && !color && !brand) return null;
|
|
4025
4102
|
const bg = color && /^#[0-9a-fA-F]{6}$/.test(color) ? color : void 0;
|
|
4026
|
-
const lg =
|
|
4103
|
+
const lg = size2 === "lg";
|
|
4104
|
+
if (size2 === "xs") {
|
|
4105
|
+
return /* @__PURE__ */ jsx(
|
|
4106
|
+
"span",
|
|
4107
|
+
{
|
|
4108
|
+
className: "inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-[3px] border align-middle text-[6px] font-semibold leading-none tabular-nums",
|
|
4109
|
+
style: bg ? { backgroundColor: bg, color: ink(bg), borderColor: "transparent" } : void 0,
|
|
4110
|
+
title: [brand, last && `\u2022\u2022\u2022\u2022 ${last}`].filter(Boolean).join(" "),
|
|
4111
|
+
children: last
|
|
4112
|
+
}
|
|
4113
|
+
);
|
|
4114
|
+
}
|
|
4027
4115
|
return /* @__PURE__ */ jsxs(
|
|
4028
4116
|
"span",
|
|
4029
4117
|
{
|
|
@@ -4093,7 +4181,9 @@ function eligibleAccountsFor(bankAccounts, direction, type) {
|
|
|
4093
4181
|
const active = bankAccounts.filter((a) => a.isActive !== false);
|
|
4094
4182
|
if (direction === "debit") {
|
|
4095
4183
|
if (txType === "credit_card") return active.filter((a) => a.accountType === "card_payable");
|
|
4096
|
-
|
|
4184
|
+
const own = (type?.allowedAccountTypes?.length ? type.allowedAccountTypes : ACCOUNT_TYPES_FOR_TX2[txType])?.filter((k) => !k.startsWith("card_"));
|
|
4185
|
+
const kinds = own?.length ? own : ["bank", "cash_physical", "cash_session"];
|
|
4186
|
+
return active.filter((a) => kinds.includes(a.accountType));
|
|
4097
4187
|
}
|
|
4098
4188
|
const allowed = type?.allowedAccountTypes && type.allowedAccountTypes.length ? type.allowedAccountTypes : ACCOUNT_TYPES_FOR_TX2[txType];
|
|
4099
4189
|
if (!allowed || !allowed.length) return bankAccounts;
|
|
@@ -4415,10 +4505,10 @@ function PaymentModal({ movement, receiptUrl, onClose, onPaid }) {
|
|
|
4415
4505
|
const payMovement = useFinancialStore((s) => s.payMovement);
|
|
4416
4506
|
const remaining = movement.amount - movement.paidAmount;
|
|
4417
4507
|
const [saving, setSaving] = useState(false);
|
|
4418
|
-
const command =
|
|
4508
|
+
const command = React25__default.useRef(createPendingCommand(() => createIdempotencyKey("financial:payment"), (input) => input.movementId));
|
|
4419
4509
|
const [pending2, setPending] = useState(false);
|
|
4420
4510
|
const [visible, setVisible] = useState(false);
|
|
4421
|
-
|
|
4511
|
+
React25__default.useEffect(() => {
|
|
4422
4512
|
requestAnimationFrame(() => setVisible(true));
|
|
4423
4513
|
}, []);
|
|
4424
4514
|
const source = movement.metadata ?? {};
|
|
@@ -4537,6 +4627,32 @@ function PaymentModal({ movement, receiptUrl, onClose, onPaid }) {
|
|
|
4537
4627
|
document.body
|
|
4538
4628
|
);
|
|
4539
4629
|
}
|
|
4630
|
+
var METHOD_ICONS = {
|
|
4631
|
+
cash: Banknote,
|
|
4632
|
+
pix: QrCode,
|
|
4633
|
+
credit_card: CreditCard,
|
|
4634
|
+
debit_card: CreditCard,
|
|
4635
|
+
bank_transfer: ArrowRightLeft,
|
|
4636
|
+
check: FileCheck,
|
|
4637
|
+
boleto: Receipt,
|
|
4638
|
+
voucher: Ticket
|
|
4639
|
+
};
|
|
4640
|
+
function MethodIcon({ type }) {
|
|
4641
|
+
const Icon = METHOD_ICONS[type?.transactionType ?? ""] ?? Wallet;
|
|
4642
|
+
return /* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": true });
|
|
4643
|
+
}
|
|
4644
|
+
function AccountIcon({ account }) {
|
|
4645
|
+
if (!account) return null;
|
|
4646
|
+
if (account.accountType === "card_payable" && (account.lastFour || account.color || account.cardBrandId)) {
|
|
4647
|
+
return /* @__PURE__ */ jsx(CardVisual, { size: "xs", lastFour: account.lastFour ?? void 0, color: account.color ?? void 0, brandId: account.cardBrandId ?? void 0 });
|
|
4648
|
+
}
|
|
4649
|
+
if (account.accountType.startsWith("card_")) return /* @__PURE__ */ jsx(CreditCard, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": true });
|
|
4650
|
+
if (account.accountType === "cash_physical" || account.accountType === "cash_session") {
|
|
4651
|
+
return /* @__PURE__ */ jsx(Banknote, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": true });
|
|
4652
|
+
}
|
|
4653
|
+
const bank = findBrBank(account.bankCode, account.bankName ?? account.name);
|
|
4654
|
+
return bank?.logo ? /* @__PURE__ */ jsx(BankLogo, { bank, size: 16 }) : /* @__PURE__ */ jsx(Landmark, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": true });
|
|
4655
|
+
}
|
|
4540
4656
|
var NONE = "__none__";
|
|
4541
4657
|
var TRIGGER_CLASS = `h-auto w-auto justify-start gap-1 rounded-none border-0 bg-transparent p-0 text-xs font-normal shadow-none ring-offset-0 focus:ring-0 focus:ring-offset-0 [&>svg]:h-3 [&>svg]:w-3 ${INLINE_LINK_TONE.dashed}`;
|
|
4542
4658
|
function InstallmentSourceFields({
|
|
@@ -4559,7 +4675,7 @@ function InstallmentSourceFields({
|
|
|
4559
4675
|
onChange({ payMethodTypeId: typeId || void 0, payAccountId: typeId ? conta : void 0 });
|
|
4560
4676
|
}
|
|
4561
4677
|
const tone = (filled) => filled ? "text-foreground" : "text-destructive border-b border-dashed border-destructive";
|
|
4562
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-
|
|
4678
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-col items-start gap-0.5", children: [
|
|
4563
4679
|
/* @__PURE__ */ jsxs(
|
|
4564
4680
|
Select,
|
|
4565
4681
|
{
|
|
@@ -4576,37 +4692,202 @@ function InstallmentSourceFields({
|
|
|
4576
4692
|
}
|
|
4577
4693
|
),
|
|
4578
4694
|
/* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
4579
|
-
paymentMethodTypes.map((tp) => /* @__PURE__ */ jsx(SelectItem, { value: tp.id, children:
|
|
4695
|
+
paymentMethodTypes.map((tp) => /* @__PURE__ */ jsx(SelectItem, { value: tp.id, children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
|
|
4696
|
+
/* @__PURE__ */ jsx(MethodIcon, { type: tp }),
|
|
4697
|
+
tp.name
|
|
4698
|
+
] }) }, tp.id)),
|
|
4580
4699
|
value.payMethodTypeId && /* @__PURE__ */ jsx(SelectItem, { value: NONE, className: "text-muted-foreground", children: t2("financial.invoiceForm.clear") })
|
|
4581
4700
|
] })
|
|
4582
4701
|
]
|
|
4583
4702
|
}
|
|
4584
4703
|
),
|
|
4585
|
-
/* @__PURE__ */
|
|
4586
|
-
|
|
4704
|
+
/* @__PURE__ */ jsx(
|
|
4705
|
+
AccountPicker,
|
|
4587
4706
|
{
|
|
4588
|
-
|
|
4707
|
+
accounts,
|
|
4708
|
+
value: value.payAccountId,
|
|
4589
4709
|
disabled: disabled || !value.payMethodTypeId,
|
|
4590
|
-
|
|
4710
|
+
title: value.payMethodTypeId ? void 0 : t2("financial.invoiceForm.selectMethodFirst"),
|
|
4711
|
+
placeholder: t2("financial.payment.account"),
|
|
4712
|
+
ariaLabel: t2("financial.invoiceForm.paidFrom"),
|
|
4713
|
+
clearLabel: t2("financial.invoiceForm.clear"),
|
|
4714
|
+
className: `${INLINE_LINK_TONE.dashed} ${tone(!!selectedAccount)}`,
|
|
4715
|
+
onChange: (id) => onChange({ ...value, payAccountId: id })
|
|
4716
|
+
}
|
|
4717
|
+
)
|
|
4718
|
+
] });
|
|
4719
|
+
}
|
|
4720
|
+
var norm2 = (v) => v.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
|
|
4721
|
+
function AccountPicker({ accounts, value, onChange, disabled, title, placeholder, ariaLabel, clearLabel, className }) {
|
|
4722
|
+
const [open, setOpen] = React25__default.useState(false);
|
|
4723
|
+
const [q, setQ] = React25__default.useState("");
|
|
4724
|
+
const selected = accounts.find((a) => a.id === value);
|
|
4725
|
+
const list = q ? accounts.filter((a) => norm2(a.name).includes(norm2(q))) : accounts;
|
|
4726
|
+
const pick = (id) => {
|
|
4727
|
+
onChange(id);
|
|
4728
|
+
setOpen(false);
|
|
4729
|
+
setQ("");
|
|
4730
|
+
};
|
|
4731
|
+
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: (o) => {
|
|
4732
|
+
setOpen(o);
|
|
4733
|
+
if (!o) setQ("");
|
|
4734
|
+
}, children: [
|
|
4735
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
4736
|
+
"button",
|
|
4737
|
+
{
|
|
4738
|
+
type: "button",
|
|
4739
|
+
disabled,
|
|
4740
|
+
title,
|
|
4741
|
+
"aria-label": ariaLabel,
|
|
4742
|
+
className: `inline-flex max-w-full items-center gap-1 text-xs disabled:cursor-not-allowed disabled:opacity-50 ${className ?? ""}`,
|
|
4591
4743
|
children: [
|
|
4592
|
-
/* @__PURE__ */
|
|
4593
|
-
|
|
4594
|
-
{
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
className: `${TRIGGER_CLASS} ${tone(!!selectedAccount)}`,
|
|
4598
|
-
children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t2("financial.payment.account") })
|
|
4599
|
-
}
|
|
4600
|
-
),
|
|
4601
|
-
/* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
4602
|
-
accounts.map((a) => /* @__PURE__ */ jsx(SelectItem, { value: a.id, children: a.name }, a.id)),
|
|
4603
|
-
value.payAccountId && /* @__PURE__ */ jsx(SelectItem, { value: NONE, className: "text-muted-foreground", children: t2("financial.invoiceForm.clear") })
|
|
4604
|
-
] })
|
|
4744
|
+
selected ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4745
|
+
/* @__PURE__ */ jsx(AccountIcon, { account: selected }),
|
|
4746
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: selected.name })
|
|
4747
|
+
] }) : placeholder,
|
|
4748
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "h-3 w-3 shrink-0 opacity-50", "aria-hidden": true })
|
|
4605
4749
|
]
|
|
4606
4750
|
}
|
|
4607
|
-
)
|
|
4751
|
+
) }),
|
|
4752
|
+
/* @__PURE__ */ jsxs(PopoverContent, { align: "start", className: "w-64 p-1", children: [
|
|
4753
|
+
/* @__PURE__ */ jsxs("div", { className: "relative mb-1", children: [
|
|
4754
|
+
/* @__PURE__ */ jsx(Search, { className: "pointer-events-none absolute left-2 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground", "aria-hidden": true }),
|
|
4755
|
+
/* @__PURE__ */ jsx(
|
|
4756
|
+
"input",
|
|
4757
|
+
{
|
|
4758
|
+
autoFocus: true,
|
|
4759
|
+
value: q,
|
|
4760
|
+
onChange: (e) => setQ(e.target.value),
|
|
4761
|
+
onKeyDown: (e) => {
|
|
4762
|
+
if (e.key === "Enter" && list[0]) {
|
|
4763
|
+
e.preventDefault();
|
|
4764
|
+
pick(list[0].id);
|
|
4765
|
+
}
|
|
4766
|
+
},
|
|
4767
|
+
placeholder: "Buscar conta\u2026",
|
|
4768
|
+
className: "h-8 w-full rounded-md border-0 bg-muted/50 pl-7 pr-2 text-xs outline-none focus:ring-0"
|
|
4769
|
+
}
|
|
4770
|
+
)
|
|
4771
|
+
] }),
|
|
4772
|
+
/* @__PURE__ */ jsx("div", { className: "max-h-64 overflow-y-auto", children: list.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-2 py-3 text-center text-xs text-muted-foreground", children: "Nenhuma conta encontrada" }) : list.map((a) => /* @__PURE__ */ jsxs(
|
|
4773
|
+
"button",
|
|
4774
|
+
{
|
|
4775
|
+
type: "button",
|
|
4776
|
+
onClick: () => pick(a.id),
|
|
4777
|
+
className: `flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm transition-colors hover:bg-muted ${a.id === value ? "font-medium" : ""}`,
|
|
4778
|
+
children: [
|
|
4779
|
+
/* @__PURE__ */ jsx(AccountIcon, { account: a }),
|
|
4780
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: a.name }),
|
|
4781
|
+
a.id === value && /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": true })
|
|
4782
|
+
]
|
|
4783
|
+
},
|
|
4784
|
+
a.id
|
|
4785
|
+
)) }),
|
|
4786
|
+
value && /* @__PURE__ */ jsx("button", { type: "button", onClick: () => pick(void 0), className: "mt-1 w-full rounded-md px-2 py-1.5 text-left text-xs text-muted-foreground hover:bg-muted", children: clearLabel })
|
|
4787
|
+
] })
|
|
4608
4788
|
] });
|
|
4609
4789
|
}
|
|
4790
|
+
var STATUS = {
|
|
4791
|
+
open: { bg: "bg-info-soft text-info-soft-foreground", icon: CircleDashed, labelKey: "financial.invoice.statusOpen" },
|
|
4792
|
+
pending: { bg: "bg-warning-soft text-warning-soft-foreground", icon: CircleDashed, labelKey: "financial.invoice.statusPending" },
|
|
4793
|
+
partial: { bg: "bg-warning-soft text-warning-soft-foreground", icon: CircleEllipsis, labelKey: "financial.invoice.statusPartial" },
|
|
4794
|
+
paid: { bg: "bg-success-soft text-success-soft-foreground", icon: CircleCheckBig, labelKey: "financial.invoice.statusPaid" },
|
|
4795
|
+
overdue: { bg: "bg-destructive-soft text-destructive-soft-foreground", icon: CircleAlert, labelKey: "financial.invoice.statusOverdue" },
|
|
4796
|
+
draft: { bg: "bg-muted text-muted-foreground", icon: CircleDashed, labelKey: "financial.invoice.statusDraft" },
|
|
4797
|
+
cancelled: { bg: "bg-muted text-muted-foreground", icon: Ban, labelKey: "financial.invoice.statusCancelled" }
|
|
4798
|
+
};
|
|
4799
|
+
function InstallmentStatusBadge({ status }) {
|
|
4800
|
+
const t2 = useTranslation();
|
|
4801
|
+
const s = STATUS[status ?? ""] ?? STATUS.pending;
|
|
4802
|
+
const Icon = s.icon;
|
|
4803
|
+
return /* @__PURE__ */ jsxs("span", { className: `inline-flex shrink-0 items-center gap-0.5 rounded-full px-1.5 py-0.5 text-[9px] font-medium capitalize ${s.bg}`, children: [
|
|
4804
|
+
/* @__PURE__ */ jsx(Icon, { className: "h-2 w-2" }),
|
|
4805
|
+
" ",
|
|
4806
|
+
t2(s.labelKey)
|
|
4807
|
+
] });
|
|
4808
|
+
}
|
|
4809
|
+
function InstallmentRow({
|
|
4810
|
+
number,
|
|
4811
|
+
amount,
|
|
4812
|
+
status,
|
|
4813
|
+
dueDate,
|
|
4814
|
+
onDueDateChange,
|
|
4815
|
+
dueExtra,
|
|
4816
|
+
source,
|
|
4817
|
+
actions,
|
|
4818
|
+
onClick
|
|
4819
|
+
}) {
|
|
4820
|
+
const t2 = useTranslation();
|
|
4821
|
+
const stop = (e) => e.stopPropagation();
|
|
4822
|
+
return /* @__PURE__ */ jsxs(
|
|
4823
|
+
"div",
|
|
4824
|
+
{
|
|
4825
|
+
className: `flex flex-wrap items-center gap-3 px-4 py-3 ${onClick ? "cursor-pointer transition-colors hover:bg-muted/20" : ""}`,
|
|
4826
|
+
onClick,
|
|
4827
|
+
children: [
|
|
4828
|
+
/* @__PURE__ */ jsxs("span", { className: "w-6 shrink-0 text-xs font-medium text-muted-foreground", children: [
|
|
4829
|
+
"#",
|
|
4830
|
+
number
|
|
4831
|
+
] }),
|
|
4832
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col items-start gap-0.5", children: [
|
|
4833
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
4834
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-sm font-medium tabular-nums", children: amount }),
|
|
4835
|
+
status && /* @__PURE__ */ jsx(InstallmentStatusBadge, { status })
|
|
4836
|
+
] }),
|
|
4837
|
+
/* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1 whitespace-nowrap text-[10px] text-muted-foreground", onClick: stop, children: [
|
|
4838
|
+
t2("financial.payment.due"),
|
|
4839
|
+
onDueDateChange ? /* @__PURE__ */ jsx(DatePicker, { value: dueDate, variant: "inline", format: "numeric", onChange: onDueDateChange }) : dueDate,
|
|
4840
|
+
dueExtra
|
|
4841
|
+
] })
|
|
4842
|
+
] }),
|
|
4843
|
+
/* @__PURE__ */ jsx("div", { className: "w-44 shrink-0", onClick: stop, children: source }),
|
|
4844
|
+
(actions || onClick) && /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1.5", onClick: stop, children: [
|
|
4845
|
+
actions,
|
|
4846
|
+
onClick && /* @__PURE__ */ jsx(ChevronRight, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": true })
|
|
4847
|
+
] })
|
|
4848
|
+
]
|
|
4849
|
+
}
|
|
4850
|
+
);
|
|
4851
|
+
}
|
|
4852
|
+
var BTN = "inline-flex shrink-0 items-center gap-1 px-3 py-1.5 text-xs font-medium transition-colors active:shadow-button-inset disabled:pointer-events-none disabled:opacity-40";
|
|
4853
|
+
function InstallmentPayButton({ onClick, disabled, title, children, variant = "primary" }) {
|
|
4854
|
+
return /* @__PURE__ */ jsxs(
|
|
4855
|
+
"button",
|
|
4856
|
+
{
|
|
4857
|
+
type: "button",
|
|
4858
|
+
onClick,
|
|
4859
|
+
disabled,
|
|
4860
|
+
title,
|
|
4861
|
+
className: variant === "primary" ? `${BTN} rounded-button border border-primary bg-primary text-primary-foreground shadow-button-primary hover:bg-primary/90` : `${BTN} rounded-lg border bg-card shadow-button hover:bg-muted`,
|
|
4862
|
+
children: [
|
|
4863
|
+
/* @__PURE__ */ jsx(DollarSign, { className: "h-3 w-3" }),
|
|
4864
|
+
children
|
|
4865
|
+
]
|
|
4866
|
+
}
|
|
4867
|
+
);
|
|
4868
|
+
}
|
|
4869
|
+
function InstallmentActionButton({ onClick, icon: Icon, children }) {
|
|
4870
|
+
return /* @__PURE__ */ jsxs("button", { type: "button", onClick, className: `${BTN} rounded-lg border bg-card shadow-button hover:bg-muted`, children: [
|
|
4871
|
+
/* @__PURE__ */ jsx(Icon, { className: "h-3 w-3" }),
|
|
4872
|
+
children
|
|
4873
|
+
] });
|
|
4874
|
+
}
|
|
4875
|
+
function InstallmentReceiptButton({ onClick, title, attached, pending: pending2, count }) {
|
|
4876
|
+
return /* @__PURE__ */ jsxs(
|
|
4877
|
+
"button",
|
|
4878
|
+
{
|
|
4879
|
+
type: "button",
|
|
4880
|
+
onClick,
|
|
4881
|
+
title,
|
|
4882
|
+
"aria-label": title,
|
|
4883
|
+
className: `inline-flex shrink-0 items-center gap-1 rounded-lg border bg-card px-2.5 py-1.5 text-xs font-medium shadow-button transition-colors hover:bg-muted active:shadow-button-inset ${attached ? "text-success" : pending2 ? "text-primary" : ""}`,
|
|
4884
|
+
children: [
|
|
4885
|
+
/* @__PURE__ */ jsx(Paperclip, { className: "h-3 w-3" }),
|
|
4886
|
+
!!count && /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: count })
|
|
4887
|
+
]
|
|
4888
|
+
}
|
|
4889
|
+
);
|
|
4890
|
+
}
|
|
4610
4891
|
|
|
4611
4892
|
// src/views/focusItem.ts
|
|
4612
4893
|
var CHAVE = "fayz:financial:focus-item";
|
|
@@ -4631,9 +4912,9 @@ function consumirItemParaAbrir(invoiceId) {
|
|
|
4631
4912
|
}
|
|
4632
4913
|
}
|
|
4633
4914
|
function useStockedItemTypes(itemTypes, entityLookups) {
|
|
4634
|
-
const [empty, setEmpty] =
|
|
4915
|
+
const [empty, setEmpty] = React25__default.useState(null);
|
|
4635
4916
|
const backed = itemTypes.filter((type) => entityLookups[type.value]?.count).map((type) => type.value).sort().join(",");
|
|
4636
|
-
|
|
4917
|
+
React25__default.useEffect(() => {
|
|
4637
4918
|
const kinds = backed ? backed.split(",") : [];
|
|
4638
4919
|
if (!kinds.length) {
|
|
4639
4920
|
setEmpty(null);
|
|
@@ -4654,7 +4935,7 @@ function useStockedItemTypes(itemTypes, entityLookups) {
|
|
|
4654
4935
|
cancelled = true;
|
|
4655
4936
|
};
|
|
4656
4937
|
}, [backed]);
|
|
4657
|
-
return
|
|
4938
|
+
return React25__default.useMemo(
|
|
4658
4939
|
() => empty?.size ? itemTypes.filter((type) => !empty.has(type.value)) : itemTypes,
|
|
4659
4940
|
[itemTypes, empty]
|
|
4660
4941
|
);
|
|
@@ -4902,14 +5183,14 @@ function InvoiceFormView({ direction, editId, onSaved, focusReceipt = false, fro
|
|
|
4902
5183
|
};
|
|
4903
5184
|
}, [giftCardsEnabled, provider]);
|
|
4904
5185
|
const entityLookups = useMemo(() => giftCardLookup ? { ...config.entityLookups, gift_card: giftCardLookup } : config.entityLookups, [config.entityLookups, giftCardLookup]);
|
|
4905
|
-
const translatedItemTypes =
|
|
5186
|
+
const translatedItemTypes = React25__default.useMemo(
|
|
4906
5187
|
() => itemTypesRaw.map((tp) => {
|
|
4907
5188
|
const traduzido = t2(`financial.itemType.${tp.value}`);
|
|
4908
5189
|
return traduzido === `financial.itemType.${tp.value}` ? tp : { ...tp, label: traduzido };
|
|
4909
5190
|
}),
|
|
4910
5191
|
[itemTypesRaw, t2]
|
|
4911
5192
|
);
|
|
4912
|
-
const offeredItemTypes =
|
|
5193
|
+
const offeredItemTypes = React25__default.useMemo(
|
|
4913
5194
|
() => availableInvoiceItemTypes(
|
|
4914
5195
|
giftCardsEnabled && !translatedItemTypes.some((type) => type.value === "gift_card") ? [...translatedItemTypes, { value: "gift_card", label: t2("financial.itemType.gift_card"), icon: "Gift" }] : translatedItemTypes,
|
|
4915
5196
|
Object.keys(entityLookups),
|
|
@@ -4930,6 +5211,7 @@ function InvoiceFormView({ direction, editId, onSaved, focusReceipt = false, fro
|
|
|
4930
5211
|
const guardMovements = useLimitGuard("movements_month");
|
|
4931
5212
|
const can = usePermissionOptional();
|
|
4932
5213
|
const isEdit = !!editId;
|
|
5214
|
+
const [attachmentsOpen, setAttachmentsOpen] = useState(false);
|
|
4933
5215
|
useEffect(() => {
|
|
4934
5216
|
void fetchBankAccounts();
|
|
4935
5217
|
void fetchPaymentMethods();
|
|
@@ -5205,13 +5487,13 @@ function InvoiceFormView({ direction, editId, onSaved, focusReceipt = false, fro
|
|
|
5205
5487
|
if (isEdit || totalAmount <= 0 || installments.length > 0) return;
|
|
5206
5488
|
generateInstallments(1);
|
|
5207
5489
|
}, [isEdit, totalAmount, installments.length]);
|
|
5208
|
-
const fromCard =
|
|
5490
|
+
const fromCard = React25__default.useMemo(
|
|
5209
5491
|
() => fromCardId ? bankAccounts.find((a) => a.id === fromCardId) : void 0,
|
|
5210
5492
|
[fromCardId, bankAccounts]
|
|
5211
5493
|
);
|
|
5212
5494
|
const cardLast4 = (fromCard?.accountNumber ?? "").replace(/\D/g, "").slice(-4);
|
|
5213
5495
|
const nomeJaTemOsDigitos = !!cardLast4 && (fromCard?.name ?? "").replace(/\D/g, "").endsWith(cardLast4);
|
|
5214
|
-
const cardMethodName =
|
|
5496
|
+
const cardMethodName = React25__default.useMemo(() => {
|
|
5215
5497
|
const id = installments[0]?.payMethodTypeId;
|
|
5216
5498
|
const escolhida = id ? paymentMethodTypes.find((tp) => tp.id === id) : void 0;
|
|
5217
5499
|
return (escolhida ?? paymentMethodTypes.find((tp) => tp.transactionType === "credit_card"))?.name;
|
|
@@ -5532,7 +5814,6 @@ function InvoiceFormView({ direction, editId, onSaved, focusReceipt = false, fro
|
|
|
5532
5814
|
const saved = savedMovements[i];
|
|
5533
5815
|
const isPaid2 = saved?.status === "paid";
|
|
5534
5816
|
const isPartial = saved?.status === "partial";
|
|
5535
|
-
const StatusIcon = isPaid2 ? CircleCheckBig : CircleDashed;
|
|
5536
5817
|
const canAttach = isEdit ? !!saved && !isPaid2 : true;
|
|
5537
5818
|
const semFonte = Math.abs(inst.amount) < 5e-3 && !isPaid2 && !isPartial;
|
|
5538
5819
|
const fonteTravada = isPaid2 || isPartial;
|
|
@@ -5540,75 +5821,61 @@ function InvoiceFormView({ direction, editId, onSaved, focusReceipt = false, fro
|
|
|
5540
5821
|
const contaEscolhida = bankAccounts.find((a) => a.id === inst.payAccountId);
|
|
5541
5822
|
const faltaParaPagar = !inst.payMethodTypeId ? t2("financial.payment.methodRequired") : !inst.payAccountId ? t2("financial.payment.accountRequired") : null;
|
|
5542
5823
|
return /* @__PURE__ */ jsxs("div", { children: [
|
|
5543
|
-
/* @__PURE__ */
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
i + 1
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs text-muted-foreground", children: "\u2014" })
|
|
5557
|
-
) : fonteTravada ? /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-xs text-muted-foreground", children: [formaEscolhida?.name, contaEscolhida?.name].filter(Boolean).join(" \xB7 ") }) : /* @__PURE__ */ jsx(
|
|
5558
|
-
InstallmentSourceFields,
|
|
5559
|
-
{
|
|
5560
|
-
direction,
|
|
5561
|
-
value: { payMethodTypeId: inst.payMethodTypeId, payAccountId: inst.payAccountId },
|
|
5562
|
-
onChange: (next) => patch(next)
|
|
5563
|
-
}
|
|
5564
|
-
),
|
|
5565
|
-
/* @__PURE__ */ jsxs("div", { className: "ml-auto flex items-center gap-1.5", children: [
|
|
5566
|
-
!hasPayments ? /* @__PURE__ */ jsx(
|
|
5567
|
-
DatePicker,
|
|
5568
|
-
{
|
|
5569
|
-
value: inst.dueDate,
|
|
5570
|
-
variant: "inline",
|
|
5571
|
-
format: "numeric",
|
|
5572
|
-
onChange: (v) => patch({ dueDate: v })
|
|
5573
|
-
}
|
|
5574
|
-
) : /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: inst.dueDate }),
|
|
5575
|
-
canAttach && /* @__PURE__ */ jsx(
|
|
5576
|
-
"button",
|
|
5824
|
+
/* @__PURE__ */ jsx(
|
|
5825
|
+
InstallmentRow,
|
|
5826
|
+
{
|
|
5827
|
+
number: i + 1,
|
|
5828
|
+
amount: money4(inst.amount),
|
|
5829
|
+
status: saved?.status,
|
|
5830
|
+
dueDate: inst.dueDate,
|
|
5831
|
+
onDueDateChange: !hasPayments ? (v) => patch({ dueDate: v }) : void 0,
|
|
5832
|
+
source: semFonte ? (
|
|
5833
|
+
// A zero-value line (gift, 100% discount) has no method to ask for.
|
|
5834
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "\u2014" })
|
|
5835
|
+
) : fonteTravada ? /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-muted-foreground", children: [formaEscolhida?.name, contaEscolhida?.name].filter(Boolean).join(" \xB7 ") }) : /* @__PURE__ */ jsx(
|
|
5836
|
+
InstallmentSourceFields,
|
|
5577
5837
|
{
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
patch({ receiptUrl: pendingReceipt });
|
|
5582
|
-
setPendingReceipt(void 0);
|
|
5583
|
-
return;
|
|
5584
|
-
}
|
|
5585
|
-
setReceiptTarget(i);
|
|
5586
|
-
receiptPicker.open();
|
|
5587
|
-
},
|
|
5588
|
-
title: !inst.receiptUrl && pendingReceipt ? t2("financial.receipt.attachRead") : t2("financial.quickTx.receiptCapture"),
|
|
5589
|
-
"aria-label": !inst.receiptUrl && pendingReceipt ? t2("financial.receipt.attachRead") : t2("financial.quickTx.receiptCapture"),
|
|
5590
|
-
className: `flex h-7 w-7 shrink-0 items-center justify-center rounded-md transition-colors ${inst.receiptUrl ? "text-success hover:bg-success-soft" : pendingReceipt ? "text-primary hover:bg-primary/10" : "text-muted-foreground hover:bg-muted hover:text-foreground"}`,
|
|
5591
|
-
children: inst.receiptUrl ? /* @__PURE__ */ jsx(Paperclip, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(Camera, { className: "h-3.5 w-3.5" })
|
|
5838
|
+
direction,
|
|
5839
|
+
value: { payMethodTypeId: inst.payMethodTypeId, payAccountId: inst.payAccountId },
|
|
5840
|
+
onChange: (next) => patch(next)
|
|
5592
5841
|
}
|
|
5593
5842
|
),
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5843
|
+
actions: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5844
|
+
(canAttach || isEdit) && /* @__PURE__ */ jsx(
|
|
5845
|
+
InstallmentReceiptButton,
|
|
5846
|
+
{
|
|
5847
|
+
attached: !!inst.receiptUrl,
|
|
5848
|
+
pending: !inst.receiptUrl && !!pendingReceipt,
|
|
5849
|
+
title: !inst.receiptUrl && pendingReceipt ? t2("financial.receipt.attachRead") : t2("financial.quickTx.receiptCapture"),
|
|
5850
|
+
onClick: () => {
|
|
5851
|
+
if (isEdit && editId) {
|
|
5852
|
+
setAttachmentsOpen(true);
|
|
5853
|
+
return;
|
|
5854
|
+
}
|
|
5855
|
+
if (!inst.receiptUrl && pendingReceipt) {
|
|
5856
|
+
patch({ receiptUrl: pendingReceipt });
|
|
5857
|
+
setPendingReceipt(void 0);
|
|
5858
|
+
return;
|
|
5859
|
+
}
|
|
5860
|
+
setReceiptTarget(i);
|
|
5861
|
+
receiptPicker.open();
|
|
5862
|
+
}
|
|
5863
|
+
}
|
|
5864
|
+
),
|
|
5865
|
+
!isPaid2 && (saved || !isEdit && !!contactId && items.length > 0 && inst.amount > 0) && /* @__PURE__ */ jsx(
|
|
5866
|
+
InstallmentPayButton,
|
|
5867
|
+
{
|
|
5868
|
+
disabled: saving || !!faltaParaPagar,
|
|
5869
|
+
title: faltaParaPagar ?? void 0,
|
|
5870
|
+
onClick: () => {
|
|
5871
|
+
void pagarParcela(i);
|
|
5872
|
+
},
|
|
5873
|
+
children: t2("financial.invoice.pay")
|
|
5874
|
+
}
|
|
5875
|
+
)
|
|
5876
|
+
] })
|
|
5877
|
+
}
|
|
5878
|
+
),
|
|
5612
5879
|
!isEdit && inst.receiptUrl && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 border-t bg-muted/20 px-3 py-2", children: [
|
|
5613
5880
|
/* @__PURE__ */ jsx(
|
|
5614
5881
|
"img",
|
|
@@ -5920,6 +6187,7 @@ function InvoiceFormView({ direction, editId, onSaved, focusReceipt = false, fro
|
|
|
5920
6187
|
}
|
|
5921
6188
|
),
|
|
5922
6189
|
receiptPicker.input,
|
|
6190
|
+
attachmentsOpen && editId && /* @__PURE__ */ jsx(InvoiceAttachmentsModal, { invoiceId: editId, onClose: () => setAttachmentsOpen(false) }),
|
|
5923
6191
|
payingMovement && /* @__PURE__ */ jsx(
|
|
5924
6192
|
PaymentModal,
|
|
5925
6193
|
{
|
|
@@ -6015,6 +6283,11 @@ function groupPaymentsByBill(bills, payments) {
|
|
|
6015
6283
|
}
|
|
6016
6284
|
return { byBillId, unattributed };
|
|
6017
6285
|
}
|
|
6286
|
+
var reversalOf = (m) => m.metadata?.reversal_of;
|
|
6287
|
+
function reversiblePayments(payments) {
|
|
6288
|
+
const reversed = new Set(payments.map(reversalOf).filter(Boolean));
|
|
6289
|
+
return payments.filter((m) => !reversalOf(m) && !reversed.has(m.id));
|
|
6290
|
+
}
|
|
6018
6291
|
|
|
6019
6292
|
// src/lib/payment-how.ts
|
|
6020
6293
|
var NOT_A_HOLDER = /* @__PURE__ */ new Set(["person", "system"]);
|
|
@@ -6062,6 +6335,7 @@ function PaymentReceiptModal({
|
|
|
6062
6335
|
const { currency } = useFinancialConfig();
|
|
6063
6336
|
const fmt = (n) => formatCurrency(n, currency);
|
|
6064
6337
|
const ordenados = [...payments].sort((a, b) => (a.paymentDate ?? "").localeCompare(b.paymentDate ?? "") || (a.createdAt ?? "").localeCompare(b.createdAt ?? ""));
|
|
6338
|
+
const estornaveis = new Set(reversiblePayments(ordenados).map((m) => m.id));
|
|
6065
6339
|
const total = ordenados.reduce((soma, m) => soma + (ehEstorno(m) ? -1 : 1) * (m.paidAmount || m.amount), 0);
|
|
6066
6340
|
return /* @__PURE__ */ jsx(Modal, { open: true, onOpenChange: (o) => {
|
|
6067
6341
|
if (!o) onClose();
|
|
@@ -6101,7 +6375,7 @@ function PaymentReceiptModal({
|
|
|
6101
6375
|
] }),
|
|
6102
6376
|
/* @__PURE__ */ jsx("span", { className: "text-xs", children: payment.notes })
|
|
6103
6377
|
] }),
|
|
6104
|
-
onReverse &&
|
|
6378
|
+
onReverse && estornaveis.has(payment.id) && /* @__PURE__ */ jsxs("div", { className: "space-y-1 border-t border-border/60 pt-2", children: [
|
|
6105
6379
|
/* @__PURE__ */ jsx(Hint, { label: t2("financial.paymentReceipt.unlinkUnavailable"), children: /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", className: "w-full", disabled: true, children: [
|
|
6106
6380
|
/* @__PURE__ */ jsx(Unlink, { className: "h-3.5 w-3.5", "aria-hidden": true }),
|
|
6107
6381
|
t2("financial.paymentReceipt.unlink")
|
|
@@ -6133,14 +6407,6 @@ var ITEM_ICONS = {
|
|
|
6133
6407
|
gift_card: Gift,
|
|
6134
6408
|
other: Receipt
|
|
6135
6409
|
};
|
|
6136
|
-
var HOW_ICONS = {
|
|
6137
|
-
cash: Banknote,
|
|
6138
|
-
pix: QrCode,
|
|
6139
|
-
credit_card: CreditCard,
|
|
6140
|
-
debit_card: CreditCard,
|
|
6141
|
-
bank_transfer: ArrowRightLeft,
|
|
6142
|
-
check: FileCheck
|
|
6143
|
-
};
|
|
6144
6410
|
var STATUS_COLORS = {
|
|
6145
6411
|
open: { bg: "bg-info-soft text-info-soft-foreground", icon: CircleDashed, labelKey: "financial.invoice.statusOpen", tone: "info" },
|
|
6146
6412
|
pending: { bg: "bg-warning-soft text-warning-soft-foreground", icon: CircleDashed, labelKey: "financial.invoice.statusPending", tone: "warning" },
|
|
@@ -6174,7 +6440,6 @@ function InvoiceDetailView({ invoiceId, direction, onBack, onEdit, backLabel, em
|
|
|
6174
6440
|
const unitName = useUnitStore((st) => unitMode && invoice?.unitId ? st.byId[invoice.unitId]?.name : void 0);
|
|
6175
6441
|
const [items, setItems] = useState([]);
|
|
6176
6442
|
const [attachments, setAttachments] = useState([]);
|
|
6177
|
-
const [viewing, setViewing] = useState(null);
|
|
6178
6443
|
const [movements, setMovements] = useState([]);
|
|
6179
6444
|
const [payments, setPayments] = useState([]);
|
|
6180
6445
|
const [holders, setHolders] = useState(/* @__PURE__ */ new Map());
|
|
@@ -6184,13 +6449,8 @@ function InvoiceDetailView({ invoiceId, direction, onBack, onEdit, backLabel, em
|
|
|
6184
6449
|
const [receiptBill, setReceiptBill] = useState(null);
|
|
6185
6450
|
const [reverseReason, setReverseReason] = useState("");
|
|
6186
6451
|
const [payingMovement, setPayingMovement] = useState(null);
|
|
6187
|
-
const [
|
|
6452
|
+
const [attachmentsOpen, setAttachmentsOpen] = useState(false);
|
|
6188
6453
|
const [pendingReceipt, setPendingReceipt] = useState();
|
|
6189
|
-
const receiptPicker = useReceiptPicker((dataUrl) => {
|
|
6190
|
-
setPendingReceipt(dataUrl);
|
|
6191
|
-
setPayingMovement(receiptFor);
|
|
6192
|
-
setReceiptFor(null);
|
|
6193
|
-
});
|
|
6194
6454
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
6195
6455
|
const [confirmCancel, setConfirmCancel] = useState(false);
|
|
6196
6456
|
const [cancelling, setCancelling] = useState(false);
|
|
@@ -6221,6 +6481,17 @@ function InvoiceDetailView({ invoiceId, direction, onBack, onEdit, backLabel, em
|
|
|
6221
6481
|
void loadData();
|
|
6222
6482
|
}
|
|
6223
6483
|
}
|
|
6484
|
+
async function patchInvoiceDate(invoiceDate) {
|
|
6485
|
+
if (!invoice || !invoiceDate || invoiceDate === invoice.invoiceDate) return;
|
|
6486
|
+
const antes = invoice;
|
|
6487
|
+
setInvoice({ ...invoice, invoiceDate });
|
|
6488
|
+
try {
|
|
6489
|
+
await provider.updateInvoice(invoice.id, { invoiceDate });
|
|
6490
|
+
} catch (e) {
|
|
6491
|
+
setInvoice(antes);
|
|
6492
|
+
toast.error(e?.message ?? String(e));
|
|
6493
|
+
}
|
|
6494
|
+
}
|
|
6224
6495
|
const reqRef = useRef(0);
|
|
6225
6496
|
async function loadData() {
|
|
6226
6497
|
const req = ++reqRef.current;
|
|
@@ -6311,8 +6582,8 @@ function InvoiceDetailView({ invoiceId, direction, onBack, onEdit, backLabel, em
|
|
|
6311
6582
|
setCancelling(false);
|
|
6312
6583
|
}
|
|
6313
6584
|
}
|
|
6314
|
-
const [chartNames, setChartNames] =
|
|
6315
|
-
|
|
6585
|
+
const [chartNames, setChartNames] = React25__default.useState(/* @__PURE__ */ new Map());
|
|
6586
|
+
React25__default.useEffect(() => {
|
|
6316
6587
|
let cancelled2 = false;
|
|
6317
6588
|
void provider.getChartOfAccounts().then((rows) => {
|
|
6318
6589
|
if (!cancelled2) setChartNames(new Map(rows.map((r) => [r.id, r.name])));
|
|
@@ -6432,7 +6703,14 @@ function InvoiceDetailView({ invoiceId, direction, onBack, onEdit, backLabel, em
|
|
|
6432
6703
|
{ id: "total", label: t2("financial.invoice.total"), value: formatCurrency(invoice.totalAmount, currency), icon: DollarSign },
|
|
6433
6704
|
{ id: "items", label: t2("financial.invoice.items"), value: items.length, icon: LayoutList },
|
|
6434
6705
|
{ id: "installments", label: t2("financial.invoice.installments"), value: `${invoice.totalInstallments}x`, icon: Layers },
|
|
6435
|
-
{
|
|
6706
|
+
{
|
|
6707
|
+
id: "date",
|
|
6708
|
+
label: t2("financial.invoice.date"),
|
|
6709
|
+
icon: CalendarDays,
|
|
6710
|
+
value: invoice.status !== "cancelled" ? /* @__PURE__ */ jsx(DatePicker, { value: invoice.invoiceDate, variant: "inline", format: "numeric", onChange: (v) => {
|
|
6711
|
+
void patchInvoiceDate(v);
|
|
6712
|
+
} }) : invoice.invoiceDate
|
|
6713
|
+
}
|
|
6436
6714
|
],
|
|
6437
6715
|
customerLabel: direction === "debit" ? t2("financial.invoice.payTo") : t2("financial.invoice.receiveFrom"),
|
|
6438
6716
|
unit: unitName ? { label: t2("financial.invoice.unit"), value: unitName } : void 0,
|
|
@@ -6450,7 +6728,7 @@ function InvoiceDetailView({ invoiceId, direction, onBack, onEdit, backLabel, em
|
|
|
6450
6728
|
"button",
|
|
6451
6729
|
{
|
|
6452
6730
|
type: "button",
|
|
6453
|
-
onClick: () =>
|
|
6731
|
+
onClick: () => setAttachmentsOpen(true),
|
|
6454
6732
|
title: attachments.map((a) => a.fileName).join("\n"),
|
|
6455
6733
|
className: "mb-2 inline-flex items-center gap-1 rounded-md px-1.5 py-1 text-xs text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
6456
6734
|
children: [
|
|
@@ -6465,14 +6743,12 @@ function InvoiceDetailView({ invoiceId, direction, onBack, onEdit, backLabel, em
|
|
|
6465
6743
|
const isPaid2 = mov.status === "paid";
|
|
6466
6744
|
const isPartial = mov.status === "partial";
|
|
6467
6745
|
const hasPaidDetails = isPaid2 || isPartial;
|
|
6468
|
-
const movStatus = STATUS_COLORS[mov.status] ?? STATUS_COLORS.pending;
|
|
6469
|
-
const MovIcon = movStatus.icon;
|
|
6470
6746
|
const instPayments = settlements.byBillId.get(mov.id) ?? [];
|
|
6471
6747
|
const hows = instPayments.map((payment) => describePayment(payment, howCtx));
|
|
6472
6748
|
const paymentSummary = [...new Set(hows.map((how2) => [how2.method, how2.account?.name].filter(Boolean).join(" \xB7 ")).filter(Boolean))].join(" / ");
|
|
6473
6749
|
const how = hows[0];
|
|
6474
6750
|
const howCard = how?.account?.accountType === "card_payable" ? how.account : void 0;
|
|
6475
|
-
const HowIcon =
|
|
6751
|
+
const HowIcon = METHOD_ICONS[how?.typeKind ?? ""] ?? (how ? CreditCard : null);
|
|
6476
6752
|
const srcMeta = mov.metadata ?? {};
|
|
6477
6753
|
const srcStr = (v) => typeof v === "string" && v ? v : void 0;
|
|
6478
6754
|
const srcTypeId = srcStr(srcMeta.payMethodTypeId);
|
|
@@ -6480,66 +6756,41 @@ function InvoiceDetailView({ invoiceId, direction, onBack, onEdit, backLabel, em
|
|
|
6480
6756
|
const editavel = !hasPaidDetails && invoice.status !== "cancelled";
|
|
6481
6757
|
const canChooseSource = editavel && Math.abs(mov.amount) >= 5e-3;
|
|
6482
6758
|
const faltaParaPagar = !srcTypeId ? t2("financial.payment.methodRequired") : !srcAccountId ? t2("financial.payment.accountRequired") : null;
|
|
6483
|
-
|
|
6484
|
-
|
|
6759
|
+
const ativa = invoice.status !== "cancelled";
|
|
6760
|
+
return /* @__PURE__ */ jsx(
|
|
6761
|
+
InstallmentRow,
|
|
6485
6762
|
{
|
|
6486
|
-
|
|
6763
|
+
number: mov.installmentNumber ?? 1,
|
|
6764
|
+
amount: formatCurrency(mov.amount, currency),
|
|
6765
|
+
status: mov.status,
|
|
6766
|
+
dueDate: mov.dueDate,
|
|
6767
|
+
onDueDateChange: editavel ? (v) => {
|
|
6768
|
+
void patchDueDate(mov, v);
|
|
6769
|
+
} : void 0,
|
|
6770
|
+
dueExtra: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6771
|
+
mov.paidAmount > 0 && !isPaid2 && ` \xB7 ${t2("financial.invoice.paidLabel")} ${formatCurrency(mov.paidAmount, currency)}`,
|
|
6772
|
+
mov.paymentDate && ` \xB7 ${t2("financial.invoice.paidOn")} ${mov.paymentDate}`
|
|
6773
|
+
] }),
|
|
6487
6774
|
onClick: hasPaidDetails ? () => setReceiptBill(mov) : void 0,
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
t2(movStatus.labelKey)
|
|
6499
|
-
] }),
|
|
6500
|
-
/* @__PURE__ */ jsxs(
|
|
6501
|
-
"span",
|
|
6502
|
-
{
|
|
6503
|
-
className: "flex shrink-0 items-center gap-1 whitespace-nowrap text-[10px] text-muted-foreground",
|
|
6504
|
-
onClick: (e) => e.stopPropagation(),
|
|
6505
|
-
children: [
|
|
6506
|
-
t2("financial.payment.due"),
|
|
6507
|
-
editavel ? /* @__PURE__ */ jsx(
|
|
6508
|
-
DatePicker,
|
|
6509
|
-
{
|
|
6510
|
-
value: mov.dueDate,
|
|
6511
|
-
variant: "inline",
|
|
6512
|
-
format: "numeric",
|
|
6513
|
-
onChange: (v) => {
|
|
6514
|
-
void patchDueDate(mov, v);
|
|
6515
|
-
}
|
|
6516
|
-
}
|
|
6517
|
-
) : mov.dueDate,
|
|
6518
|
-
mov.paidAmount > 0 && !isPaid2 && ` \xB7 ${t2("financial.invoice.paidLabel")} ${formatCurrency(mov.paidAmount, currency)}`,
|
|
6519
|
-
mov.paymentDate && ` \xB7 ${t2("financial.invoice.paidOn")} ${mov.paymentDate}`
|
|
6520
|
-
]
|
|
6521
|
-
}
|
|
6522
|
-
)
|
|
6523
|
-
] }),
|
|
6524
|
-
canChooseSource && /* @__PURE__ */ jsx("div", { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx(
|
|
6525
|
-
InstallmentSourceFields,
|
|
6526
|
-
{
|
|
6527
|
-
direction,
|
|
6528
|
-
value: { payMethodTypeId: srcTypeId, payAccountId: srcAccountId },
|
|
6529
|
-
onChange: (next) => {
|
|
6530
|
-
void patchSource(mov, {
|
|
6531
|
-
payMethodTypeId: next.payMethodTypeId ?? null,
|
|
6532
|
-
payAccountId: next.payAccountId ?? null
|
|
6533
|
-
});
|
|
6534
|
-
}
|
|
6775
|
+
source: canChooseSource ? /* @__PURE__ */ jsx(
|
|
6776
|
+
InstallmentSourceFields,
|
|
6777
|
+
{
|
|
6778
|
+
direction,
|
|
6779
|
+
value: { payMethodTypeId: srcTypeId, payAccountId: srcAccountId },
|
|
6780
|
+
onChange: (next) => {
|
|
6781
|
+
void patchSource(mov, {
|
|
6782
|
+
payMethodTypeId: next.payMethodTypeId ?? null,
|
|
6783
|
+
payAccountId: next.payAccountId ?? null
|
|
6784
|
+
});
|
|
6535
6785
|
}
|
|
6536
|
-
|
|
6786
|
+
}
|
|
6787
|
+
) : void 0,
|
|
6788
|
+
actions: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6537
6789
|
paymentSummary && /* @__PURE__ */ jsx(
|
|
6538
6790
|
"button",
|
|
6539
6791
|
{
|
|
6540
6792
|
type: "button",
|
|
6541
|
-
onClick: (
|
|
6542
|
-
e.stopPropagation();
|
|
6793
|
+
onClick: () => {
|
|
6543
6794
|
if (hasPaidDetails) setReceiptBill(mov);
|
|
6544
6795
|
},
|
|
6545
6796
|
title: paymentSummary,
|
|
@@ -6548,72 +6799,38 @@ function InvoiceDetailView({ invoiceId, direction, onBack, onEdit, backLabel, em
|
|
|
6548
6799
|
children: howCard ? /* @__PURE__ */ jsx(CardVisual, { lastFour: howCard.lastFour ?? void 0, color: howCard.color ?? void 0, brandId: howCard.cardBrandId ?? void 0 }) : HowIcon ? /* @__PURE__ */ jsx(HowIcon, { className: "h-4 w-4", "aria-hidden": true }) : null
|
|
6549
6800
|
}
|
|
6550
6801
|
),
|
|
6551
|
-
|
|
6552
|
-
|
|
6802
|
+
/* @__PURE__ */ jsx(
|
|
6803
|
+
InstallmentReceiptButton,
|
|
6553
6804
|
{
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
},
|
|
6559
|
-
title: t2("financial.quickTx.receiptCapture"),
|
|
6560
|
-
"aria-label": t2("financial.quickTx.receiptCapture"),
|
|
6561
|
-
className: "inline-flex shrink-0 items-center gap-1 rounded-lg border bg-card px-2.5 py-1.5 text-xs font-medium shadow-button transition-colors hover:bg-muted active:shadow-button-inset",
|
|
6562
|
-
children: /* @__PURE__ */ jsx(Camera, { className: "h-3 w-3" })
|
|
6805
|
+
title: "Anexos",
|
|
6806
|
+
attached: attachments.length > 0,
|
|
6807
|
+
count: attachments.length,
|
|
6808
|
+
onClick: () => setAttachmentsOpen(true)
|
|
6563
6809
|
}
|
|
6564
6810
|
),
|
|
6565
|
-
!isPaid2 && !isPartial &&
|
|
6566
|
-
|
|
6811
|
+
!isPaid2 && !isPartial && ativa && /* @__PURE__ */ jsxs(
|
|
6812
|
+
InstallmentPayButton,
|
|
6567
6813
|
{
|
|
6568
|
-
onClick: (
|
|
6569
|
-
e.stopPropagation();
|
|
6570
|
-
setPayingMovement(mov);
|
|
6571
|
-
},
|
|
6814
|
+
onClick: () => setPayingMovement(mov),
|
|
6572
6815
|
disabled: !!faltaParaPagar,
|
|
6573
6816
|
title: faltaParaPagar ?? void 0,
|
|
6574
|
-
className: "inline-flex items-center gap-1 rounded-button bg-primary border border-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 shadow-button-primary active:shadow-button-inset transition-colors shrink-0 disabled:opacity-40 disabled:pointer-events-none",
|
|
6575
6817
|
children: [
|
|
6576
|
-
/* @__PURE__ */ jsx(DollarSign, { className: "h-3 w-3" }),
|
|
6577
6818
|
t2("financial.invoice.pay"),
|
|
6578
6819
|
" ",
|
|
6579
6820
|
remaining < mov.amount ? formatCurrency(remaining, currency) : ""
|
|
6580
6821
|
]
|
|
6581
6822
|
}
|
|
6582
6823
|
),
|
|
6583
|
-
isPaid2 && instPayments.length > 0 &&
|
|
6584
|
-
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
t2("financial.invoice.reverse")
|
|
6594
|
-
]
|
|
6595
|
-
}
|
|
6596
|
-
),
|
|
6597
|
-
isPartial && invoice.status !== "cancelled" && /* @__PURE__ */ jsxs(
|
|
6598
|
-
"button",
|
|
6599
|
-
{
|
|
6600
|
-
onClick: (e) => {
|
|
6601
|
-
e.stopPropagation();
|
|
6602
|
-
setPayingMovement(mov);
|
|
6603
|
-
},
|
|
6604
|
-
className: "inline-flex items-center gap-1 rounded-lg border px-3 py-1.5 text-xs font-medium hover:bg-muted bg-card shadow-button active:shadow-button-inset transition-colors shrink-0",
|
|
6605
|
-
children: [
|
|
6606
|
-
/* @__PURE__ */ jsx(DollarSign, { className: "h-3 w-3" }),
|
|
6607
|
-
t2("financial.invoice.pay"),
|
|
6608
|
-
" ",
|
|
6609
|
-
formatCurrency(remaining, currency)
|
|
6610
|
-
]
|
|
6611
|
-
}
|
|
6612
|
-
),
|
|
6613
|
-
hasPaidDetails && /* @__PURE__ */ jsx(ChevronRight, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": true })
|
|
6614
|
-
]
|
|
6615
|
-
}
|
|
6616
|
-
) }, mov.id);
|
|
6824
|
+
isPaid2 && reversiblePayments(instPayments).length > 0 && ativa && /* @__PURE__ */ jsx(InstallmentActionButton, { icon: Undo2, onClick: () => setReversing(reversiblePayments(instPayments).at(-1)), children: t2("financial.invoice.reverse") }),
|
|
6825
|
+
isPartial && ativa && /* @__PURE__ */ jsxs(InstallmentPayButton, { variant: "outline", onClick: () => setPayingMovement(mov), children: [
|
|
6826
|
+
t2("financial.invoice.pay"),
|
|
6827
|
+
" ",
|
|
6828
|
+
formatCurrency(remaining, currency)
|
|
6829
|
+
] })
|
|
6830
|
+
] })
|
|
6831
|
+
},
|
|
6832
|
+
mov.id
|
|
6833
|
+
);
|
|
6617
6834
|
}) }),
|
|
6618
6835
|
settlements.unattributed.length > 0 && /* @__PURE__ */ jsxs("div", { className: "border-t bg-warning-soft/40 px-4 py-2.5", children: [
|
|
6619
6836
|
/* @__PURE__ */ jsx("p", { className: "text-[11px] font-medium text-foreground", children: t2("financial.invoice.unlinkedPayments") }),
|
|
@@ -6632,14 +6849,14 @@ function InvoiceDetailView({ invoiceId, direction, onBack, onEdit, backLabel, em
|
|
|
6632
6849
|
extraSections: sideBlocks
|
|
6633
6850
|
}
|
|
6634
6851
|
),
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
AttachmentViewer,
|
|
6852
|
+
attachmentsOpen && /* @__PURE__ */ jsx(
|
|
6853
|
+
InvoiceAttachmentsModal,
|
|
6638
6854
|
{
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6855
|
+
invoiceId: invoice.id,
|
|
6856
|
+
onClose: () => setAttachmentsOpen(false),
|
|
6857
|
+
onChanged: () => {
|
|
6858
|
+
void loadData();
|
|
6859
|
+
}
|
|
6643
6860
|
}
|
|
6644
6861
|
),
|
|
6645
6862
|
receiptBill && /* @__PURE__ */ jsx(
|
|
@@ -7362,7 +7579,7 @@ function CashRegistersView({ variant = "page" } = {}) {
|
|
|
7362
7579
|
const [tab, setTab] = useState("open");
|
|
7363
7580
|
const [reviewRows, setReviewRows] = useState(null);
|
|
7364
7581
|
const [reviewError, setReviewError] = useState(null);
|
|
7365
|
-
const loadReviews =
|
|
7582
|
+
const loadReviews = React25__default.useCallback(async () => {
|
|
7366
7583
|
try {
|
|
7367
7584
|
setReviewError(null);
|
|
7368
7585
|
setReviewRows(await provider.getCashSessionReviews?.() ?? []);
|
|
@@ -7962,7 +8179,7 @@ function StatementsView({ onNavigate }) {
|
|
|
7962
8179
|
"extrato"
|
|
7963
8180
|
);
|
|
7964
8181
|
};
|
|
7965
|
-
const headerActions =
|
|
8182
|
+
const headerActions = React25__default.useMemo(() => [{
|
|
7966
8183
|
id: "new-transfer",
|
|
7967
8184
|
label: t2("financial.statements.newTransfer"),
|
|
7968
8185
|
icon: ArrowRightLeft,
|
|
@@ -8158,15 +8375,15 @@ function CommissionsView() {
|
|
|
8158
8375
|
const fetchCommissions = useFinancialStore((s) => s.fetchCommissions);
|
|
8159
8376
|
const generateCommissions = useFinancialStore((s) => s.generateCommissions);
|
|
8160
8377
|
const provider = useFinancialProvider();
|
|
8161
|
-
const [from, setFrom] =
|
|
8162
|
-
const [to, setTo] =
|
|
8163
|
-
const [preset, setPreset] =
|
|
8164
|
-
const [running, setRunning] =
|
|
8165
|
-
const [lastRun, setLastRun] =
|
|
8166
|
-
const [generation, setGeneration] =
|
|
8167
|
-
const [busy, setBusy] =
|
|
8168
|
-
const [error, setError] =
|
|
8169
|
-
const loadGeneration =
|
|
8378
|
+
const [from, setFrom] = React25__default.useState(firstOfMonth());
|
|
8379
|
+
const [to, setTo] = React25__default.useState(today2());
|
|
8380
|
+
const [preset, setPreset] = React25__default.useState("this_month");
|
|
8381
|
+
const [running, setRunning] = React25__default.useState(false);
|
|
8382
|
+
const [lastRun, setLastRun] = React25__default.useState(null);
|
|
8383
|
+
const [generation, setGeneration] = React25__default.useState(null);
|
|
8384
|
+
const [busy, setBusy] = React25__default.useState(null);
|
|
8385
|
+
const [error, setError] = React25__default.useState(null);
|
|
8386
|
+
const loadGeneration = React25__default.useCallback(async () => {
|
|
8170
8387
|
try {
|
|
8171
8388
|
const gens = await provider.getCommissionGenerations?.() ?? [];
|
|
8172
8389
|
const doPeriodo = gens.filter((g) => g.periodStart === from && g.periodEnd === to);
|
|
@@ -8174,11 +8391,11 @@ function CommissionsView() {
|
|
|
8174
8391
|
} catch {
|
|
8175
8392
|
}
|
|
8176
8393
|
}, [provider, from, to]);
|
|
8177
|
-
|
|
8394
|
+
React25__default.useEffect(() => {
|
|
8178
8395
|
void fetchCommissions({ periodStart: from, periodEnd: to });
|
|
8179
8396
|
void loadGeneration();
|
|
8180
8397
|
}, [fetchCommissions, loadGeneration, from, to]);
|
|
8181
|
-
const byPerson =
|
|
8398
|
+
const byPerson = React25__default.useMemo(() => {
|
|
8182
8399
|
const map = /* @__PURE__ */ new Map();
|
|
8183
8400
|
for (const c of commissions2) {
|
|
8184
8401
|
const key = c.personId;
|
|
@@ -8231,7 +8448,7 @@ function CommissionsView() {
|
|
|
8231
8448
|
setBusy(null);
|
|
8232
8449
|
}
|
|
8233
8450
|
}
|
|
8234
|
-
const headerActions =
|
|
8451
|
+
const headerActions = React25__default.useMemo(() => [{
|
|
8235
8452
|
id: "commission-rules",
|
|
8236
8453
|
label: "Configurar regras de comiss\xE3o",
|
|
8237
8454
|
icon: Settings,
|
|
@@ -8679,13 +8896,13 @@ function money3(v) {
|
|
|
8679
8896
|
function GoalsView() {
|
|
8680
8897
|
const { labels } = useFinancialConfig();
|
|
8681
8898
|
const provider = useFinancialProvider();
|
|
8682
|
-
const [units, setUnits] =
|
|
8683
|
-
const [unitId, setUnitId] =
|
|
8684
|
-
const [year, setYear] =
|
|
8685
|
-
const [rows, setRows] =
|
|
8686
|
-
const [editing, setEditing] =
|
|
8687
|
-
const [error, setError] =
|
|
8688
|
-
|
|
8899
|
+
const [units, setUnits] = React25__default.useState([]);
|
|
8900
|
+
const [unitId, setUnitId] = React25__default.useState("");
|
|
8901
|
+
const [year, setYear] = React25__default.useState((/* @__PURE__ */ new Date()).getFullYear());
|
|
8902
|
+
const [rows, setRows] = React25__default.useState(null);
|
|
8903
|
+
const [editing, setEditing] = React25__default.useState(null);
|
|
8904
|
+
const [error, setError] = React25__default.useState(null);
|
|
8905
|
+
React25__default.useEffect(() => {
|
|
8689
8906
|
void (async () => {
|
|
8690
8907
|
const cat = await provider.getCommissionCatalogs?.();
|
|
8691
8908
|
const us = cat?.units ?? [];
|
|
@@ -8693,7 +8910,7 @@ function GoalsView() {
|
|
|
8693
8910
|
setUnitId((cur) => cur || us[0]?.id || "");
|
|
8694
8911
|
})();
|
|
8695
8912
|
}, [provider]);
|
|
8696
|
-
const load =
|
|
8913
|
+
const load = React25__default.useCallback(async () => {
|
|
8697
8914
|
if (!unitId) return;
|
|
8698
8915
|
setRows(null);
|
|
8699
8916
|
try {
|
|
@@ -8704,7 +8921,7 @@ function GoalsView() {
|
|
|
8704
8921
|
setRows([]);
|
|
8705
8922
|
}
|
|
8706
8923
|
}, [provider, unitId, year]);
|
|
8707
|
-
|
|
8924
|
+
React25__default.useEffect(() => {
|
|
8708
8925
|
void load();
|
|
8709
8926
|
}, [load]);
|
|
8710
8927
|
const totalRealizado = (rows ?? []).reduce((s, r) => s + r.achievedAmount, 0);
|
|
@@ -8835,11 +9052,11 @@ function GoalDialog({
|
|
|
8835
9052
|
onSaved
|
|
8836
9053
|
}) {
|
|
8837
9054
|
const provider = useFinancialProvider();
|
|
8838
|
-
const [target, setTarget] =
|
|
8839
|
-
const [sup, setSup] =
|
|
8840
|
-
const [hyper, setHyper] =
|
|
8841
|
-
const [saving, setSaving] =
|
|
8842
|
-
const [error, setError] =
|
|
9055
|
+
const [target, setTarget] = React25__default.useState(String(goal.targetAmount || ""));
|
|
9056
|
+
const [sup, setSup] = React25__default.useState(String(goal.superAmount || ""));
|
|
9057
|
+
const [hyper, setHyper] = React25__default.useState(String(goal.hyperAmount || ""));
|
|
9058
|
+
const [saving, setSaving] = React25__default.useState(false);
|
|
9059
|
+
const [error, setError] = React25__default.useState(null);
|
|
8843
9060
|
const t2 = Number(target) || 0;
|
|
8844
9061
|
const s = Number(sup) || 0;
|
|
8845
9062
|
const h = Number(hyper) || 0;
|
|
@@ -8930,21 +9147,21 @@ function GiftCardsView() {
|
|
|
8930
9147
|
const provider = useFinancialProvider();
|
|
8931
9148
|
const { currency } = useFinancialConfig();
|
|
8932
9149
|
const can = usePermissionOptional();
|
|
8933
|
-
const [enabled, setEnabled] =
|
|
8934
|
-
const [cards, setCards] =
|
|
8935
|
-
const [error, setError] =
|
|
8936
|
-
const [issuing, setIssuing] =
|
|
8937
|
-
const [issued, setIssued] =
|
|
8938
|
-
const [activating, setActivating] =
|
|
8939
|
-
const [search, setSearch] =
|
|
8940
|
-
const [state, setState] =
|
|
8941
|
-
const [minValue, setMinValue] =
|
|
8942
|
-
const [maxValue, setMaxValue] =
|
|
8943
|
-
const [from, setFrom] =
|
|
8944
|
-
const [to, setTo] =
|
|
8945
|
-
const money4 =
|
|
8946
|
-
const seq =
|
|
8947
|
-
const load =
|
|
9150
|
+
const [enabled, setEnabled] = React25__default.useState(null);
|
|
9151
|
+
const [cards, setCards] = React25__default.useState(null);
|
|
9152
|
+
const [error, setError] = React25__default.useState(null);
|
|
9153
|
+
const [issuing, setIssuing] = React25__default.useState(false);
|
|
9154
|
+
const [issued, setIssued] = React25__default.useState(null);
|
|
9155
|
+
const [activating, setActivating] = React25__default.useState(null);
|
|
9156
|
+
const [search, setSearch] = React25__default.useState("");
|
|
9157
|
+
const [state, setState] = React25__default.useState("");
|
|
9158
|
+
const [minValue, setMinValue] = React25__default.useState("");
|
|
9159
|
+
const [maxValue, setMaxValue] = React25__default.useState("");
|
|
9160
|
+
const [from, setFrom] = React25__default.useState("");
|
|
9161
|
+
const [to, setTo] = React25__default.useState("");
|
|
9162
|
+
const money4 = React25__default.useCallback((v) => formatCurrency(v, currency), [currency]);
|
|
9163
|
+
const seq = React25__default.useRef(0);
|
|
9164
|
+
const load = React25__default.useCallback(async () => {
|
|
8948
9165
|
const mine = ++seq.current;
|
|
8949
9166
|
setCards(null);
|
|
8950
9167
|
setError(null);
|
|
@@ -8965,7 +9182,7 @@ function GiftCardsView() {
|
|
|
8965
9182
|
setCards([]);
|
|
8966
9183
|
}
|
|
8967
9184
|
}, [provider, search, state, minValue, maxValue, from, to]);
|
|
8968
|
-
|
|
9185
|
+
React25__default.useEffect(() => {
|
|
8969
9186
|
void (async () => {
|
|
8970
9187
|
try {
|
|
8971
9188
|
setEnabled(await provider.giftCardsEnabled?.() === true);
|
|
@@ -8974,10 +9191,10 @@ function GiftCardsView() {
|
|
|
8974
9191
|
}
|
|
8975
9192
|
})();
|
|
8976
9193
|
}, [provider]);
|
|
8977
|
-
|
|
9194
|
+
React25__default.useEffect(() => {
|
|
8978
9195
|
if (enabled) void load();
|
|
8979
9196
|
}, [enabled, load]);
|
|
8980
|
-
const columns =
|
|
9197
|
+
const columns = React25__default.useMemo(() => [
|
|
8981
9198
|
{
|
|
8982
9199
|
accessorKey: "code",
|
|
8983
9200
|
header: "C\xF3digo",
|
|
@@ -9158,12 +9375,12 @@ function IssueDialog({
|
|
|
9158
9375
|
onIssued
|
|
9159
9376
|
}) {
|
|
9160
9377
|
const provider = useFinancialProvider();
|
|
9161
|
-
const [quantity, setQuantity] =
|
|
9162
|
-
const [amount, setAmount] =
|
|
9163
|
-
const [expiresAt, setExpiresAt] =
|
|
9164
|
-
const [note, setNote] =
|
|
9165
|
-
const [saving, setSaving] =
|
|
9166
|
-
const [error, setError] =
|
|
9378
|
+
const [quantity, setQuantity] = React25__default.useState("10");
|
|
9379
|
+
const [amount, setAmount] = React25__default.useState("100");
|
|
9380
|
+
const [expiresAt, setExpiresAt] = React25__default.useState("");
|
|
9381
|
+
const [note, setNote] = React25__default.useState("");
|
|
9382
|
+
const [saving, setSaving] = React25__default.useState(false);
|
|
9383
|
+
const [error, setError] = React25__default.useState(null);
|
|
9167
9384
|
const q = Math.trunc(Number(quantity)) || 0;
|
|
9168
9385
|
const a = Number(amount) || 0;
|
|
9169
9386
|
const total = q * a;
|
|
@@ -10438,11 +10655,11 @@ function ReconciliationView() {
|
|
|
10438
10655
|
setBusy(false);
|
|
10439
10656
|
}
|
|
10440
10657
|
}
|
|
10441
|
-
const RefreshIcon =
|
|
10658
|
+
const RefreshIcon = React25__default.useMemo(
|
|
10442
10659
|
() => ({ className }) => /* @__PURE__ */ jsx(RefreshCw, { className: `${className ?? ""} ${loading ? "animate-spin" : ""}` }),
|
|
10443
10660
|
[loading]
|
|
10444
10661
|
);
|
|
10445
|
-
const headerActions =
|
|
10662
|
+
const headerActions = React25__default.useMemo(() => [{
|
|
10446
10663
|
id: "refresh",
|
|
10447
10664
|
label: t2("financial.reconciliation.refresh"),
|
|
10448
10665
|
icon: RefreshIcon,
|
|
@@ -10867,13 +11084,13 @@ function RecurringBillsList({ direction, onNavigate }) {
|
|
|
10867
11084
|
const provider = useFinancialProvider();
|
|
10868
11085
|
const { currency } = useFinancialConfig();
|
|
10869
11086
|
const can = usePermissionOptional();
|
|
10870
|
-
const [rows, setRows] =
|
|
10871
|
-
const [search, setSearch] =
|
|
10872
|
-
const [status, setStatus] =
|
|
10873
|
-
const [changing, setChanging] =
|
|
11087
|
+
const [rows, setRows] = React25__default.useState(null);
|
|
11088
|
+
const [search, setSearch] = React25__default.useState("");
|
|
11089
|
+
const [status, setStatus] = React25__default.useState("all");
|
|
11090
|
+
const [changing, setChanging] = React25__default.useState(null);
|
|
10874
11091
|
const isPayable = direction === "payable";
|
|
10875
11092
|
const prefix = isPayable ? "payables" : "receivables";
|
|
10876
|
-
const load =
|
|
11093
|
+
const load = React25__default.useCallback(async () => {
|
|
10877
11094
|
setRows(null);
|
|
10878
11095
|
try {
|
|
10879
11096
|
setRows(await provider.getRecurringBills?.(direction) ?? []);
|
|
@@ -10882,10 +11099,10 @@ function RecurringBillsList({ direction, onNavigate }) {
|
|
|
10882
11099
|
toast.error(error?.message ?? "N\xE3o foi poss\xEDvel carregar as recorr\xEAncias.");
|
|
10883
11100
|
}
|
|
10884
11101
|
}, [provider, direction]);
|
|
10885
|
-
|
|
11102
|
+
React25__default.useEffect(() => {
|
|
10886
11103
|
void load();
|
|
10887
11104
|
}, [load]);
|
|
10888
|
-
const filtered =
|
|
11105
|
+
const filtered = React25__default.useMemo(() => {
|
|
10889
11106
|
const term = search.trim().toLowerCase();
|
|
10890
11107
|
const visiveis = (rows ?? []).filter((row) => {
|
|
10891
11108
|
if (status === "active" && !row.isActive) return false;
|
|
@@ -10895,7 +11112,7 @@ function RecurringBillsList({ direction, onNavigate }) {
|
|
|
10895
11112
|
});
|
|
10896
11113
|
return [...visiveis].sort((a, b) => Number(b.isActive) - Number(a.isActive) || (a.dueDay ?? 0) - (b.dueDay ?? 0) || a.description.localeCompare(b.description));
|
|
10897
11114
|
}, [rows, search, status]);
|
|
10898
|
-
const porMes =
|
|
11115
|
+
const porMes = React25__default.useMemo(() => {
|
|
10899
11116
|
const fator = { weekly: 52 / 12, monthly: 1, quarterly: 1 / 3, yearly: 1 / 12 };
|
|
10900
11117
|
const ativas = filtered.filter((row) => row.isActive);
|
|
10901
11118
|
return {
|
|
@@ -10916,7 +11133,7 @@ function RecurringBillsList({ direction, onNavigate }) {
|
|
|
10916
11133
|
setChanging(null);
|
|
10917
11134
|
}
|
|
10918
11135
|
}
|
|
10919
|
-
const columns =
|
|
11136
|
+
const columns = React25__default.useMemo(() => [
|
|
10920
11137
|
{
|
|
10921
11138
|
accessorKey: "description",
|
|
10922
11139
|
header: "Descri\xE7\xE3o",
|
|
@@ -11013,40 +11230,40 @@ function RecurringBillFormView({ direction, valueId, onBack }) {
|
|
|
11013
11230
|
const provider = useFinancialProvider();
|
|
11014
11231
|
const { locations, currency, itemTypes: configuredItemTypes, entityLookups } = useFinancialConfig();
|
|
11015
11232
|
const isPayable = direction === "payable";
|
|
11016
|
-
const [value, setValue] =
|
|
11017
|
-
const [loaded, setLoaded] =
|
|
11018
|
-
const [contact, setContact] =
|
|
11019
|
-
const [counterpartyAccounting, setCounterpartyAccounting] =
|
|
11233
|
+
const [value, setValue] = React25__default.useState(null);
|
|
11234
|
+
const [loaded, setLoaded] = React25__default.useState(!valueId);
|
|
11235
|
+
const [contact, setContact] = React25__default.useState(null);
|
|
11236
|
+
const [counterpartyAccounting, setCounterpartyAccounting] = React25__default.useState({
|
|
11020
11237
|
allowedAccountIds: [],
|
|
11021
11238
|
limitAccounts: false,
|
|
11022
11239
|
addItemsAutomatically: false
|
|
11023
11240
|
});
|
|
11024
|
-
const accountingPolicyRequest =
|
|
11025
|
-
const counterpartyLookup =
|
|
11241
|
+
const accountingPolicyRequest = React25__default.useRef(0);
|
|
11242
|
+
const counterpartyLookup = React25__default.useMemo(
|
|
11026
11243
|
() => createFinancialCounterpartyLookup(isPayable ? "debit" : "credit"),
|
|
11027
11244
|
[isPayable]
|
|
11028
11245
|
);
|
|
11029
11246
|
const contactCreate = useLookupCreate(counterpartyLookup, (created) => {
|
|
11030
11247
|
setContact({ id: created.id, name: created.label });
|
|
11031
11248
|
});
|
|
11032
|
-
const initialItem =
|
|
11033
|
-
const [items, setItems] =
|
|
11034
|
-
const [expandedItemId, setExpandedItemId] =
|
|
11035
|
-
const [addingItem, setAddingItem] =
|
|
11036
|
-
const [frequency, setFrequency] =
|
|
11037
|
-
const [dueDay, setDueDay] =
|
|
11038
|
-
const [startsOn, setStartsOn] =
|
|
11039
|
-
const [endsOn, setEndsOn] =
|
|
11040
|
-
const [unitId, setUnitId] =
|
|
11041
|
-
const [availableLocations, setAvailableLocations] =
|
|
11042
|
-
const [notes, setNotes] =
|
|
11043
|
-
const [isActive, setIsActive] =
|
|
11044
|
-
const [accounts, setAccounts] =
|
|
11045
|
-
const [costCenters, setCostCenters] =
|
|
11046
|
-
const [saving, setSaving] =
|
|
11047
|
-
const [ending, setEnding] =
|
|
11048
|
-
const [error, setError] =
|
|
11049
|
-
|
|
11249
|
+
const initialItem = React25__default.useRef(newRecurringItem());
|
|
11250
|
+
const [items, setItems] = React25__default.useState([initialItem.current]);
|
|
11251
|
+
const [expandedItemId, setExpandedItemId] = React25__default.useState(initialItem.current._id);
|
|
11252
|
+
const [addingItem, setAddingItem] = React25__default.useState(false);
|
|
11253
|
+
const [frequency, setFrequency] = React25__default.useState("monthly");
|
|
11254
|
+
const [dueDay, setDueDay] = React25__default.useState("1");
|
|
11255
|
+
const [startsOn, setStartsOn] = React25__default.useState(today3());
|
|
11256
|
+
const [endsOn, setEndsOn] = React25__default.useState("");
|
|
11257
|
+
const [unitId, setUnitId] = React25__default.useState(locations[0]?.id ?? "");
|
|
11258
|
+
const [availableLocations, setAvailableLocations] = React25__default.useState(locations);
|
|
11259
|
+
const [notes, setNotes] = React25__default.useState("");
|
|
11260
|
+
const [isActive, setIsActive] = React25__default.useState(true);
|
|
11261
|
+
const [accounts, setAccounts] = React25__default.useState([]);
|
|
11262
|
+
const [costCenters, setCostCenters] = React25__default.useState([]);
|
|
11263
|
+
const [saving, setSaving] = React25__default.useState(false);
|
|
11264
|
+
const [ending, setEnding] = React25__default.useState(false);
|
|
11265
|
+
const [error, setError] = React25__default.useState(null);
|
|
11266
|
+
React25__default.useEffect(() => {
|
|
11050
11267
|
if (locations.length > 0) {
|
|
11051
11268
|
setAvailableLocations(locations);
|
|
11052
11269
|
return;
|
|
@@ -11061,7 +11278,7 @@ function RecurringBillFormView({ direction, valueId, onBack }) {
|
|
|
11061
11278
|
cancelled = true;
|
|
11062
11279
|
};
|
|
11063
11280
|
}, [locations]);
|
|
11064
|
-
|
|
11281
|
+
React25__default.useEffect(() => {
|
|
11065
11282
|
let cancelled = false;
|
|
11066
11283
|
void Promise.all([
|
|
11067
11284
|
provider.getChartOfAccounts(),
|
|
@@ -11108,21 +11325,21 @@ function RecurringBillFormView({ direction, valueId, onBack }) {
|
|
|
11108
11325
|
cancelled = true;
|
|
11109
11326
|
};
|
|
11110
11327
|
}, [provider, direction, valueId]);
|
|
11111
|
-
const offeredItemTypes =
|
|
11328
|
+
const offeredItemTypes = React25__default.useMemo(() => availableInvoiceItemTypes(
|
|
11112
11329
|
configuredItemTypes,
|
|
11113
11330
|
Object.keys(entityLookups),
|
|
11114
11331
|
configuredItemTypes.find((item) => item.value === "other")?.label ?? "Outro",
|
|
11115
11332
|
direction
|
|
11116
11333
|
), [configuredItemTypes, entityLookups, direction]);
|
|
11117
11334
|
const itemTypes = useStockedItemTypes(offeredItemTypes, entityLookups);
|
|
11118
|
-
const selectableAccounts =
|
|
11335
|
+
const selectableAccounts = React25__default.useMemo(() => {
|
|
11119
11336
|
const postable = postableAccounts(accounts);
|
|
11120
11337
|
if (!counterpartyAccounting.limitAccounts) return postable;
|
|
11121
11338
|
const allowed = new Set(counterpartyAccounting.allowedAccountIds);
|
|
11122
11339
|
return postable.filter((account) => allowed.has(account.id));
|
|
11123
11340
|
}, [accounts, counterpartyAccounting]);
|
|
11124
11341
|
const hasItemLookups = itemTypes.some((item) => entityLookups[item.value]);
|
|
11125
|
-
const amount =
|
|
11342
|
+
const amount = React25__default.useMemo(() => items.reduce(
|
|
11126
11343
|
(sum, item) => sum + item.quantity * item.unitPrice - (item.discount ?? 0) + (item.surcharge ?? 0),
|
|
11127
11344
|
0
|
|
11128
11345
|
), [items]);
|
|
@@ -11130,8 +11347,8 @@ function RecurringBillFormView({ direction, valueId, onBack }) {
|
|
|
11130
11347
|
const numericDueDay = Math.trunc(Number(dueDay));
|
|
11131
11348
|
const invalid = items.length === 0 ? "Adicione pelo menos um item." : items.some((item) => !item.description.trim()) ? "Informe a descri\xE7\xE3o de todos os itens." : !contact?.id ? `Selecione ${isPayable ? "quem recebe" : "quem paga"}.` : !(amount > 0) ? "Informe um valor maior que zero." : numericDueDay < 1 || numericDueDay > 31 ? "O dia do vencimento vai de 1 a 31." : !startsOn ? "Informe o in\xEDcio da recorr\xEAncia." : endsOn && endsOn < startsOn ? "O t\xE9rmino n\xE3o pode vir antes do in\xEDcio." : null;
|
|
11132
11349
|
const fields = { items, contactId: contact?.id ?? "", frequency, dueDay, startsOn, endsOn, unitId, notes, isActive };
|
|
11133
|
-
const snapshot =
|
|
11134
|
-
|
|
11350
|
+
const snapshot = React25__default.useRef(null);
|
|
11351
|
+
React25__default.useEffect(() => {
|
|
11135
11352
|
if (loaded && snapshot.current === null) snapshot.current = JSON.stringify(fields);
|
|
11136
11353
|
}, [loaded]);
|
|
11137
11354
|
const dirty = snapshot.current !== null && JSON.stringify(fields) !== snapshot.current;
|
|
@@ -11521,16 +11738,8 @@ function buildNav(config, activeView, navigate, t2) {
|
|
|
11521
11738
|
children: [
|
|
11522
11739
|
{ id: "payables-new", kind: "action", label: t2("financial.nav.new"), active: activeView.startsWith("payables-new"), onClick: () => navigate("payables-new") },
|
|
11523
11740
|
{ id: "payables-list", label: t2("financial.nav.list"), active: activeView === "payables-list", onClick: () => navigate("payables-list") },
|
|
11524
|
-
{ id: "payables-recurring", label: t2("financial.nav.recurring"), active: activeView.startsWith("payables-recurring"), onClick: () => navigate("payables-recurring") }
|
|
11525
|
-
//
|
|
11526
|
-
//
|
|
11527
|
-
// «Da minha caixinha» SAIU do menu. No V1 ela é `{caixaAberto && …}`:
|
|
11528
|
-
// aparece enquanto a sessão daquela pessoa está aberta e some quando
|
|
11529
|
-
// ela fecha. Como aba fixa ela prometia uma tela que quase ninguém vê
|
|
11530
|
-
// — e pagar do dinheiro da gaveta é uma FORMA de pagamento do mesmo
|
|
11531
|
-
// lançamento, não um cadastro à parte. A rota segue de pé.
|
|
11532
|
-
{ id: "payables-digitize", label: "Digitalizar Despesa", active: activeView === "payables-digitize", onClick: () => navigate("payables-digitize") },
|
|
11533
|
-
{ id: "payables-payroll", label: "Importar Folha", active: activeView === "payables-payroll", onClick: () => navigate("payables-payroll") }
|
|
11741
|
+
{ id: "payables-recurring", label: t2("financial.nav.recurring"), active: activeView.startsWith("payables-recurring"), onClick: () => navigate("payables-recurring") }
|
|
11742
|
+
// Digitize expense and import payroll live in the list's create menu, not here.
|
|
11534
11743
|
]
|
|
11535
11744
|
});
|
|
11536
11745
|
}
|
|
@@ -11780,8 +11989,9 @@ function FinancialPage({ config: appConfig, provider, store: store6, registries
|
|
|
11780
11989
|
// tamanho do buraco, medido no banco do V1.
|
|
11781
11990
|
case "payables-petty-cash":
|
|
11782
11991
|
return /* @__PURE__ */ jsx(PettyCashView, {});
|
|
11992
|
+
// Digitizing is the list's receipt capture now — the old link lands on the list.
|
|
11783
11993
|
case "payables-digitize":
|
|
11784
|
-
return /* @__PURE__ */ jsx(
|
|
11994
|
+
return /* @__PURE__ */ jsx(PayablesView, { intent: { view: "payables", mode: "list" }, onNavigate: navigate, previousView, back });
|
|
11785
11995
|
case "payables-payroll":
|
|
11786
11996
|
return /* @__PURE__ */ jsx(ImportPayrollView, {});
|
|
11787
11997
|
case "cash-reviewers":
|
|
@@ -11988,7 +12198,7 @@ function BalanceHero() {
|
|
|
11988
12198
|
const summary = useFinancialStore((s) => s.summary);
|
|
11989
12199
|
const navigate = useDashboardNavigate();
|
|
11990
12200
|
useEnsureSummary();
|
|
11991
|
-
const [hidden, setHidden] =
|
|
12201
|
+
const [hidden, setHidden] = React25__default.useState(false);
|
|
11992
12202
|
const money4 = (v) => hidden ? "\u2022\u2022\u2022\u2022\u2022\u2022" : formatCurrency(v ?? 0, currency);
|
|
11993
12203
|
const inflow = summary?.monthlyInflow ?? 0;
|
|
11994
12204
|
const outflow = summary?.monthlyOutflow ?? 0;
|
|
@@ -12061,7 +12271,7 @@ function categorizeSpend(notes) {
|
|
|
12061
12271
|
function SpendByCategoryChart() {
|
|
12062
12272
|
const t2 = useTranslation();
|
|
12063
12273
|
const provider = useFinancialProvider();
|
|
12064
|
-
const [rows, setRows] =
|
|
12274
|
+
const [rows, setRows] = React25__default.useState([]);
|
|
12065
12275
|
useEffect(() => {
|
|
12066
12276
|
let alive = true;
|
|
12067
12277
|
void (async () => {
|
|
@@ -12104,7 +12314,7 @@ function UpcomingBills() {
|
|
|
12104
12314
|
const { currency } = useFinancialConfig();
|
|
12105
12315
|
const provider = useFinancialProvider();
|
|
12106
12316
|
const dueLabel = useDueLabel();
|
|
12107
|
-
const [bills, setBills] =
|
|
12317
|
+
const [bills, setBills] = React25__default.useState([]);
|
|
12108
12318
|
useEffect(() => {
|
|
12109
12319
|
let alive = true;
|
|
12110
12320
|
void (async () => {
|
|
@@ -13778,6 +13988,33 @@ function createSupabaseFinancialProvider() {
|
|
|
13778
13988
|
};
|
|
13779
13989
|
});
|
|
13780
13990
|
},
|
|
13991
|
+
async addInvoiceAttachment(invoiceId, file) {
|
|
13992
|
+
const { pub } = getClients();
|
|
13993
|
+
const tenantId = getTenantId();
|
|
13994
|
+
if (!tenantId) throw new Error("Conta sem empresa ativa");
|
|
13995
|
+
const safe = file.name.replace(/[^\w.\-]+/g, "_");
|
|
13996
|
+
const path = `${tenantId}/financial_invoice/${invoiceId}/${Date.now()}_${safe}`;
|
|
13997
|
+
const { error: upErr } = await pub.storage.from("attachments").upload(path, file, { contentType: file.type || void 0 });
|
|
13998
|
+
if (upErr) throw upErr;
|
|
13999
|
+
const { error } = await pub.from("documents").insert({
|
|
14000
|
+
tenant_id: tenantId,
|
|
14001
|
+
kind: "attachment",
|
|
14002
|
+
status: "active",
|
|
14003
|
+
subject_type: "financial_invoice",
|
|
14004
|
+
subject_id: invoiceId,
|
|
14005
|
+
file_name: file.name,
|
|
14006
|
+
file_size: file.size,
|
|
14007
|
+
mime_type: file.type || null,
|
|
14008
|
+
storage_provider: "supabase",
|
|
14009
|
+
storage_bucket: "attachments",
|
|
14010
|
+
storage_path: path
|
|
14011
|
+
});
|
|
14012
|
+
if (error) {
|
|
14013
|
+
await pub.storage.from("attachments").remove([path]).catch(() => {
|
|
14014
|
+
});
|
|
14015
|
+
throw error;
|
|
14016
|
+
}
|
|
14017
|
+
},
|
|
13781
14018
|
async createInvoice(input) {
|
|
13782
14019
|
const { core, pub } = getClients();
|
|
13783
14020
|
const tenantId = getTenantId();
|
|
@@ -16252,21 +16489,21 @@ function ChartOfAccountsTree({ entity, mockData, dataProvider, embedded }) {
|
|
|
16252
16489
|
const canCreate = can("financial", "create");
|
|
16253
16490
|
const canEdit = can("financial", "edit");
|
|
16254
16491
|
const canDelete = can("financial", "delete");
|
|
16255
|
-
const provider =
|
|
16492
|
+
const provider = React25__default.useMemo(
|
|
16256
16493
|
() => dataProvider ?? resolveDataProvider(entity, mockData ?? []),
|
|
16257
16494
|
[entity, mockData, dataProvider]
|
|
16258
16495
|
);
|
|
16259
16496
|
const table = entity.data?.table;
|
|
16260
|
-
const [nodes, setNodes] =
|
|
16261
|
-
const [loadError, setLoadError] =
|
|
16262
|
-
const [expanded, setExpanded] =
|
|
16263
|
-
const [query, setQuery] =
|
|
16264
|
-
const [showInactive, setShowInactive] =
|
|
16265
|
-
const [editing, setEditing] =
|
|
16266
|
-
const [confirmDelete, setConfirmDelete] =
|
|
16267
|
-
const [busy, setBusy] =
|
|
16268
|
-
const initialized =
|
|
16269
|
-
const reload =
|
|
16497
|
+
const [nodes, setNodes] = React25__default.useState(null);
|
|
16498
|
+
const [loadError, setLoadError] = React25__default.useState(null);
|
|
16499
|
+
const [expanded, setExpanded] = React25__default.useState(/* @__PURE__ */ new Set());
|
|
16500
|
+
const [query, setQuery] = React25__default.useState("");
|
|
16501
|
+
const [showInactive, setShowInactive] = React25__default.useState(true);
|
|
16502
|
+
const [editing, setEditing] = React25__default.useState(null);
|
|
16503
|
+
const [confirmDelete, setConfirmDelete] = React25__default.useState(null);
|
|
16504
|
+
const [busy, setBusy] = React25__default.useState(false);
|
|
16505
|
+
const initialized = React25__default.useRef(false);
|
|
16506
|
+
const reload = React25__default.useCallback(async () => {
|
|
16270
16507
|
try {
|
|
16271
16508
|
const rows = await loadAll(provider);
|
|
16272
16509
|
setNodes(rows);
|
|
@@ -16281,17 +16518,17 @@ function ChartOfAccountsTree({ entity, mockData, dataProvider, embedded }) {
|
|
|
16281
16518
|
setNodes((prev) => prev ?? []);
|
|
16282
16519
|
}
|
|
16283
16520
|
}, [provider]);
|
|
16284
|
-
|
|
16521
|
+
React25__default.useEffect(() => {
|
|
16285
16522
|
void reload();
|
|
16286
16523
|
}, [reload]);
|
|
16287
|
-
const shown =
|
|
16524
|
+
const shown = React25__default.useMemo(
|
|
16288
16525
|
() => (nodes ?? []).filter((n) => showInactive || n.isActive),
|
|
16289
16526
|
[nodes, showInactive]
|
|
16290
16527
|
);
|
|
16291
|
-
const tree =
|
|
16292
|
-
const fullTree =
|
|
16293
|
-
const search =
|
|
16294
|
-
const groupIds =
|
|
16528
|
+
const tree = React25__default.useMemo(() => buildChartTree(shown), [shown]);
|
|
16529
|
+
const fullTree = React25__default.useMemo(() => buildChartTree(nodes ?? []), [nodes]);
|
|
16530
|
+
const search = React25__default.useMemo(() => searchVisibleIds(tree, query), [tree, query]);
|
|
16531
|
+
const groupIds = React25__default.useMemo(
|
|
16295
16532
|
() => [...tree.byId.values()].filter((n) => isGroupNode(tree, n)).map((n) => n.id),
|
|
16296
16533
|
[tree]
|
|
16297
16534
|
);
|
|
@@ -16387,7 +16624,7 @@ function ChartOfAccountsTree({ entity, mockData, dataProvider, embedded }) {
|
|
|
16387
16624
|
const ok = await run(() => provider.remove(node.id), t2("financial.chartTree.deleted", { name: node.name }));
|
|
16388
16625
|
if (ok) setConfirmDelete(null);
|
|
16389
16626
|
}
|
|
16390
|
-
const parentOptions =
|
|
16627
|
+
const parentOptions = React25__default.useCallback((q, selfId) => {
|
|
16391
16628
|
const blocked = selfId ? descendantIds(fullTree, selfId).add(selfId) : /* @__PURE__ */ new Set();
|
|
16392
16629
|
const needle = q.trim().toLowerCase();
|
|
16393
16630
|
return [...fullTree.byId.values()].filter((n) => !blocked.has(n.id) && isGroupNode(fullTree, n)).filter((n) => !needle || accountLabel(n).toLowerCase().includes(needle)).sort((a, b) => a.code.localeCompare(b.code, void 0, { numeric: true })).slice(0, 50).map((n) => ({ id: n.id, label: accountLabel(n) }));
|
|
@@ -16690,7 +16927,7 @@ var chartOfAccountsSeed = [
|
|
|
16690
16927
|
{ id: "coa-4.2", code: "4.2", name: "Utilities", nodeType: "leaf", accountType: "expense", parentId: "coa-4", isActive: true },
|
|
16691
16928
|
{ id: "coa-4.3", code: "4.3", name: "Payroll", nodeType: "leaf", accountType: "expense", parentId: "coa-4", isActive: true }
|
|
16692
16929
|
];
|
|
16693
|
-
var ChartOfAccountsRegistryView = (props) =>
|
|
16930
|
+
var ChartOfAccountsRegistryView = (props) => React25__default.createElement(ChartOfAccountsTree, { ...props, entity: chartOfAccountsEntity, mockData: chartOfAccountsSeed });
|
|
16694
16931
|
ChartOfAccountsRegistryView.displayName = "ChartOfAccountsRegistryView";
|
|
16695
16932
|
var costCenterEntity = {
|
|
16696
16933
|
name: "Cost Center",
|
|
@@ -16788,7 +17025,7 @@ var bankAccountEntity = {
|
|
|
16788
17025
|
labelWhen: (v) => v.kind === "card_payable" ? "Banco emissor" : void 0,
|
|
16789
17026
|
visibleWhen: (v) => hasIssuer(v.kind),
|
|
16790
17027
|
group: "bank",
|
|
16791
|
-
renderInput: ({ value, values, onChange, setValue }) =>
|
|
17028
|
+
renderInput: ({ value, values, onChange, setValue }) => React25__default.createElement(BankPicker, {
|
|
16792
17029
|
code: values.bankCode ?? "",
|
|
16793
17030
|
name: value ?? "",
|
|
16794
17031
|
onChange: (next) => {
|
|
@@ -17657,10 +17894,10 @@ function CashSessionHeaderControl({ config, provider, store: store6 }) {
|
|
|
17657
17894
|
const fetchCashSessions = useStore(store6, (s) => s.fetchCashSessions);
|
|
17658
17895
|
const open = useStore(store6, (s) => s.cashSessionModalOpen);
|
|
17659
17896
|
const setOpen = useStore(store6, (s) => s.setCashSessionModalOpen);
|
|
17660
|
-
|
|
17897
|
+
React25__default.useEffect(() => {
|
|
17661
17898
|
void fetchCashSessions?.();
|
|
17662
17899
|
}, [fetchCashSessions]);
|
|
17663
|
-
|
|
17900
|
+
React25__default.useEffect(() => {
|
|
17664
17901
|
if (!open) return;
|
|
17665
17902
|
const close = () => setOpen(false);
|
|
17666
17903
|
window.addEventListener("hashchange", close);
|
|
@@ -17780,7 +18017,7 @@ var en = {
|
|
|
17780
18017
|
"financial.invoice.items": "Items",
|
|
17781
18018
|
"financial.invoice.keepInvoice": "Keep Invoice",
|
|
17782
18019
|
"financial.invoice.new": "New",
|
|
17783
|
-
"financial.invoice.newManual": "
|
|
18020
|
+
"financial.invoice.newManual": "Create",
|
|
17784
18021
|
"financial.invoiceForm.createContact": "Create",
|
|
17785
18022
|
"financial.invoiceForm.alreadyPaid": "Already paid",
|
|
17786
18023
|
"financial.invoiceForm.paidWith": "Payment method",
|
|
@@ -18519,6 +18756,10 @@ var en = {
|
|
|
18519
18756
|
"financial.quickTx.receiptRemove": "Remove receipt",
|
|
18520
18757
|
"financial.quickTx.receiptInvalid": "Please choose an image file",
|
|
18521
18758
|
"financial.quickTx.sendReceipt": "Send receipt",
|
|
18759
|
+
"financial.quickTx.digitizeExpense": "Digitize expense",
|
|
18760
|
+
"financial.quickTx.digitizeReceipt": "Digitize receipt",
|
|
18761
|
+
"financial.invoice.importPayroll": "Import payroll",
|
|
18762
|
+
"financial.invoice.importPayrollSoon": "Coming soon",
|
|
18522
18763
|
"financial.receipt.ask": "Send the receipt photo\u2026",
|
|
18523
18764
|
"financial.receipt.attachRead": "Attach the receipt the assistant read",
|
|
18524
18765
|
"financial.receipt.fromReceipt": "From the receipt",
|
|
@@ -18670,7 +18911,7 @@ var ptBR = {
|
|
|
18670
18911
|
"financial.invoice.items": "Itens",
|
|
18671
18912
|
"financial.invoice.keepInvoice": "Manter Fatura",
|
|
18672
18913
|
"financial.invoice.new": "Nova",
|
|
18673
|
-
"financial.invoice.newManual": "Cadastrar
|
|
18914
|
+
"financial.invoice.newManual": "Cadastrar",
|
|
18674
18915
|
"financial.invoiceForm.createContact": "Cadastrar",
|
|
18675
18916
|
"financial.invoiceForm.alreadyPaid": "J\xE1 foi pago",
|
|
18676
18917
|
"financial.invoiceForm.paidWith": "Forma de pagamento",
|
|
@@ -19412,6 +19653,10 @@ var ptBR = {
|
|
|
19412
19653
|
"financial.quickTx.receiptRemove": "Remover recibo",
|
|
19413
19654
|
"financial.quickTx.receiptInvalid": "Escolha um arquivo de imagem",
|
|
19414
19655
|
"financial.quickTx.sendReceipt": "Enviar recibo",
|
|
19656
|
+
"financial.quickTx.digitizeExpense": "Digitalizar despesa",
|
|
19657
|
+
"financial.quickTx.digitizeReceipt": "Digitalizar comprovante",
|
|
19658
|
+
"financial.invoice.importPayroll": "Importar folha",
|
|
19659
|
+
"financial.invoice.importPayrollSoon": "Em breve",
|
|
19415
19660
|
"financial.receipt.ask": "Mande a foto do recibo\u2026",
|
|
19416
19661
|
"financial.receipt.attachRead": "Anexar o recibo que o assistente leu",
|
|
19417
19662
|
"financial.receipt.fromReceipt": "Do recibo",
|
|
@@ -19577,14 +19822,14 @@ function CommissionRuleDialog({
|
|
|
19577
19822
|
onClose,
|
|
19578
19823
|
onSaved
|
|
19579
19824
|
}) {
|
|
19580
|
-
const [name, setName] =
|
|
19581
|
-
const [description, setDescription] =
|
|
19582
|
-
const [priority, setPriority] =
|
|
19583
|
-
const [isActive, setIsActive] =
|
|
19584
|
-
const [isDefault, setIsDefault] =
|
|
19585
|
-
const [saving, setSaving] =
|
|
19586
|
-
const [error, setError] =
|
|
19587
|
-
const initial =
|
|
19825
|
+
const [name, setName] = React25__default.useState(rule?.name ?? "");
|
|
19826
|
+
const [description, setDescription] = React25__default.useState(rule?.description ?? "");
|
|
19827
|
+
const [priority, setPriority] = React25__default.useState(String(rule?.priority ?? 1));
|
|
19828
|
+
const [isActive, setIsActive] = React25__default.useState(rule?.isActive ?? true);
|
|
19829
|
+
const [isDefault, setIsDefault] = React25__default.useState(rule?.isDefault ?? !hasDefault);
|
|
19830
|
+
const [saving, setSaving] = React25__default.useState(false);
|
|
19831
|
+
const [error, setError] = React25__default.useState(null);
|
|
19832
|
+
const initial = React25__default.useMemo(() => {
|
|
19588
19833
|
const get = (t2, key = "ids") => rule?.criteria.find((c) => c.criteriaType === t2)?.criteriaValue?.[key] ?? [];
|
|
19589
19834
|
return {
|
|
19590
19835
|
services: get("service"),
|
|
@@ -19595,12 +19840,12 @@ function CommissionRuleDialog({
|
|
|
19595
19840
|
ranges: get("time_range", "ranges")
|
|
19596
19841
|
};
|
|
19597
19842
|
}, [rule]);
|
|
19598
|
-
const [services, setServices] =
|
|
19599
|
-
const [categories, setCategories] =
|
|
19600
|
-
const [professionals, setProfessionals] =
|
|
19601
|
-
const [units, setUnits] =
|
|
19602
|
-
const [weekdays, setWeekdays] =
|
|
19603
|
-
const [ranges, setRanges] =
|
|
19843
|
+
const [services, setServices] = React25__default.useState(initial.services);
|
|
19844
|
+
const [categories, setCategories] = React25__default.useState(initial.categories);
|
|
19845
|
+
const [professionals, setProfessionals] = React25__default.useState(initial.professionals);
|
|
19846
|
+
const [units, setUnits] = React25__default.useState(initial.units);
|
|
19847
|
+
const [weekdays, setWeekdays] = React25__default.useState(initial.weekdays);
|
|
19848
|
+
const [ranges, setRanges] = React25__default.useState(initial.ranges);
|
|
19604
19849
|
const criteriaCount = [services, categories, professionals, units].filter((a) => a.length > 0).length + (weekdays.length ? 1 : 0) + (ranges.length ? 1 : 0);
|
|
19605
19850
|
async function handleSave() {
|
|
19606
19851
|
if (!name.trim()) {
|
|
@@ -19843,11 +20088,11 @@ function blankFunction(order) {
|
|
|
19843
20088
|
};
|
|
19844
20089
|
}
|
|
19845
20090
|
function CommissionFunctionsDialog({ rule, provider, onClose, onSaved }) {
|
|
19846
|
-
const [functions, setFunctions] =
|
|
20091
|
+
const [functions, setFunctions] = React25__default.useState(
|
|
19847
20092
|
rule.functions.length ? rule.functions : [blankFunction(0)]
|
|
19848
20093
|
);
|
|
19849
|
-
const [saving, setSaving] =
|
|
19850
|
-
const [error, setError] =
|
|
20094
|
+
const [saving, setSaving] = React25__default.useState(false);
|
|
20095
|
+
const [error, setError] = React25__default.useState(null);
|
|
19851
20096
|
function patch(i, changes) {
|
|
19852
20097
|
setFunctions((fs) => fs.map((f, j) => j === i ? { ...f, ...changes } : f));
|
|
19853
20098
|
}
|
|
@@ -20131,19 +20376,19 @@ function functionChip(fn) {
|
|
|
20131
20376
|
return fn.valueType === "percentage" ? `${who}: ${fn.valueAmount}%` : `${who}: R$ ${fn.valueAmount.toFixed(2)}`;
|
|
20132
20377
|
}
|
|
20133
20378
|
function CommissionRulesView({ provider }) {
|
|
20134
|
-
const [rules, setRules] =
|
|
20135
|
-
const [catalogs, setCatalogs] =
|
|
20379
|
+
const [rules, setRules] = React25__default.useState(null);
|
|
20380
|
+
const [catalogs, setCatalogs] = React25__default.useState({
|
|
20136
20381
|
services: [],
|
|
20137
20382
|
categories: [],
|
|
20138
20383
|
professionals: [],
|
|
20139
20384
|
units: []
|
|
20140
20385
|
});
|
|
20141
|
-
const [error, setError] =
|
|
20142
|
-
const [funnel, setFunnel] =
|
|
20143
|
-
const [editing, setEditing] =
|
|
20144
|
-
const [functionsFor, setFunctionsFor] =
|
|
20145
|
-
const [deleting, setDeleting] =
|
|
20146
|
-
const load =
|
|
20386
|
+
const [error, setError] = React25__default.useState(null);
|
|
20387
|
+
const [funnel, setFunnel] = React25__default.useState({});
|
|
20388
|
+
const [editing, setEditing] = React25__default.useState(null);
|
|
20389
|
+
const [functionsFor, setFunctionsFor] = React25__default.useState(null);
|
|
20390
|
+
const [deleting, setDeleting] = React25__default.useState(null);
|
|
20391
|
+
const load = React25__default.useCallback(async () => {
|
|
20147
20392
|
try {
|
|
20148
20393
|
setError(null);
|
|
20149
20394
|
const [r, c] = await Promise.all([
|
|
@@ -20157,17 +20402,17 @@ function CommissionRulesView({ provider }) {
|
|
|
20157
20402
|
setRules([]);
|
|
20158
20403
|
}
|
|
20159
20404
|
}, [provider]);
|
|
20160
|
-
|
|
20405
|
+
React25__default.useEffect(() => {
|
|
20161
20406
|
void load();
|
|
20162
20407
|
}, [load]);
|
|
20163
20408
|
const funnelActive = Object.values(funnel).some(Boolean);
|
|
20164
|
-
const visible =
|
|
20409
|
+
const visible = React25__default.useMemo(() => {
|
|
20165
20410
|
if (!rules) return [];
|
|
20166
20411
|
const ranked = rankRules(rules);
|
|
20167
20412
|
if (!funnelActive) return ranked;
|
|
20168
20413
|
return ranked.filter((r) => r.isDefault || ruleMatches(r, funnel, catalogs));
|
|
20169
20414
|
}, [rules, funnel, funnelActive, catalogs]);
|
|
20170
|
-
const winner =
|
|
20415
|
+
const winner = React25__default.useMemo(() => {
|
|
20171
20416
|
if (!funnelActive) return null;
|
|
20172
20417
|
return visible.find((r) => r.isActive && !r.isDefault) ?? visible.find((r) => r.isActive && r.isDefault) ?? null;
|
|
20173
20418
|
}, [visible, funnelActive]);
|
|
@@ -20182,7 +20427,7 @@ function CommissionRulesView({ provider }) {
|
|
|
20182
20427
|
await provider.duplicateCommissionRule?.(rule.id);
|
|
20183
20428
|
await load();
|
|
20184
20429
|
}
|
|
20185
|
-
const headerActions =
|
|
20430
|
+
const headerActions = React25__default.useMemo(() => [{
|
|
20186
20431
|
id: "new-rule",
|
|
20187
20432
|
label: "Adicionar regra",
|
|
20188
20433
|
icon: Plus,
|
|
@@ -20964,7 +21209,7 @@ function PersonStatementWidget({ person, provider, config }) {
|
|
|
20964
21209
|
] });
|
|
20965
21210
|
}
|
|
20966
21211
|
function SupplierFinancialSettings({ person, provider }) {
|
|
20967
|
-
const initial =
|
|
21212
|
+
const initial = React25__default.useMemo(() => counterpartyAccountingPolicy(person), [person]);
|
|
20968
21213
|
const [accounts, setAccounts] = useState([]);
|
|
20969
21214
|
const [costCenters, setCostCenters] = useState([]);
|
|
20970
21215
|
const [defaultAccountId, setDefaultAccountId] = useState(initial.defaultAccountId ?? "");
|
|
@@ -44175,6 +44420,76 @@ DROP TRIGGER IF EXISTS payee_accounts_one_default ON public.payee_accounts;
|
|
|
44175
44420
|
CREATE TRIGGER payee_accounts_one_default
|
|
44176
44421
|
BEFORE INSERT OR UPDATE OF is_default ON public.payee_accounts
|
|
44177
44422
|
FOR EACH ROW EXECUTE FUNCTION public.trg_payee_accounts_one_default();
|
|
44423
|
+
`;
|
|
44424
|
+
var MIGRATION_116_UM_ESTORNO_NAO_SE_ESTORNA = `-- ---------------------------------------------------------------------------
|
|
44425
|
+
-- 116 \u2014 um estorno n\xE3o se estorna.
|
|
44426
|
+
--
|
|
44427
|
+
-- \`financial_reverse_movement\` aceitava qualquer \`payment\`, inclusive a linha
|
|
44428
|
+
-- que ela mesma lan\xE7a como contrapartida. A tela mirava \xABo \xFAltimo pagamento da
|
|
44429
|
+
-- parcela\xBB, que depois do primeiro estorno \xC9 o estorno: cada clique estornava o
|
|
44430
|
+
-- estorno anterior, o dinheiro ia e voltava, e o pagamento vivo continuava l\xE1 \u2014
|
|
44431
|
+
-- a conta seguia \xABpaga\xBB para sempre. Agora o banco recusa com uma mensagem que
|
|
44432
|
+
-- a tela mostra.
|
|
44433
|
+
--
|
|
44434
|
+
-- Idempotente: s\xF3 rep\xF5e a fun\xE7\xE3o.
|
|
44435
|
+
-- ---------------------------------------------------------------------------
|
|
44436
|
+
|
|
44437
|
+
CREATE OR REPLACE FUNCTION public.financial_reverse_movement(p_movement_id uuid, p_reason text, p_idempotency_key text DEFAULT NULL::text) RETURNS jsonb
|
|
44438
|
+
LANGUAGE plpgsql SECURITY DEFINER
|
|
44439
|
+
SET search_path TO ''
|
|
44440
|
+
AS $$
|
|
44441
|
+
DECLARE
|
|
44442
|
+
v_tenant uuid := public.plg_financial_require_tenant();
|
|
44443
|
+
v_m public.plg_financial_movements%ROWTYPE;
|
|
44444
|
+
v_rev uuid;
|
|
44445
|
+
BEGIN
|
|
44446
|
+
IF nullif(btrim(coalesce(p_reason, '')), '') IS NULL THEN
|
|
44447
|
+
RAISE EXCEPTION 'financial_reverse_movement: a reason is required' USING ERRCODE = '22023';
|
|
44448
|
+
END IF;
|
|
44449
|
+
SELECT * INTO v_m FROM public.plg_financial_movements WHERE id = p_movement_id AND tenant_id = v_tenant;
|
|
44450
|
+
IF NOT FOUND THEN
|
|
44451
|
+
RAISE EXCEPTION 'financial_reverse_movement: movement % not found', p_movement_id USING ERRCODE = 'P0002';
|
|
44452
|
+
END IF;
|
|
44453
|
+
PERFORM public.plg_financial_require_permission('financial.edit', v_m.unit_id);
|
|
44454
|
+
IF v_m.movement_kind NOT IN ('payment', 'transfer') OR v_m.debit_account_id IS NULL THEN
|
|
44455
|
+
RAISE EXCEPTION 'financial_reverse_movement: % is not a money event', p_movement_id USING ERRCODE = '55000';
|
|
44456
|
+
END IF;
|
|
44457
|
+
IF v_m.reverses_id IS NOT NULL THEN
|
|
44458
|
+
RAISE EXCEPTION 'Este lan\xE7amento j\xE1 \xE9 um estorno e n\xE3o pode ser estornado.' USING ERRCODE = '55000';
|
|
44459
|
+
END IF;
|
|
44460
|
+
IF v_m.reversed_by_id IS NOT NULL THEN
|
|
44461
|
+
RETURN jsonb_build_object('reversal_id', v_m.reversed_by_id, 'movement_id', v_m.id, 'replayed', true);
|
|
44462
|
+
END IF;
|
|
44463
|
+
IF p_idempotency_key IS NOT NULL THEN
|
|
44464
|
+
PERFORM public.plg_financial_claim_idempotency(v_tenant, p_idempotency_key);
|
|
44465
|
+
SELECT m.id INTO v_rev FROM public.plg_financial_movements m WHERE m.tenant_id = v_tenant AND m.idempotency_key = p_idempotency_key;
|
|
44466
|
+
IF v_rev IS NOT NULL THEN
|
|
44467
|
+
RETURN jsonb_build_object('reversal_id', v_rev, 'movement_id', v_m.id, 'replayed', true);
|
|
44468
|
+
END IF;
|
|
44469
|
+
END IF;
|
|
44470
|
+
|
|
44471
|
+
INSERT INTO public.plg_financial_movements
|
|
44472
|
+
(tenant_id, unit_id, invoice_id, financial_invoice_id, financial_invoice_installment_id, direction, movement_kind, amount, paid_amount, status,
|
|
44473
|
+
due_date, payment_date, installment_number, method, cash_session_id, bank_account_id, reason, notes, metadata,
|
|
44474
|
+
idempotency_key, created_by, reverses_id, debit_account_id, credit_account_id)
|
|
44475
|
+
VALUES
|
|
44476
|
+
(v_m.tenant_id, v_m.unit_id, v_m.invoice_id, v_m.financial_invoice_id, v_m.financial_invoice_installment_id,
|
|
44477
|
+
CASE WHEN v_m.direction = 'credit' THEN 'debit' ELSE 'credit' END, v_m.movement_kind, v_m.amount, v_m.amount, 'paid',
|
|
44478
|
+
current_date, current_date, v_m.installment_number, v_m.method, v_m.cash_session_id, v_m.bank_account_id, btrim(p_reason),
|
|
44479
|
+
'Estorno de ' || v_m.id::text,
|
|
44480
|
+
jsonb_build_object('source', 'financial_reverse_movement', 'reversal_of', v_m.id, 'reason', btrim(p_reason)),
|
|
44481
|
+
p_idempotency_key, auth.uid(), v_m.id, v_m.credit_account_id, v_m.debit_account_id)
|
|
44482
|
+
RETURNING id INTO v_rev;
|
|
44483
|
+
|
|
44484
|
+
UPDATE public.plg_financial_movements SET reversed_by_id = v_rev, reason = coalesce(reason, btrim(p_reason)), updated_at = now()
|
|
44485
|
+
WHERE id = v_m.id;
|
|
44486
|
+
IF v_m.financial_invoice_installment_id IS NOT NULL THEN PERFORM public.plg_financial_sync_mirror(v_m.financial_invoice_installment_id); END IF;
|
|
44487
|
+
|
|
44488
|
+
PERFORM public.plg_financial_audit(v_tenant, 'financial.movement.reverse', 'plg_financial_movements', v_m.id::text,
|
|
44489
|
+
jsonb_build_object('reversal_id', v_rev, 'amount', v_m.amount, 'reason', btrim(p_reason), 'idempotency_key', p_idempotency_key));
|
|
44490
|
+
RETURN jsonb_build_object('reversal_id', v_rev, 'movement_id', v_m.id, 'replayed', false);
|
|
44491
|
+
END $$;
|
|
44492
|
+
|
|
44178
44493
|
`;
|
|
44179
44494
|
var MIGRATIONS = [
|
|
44180
44495
|
{ id: "000_baseline", sql: MIGRATION_000_BASELINE },
|
|
@@ -44292,7 +44607,8 @@ var MIGRATIONS = [
|
|
|
44292
44607
|
{ id: "112_a_linha_do_extrato_nao_e_um_lancamento_ainda", sql: MIGRATION_112_A_LINHA_DO_EXTRATO_NAO_E_UM_LANCAMENTO_AINDA },
|
|
44293
44608
|
{ id: "113_so_a_conta_integrada_aparece_na_conciliacao", sql: MIGRATION_113_SO_A_CONTA_INTEGRADA_APARECE_NA_CONCILIACAO },
|
|
44294
44609
|
{ id: "114_a_parcela_diz_por_qual_conta_ela_foi_paga", sql: MIGRATION_114_A_PARCELA_DIZ_POR_QUAL_CONTA_ELA_FOI_PAGA },
|
|
44295
|
-
{ id: "115_a_remessa_aponta_para_a_conta_que_existe", sql: MIGRATION_115_A_REMESSA_APONTA_PARA_A_CONTA_QUE_EXISTE }
|
|
44610
|
+
{ id: "115_a_remessa_aponta_para_a_conta_que_existe", sql: MIGRATION_115_A_REMESSA_APONTA_PARA_A_CONTA_QUE_EXISTE },
|
|
44611
|
+
{ id: "116_um_estorno_nao_se_estorna", sql: MIGRATION_116_UM_ESTORNO_NAO_SE_ESTORNA }
|
|
44296
44612
|
];
|
|
44297
44613
|
var STANDALONE_CONFIG = resolveConfig();
|
|
44298
44614
|
registerTranslations(financialLocales);
|
|
@@ -44302,8 +44618,8 @@ function ReceivePaymentModal({
|
|
|
44302
44618
|
onClose,
|
|
44303
44619
|
onPaid
|
|
44304
44620
|
}) {
|
|
44305
|
-
const provider =
|
|
44306
|
-
const store6 =
|
|
44621
|
+
const provider = React25__default.useMemo(() => createSafeFinancialProvider(), []);
|
|
44622
|
+
const store6 = React25__default.useMemo(() => createFinancialStore(provider), [provider]);
|
|
44307
44623
|
return /* @__PURE__ */ jsx(FinancialContextProvider, { config: STANDALONE_CONFIG, provider, store: store6, children: /* @__PURE__ */ jsx(
|
|
44308
44624
|
PaymentModal,
|
|
44309
44625
|
{
|
|
@@ -44321,7 +44637,7 @@ function createFinancialSettingsPlugin(options) {
|
|
|
44321
44637
|
...financialRegistries.filter((r) => RECEIVING_REGISTRIES.includes(r.id)),
|
|
44322
44638
|
...options?.extraRegistries ?? []
|
|
44323
44639
|
];
|
|
44324
|
-
const SettingsTab = () =>
|
|
44640
|
+
const SettingsTab = () => React25__default.createElement(PluginSettingsPanel, {
|
|
44325
44641
|
title: "Pagamentos",
|
|
44326
44642
|
registries,
|
|
44327
44643
|
hostPluginId: "financial",
|
|
@@ -44378,27 +44694,27 @@ function ClientAccountPanel({
|
|
|
44378
44694
|
currency = BRL
|
|
44379
44695
|
}) {
|
|
44380
44696
|
const provider = useFinancialProvider();
|
|
44381
|
-
const [account, setAccount] =
|
|
44382
|
-
const [busy, setBusy] =
|
|
44383
|
-
const [viewInvoiceId, setViewInvoiceId] =
|
|
44384
|
-
const [comprando, setComprando] =
|
|
44385
|
-
const [buscaServico, setBuscaServico] =
|
|
44386
|
-
const [catalogo, setCatalogo] =
|
|
44387
|
-
const [escolhidos, setEscolhidos] =
|
|
44388
|
-
const [comprandoBusy, setComprandoBusy] =
|
|
44389
|
-
const [erroCompra, setErroCompra] =
|
|
44390
|
-
const load =
|
|
44697
|
+
const [account, setAccount] = React25__default.useState(null);
|
|
44698
|
+
const [busy, setBusy] = React25__default.useState(false);
|
|
44699
|
+
const [viewInvoiceId, setViewInvoiceId] = React25__default.useState(null);
|
|
44700
|
+
const [comprando, setComprando] = React25__default.useState(false);
|
|
44701
|
+
const [buscaServico, setBuscaServico] = React25__default.useState("");
|
|
44702
|
+
const [catalogo, setCatalogo] = React25__default.useState([]);
|
|
44703
|
+
const [escolhidos, setEscolhidos] = React25__default.useState([]);
|
|
44704
|
+
const [comprandoBusy, setComprandoBusy] = React25__default.useState(false);
|
|
44705
|
+
const [erroCompra, setErroCompra] = React25__default.useState(null);
|
|
44706
|
+
const load = React25__default.useCallback(async () => {
|
|
44391
44707
|
if (!personId) return;
|
|
44392
44708
|
setAccount(await provider.getClientAccount(personId));
|
|
44393
44709
|
}, [personId, provider]);
|
|
44394
|
-
|
|
44710
|
+
React25__default.useEffect(() => {
|
|
44395
44711
|
void load();
|
|
44396
44712
|
}, [load]);
|
|
44397
44713
|
const viewInvoice = account?.invoices.find((i) => i.id === viewInvoiceId) ?? null;
|
|
44398
44714
|
const viewEditable = invoiceOpensForEditing(viewInvoice?.status);
|
|
44399
44715
|
const forThis = account?.invoices.filter((i) => orderId && i.orderId === orderId) ?? [];
|
|
44400
44716
|
const hasForThis = forThis.length > 0;
|
|
44401
|
-
|
|
44717
|
+
React25__default.useEffect(() => {
|
|
44402
44718
|
if (!comprando) return;
|
|
44403
44719
|
let vivo = true;
|
|
44404
44720
|
const t2 = setTimeout(async () => {
|
|
@@ -44673,8 +44989,8 @@ function ClientAccountPanel({
|
|
|
44673
44989
|
] });
|
|
44674
44990
|
}
|
|
44675
44991
|
function ClientAccountInline(props) {
|
|
44676
|
-
const provider =
|
|
44677
|
-
const store6 =
|
|
44992
|
+
const provider = React25__default.useMemo(() => createSafeFinancialProvider(), []);
|
|
44993
|
+
const store6 = React25__default.useMemo(() => createFinancialStore(provider), [provider]);
|
|
44678
44994
|
return /* @__PURE__ */ jsx(FinancialContextProvider, { config: STANDALONE_CONFIG, provider, store: store6, children: /* @__PURE__ */ jsx(ClientAccountPanel, { ...props }) });
|
|
44679
44995
|
}
|
|
44680
44996
|
function ClientAccountModal({
|
|
@@ -44723,11 +45039,11 @@ function createFinancialPlugin(options) {
|
|
|
44723
45039
|
const settingsRegistries = registries.filter((r) => r.id !== "bank-accounts");
|
|
44724
45040
|
const AccountsRegistryPage = createCrudPage(financialAccountEntity, { feature: "financial" });
|
|
44725
45041
|
AccountsRegistryPage.displayName = "FinancialAccountsRegistryPage";
|
|
44726
|
-
const PersonStatementBound = (props) =>
|
|
45042
|
+
const PersonStatementBound = (props) => React25__default.createElement(PersonStatementWidget, { person: props.item, provider, config });
|
|
44727
45043
|
PersonStatementBound.displayName = "FinancialPersonStatement";
|
|
44728
|
-
const SupplierFinancialSettingsBound = (props) =>
|
|
45044
|
+
const SupplierFinancialSettingsBound = (props) => React25__default.createElement(SupplierFinancialSettings, { person: props.item, provider });
|
|
44729
45045
|
SupplierFinancialSettingsBound.displayName = "FinancialSupplierSettings";
|
|
44730
|
-
const PageComponent = () =>
|
|
45046
|
+
const PageComponent = () => React25__default.createElement(FinancialPage, { config, provider, store: store6, registries });
|
|
44731
45047
|
const AgentMount = createFinancialAgentMount({ config, provider });
|
|
44732
45048
|
return {
|
|
44733
45049
|
id: "financial",
|
|
@@ -44785,7 +45101,7 @@ function createFinancialPlugin(options) {
|
|
|
44785
45101
|
// tem — lá é um ícone no cabeçalho, de qualquer tela.
|
|
44786
45102
|
headerControls: config.modules.cashRegisters ? [{
|
|
44787
45103
|
id: "financial.cash-session",
|
|
44788
|
-
component: (() =>
|
|
45104
|
+
component: (() => React25__default.createElement(CashSessionHeaderControl, { config, provider, store: store6 })),
|
|
44789
45105
|
order: 90,
|
|
44790
45106
|
permission: { feature: "financial", action: "read" }
|
|
44791
45107
|
}] : [],
|
|
@@ -45016,9 +45332,9 @@ function createFinancialPlugin(options) {
|
|
|
45016
45332
|
// lado, e a corrida de "Plugins" não é partida ao meio.
|
|
45017
45333
|
group: "Financeiro",
|
|
45018
45334
|
component: (() => {
|
|
45019
|
-
const FinancialSettingsTab = () =>
|
|
45335
|
+
const FinancialSettingsTab = () => React25__default.createElement(PluginSettingsPanel, {
|
|
45020
45336
|
title: "Financial Settings",
|
|
45021
|
-
generalSettings:
|
|
45337
|
+
generalSettings: React25__default.createElement(FinancialGeneralSettings, { config }),
|
|
45022
45338
|
registries: settingsRegistries,
|
|
45023
45339
|
hostPluginId: "financial",
|
|
45024
45340
|
routeBase: "/settings/financial"
|
|
@@ -45043,7 +45359,7 @@ function createFinancialPlugin(options) {
|
|
|
45043
45359
|
icon: "HandCoins",
|
|
45044
45360
|
group: "Financeiro",
|
|
45045
45361
|
component: (() => {
|
|
45046
|
-
const CommissionRulesTab = () =>
|
|
45362
|
+
const CommissionRulesTab = () => React25__default.createElement(CommissionRulesView, { provider });
|
|
45047
45363
|
CommissionRulesTab.displayName = "CommissionRulesTab";
|
|
45048
45364
|
return CommissionRulesTab;
|
|
45049
45365
|
})(),
|