@fayz-ai/plugin-fiscal-br 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data/inbox.d.ts +73 -0
- package/dist/data/inbox.d.ts.map +1 -1
- package/dist/index.js +803 -144
- package/dist/index.js.map +1 -1
- package/dist/migrations/index.d.ts +1 -0
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/views/InboundNotesView.d.ts.map +1 -1
- package/dist/views/InvoiceNotesButton.d.ts.map +1 -1
- package/dist/views/ManifestView.d.ts.map +1 -1
- package/dist/views/NoteAttachmentsCard.d.ts +19 -0
- package/dist/views/NoteAttachmentsCard.d.ts.map +1 -0
- package/dist/views/NoteReconcileView.d.ts.map +1 -1
- package/dist/views/PullByKeyDialog.d.ts +13 -0
- package/dist/views/PullByKeyDialog.d.ts.map +1 -0
- package/dist/views/inventoryView.d.ts.map +1 -1
- package/functions/fiscalbr-dfe-pull/index.ts +192 -0
- package/functions/fiscalbr-payment-extract/index.ts +138 -0
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { recordRailFields, RECORD_GROUP, activeFacet, getSupabaseClientOptional, connectionSettings, connectionStatus, definePlugin, createConnectionStore, settingsStatus, maskCpfCnpj } from '@fayz-ai/core';
|
|
2
|
-
import
|
|
3
|
-
import { ModalHeader, ModalTitle, ModalBody, Skeleton, AiActionButton,
|
|
1
|
+
import { recordRailFields, RECORD_GROUP, activeFacet, describeError, getSupabaseClientOptional, connectionSettings, connectionStatus, definePlugin, createConnectionStore, settingsStatus, maskCpfCnpj } from '@fayz-ai/core';
|
|
2
|
+
import React7, { useState, useCallback, useEffect, useMemo, useRef } from 'react';
|
|
3
|
+
import { ModalHeader, ModalTitle, ModalBody, Skeleton, AiActionButton, Dropdown, DropdownTrigger, Button, DropdownContent, DropdownItem, Hint, Card, SearchSelect, Input, EmBreve, DatePicker, ModalFooter, SubpageHeader, useFilterDraft, RowActions, PageHeaderActions, FilterPanel, FilterPanelField, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, SearchField, TooltipProvider, DataTable, Tooltip, TooltipTrigger, TooltipContent, ListFilterBar, Modal, ModalContent, ModalDescription, Badge, SegmentedControl, ComingSoon, toast, CardHeader, CardTitle, CardContent, CardDescription, Switch } from '@fayz-ai/ui';
|
|
4
4
|
export { ComingSoon, EmBreve } from '@fayz-ai/ui';
|
|
5
|
-
import { registerDocumentOpener, getActiveTenantId, useUnitFilter, usePermissionOptional, UNIT_DETAIL_ZONES, adminNavigateTo } from '@fayz-ai/admin';
|
|
6
|
-
import {
|
|
5
|
+
import { registerDocumentOpener, PersonLink, getActiveTenantId, useUnitFilter, usePermissionOptional, UNIT_DETAIL_ZONES, adminNavigateTo } from '@fayz-ai/admin';
|
|
6
|
+
import { Loader2, Download, ChevronDown, FileCode2, FileText, RefreshCw, UserPlus, Gift, AlertTriangle, ChevronRight, Check, Trash2, Plus, Image, UploadCloud, Paperclip, ScanLine, Eye, ListChecks, Inbox, KeyRound, FileDown, ShieldCheck, ExternalLink, CheckCircle2, FileCheck2, XCircle, X, Info } from 'lucide-react';
|
|
7
7
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
8
|
import { FINANCIAL_INVOICE_ZONES } from '@fayz-ai/plugin-financial';
|
|
9
9
|
|
|
@@ -3771,6 +3771,119 @@ REVOKE ALL ON FUNCTION public.fiscalbr_note_apply(uuid, text, jsonb, jsonb) FROM
|
|
|
3771
3771
|
GRANT EXECUTE ON FUNCTION public.fiscalbr_note_for_provider(uuid, text) TO authenticated;
|
|
3772
3772
|
GRANT EXECUTE ON FUNCTION public.fiscalbr_note_apply(uuid, text, jsonb, jsonb) TO authenticated;
|
|
3773
3773
|
`;
|
|
3774
|
+
var MIGRATION_020_A_NOTA_ACHA_O_FORNECEDOR_PELO_CNPJ = `-- A nota acha o fornecedor pelo CNPJ \u2014 e, se n\xE3o achar, cadastra.
|
|
3775
|
+
--
|
|
3776
|
+
-- O est\xE1gio (009) s\xF3 casava o CNPJ no momento do import. As notas que vieram
|
|
3777
|
+
-- do V1 atravessaram sem o v\xEDnculo (003 deixou para "a costura"), e um
|
|
3778
|
+
-- fornecedor cadastrado depois nunca era religado: 1029 notas com o fornecedor
|
|
3779
|
+
-- no cadastro e a tela dizendo "n\xE3o est\xE1 no cadastro", e o t\xEDtulo aceito no V2
|
|
3780
|
+
-- nascendo sem contraparte (o tra\xE7o em Contas a Pagar).
|
|
3781
|
+
--
|
|
3782
|
+
-- O V1 nunca pediu cadastro: ao aceitar, \`resolveSupplierId\` procura o
|
|
3783
|
+
-- fornecedor pelo CNPJ e, sem achar, cria com o nome e o CNPJ da nota. Esta
|
|
3784
|
+
-- fun\xE7\xE3o \xE9 esse gesto, com duas pontas:
|
|
3785
|
+
--
|
|
3786
|
+
-- p_create = false s\xF3 casa (ao abrir a nota)
|
|
3787
|
+
-- p_create = true casa ou cria (antes de aceitar)
|
|
3788
|
+
--
|
|
3789
|
+
-- O t\xEDtulo da nota, se j\xE1 existe e est\xE1 SEM contraparte, recebe a mesma pessoa.
|
|
3790
|
+
-- Nunca troca um v\xEDnculo gravado. Idempotente.
|
|
3791
|
+
|
|
3792
|
+
CREATE OR REPLACE FUNCTION public.plg_fiscalbr_supplier_for_cnpj(p_tenant uuid, p_cnpj text)
|
|
3793
|
+
RETURNS uuid
|
|
3794
|
+
LANGUAGE sql
|
|
3795
|
+
STABLE
|
|
3796
|
+
SET search_path TO ''
|
|
3797
|
+
AS $$
|
|
3798
|
+
SELECT p.id FROM public.people p
|
|
3799
|
+
WHERE p.tenant_id = p_tenant
|
|
3800
|
+
AND p_cnpj <> ''
|
|
3801
|
+
AND public.plg_fiscalbr_digits(p.document_number) = p_cnpj
|
|
3802
|
+
ORDER BY (p.kind = 'supplier') DESC, p.created_at
|
|
3803
|
+
LIMIT 1
|
|
3804
|
+
$$;
|
|
3805
|
+
|
|
3806
|
+
CREATE OR REPLACE FUNCTION public.fiscalbr_link_inbox_supplier(p_document_id uuid, p_create boolean DEFAULT false)
|
|
3807
|
+
RETURNS jsonb
|
|
3808
|
+
LANGUAGE plpgsql
|
|
3809
|
+
SECURITY DEFINER
|
|
3810
|
+
SET search_path TO ''
|
|
3811
|
+
AS $$
|
|
3812
|
+
DECLARE
|
|
3813
|
+
v_tenant uuid := public.plg_financial_require_tenant();
|
|
3814
|
+
v_doc public.plg_fiscalbr_inbox_documents%ROWTYPE;
|
|
3815
|
+
v_cnpj text;
|
|
3816
|
+
v_party uuid;
|
|
3817
|
+
v_created boolean := false;
|
|
3818
|
+
BEGIN
|
|
3819
|
+
SELECT * INTO v_doc FROM public.plg_fiscalbr_inbox_documents
|
|
3820
|
+
WHERE id = p_document_id AND tenant_id = v_tenant;
|
|
3821
|
+
IF NOT FOUND THEN
|
|
3822
|
+
RAISE EXCEPTION 'fiscal: inbox note not found' USING ERRCODE = 'P0002';
|
|
3823
|
+
END IF;
|
|
3824
|
+
PERFORM public.plg_financial_require_permission(
|
|
3825
|
+
CASE WHEN p_create THEN 'financial.create' ELSE 'financial.read' END, v_doc.unit_id);
|
|
3826
|
+
|
|
3827
|
+
v_party := v_doc.supplier_party_id;
|
|
3828
|
+
v_cnpj := public.plg_fiscalbr_digits(v_doc.supplier_cnpj);
|
|
3829
|
+
|
|
3830
|
+
IF v_party IS NULL THEN
|
|
3831
|
+
v_party := public.plg_fiscalbr_supplier_for_cnpj(v_tenant, v_cnpj);
|
|
3832
|
+
END IF;
|
|
3833
|
+
|
|
3834
|
+
-- Without a CNPJ there is nothing to match on; a name-only person would be a
|
|
3835
|
+
-- duplicate waiting to happen, so creation needs the document.
|
|
3836
|
+
IF v_party IS NULL AND p_create AND v_cnpj <> '' THEN
|
|
3837
|
+
INSERT INTO public.people (tenant_id, kind, name, document_number)
|
|
3838
|
+
VALUES (v_tenant, 'supplier', coalesce(nullif(trim(v_doc.supplier_name), ''), 'Fornecedor ' || v_cnpj), v_cnpj)
|
|
3839
|
+
RETURNING id INTO v_party;
|
|
3840
|
+
v_created := true;
|
|
3841
|
+
END IF;
|
|
3842
|
+
|
|
3843
|
+
IF v_party IS NOT NULL AND v_doc.supplier_party_id IS NULL THEN
|
|
3844
|
+
UPDATE public.plg_fiscalbr_inbox_documents
|
|
3845
|
+
SET supplier_party_id = v_party
|
|
3846
|
+
WHERE id = v_doc.id AND supplier_party_id IS NULL;
|
|
3847
|
+
END IF;
|
|
3848
|
+
|
|
3849
|
+
IF v_party IS NOT NULL AND v_doc.invoice_id IS NOT NULL THEN
|
|
3850
|
+
UPDATE public.plg_financial_invoices
|
|
3851
|
+
SET counterparty_person_id = v_party
|
|
3852
|
+
WHERE id = v_doc.invoice_id AND tenant_id = v_tenant AND counterparty_person_id IS NULL;
|
|
3853
|
+
END IF;
|
|
3854
|
+
|
|
3855
|
+
RETURN jsonb_build_object('supplier_party_id', v_party, 'created', v_created);
|
|
3856
|
+
END;
|
|
3857
|
+
$$;
|
|
3858
|
+
|
|
3859
|
+
REVOKE ALL ON FUNCTION public.fiscalbr_link_inbox_supplier(uuid, boolean) FROM PUBLIC;
|
|
3860
|
+
GRANT EXECUTE ON FUNCTION public.fiscalbr_link_inbox_supplier(uuid, boolean) TO authenticated;
|
|
3861
|
+
|
|
3862
|
+
-- Backfill: match only, NULLs only. Nothing is created here \u2014 creating a person
|
|
3863
|
+
-- is the operator's gesture (accepting), not a migration's.
|
|
3864
|
+
WITH p AS (
|
|
3865
|
+
SELECT DISTINCT ON (tenant_id, dg) tenant_id, dg, id
|
|
3866
|
+
FROM (SELECT tenant_id, id, kind, created_at, public.plg_fiscalbr_digits(document_number) AS dg
|
|
3867
|
+
FROM public.people
|
|
3868
|
+
WHERE document_number IS NOT NULL) x
|
|
3869
|
+
WHERE length(dg) = 14
|
|
3870
|
+
ORDER BY tenant_id, dg, (kind = 'supplier') DESC, created_at
|
|
3871
|
+
)
|
|
3872
|
+
UPDATE public.plg_fiscalbr_inbox_documents d
|
|
3873
|
+
SET supplier_party_id = p.id
|
|
3874
|
+
FROM p
|
|
3875
|
+
WHERE d.supplier_party_id IS NULL
|
|
3876
|
+
AND p.tenant_id = d.tenant_id
|
|
3877
|
+
AND p.dg = public.plg_fiscalbr_digits(d.supplier_cnpj);
|
|
3878
|
+
|
|
3879
|
+
UPDATE public.plg_financial_invoices i
|
|
3880
|
+
SET counterparty_person_id = d.supplier_party_id
|
|
3881
|
+
FROM public.plg_fiscalbr_inbox_documents d
|
|
3882
|
+
WHERE d.invoice_id = i.id
|
|
3883
|
+
AND d.tenant_id = i.tenant_id
|
|
3884
|
+
AND d.supplier_party_id IS NOT NULL
|
|
3885
|
+
AND i.counterparty_person_id IS NULL;
|
|
3886
|
+
`;
|
|
3774
3887
|
var MIGRATIONS = [
|
|
3775
3888
|
{ id: "000_baseline", sql: MIGRATION_000_BASELINE },
|
|
3776
3889
|
{ id: "001_preserve_terminal_results_and_recover_leases", sql: MIGRATION_001_PRESERVE_TERMINAL_RESULTS_AND_RECOVER_LEASES },
|
|
@@ -3791,7 +3904,8 @@ var MIGRATIONS = [
|
|
|
3791
3904
|
{ id: "016_a_nota_guarda_o_proprio_xml", sql: MIGRATION_016_A_NOTA_GUARDA_O_PROPRIO_XML },
|
|
3792
3905
|
{ id: "017_quem_emite_e_o_cnpj_nao_a_loja", sql: MIGRATION_017_QUEM_EMITE_E_O_CNPJ_NAO_A_LOJA },
|
|
3793
3906
|
{ id: "018_a_nota_do_v1_alcanca_a_conta", sql: MIGRATION_018_A_NOTA_DO_V1_ALCANCA_A_CONTA },
|
|
3794
|
-
{ id: "019_a_nota_emitida_se_cancela_pelo_v2", sql: MIGRATION_019_A_NOTA_EMITIDA_SE_CANCELA_PELO_V2 }
|
|
3907
|
+
{ id: "019_a_nota_emitida_se_cancela_pelo_v2", sql: MIGRATION_019_A_NOTA_EMITIDA_SE_CANCELA_PELO_V2 },
|
|
3908
|
+
{ id: "020_a_nota_acha_o_fornecedor_pelo_cnpj", sql: MIGRATION_020_A_NOTA_ACHA_O_FORNECEDOR_PELO_CNPJ }
|
|
3795
3909
|
];
|
|
3796
3910
|
var taxGroupEntity = {
|
|
3797
3911
|
name: "Grupo fiscal",
|
|
@@ -4366,6 +4480,44 @@ async function stageNoteFromXml(xml, options = {}) {
|
|
|
4366
4480
|
parsed
|
|
4367
4481
|
};
|
|
4368
4482
|
}
|
|
4483
|
+
var PullByKeyError = class extends Error {
|
|
4484
|
+
constructor(message, code, options) {
|
|
4485
|
+
super(message);
|
|
4486
|
+
this.code = code;
|
|
4487
|
+
this.options = options;
|
|
4488
|
+
}
|
|
4489
|
+
};
|
|
4490
|
+
async function pullNoteByKey(key, options = {}) {
|
|
4491
|
+
const { data, error } = await sb().functions.invoke("fiscalbr-dfe-pull", {
|
|
4492
|
+
body: { key: key.replace(/\D/g, ""), legalEntityId: options.legalEntityId, tenantId: getActiveTenantId() ?? null }
|
|
4493
|
+
});
|
|
4494
|
+
if (error) {
|
|
4495
|
+
let body = null;
|
|
4496
|
+
try {
|
|
4497
|
+
body = await error?.context?.json?.();
|
|
4498
|
+
} catch {
|
|
4499
|
+
}
|
|
4500
|
+
throw new PullByKeyError(body?.error || error.message || "Falha ao falar com a SEFAZ.", body?.code, body?.options);
|
|
4501
|
+
}
|
|
4502
|
+
if (data?.pending) return { status: "pending", message: String(data.message ?? "") };
|
|
4503
|
+
if (!data?.xml) throw new PullByKeyError("A SEFAZ n\xE3o devolveu o XML desta nota.");
|
|
4504
|
+
return { status: "staged", ...await stageNoteFromXml(String(data.xml), { unitId: options.unitId }) };
|
|
4505
|
+
}
|
|
4506
|
+
async function getInboxNotePdf(accessKey) {
|
|
4507
|
+
const { data, error } = await sb().functions.invoke("fiscalbr-dfe-pull", {
|
|
4508
|
+
body: { action: "pdf", key: accessKey, tenantId: getActiveTenantId() ?? null }
|
|
4509
|
+
});
|
|
4510
|
+
if (error) {
|
|
4511
|
+
let body = null;
|
|
4512
|
+
try {
|
|
4513
|
+
body = await error?.context?.json?.();
|
|
4514
|
+
} catch {
|
|
4515
|
+
}
|
|
4516
|
+
throw new PullByKeyError(body?.error || error.message || "Falha ao buscar o DANFE.", body?.code);
|
|
4517
|
+
}
|
|
4518
|
+
if (!(data instanceof Blob)) throw new PullByKeyError("O servi\xE7o fiscal n\xE3o devolveu um PDF.");
|
|
4519
|
+
return data;
|
|
4520
|
+
}
|
|
4369
4521
|
async function saveNoteDecision(input) {
|
|
4370
4522
|
const { data, error } = await sb().rpc("fiscalbr_save_inbox_decision", {
|
|
4371
4523
|
p_document_id: input.documentId,
|
|
@@ -4404,7 +4556,16 @@ async function saveNoteDecision(input) {
|
|
|
4404
4556
|
reconciled: Number(res.reconciled ?? 0)
|
|
4405
4557
|
};
|
|
4406
4558
|
}
|
|
4559
|
+
async function linkInboxSupplier(documentId, create = false) {
|
|
4560
|
+
const { data, error } = await sb().rpc("fiscalbr_link_inbox_supplier", { p_document_id: documentId, p_create: create });
|
|
4561
|
+
if (error) throw error;
|
|
4562
|
+
const res = data ?? {};
|
|
4563
|
+
return { supplierPartyId: res.supplier_party_id ?? null, created: Boolean(res.created) };
|
|
4564
|
+
}
|
|
4407
4565
|
async function acceptNote(documentId, locationId) {
|
|
4566
|
+
await linkInboxSupplier(documentId, true).catch((e) => {
|
|
4567
|
+
if (e?.code !== "PGRST202" && e?.code !== "42883") throw e;
|
|
4568
|
+
});
|
|
4408
4569
|
const { data, error } = await sb().rpc("fiscalbr_accept_inbox_document", {
|
|
4409
4570
|
p_document_id: documentId,
|
|
4410
4571
|
p_location_id: locationId ?? null
|
|
@@ -4531,6 +4692,222 @@ async function listSupplierMap(supplierCnpj) {
|
|
|
4531
4692
|
lastUsedAt: m.last_used_at ?? null
|
|
4532
4693
|
}));
|
|
4533
4694
|
}
|
|
4695
|
+
var NOTE_SUBJECT = "fiscalbr_inbox_document";
|
|
4696
|
+
var INVOICE_SUBJECT = "financial_invoice";
|
|
4697
|
+
async function listNoteAttachments(noteId, invoiceId) {
|
|
4698
|
+
const subjects = [`and(subject_type.eq.${NOTE_SUBJECT},subject_id.eq.${noteId})`];
|
|
4699
|
+
if (invoiceId) subjects.push(`and(subject_type.eq.${INVOICE_SUBJECT},subject_id.eq.${invoiceId})`);
|
|
4700
|
+
const { data, error } = await sb().from("documents").select("id, file_name, file_size, mime_type, storage_bucket, storage_path, created_at").or(subjects.join(",")).eq("is_active", true).order("created_at");
|
|
4701
|
+
if (error) throw error;
|
|
4702
|
+
const rows = data ?? [];
|
|
4703
|
+
const signed = /* @__PURE__ */ new Map();
|
|
4704
|
+
const byBucket = /* @__PURE__ */ new Map();
|
|
4705
|
+
for (const r of rows) {
|
|
4706
|
+
if (!r.storage_bucket || !r.storage_path) continue;
|
|
4707
|
+
byBucket.set(r.storage_bucket, [...byBucket.get(r.storage_bucket) ?? [], r.storage_path]);
|
|
4708
|
+
}
|
|
4709
|
+
for (const [bucket, paths] of byBucket) {
|
|
4710
|
+
const { data: urls } = await sb().storage.from(bucket).createSignedUrls(paths, 60 * 30);
|
|
4711
|
+
for (const u of urls ?? []) if (u.path && u.signedUrl) signed.set(u.path, u.signedUrl);
|
|
4712
|
+
}
|
|
4713
|
+
return rows.map((r) => ({
|
|
4714
|
+
id: r.id,
|
|
4715
|
+
fileName: r.file_name ?? "Anexo",
|
|
4716
|
+
fileSize: r.file_size ?? void 0,
|
|
4717
|
+
mimeType: r.mime_type ?? void 0,
|
|
4718
|
+
url: signed.get(r.storage_path) ?? void 0,
|
|
4719
|
+
createdAt: r.created_at
|
|
4720
|
+
}));
|
|
4721
|
+
}
|
|
4722
|
+
async function addNoteAttachment(noteId, invoiceId, file) {
|
|
4723
|
+
const tenantId = getActiveTenantId();
|
|
4724
|
+
if (!tenantId) throw new Error("Conta sem empresa ativa");
|
|
4725
|
+
const subjectType = invoiceId ? INVOICE_SUBJECT : NOTE_SUBJECT;
|
|
4726
|
+
const subjectId = invoiceId ?? noteId;
|
|
4727
|
+
const path = `${tenantId}/${subjectType}/${subjectId}/${Date.now()}_${file.name.replace(/[^\w.\-]+/g, "_")}`;
|
|
4728
|
+
const { error: upErr } = await sb().storage.from("attachments").upload(path, file, { contentType: file.type || void 0 });
|
|
4729
|
+
if (upErr) throw upErr;
|
|
4730
|
+
const { error } = await sb().from("documents").insert({
|
|
4731
|
+
tenant_id: tenantId,
|
|
4732
|
+
kind: "attachment",
|
|
4733
|
+
status: "active",
|
|
4734
|
+
subject_type: subjectType,
|
|
4735
|
+
subject_id: subjectId,
|
|
4736
|
+
file_name: file.name,
|
|
4737
|
+
file_size: file.size,
|
|
4738
|
+
mime_type: file.type || null,
|
|
4739
|
+
storage_provider: "supabase",
|
|
4740
|
+
storage_bucket: "attachments",
|
|
4741
|
+
storage_path: path
|
|
4742
|
+
});
|
|
4743
|
+
if (error) {
|
|
4744
|
+
await sb().storage.from("attachments").remove([path]).catch(() => {
|
|
4745
|
+
});
|
|
4746
|
+
throw error;
|
|
4747
|
+
}
|
|
4748
|
+
}
|
|
4749
|
+
async function removeNoteAttachment(id) {
|
|
4750
|
+
const { error } = await sb().from("documents").update({ is_active: false }).eq("id", id);
|
|
4751
|
+
if (error) throw error;
|
|
4752
|
+
}
|
|
4753
|
+
async function moveNoteAttachmentsToInvoice(noteId, invoiceId) {
|
|
4754
|
+
const { error } = await sb().from("documents").update({ subject_type: INVOICE_SUBJECT, subject_id: invoiceId }).eq("subject_type", NOTE_SUBJECT).eq("subject_id", noteId);
|
|
4755
|
+
if (error) throw error;
|
|
4756
|
+
}
|
|
4757
|
+
async function extractPaymentCode(file) {
|
|
4758
|
+
const base64 = await new Promise((resolve, reject) => {
|
|
4759
|
+
const reader = new FileReader();
|
|
4760
|
+
reader.onload = () => {
|
|
4761
|
+
const r = String(reader.result);
|
|
4762
|
+
resolve(r.slice(r.indexOf(",") + 1));
|
|
4763
|
+
};
|
|
4764
|
+
reader.onerror = () => reject(reader.error);
|
|
4765
|
+
reader.readAsDataURL(file);
|
|
4766
|
+
});
|
|
4767
|
+
const { data, error } = await sb().functions.invoke("fiscalbr-payment-extract", {
|
|
4768
|
+
body: { name: file.name, mime: file.type, base64 }
|
|
4769
|
+
});
|
|
4770
|
+
if (error) {
|
|
4771
|
+
let body = null;
|
|
4772
|
+
try {
|
|
4773
|
+
body = await error?.context?.json?.();
|
|
4774
|
+
} catch {
|
|
4775
|
+
}
|
|
4776
|
+
throw new Error(body?.error || error.message || "Falha ao ler o boleto.");
|
|
4777
|
+
}
|
|
4778
|
+
if (!data?.ok || data.kind === "none" || !data.code) return null;
|
|
4779
|
+
const code = String(data.code);
|
|
4780
|
+
if (data.kind === "barcode") {
|
|
4781
|
+
const parsed = parseBoleto(code);
|
|
4782
|
+
return {
|
|
4783
|
+
kind: "barcode",
|
|
4784
|
+
code: code.replace(/\D/g, ""),
|
|
4785
|
+
amount: parsed?.amount ?? (typeof data.amount === "number" ? data.amount : null),
|
|
4786
|
+
dueDate: parsed?.dueDate ?? (data.due_date ?? null)
|
|
4787
|
+
};
|
|
4788
|
+
}
|
|
4789
|
+
return { kind: "pix", code, amount: typeof data.amount === "number" ? data.amount : null, dueDate: data.due_date ?? null };
|
|
4790
|
+
}
|
|
4791
|
+
function parseBoleto(raw) {
|
|
4792
|
+
const d = raw.replace(/\D/g, "");
|
|
4793
|
+
if (d.startsWith("8")) return null;
|
|
4794
|
+
let barcode;
|
|
4795
|
+
if (d.length === 44) barcode = d;
|
|
4796
|
+
else if (d.length === 47) barcode = d.slice(0, 4) + d[32] + d.slice(33, 47) + d.slice(4, 9) + d.slice(10, 20) + d.slice(21, 31);
|
|
4797
|
+
else return null;
|
|
4798
|
+
const factor = Number(barcode.slice(5, 9));
|
|
4799
|
+
const cents = Number(barcode.slice(9, 19));
|
|
4800
|
+
let dueDate = null;
|
|
4801
|
+
if (factor > 0) {
|
|
4802
|
+
const base = factor >= 1e3 && Date.now() >= Date.UTC(2025, 1, 22) ? Date.UTC(2025, 1, 22) - 1e3 * 864e5 : Date.UTC(1997, 9, 7);
|
|
4803
|
+
dueDate = new Date(base + factor * 864e5).toISOString().slice(0, 10);
|
|
4804
|
+
}
|
|
4805
|
+
return { amount: cents > 0 ? cents / 100 : null, dueDate };
|
|
4806
|
+
}
|
|
4807
|
+
var formatCnpj = (d) => `${d.slice(0, 2)}.${d.slice(2, 5)}.${d.slice(5, 8)}/${d.slice(8, 12)}-${d.slice(12)}`;
|
|
4808
|
+
var groupKey = (digits2) => digits2.replace(/(\d{4})(?=\d)/g, "$1 ");
|
|
4809
|
+
function PullByKeyDialog({ open, onOpenChange, unitId, onPulled }) {
|
|
4810
|
+
const [value, setValue] = useState("");
|
|
4811
|
+
const [busy, setBusy] = useState(false);
|
|
4812
|
+
const [error, setError] = useState(null);
|
|
4813
|
+
const [notice, setNotice] = useState(null);
|
|
4814
|
+
const [cnpjOptions, setCnpjOptions] = useState(null);
|
|
4815
|
+
const [legalEntityId, setLegalEntityId] = useState("");
|
|
4816
|
+
useEffect(() => {
|
|
4817
|
+
if (open) return;
|
|
4818
|
+
setValue("");
|
|
4819
|
+
setError(null);
|
|
4820
|
+
setNotice(null);
|
|
4821
|
+
setCnpjOptions(null);
|
|
4822
|
+
setLegalEntityId("");
|
|
4823
|
+
}, [open]);
|
|
4824
|
+
const digits2 = value.replace(/\D/g, "").slice(0, 44);
|
|
4825
|
+
const needsCnpj = !!cnpjOptions && !legalEntityId;
|
|
4826
|
+
const blocked = digits2.length !== 44 ? `Faltam ${44 - digits2.length} d\xEDgitos` : needsCnpj ? "Escolha o CNPJ" : null;
|
|
4827
|
+
const pull = async () => {
|
|
4828
|
+
setBusy(true);
|
|
4829
|
+
setError(null);
|
|
4830
|
+
setNotice(null);
|
|
4831
|
+
try {
|
|
4832
|
+
const result = await pullNoteByKey(digits2, { legalEntityId: legalEntityId || void 0, unitId });
|
|
4833
|
+
if (result.status === "pending") {
|
|
4834
|
+
setNotice(result.message);
|
|
4835
|
+
return;
|
|
4836
|
+
}
|
|
4837
|
+
onPulled(result);
|
|
4838
|
+
onOpenChange(false);
|
|
4839
|
+
} catch (e) {
|
|
4840
|
+
if (e instanceof PullByKeyError && e.code === "choose_cnpj" && e.options?.length) {
|
|
4841
|
+
setCnpjOptions(e.options);
|
|
4842
|
+
setError(null);
|
|
4843
|
+
return;
|
|
4844
|
+
}
|
|
4845
|
+
setError(e instanceof Error ? e.message : String(e));
|
|
4846
|
+
} finally {
|
|
4847
|
+
setBusy(false);
|
|
4848
|
+
}
|
|
4849
|
+
};
|
|
4850
|
+
return /* @__PURE__ */ jsx(Modal, { open, onOpenChange: (o) => {
|
|
4851
|
+
if (!busy) onOpenChange(o);
|
|
4852
|
+
}, children: /* @__PURE__ */ jsxs(ModalContent, { size: "md", children: [
|
|
4853
|
+
/* @__PURE__ */ jsxs(ModalHeader, { children: [
|
|
4854
|
+
/* @__PURE__ */ jsxs(ModalTitle, { className: "flex items-center gap-2", children: [
|
|
4855
|
+
/* @__PURE__ */ jsx(KeyRound, { className: "h-5 w-5", "aria-hidden": true }),
|
|
4856
|
+
"Puxar NF-e por chave de acesso"
|
|
4857
|
+
] }),
|
|
4858
|
+
/* @__PURE__ */ jsx(ModalDescription, { children: "Para baixar uma nota que n\xE3o veio na coleta autom\xE1tica (por exemplo, emitida antes de ligar o recebimento de DANFes). Cole a chave de acesso de 44 d\xEDgitos." })
|
|
4859
|
+
] }),
|
|
4860
|
+
/* @__PURE__ */ jsxs(ModalBody, { className: "space-y-3", children: [
|
|
4861
|
+
/* @__PURE__ */ jsx(
|
|
4862
|
+
Input,
|
|
4863
|
+
{
|
|
4864
|
+
value: groupKey(digits2),
|
|
4865
|
+
onChange: (e) => {
|
|
4866
|
+
setValue(e.target.value);
|
|
4867
|
+
setError(null);
|
|
4868
|
+
setNotice(null);
|
|
4869
|
+
},
|
|
4870
|
+
onKeyDown: (e) => {
|
|
4871
|
+
if (e.key === "Enter" && !blocked && !busy) void pull();
|
|
4872
|
+
},
|
|
4873
|
+
placeholder: "0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000",
|
|
4874
|
+
inputMode: "numeric",
|
|
4875
|
+
autoFocus: true,
|
|
4876
|
+
className: "font-mono tabular-nums",
|
|
4877
|
+
"aria-label": "Chave de acesso",
|
|
4878
|
+
"data-testid": "pull-by-key-input"
|
|
4879
|
+
}
|
|
4880
|
+
),
|
|
4881
|
+
/* @__PURE__ */ jsxs("p", { className: `text-xs tabular-nums ${digits2.length === 44 ? "text-success-soft-foreground" : "text-muted-foreground"}`, children: [
|
|
4882
|
+
digits2.length,
|
|
4883
|
+
"/44 d\xEDgitos"
|
|
4884
|
+
] }),
|
|
4885
|
+
cnpjOptions && /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
4886
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "De qual CNPJ \xE9 esta nota?" }),
|
|
4887
|
+
/* @__PURE__ */ jsxs(Select, { value: legalEntityId, onValueChange: setLegalEntityId, children: [
|
|
4888
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Escolha o CNPJ destinat\xE1rio" }) }),
|
|
4889
|
+
/* @__PURE__ */ jsx(SelectContent, { children: cnpjOptions.map((o) => /* @__PURE__ */ jsxs(SelectItem, { value: o.id, children: [
|
|
4890
|
+
o.name,
|
|
4891
|
+
" \xB7 ",
|
|
4892
|
+
formatCnpj(o.cnpj)
|
|
4893
|
+
] }, o.id)) })
|
|
4894
|
+
] })
|
|
4895
|
+
] }),
|
|
4896
|
+
error && /* @__PURE__ */ jsx("p", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", role: "alert", children: error }),
|
|
4897
|
+
notice && /* @__PURE__ */ jsx("p", { className: "rounded-md bg-warning-soft px-3 py-2 text-sm text-warning-soft-foreground", role: "status", children: notice }),
|
|
4898
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Puxar n\xE3o manifesta a nota na SEFAZ \u2014 a manifesta\xE7\xE3o continua sendo feita no sistema antigo." })
|
|
4899
|
+
] }),
|
|
4900
|
+
/* @__PURE__ */ jsxs(ModalFooter, { children: [
|
|
4901
|
+
/* @__PURE__ */ jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), disabled: busy, children: "Cancelar" }),
|
|
4902
|
+
/* @__PURE__ */ jsxs(Button, { onClick: () => {
|
|
4903
|
+
void pull();
|
|
4904
|
+
}, disabled: busy || !!blocked, "data-testid": "pull-by-key-submit", children: [
|
|
4905
|
+
busy ? /* @__PURE__ */ jsx(Loader2, { className: "mr-1.5 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx(KeyRound, { className: "mr-1.5 h-4 w-4" }),
|
|
4906
|
+
busy ? "Buscando na SEFAZ\u2026" : blocked ?? "Puxar nota"
|
|
4907
|
+
] })
|
|
4908
|
+
] })
|
|
4909
|
+
] }) });
|
|
4910
|
+
}
|
|
4534
4911
|
var money = (value) => new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(value || 0);
|
|
4535
4912
|
var day = (iso) => iso ? iso.slice(0, 10).split("-").reverse().join("/") : "\u2014";
|
|
4536
4913
|
var cnpj = (digits2) => {
|
|
@@ -4554,6 +4931,7 @@ function InboundNotesView({ onOpenNote, onOpenManifest }) {
|
|
|
4554
4931
|
const [busy, setBusy] = useState(false);
|
|
4555
4932
|
const [report, setReport] = useState(null);
|
|
4556
4933
|
const [dragging, setDragging] = useState(false);
|
|
4934
|
+
const [pullOpen, setPullOpen] = useState(false);
|
|
4557
4935
|
const fileInput = useRef(null);
|
|
4558
4936
|
const unidades = useUnitFilter({ scope: "list" });
|
|
4559
4937
|
const { draft, applied, patch, setDraft, dirty, apply, reset } = useFilterDraft({
|
|
@@ -4614,6 +4992,36 @@ function InboundNotesView({ onOpenNote, onOpenManifest }) {
|
|
|
4614
4992
|
setReport(next);
|
|
4615
4993
|
await reload();
|
|
4616
4994
|
}, [reload]);
|
|
4995
|
+
const [rowError, setRowError] = useState(null);
|
|
4996
|
+
const downloadXml = useCallback(async (note) => {
|
|
4997
|
+
setRowError(null);
|
|
4998
|
+
try {
|
|
4999
|
+
const xml = await getInboxNoteXml(note.id);
|
|
5000
|
+
if (!xml) {
|
|
5001
|
+
setRowError(`O XML da nota ${note.number} n\xE3o est\xE1 guardado.`);
|
|
5002
|
+
return;
|
|
5003
|
+
}
|
|
5004
|
+
const url = URL.createObjectURL(new Blob([xml], { type: "application/xml" }));
|
|
5005
|
+
const a = document.createElement("a");
|
|
5006
|
+
a.href = url;
|
|
5007
|
+
a.download = `${note.accessKey || note.number || "nfe"}.xml`;
|
|
5008
|
+
a.click();
|
|
5009
|
+
URL.revokeObjectURL(url);
|
|
5010
|
+
} catch (e) {
|
|
5011
|
+
setRowError(e instanceof Error ? e.message : String(e));
|
|
5012
|
+
}
|
|
5013
|
+
}, []);
|
|
5014
|
+
const openPdf = useCallback(async (note) => {
|
|
5015
|
+
setRowError(null);
|
|
5016
|
+
const tab = window.open("", "_blank");
|
|
5017
|
+
try {
|
|
5018
|
+
const pdf = await getInboxNotePdf(note.accessKey ?? "");
|
|
5019
|
+
if (tab) tab.location.href = URL.createObjectURL(pdf);
|
|
5020
|
+
} catch (e) {
|
|
5021
|
+
tab?.close();
|
|
5022
|
+
setRowError(e instanceof Error ? e.message : String(e));
|
|
5023
|
+
}
|
|
5024
|
+
}, []);
|
|
4617
5025
|
const remove = useCallback(async (note) => {
|
|
4618
5026
|
await rejectNote(note.id, "Recusada na lista de entrada");
|
|
4619
5027
|
await reload();
|
|
@@ -4653,17 +5061,12 @@ function InboundNotesView({ onOpenNote, onOpenManifest }) {
|
|
|
4653
5061
|
id: "supplier",
|
|
4654
5062
|
header: "Fornecedor",
|
|
4655
5063
|
accessorFn: (note) => note.supplierName,
|
|
5064
|
+
meta: { truncate: true },
|
|
4656
5065
|
cell: ({ row }) => /* @__PURE__ */ jsxs("div", { children: [
|
|
4657
5066
|
/* @__PURE__ */ jsx("p", { className: "font-medium leading-tight", children: row.original.supplierName || "\u2014" }),
|
|
4658
5067
|
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground tabular-nums", children: cnpj(row.original.supplierCnpj) })
|
|
4659
5068
|
] })
|
|
4660
5069
|
},
|
|
4661
|
-
{
|
|
4662
|
-
id: "items",
|
|
4663
|
-
header: () => /* @__PURE__ */ jsx("span", { className: "block text-right", children: "Itens" }),
|
|
4664
|
-
accessorFn: (note) => note.itemCount,
|
|
4665
|
-
cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "block text-right tabular-nums text-muted-foreground", children: row.original.itemCount })
|
|
4666
|
-
},
|
|
4667
5070
|
{
|
|
4668
5071
|
id: "reconciled",
|
|
4669
5072
|
header: () => /* @__PURE__ */ jsx("span", { className: "block text-center", children: "Concilia\xE7\xE3o" }),
|
|
@@ -4697,24 +5100,44 @@ function InboundNotesView({ onOpenNote, onOpenManifest }) {
|
|
|
4697
5100
|
enableSorting: false,
|
|
4698
5101
|
cell: ({ row }) => {
|
|
4699
5102
|
const note = row.original;
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
{
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
5103
|
+
const done = !!note.stockedAt || note.status === "rejected";
|
|
5104
|
+
return (
|
|
5105
|
+
// The row itself opens the note; the buttons must not fire it a second time.
|
|
5106
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-1", onClick: (e) => e.stopPropagation(), children: [
|
|
5107
|
+
/* @__PURE__ */ jsx(ActionIcon, { label: done ? "Ver nota" : "Conciliar", children: /* @__PURE__ */ jsx(
|
|
5108
|
+
Button,
|
|
5109
|
+
{
|
|
5110
|
+
size: "icon",
|
|
5111
|
+
variant: "ghost",
|
|
5112
|
+
"aria-label": done ? `Ver a nota ${note.number}` : `Conciliar a nota ${note.number}`,
|
|
5113
|
+
className: done ? "" : "bg-foreground text-background hover:bg-foreground/85 hover:text-background",
|
|
5114
|
+
onClick: () => onOpenNote(note.id),
|
|
5115
|
+
children: done ? /* @__PURE__ */ jsx(Eye, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ListChecks, { className: "h-4 w-4" })
|
|
5116
|
+
}
|
|
5117
|
+
) }),
|
|
5118
|
+
/* @__PURE__ */ jsx(
|
|
5119
|
+
RowActions,
|
|
5120
|
+
{
|
|
5121
|
+
inlineLimit: 0,
|
|
5122
|
+
actions: [
|
|
5123
|
+
{ id: "xml", label: "Baixar XML", icon: FileCode2, onSelect: () => downloadXml(note) },
|
|
5124
|
+
{ id: "pdf", label: "Abrir PDF", icon: FileText, onSelect: () => openPdf(note), hidden: !note.accessKey },
|
|
5125
|
+
{
|
|
5126
|
+
id: "reject",
|
|
5127
|
+
label: "Recusar nota",
|
|
5128
|
+
icon: Trash2,
|
|
5129
|
+
intent: "danger",
|
|
5130
|
+
onSelect: () => remove(note),
|
|
5131
|
+
hidden: done || !!note.invoiceId
|
|
5132
|
+
}
|
|
5133
|
+
]
|
|
5134
|
+
}
|
|
5135
|
+
)
|
|
5136
|
+
] })
|
|
5137
|
+
);
|
|
4715
5138
|
}
|
|
4716
5139
|
}
|
|
4717
|
-
], [onOpenNote, remove]);
|
|
5140
|
+
], [onOpenNote, remove, downloadXml, openPdf]);
|
|
4718
5141
|
const emptyMessage = query || activeCount > 0 ? /* @__PURE__ */ jsxs("div", { children: [
|
|
4719
5142
|
/* @__PURE__ */ jsx(Inbox, { className: "mx-auto h-8 w-8 text-muted-foreground", "aria-hidden": true }),
|
|
4720
5143
|
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm font-medium", children: "Nenhuma nota encontrada" }),
|
|
@@ -4730,6 +5153,10 @@ function InboundNotesView({ onOpenNote, onOpenManifest }) {
|
|
|
4730
5153
|
/* @__PURE__ */ jsx(Inbox, { className: "h-4 w-4 mr-1.5" }),
|
|
4731
5154
|
"Fila da SEFAZ"
|
|
4732
5155
|
] }),
|
|
5156
|
+
/* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: () => setPullOpen(true), "data-testid": "pull-by-key", children: [
|
|
5157
|
+
/* @__PURE__ */ jsx(KeyRound, { className: "h-4 w-4 mr-1.5" }),
|
|
5158
|
+
"Puxar por chave"
|
|
5159
|
+
] }),
|
|
4733
5160
|
/* @__PURE__ */ jsxs(Button, { size: "sm", onClick: () => fileInput.current?.click(), disabled: busy, children: [
|
|
4734
5161
|
busy ? /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 mr-1.5 animate-spin" }) : /* @__PURE__ */ jsx(UploadCloud, { className: "h-4 w-4 mr-1.5" }),
|
|
4735
5162
|
"Importar XML"
|
|
@@ -4770,6 +5197,21 @@ function InboundNotesView({ onOpenNote, onOpenManifest }) {
|
|
|
4770
5197
|
]
|
|
4771
5198
|
}
|
|
4772
5199
|
),
|
|
5200
|
+
/* @__PURE__ */ jsx(
|
|
5201
|
+
PullByKeyDialog,
|
|
5202
|
+
{
|
|
5203
|
+
open: pullOpen,
|
|
5204
|
+
onOpenChange: setPullOpen,
|
|
5205
|
+
unitId: applied.unitId || null,
|
|
5206
|
+
onPulled: (r) => {
|
|
5207
|
+
setReport({
|
|
5208
|
+
ok: [{ file: "chave", number: r.parsed.nfeNumber, items: r.itemCount, matched: r.matchedCount, repeated: r.alreadyAccepted }],
|
|
5209
|
+
failed: []
|
|
5210
|
+
});
|
|
5211
|
+
void reload();
|
|
5212
|
+
}
|
|
5213
|
+
}
|
|
5214
|
+
),
|
|
4773
5215
|
report && /* @__PURE__ */ jsxs(Card, { className: "p-4 space-y-2", children: [
|
|
4774
5216
|
report.ok.map((r) => /* @__PURE__ */ jsxs("p", { className: "text-sm", children: [
|
|
4775
5217
|
/* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
|
|
@@ -4822,6 +5264,7 @@ function InboundNotesView({ onOpenNote, onOpenManifest }) {
|
|
|
4822
5264
|
]
|
|
4823
5265
|
}
|
|
4824
5266
|
),
|
|
5267
|
+
rowError && /* @__PURE__ */ jsx("p", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", role: "alert", children: rowError }),
|
|
4825
5268
|
/* @__PURE__ */ jsxs(Card, { className: "overflow-hidden", children: [
|
|
4826
5269
|
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2 border-b border-border px-3 py-2", children: /* @__PURE__ */ jsx("div", { className: "min-w-[10rem] flex-1", children: /* @__PURE__ */ jsx(
|
|
4827
5270
|
SearchField,
|
|
@@ -4832,7 +5275,7 @@ function InboundNotesView({ onOpenNote, onOpenManifest }) {
|
|
|
4832
5275
|
"data-testid": "inbound-notes-search"
|
|
4833
5276
|
}
|
|
4834
5277
|
) }) }),
|
|
4835
|
-
/* @__PURE__ */ jsx(
|
|
5278
|
+
/* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsx(
|
|
4836
5279
|
DataTable,
|
|
4837
5280
|
{
|
|
4838
5281
|
variant: "bare",
|
|
@@ -4840,12 +5283,19 @@ function InboundNotesView({ onOpenNote, onOpenManifest }) {
|
|
|
4840
5283
|
data: loading ? [] : shown,
|
|
4841
5284
|
loading,
|
|
4842
5285
|
getRowId: (note) => note.id,
|
|
5286
|
+
onRowClick: (note) => onOpenNote(note.id),
|
|
4843
5287
|
emptyMessage
|
|
4844
5288
|
}
|
|
4845
|
-
)
|
|
5289
|
+
) })
|
|
4846
5290
|
] })
|
|
4847
5291
|
] });
|
|
4848
5292
|
}
|
|
5293
|
+
function ActionIcon({ label, children }) {
|
|
5294
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
5295
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children }),
|
|
5296
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: label })
|
|
5297
|
+
] });
|
|
5298
|
+
}
|
|
4849
5299
|
function ReconcileBadge({ done, total }) {
|
|
4850
5300
|
const full = total > 0 && done === total;
|
|
4851
5301
|
return /* @__PURE__ */ jsxs(
|
|
@@ -4869,6 +5319,182 @@ function StockBadge({ stockedAt, status }) {
|
|
|
4869
5319
|
"Estocado"
|
|
4870
5320
|
] }) : /* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-full bg-warning-soft px-2 py-0.5 text-[11px] font-medium text-warning-soft-foreground", children: "Pendente" });
|
|
4871
5321
|
}
|
|
5322
|
+
var MAX_BYTES = 15 * 1024 * 1024;
|
|
5323
|
+
var money2 = (v) => new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(v || 0);
|
|
5324
|
+
var day2 = (iso) => iso ? iso.slice(0, 10).split("-").reverse().join("/") : "\u2014";
|
|
5325
|
+
var size = (b) => !b ? "" : b < 1024 * 1024 ? `${Math.max(1, Math.round(b / 1024))} KB` : `${(b / 1024 / 1024).toFixed(1)} MB`;
|
|
5326
|
+
function applyPaymentCode(list, code) {
|
|
5327
|
+
const field = code.kind === "pix" ? "pixKey" : "barcode";
|
|
5328
|
+
const free = list.map((p, i) => ({ p, i })).filter(({ p }) => !p[field]);
|
|
5329
|
+
const sameAmount = code.amount != null ? free.find(({ p }) => Math.abs((Number(p.amount) || 0) - code.amount) < 0.01) : void 0;
|
|
5330
|
+
const target = sameAmount ?? free[0];
|
|
5331
|
+
const patch = (p) => ({
|
|
5332
|
+
...p,
|
|
5333
|
+
[field]: code.code,
|
|
5334
|
+
paymentType: code.kind === "pix" ? "pix" : "boleto",
|
|
5335
|
+
dueDate: p.dueDate || code.dueDate,
|
|
5336
|
+
amount: Number(p.amount) > 0 ? p.amount : code.amount ?? 0
|
|
5337
|
+
});
|
|
5338
|
+
if (target) return { next: list.map((p, i) => i === target.i ? patch(p) : p), index: target.i };
|
|
5339
|
+
const fresh = patch({ index: list.length, amount: 0 });
|
|
5340
|
+
return { next: [...list, fresh], index: list.length };
|
|
5341
|
+
}
|
|
5342
|
+
function NoteAttachmentsCard({ noteId, invoiceId, readOnly, instalments, onInstalments }) {
|
|
5343
|
+
const input = useRef(null);
|
|
5344
|
+
const [items, setItems] = useState(null);
|
|
5345
|
+
const [busy, setBusy] = useState(null);
|
|
5346
|
+
const [over, setOver] = useState(false);
|
|
5347
|
+
const [confirming, setConfirming] = useState(null);
|
|
5348
|
+
const [messages, setMessages] = useState([]);
|
|
5349
|
+
const current = useRef(instalments);
|
|
5350
|
+
current.current = instalments;
|
|
5351
|
+
const load = useCallback(async () => {
|
|
5352
|
+
try {
|
|
5353
|
+
setItems(await listNoteAttachments(noteId, invoiceId));
|
|
5354
|
+
} catch {
|
|
5355
|
+
setItems([]);
|
|
5356
|
+
}
|
|
5357
|
+
}, [noteId, invoiceId]);
|
|
5358
|
+
useEffect(() => {
|
|
5359
|
+
void load();
|
|
5360
|
+
}, [load]);
|
|
5361
|
+
const upload = async (files) => {
|
|
5362
|
+
const out = [];
|
|
5363
|
+
for (const file of files) {
|
|
5364
|
+
if (!(file.type.startsWith("image/") || file.type === "application/pdf") || file.size > MAX_BYTES) {
|
|
5365
|
+
out.push({ tone: "error", text: `${file.name}: envie imagem ou PDF de at\xE9 15 MB.` });
|
|
5366
|
+
continue;
|
|
5367
|
+
}
|
|
5368
|
+
setBusy(`Anexando ${file.name}\u2026`);
|
|
5369
|
+
try {
|
|
5370
|
+
await addNoteAttachment(noteId, invoiceId, file);
|
|
5371
|
+
} catch (e) {
|
|
5372
|
+
out.push({ tone: "error", text: `${file.name}: ${e instanceof Error ? e.message : String(e)}` });
|
|
5373
|
+
continue;
|
|
5374
|
+
}
|
|
5375
|
+
if (readOnly) continue;
|
|
5376
|
+
setBusy(`Lendo ${file.name}\u2026`);
|
|
5377
|
+
try {
|
|
5378
|
+
const code = await extractPaymentCode(file);
|
|
5379
|
+
if (!code) {
|
|
5380
|
+
out.push({ tone: "warn", text: `${file.name}: anexado. N\xE3o achei c\xF3digo de boleto nem Pix nele.` });
|
|
5381
|
+
} else {
|
|
5382
|
+
const { next, index } = applyPaymentCode(current.current, code);
|
|
5383
|
+
current.current = next;
|
|
5384
|
+
onInstalments(next);
|
|
5385
|
+
const p = next[index];
|
|
5386
|
+
out.push({
|
|
5387
|
+
tone: "ok",
|
|
5388
|
+
text: `${code.kind === "pix" ? "Pix" : "Boleto"} lido \u2192 parcela ${index + 1}: ${money2(Number(p.amount) || 0)}, vence ${day2(p.dueDate ?? null)}. Confira e salve.`
|
|
5389
|
+
});
|
|
5390
|
+
}
|
|
5391
|
+
} catch (e) {
|
|
5392
|
+
out.push({ tone: "warn", text: `${file.name}: anexado, mas n\xE3o consegui ler o c\xF3digo (${e instanceof Error ? e.message : String(e)}).` });
|
|
5393
|
+
}
|
|
5394
|
+
}
|
|
5395
|
+
setBusy(null);
|
|
5396
|
+
setMessages(out);
|
|
5397
|
+
await load();
|
|
5398
|
+
};
|
|
5399
|
+
const remove = async (a) => {
|
|
5400
|
+
setBusy(`Removendo ${a.fileName}\u2026`);
|
|
5401
|
+
try {
|
|
5402
|
+
await removeNoteAttachment(a.id);
|
|
5403
|
+
setMessages([{ tone: "ok", text: `${a.fileName} removido.` }]);
|
|
5404
|
+
} catch (e) {
|
|
5405
|
+
setMessages([{ tone: "error", text: `${a.fileName}: ${e instanceof Error ? e.message : String(e)}` }]);
|
|
5406
|
+
} finally {
|
|
5407
|
+
setBusy(null);
|
|
5408
|
+
await load();
|
|
5409
|
+
}
|
|
5410
|
+
};
|
|
5411
|
+
return /* @__PURE__ */ jsxs(Card, { className: "p-4", children: [
|
|
5412
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
5413
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
5414
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold", children: "Anexos da conta" }),
|
|
5415
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: "Boleto, comprovante, foto da nota. Boleto e Pix anexados s\xE3o lidos e preenchem a parcela." })
|
|
5416
|
+
] }),
|
|
5417
|
+
items && items.length > 0 && /* @__PURE__ */ jsxs("span", { className: "shrink-0 text-xs text-muted-foreground", children: [
|
|
5418
|
+
items.length,
|
|
5419
|
+
" ",
|
|
5420
|
+
items.length === 1 ? "anexo" : "anexos"
|
|
5421
|
+
] })
|
|
5422
|
+
] }),
|
|
5423
|
+
items === null ? /* @__PURE__ */ jsx("div", { className: "mt-3 h-10 animate-pulse rounded-md bg-muted" }) : items.length > 0 && /* @__PURE__ */ jsx("ul", { className: "mt-3 divide-y rounded-md border", children: items.map((a) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-2 px-3 py-2 text-sm", children: [
|
|
5424
|
+
a.mimeType?.startsWith("image/") ? /* @__PURE__ */ jsx(Image, { className: "h-4 w-4 shrink-0 text-muted-foreground", "aria-hidden": true }) : /* @__PURE__ */ jsx(FileText, { className: "h-4 w-4 shrink-0 text-muted-foreground", "aria-hidden": true }),
|
|
5425
|
+
a.url ? /* @__PURE__ */ jsx("a", { href: a.url, target: "_blank", rel: "noreferrer", className: "min-w-0 flex-1 truncate hover:underline", children: a.fileName }) : /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-muted-foreground", children: a.fileName }),
|
|
5426
|
+
confirming === a.id ? (
|
|
5427
|
+
// Inline, not a dialog: this card already lives inside a modal.
|
|
5428
|
+
/* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1", children: [
|
|
5429
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "Remover?" }),
|
|
5430
|
+
/* @__PURE__ */ jsx(Button, { variant: "destructive", size: "sm", onClick: () => {
|
|
5431
|
+
setConfirming(null);
|
|
5432
|
+
void remove(a);
|
|
5433
|
+
}, children: "Remover" }),
|
|
5434
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: () => setConfirming(null), children: "Cancelar" })
|
|
5435
|
+
] })
|
|
5436
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5437
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs text-muted-foreground", children: size(a.fileSize) }),
|
|
5438
|
+
/* @__PURE__ */ jsx(Hint, { label: "Remover anexo", children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon", "aria-label": `Remover ${a.fileName}`, disabled: !!busy, onClick: () => setConfirming(a.id), children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" }) }) })
|
|
5439
|
+
] })
|
|
5440
|
+
] }, a.id)) }),
|
|
5441
|
+
/* @__PURE__ */ jsxs(
|
|
5442
|
+
"div",
|
|
5443
|
+
{
|
|
5444
|
+
className: `mt-3 flex flex-col items-center gap-1 rounded-md border border-dashed px-4 py-5 text-center transition-colors ${over ? "border-primary bg-primary/5" : "border-input"}`,
|
|
5445
|
+
onDragOver: (e) => {
|
|
5446
|
+
e.preventDefault();
|
|
5447
|
+
setOver(true);
|
|
5448
|
+
},
|
|
5449
|
+
onDragLeave: () => setOver(false),
|
|
5450
|
+
onDrop: (e) => {
|
|
5451
|
+
e.preventDefault();
|
|
5452
|
+
setOver(false);
|
|
5453
|
+
void upload(Array.from(e.dataTransfer.files));
|
|
5454
|
+
},
|
|
5455
|
+
children: [
|
|
5456
|
+
busy ? /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
5457
|
+
/* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
5458
|
+
busy
|
|
5459
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5460
|
+
/* @__PURE__ */ jsx(UploadCloud, { className: "h-6 w-6 text-muted-foreground", "aria-hidden": true }),
|
|
5461
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm", children: "Arraste o boleto ou o comprovante aqui" }),
|
|
5462
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 flex gap-2", children: /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: () => input.current?.click(), "data-testid": "note-attach", children: [
|
|
5463
|
+
/* @__PURE__ */ jsx(Paperclip, { className: "mr-1.5 h-4 w-4" }),
|
|
5464
|
+
"Anexar arquivo"
|
|
5465
|
+
] }) }),
|
|
5466
|
+
!readOnly && /* @__PURE__ */ jsxs("p", { className: "mt-1 flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
5467
|
+
/* @__PURE__ */ jsx(ScanLine, { className: "h-3 w-3", "aria-hidden": true }),
|
|
5468
|
+
" o c\xF3digo de barras e o Pix s\xE3o lidos sozinhos"
|
|
5469
|
+
] })
|
|
5470
|
+
] }),
|
|
5471
|
+
/* @__PURE__ */ jsx(
|
|
5472
|
+
"input",
|
|
5473
|
+
{
|
|
5474
|
+
ref: input,
|
|
5475
|
+
type: "file",
|
|
5476
|
+
multiple: true,
|
|
5477
|
+
accept: "image/*,application/pdf",
|
|
5478
|
+
className: "hidden",
|
|
5479
|
+
onChange: (e) => {
|
|
5480
|
+
void upload(Array.from(e.target.files ?? []));
|
|
5481
|
+
e.target.value = "";
|
|
5482
|
+
}
|
|
5483
|
+
}
|
|
5484
|
+
)
|
|
5485
|
+
]
|
|
5486
|
+
}
|
|
5487
|
+
),
|
|
5488
|
+
messages.length > 0 && /* @__PURE__ */ jsx("ul", { className: "mt-3 space-y-1", children: messages.map((m, i) => /* @__PURE__ */ jsx(
|
|
5489
|
+
"li",
|
|
5490
|
+
{
|
|
5491
|
+
className: `text-xs ${m.tone === "ok" ? "text-success-soft-foreground" : m.tone === "warn" ? "text-warning-soft-foreground" : "text-destructive"}`,
|
|
5492
|
+
children: m.text
|
|
5493
|
+
},
|
|
5494
|
+
i
|
|
5495
|
+
)) })
|
|
5496
|
+
] });
|
|
5497
|
+
}
|
|
4872
5498
|
|
|
4873
5499
|
// src/types.ts
|
|
4874
5500
|
var STOCK_BEARING_ENTRY_TYPES = ["insumo", "revenda", "patrimonio"];
|
|
@@ -4891,9 +5517,9 @@ var norm = (u) => (u ?? "").trim().toUpperCase().replace(/\.$/, "");
|
|
|
4891
5517
|
function packagingCount(commercialUnit) {
|
|
4892
5518
|
return PACKAGING_COUNT[norm(commercialUnit)] ?? null;
|
|
4893
5519
|
}
|
|
4894
|
-
var
|
|
5520
|
+
var money3 = (v) => new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(v || 0);
|
|
4895
5521
|
var qty = (v) => new Intl.NumberFormat("pt-BR", { maximumFractionDigits: 4 }).format(v || 0);
|
|
4896
|
-
var
|
|
5522
|
+
var day3 = (iso) => iso ? iso.slice(0, 10).split("-").reverse().join("/") : "\u2014";
|
|
4897
5523
|
var ENTRY_TYPES = [
|
|
4898
5524
|
{ value: "insumo", label: "Insumo" },
|
|
4899
5525
|
{ value: "revenda", label: "Produto Revenda" },
|
|
@@ -4945,7 +5571,11 @@ function NoteReconcileView({ noteId, onBack, onOpenInvoice, chrome = "page" }) {
|
|
|
4945
5571
|
const load = useCallback(async () => {
|
|
4946
5572
|
setLoading(true);
|
|
4947
5573
|
try {
|
|
4948
|
-
|
|
5574
|
+
let detail = await getInboxNote(noteId);
|
|
5575
|
+
if (detail && !detail.supplierPartyId && detail.supplierCnpj) {
|
|
5576
|
+
const linked = await linkInboxSupplier(noteId).catch(() => null);
|
|
5577
|
+
if (linked?.supplierPartyId) detail = { ...detail, supplierPartyId: linked.supplierPartyId };
|
|
5578
|
+
}
|
|
4949
5579
|
setNote(detail);
|
|
4950
5580
|
const failed = [];
|
|
4951
5581
|
const [u, a, l] = await Promise.all([
|
|
@@ -5121,7 +5751,10 @@ function NoteReconcileView({ noteId, onBack, onOpenInvoice, chrome = "page" }) {
|
|
|
5121
5751
|
const moldura = (node, titulo, rodape2) => emModal ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5122
5752
|
/* @__PURE__ */ jsxs(ModalHeader, { className: "shrink-0 flex-row items-center justify-between gap-3 space-y-0 border-b px-6 py-3 pr-14 text-left sm:flex-row", children: [
|
|
5123
5753
|
/* @__PURE__ */ jsx(ModalTitle, { className: "min-w-0 truncate", children: titulo }),
|
|
5124
|
-
|
|
5754
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
5755
|
+
botaoIA,
|
|
5756
|
+
ferramentas
|
|
5757
|
+
] })
|
|
5125
5758
|
] }),
|
|
5126
5759
|
/* @__PURE__ */ jsx(ModalBody, { className: "px-6 py-4", children: node }),
|
|
5127
5760
|
rodape2 && /* @__PURE__ */ jsx(ModalFooter, { className: "shrink-0 flex-row items-center justify-between gap-3 space-x-0 border-t px-6 py-3 pr-16", children: rodape2 })
|
|
@@ -5133,6 +5766,36 @@ function NoteReconcileView({ noteId, onBack, onOpenInvoice, chrome = "page" }) {
|
|
|
5133
5766
|
rodape2 && /* @__PURE__ */ jsx("div", { className: `sticky bottom-0 ${sangria} flex items-center justify-between gap-3 border-t bg-card/95 py-3 pr-16 backdrop-blur`, children: rodape2 })
|
|
5134
5767
|
] })
|
|
5135
5768
|
);
|
|
5769
|
+
const [cadastrando, setCadastrando] = useState(false);
|
|
5770
|
+
const cadastrarFornecedor = useCallback(async () => {
|
|
5771
|
+
if (!note) return;
|
|
5772
|
+
setCadastrando(true);
|
|
5773
|
+
setError(null);
|
|
5774
|
+
try {
|
|
5775
|
+
const { supplierPartyId } = await linkInboxSupplier(note.id, true);
|
|
5776
|
+
if (supplierPartyId) setNote({ ...note, supplierPartyId });
|
|
5777
|
+
} catch (e) {
|
|
5778
|
+
setError(e instanceof Error ? e.message : String(e));
|
|
5779
|
+
} finally {
|
|
5780
|
+
setCadastrando(false);
|
|
5781
|
+
}
|
|
5782
|
+
}, [note]);
|
|
5783
|
+
const [abrindoPdf, setAbrindoPdf] = useState(false);
|
|
5784
|
+
const abrirPdf = useCallback(async () => {
|
|
5785
|
+
if (!note?.accessKey) return;
|
|
5786
|
+
const tab = window.open("", "_blank");
|
|
5787
|
+
setAbrindoPdf(true);
|
|
5788
|
+
setError(null);
|
|
5789
|
+
try {
|
|
5790
|
+
const pdf = await getInboxNotePdf(note.accessKey);
|
|
5791
|
+
if (tab) tab.location.href = URL.createObjectURL(pdf);
|
|
5792
|
+
} catch (e) {
|
|
5793
|
+
tab?.close();
|
|
5794
|
+
setError(e instanceof Error ? e.message : String(e));
|
|
5795
|
+
} finally {
|
|
5796
|
+
setAbrindoPdf(false);
|
|
5797
|
+
}
|
|
5798
|
+
}, [note]);
|
|
5136
5799
|
const baixarXml = useCallback(async () => {
|
|
5137
5800
|
if (!note) return;
|
|
5138
5801
|
setBaixandoXml(true);
|
|
@@ -5155,6 +5818,32 @@ function NoteReconcileView({ noteId, onBack, onOpenInvoice, chrome = "page" }) {
|
|
|
5155
5818
|
setBaixandoXml(false);
|
|
5156
5819
|
}
|
|
5157
5820
|
}, [note]);
|
|
5821
|
+
const ferramentas = note ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
5822
|
+
/* @__PURE__ */ jsxs(Dropdown, { children: [
|
|
5823
|
+
/* @__PURE__ */ jsx(DropdownTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", disabled: baixandoXml || abrindoPdf, children: [
|
|
5824
|
+
baixandoXml || abrindoPdf ? /* @__PURE__ */ jsx(Loader2, { className: "mr-1.5 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx(Download, { className: "mr-1.5 h-4 w-4" }),
|
|
5825
|
+
"Baixar",
|
|
5826
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "ml-1 h-3.5 w-3.5 opacity-60" })
|
|
5827
|
+
] }) }),
|
|
5828
|
+
/* @__PURE__ */ jsxs(DropdownContent, { align: "end", children: [
|
|
5829
|
+
/* @__PURE__ */ jsxs(DropdownItem, { className: "gap-2", disabled: !note.hasXml, onSelect: () => {
|
|
5830
|
+
void baixarXml();
|
|
5831
|
+
}, children: [
|
|
5832
|
+
/* @__PURE__ */ jsx(FileCode2, { className: "h-4 w-4" }),
|
|
5833
|
+
note.hasXml ? "XML da nota" : "XML n\xE3o guardado \u2014 reimporte o .xml"
|
|
5834
|
+
] }),
|
|
5835
|
+
/* @__PURE__ */ jsxs(DropdownItem, { className: "gap-2", disabled: !note.accessKey, onSelect: () => {
|
|
5836
|
+
void abrirPdf();
|
|
5837
|
+
}, children: [
|
|
5838
|
+
/* @__PURE__ */ jsx(FileText, { className: "h-4 w-4" }),
|
|
5839
|
+
"DANFE (PDF)"
|
|
5840
|
+
] })
|
|
5841
|
+
] })
|
|
5842
|
+
] }),
|
|
5843
|
+
/* @__PURE__ */ jsx(Hint, { label: "Atualizar", children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon", "aria-label": "Atualizar a nota", onClick: () => {
|
|
5844
|
+
void load();
|
|
5845
|
+
}, children: /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" }) }) })
|
|
5846
|
+
] }) : null;
|
|
5158
5847
|
const save = async () => {
|
|
5159
5848
|
if (!note) return;
|
|
5160
5849
|
setSaving(true);
|
|
@@ -5186,7 +5875,10 @@ function NoteReconcileView({ noteId, onBack, onOpenInvoice, chrome = "page" }) {
|
|
|
5186
5875
|
defaultLocationId: location,
|
|
5187
5876
|
instalments
|
|
5188
5877
|
});
|
|
5189
|
-
|
|
5878
|
+
const result = await acceptNote(note.id, location);
|
|
5879
|
+
if (result.invoiceId) await moveNoteAttachmentsToInvoice(note.id, result.invoiceId).catch(() => {
|
|
5880
|
+
});
|
|
5881
|
+
setAccepted(result);
|
|
5190
5882
|
await load();
|
|
5191
5883
|
} catch (e) {
|
|
5192
5884
|
setError(e instanceof Error ? e.message : String(e));
|
|
@@ -5279,13 +5971,16 @@ function NoteReconcileView({ noteId, onBack, onOpenInvoice, chrome = "page" }) {
|
|
|
5279
5971
|
return moldura(/* @__PURE__ */ jsxs("div", { className: `space-y-4 ${emModal ? "" : "pb-24"}`, children: [
|
|
5280
5972
|
cabecalho(`Concilia\xE7\xE3o \xB7 NF-e ${note.number}`),
|
|
5281
5973
|
accepted && /* @__PURE__ */ jsxs(Card, { className: "border-success bg-success-soft p-4", children: [
|
|
5282
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-success-soft-foreground", children: accepted.alreadyAccepted ? "Esta nota j\xE1 havia sido aceita \u2014 nada foi lan\xE7ado de novo." : `Aceita: ${accepted.stockLines} ${accepted.stockLines === 1 ? "linha" : "linhas"} de estoque e um t\xEDtulo de ${
|
|
5974
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-success-soft-foreground", children: accepted.alreadyAccepted ? "Esta nota j\xE1 havia sido aceita \u2014 nada foi lan\xE7ado de novo." : `Aceita: ${accepted.stockLines} ${accepted.stockLines === 1 ? "linha" : "linhas"} de estoque e um t\xEDtulo de ${money3(accepted.invoiceTotal)} em ${accepted.instalments} ${accepted.instalments === 1 ? "parcela" : "parcelas"}.` }),
|
|
5283
5975
|
accepted.invoiceId && onOpenInvoice && /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", className: "mt-2", onClick: () => onOpenInvoice(accepted.invoiceId), children: "Abrir a conta a pagar" })
|
|
5284
5976
|
] }),
|
|
5285
5977
|
/* @__PURE__ */ jsxs(Card, { className: "p-4", children: [
|
|
5286
5978
|
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold", children: "Situa\xE7\xE3o fiscal" }),
|
|
5287
5979
|
/* @__PURE__ */ jsxs("dl", { className: "mt-3 grid gap-x-6 gap-y-2 text-sm sm:grid-cols-2 lg:grid-cols-3", children: [
|
|
5288
|
-
/* @__PURE__ */
|
|
5980
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
5981
|
+
/* @__PURE__ */ jsx("dt", { className: "text-xs text-muted-foreground", children: "Fornecedor" }),
|
|
5982
|
+
/* @__PURE__ */ jsx("dd", { className: "text-sm", children: note.supplierPartyId ? /* @__PURE__ */ jsx(PersonLink, { personId: note.supplierPartyId, name: note.supplierName || "\u2014", kind: "supplier" }) : note.supplierName || "\u2014" })
|
|
5983
|
+
] }),
|
|
5289
5984
|
/* @__PURE__ */ jsx(Field, { label: "CNPJ", value: note.supplierCnpj ?? "\u2014", mono: true }),
|
|
5290
5985
|
/* @__PURE__ */ jsx(Field, { label: "Natureza da opera\xE7\xE3o", value: note.natureOperation ?? "\u2014" }),
|
|
5291
5986
|
/* @__PURE__ */ jsx(
|
|
@@ -5295,15 +5990,22 @@ function NoteReconcileView({ noteId, onBack, onOpenInvoice, chrome = "page" }) {
|
|
|
5295
5990
|
value: `${note.manifestationStatus ?? "n\xE3o manifestada"}${note.manifestationAttempts ? ` \xB7 ${note.manifestationAttempts} tentativa(s)` : ""}`
|
|
5296
5991
|
}
|
|
5297
5992
|
),
|
|
5298
|
-
/* @__PURE__ */ jsx(Field, { label: "Manifestada em", value:
|
|
5299
|
-
/* @__PURE__ */ jsx(Field, { label: "Recebida em", value:
|
|
5993
|
+
/* @__PURE__ */ jsx(Field, { label: "Manifestada em", value: day3(note.manifestedAt) }),
|
|
5994
|
+
/* @__PURE__ */ jsx(Field, { label: "Recebida em", value: day3(note.receivedAt) })
|
|
5995
|
+
] }),
|
|
5996
|
+
!note.supplierPartyId && /* @__PURE__ */ jsxs("div", { className: "mt-3 flex flex-wrap items-center justify-between gap-2 rounded-md border border-input bg-muted/40 px-3 py-2", children: [
|
|
5997
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: note.supplierCnpj ? /* @__PURE__ */ jsx(Fragment, { children: "Este fornecedor ainda n\xE3o est\xE1 no cadastro. Ao aceitar, ele \xE9 cadastrado com o nome e o CNPJ da nota." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5998
|
+
"A nota n\xE3o traz o CNPJ do fornecedor, ent\xE3o a conta a pagar vai nascer ",
|
|
5999
|
+
/* @__PURE__ */ jsx("strong", { children: "sem fornecedor" }),
|
|
6000
|
+
"."
|
|
6001
|
+
] }) }),
|
|
6002
|
+
note.supplierCnpj && !readOnly && /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", disabled: cadastrando, onClick: () => {
|
|
6003
|
+
void cadastrarFornecedor();
|
|
6004
|
+
}, children: [
|
|
6005
|
+
cadastrando ? /* @__PURE__ */ jsx(Loader2, { className: "mr-1.5 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx(UserPlus, { className: "mr-1.5 h-4 w-4" }),
|
|
6006
|
+
"Cadastrar agora"
|
|
6007
|
+
] })
|
|
5300
6008
|
] }),
|
|
5301
|
-
!note.supplierPartyId && /* @__PURE__ */ jsx("div", { className: "mt-3 rounded-md border border-warning bg-warning-soft px-3 py-2", children: /* @__PURE__ */ jsxs("p", { className: "text-xs text-warning-soft-foreground", children: [
|
|
5302
|
-
"Este fornecedor n\xE3o est\xE1 no cadastro de pessoas, ent\xE3o o t\xEDtulo a pagar vai nascer",
|
|
5303
|
-
" ",
|
|
5304
|
-
/* @__PURE__ */ jsx("strong", { children: "sem contraparte" }),
|
|
5305
|
-
". Cadastre o CNPJ antes de aceitar para a conta saber a quem se deve."
|
|
5306
|
-
] }) }),
|
|
5307
6009
|
/bonific|brinde|doacao|doação/i.test(note.natureOperation ?? "") && /* @__PURE__ */ jsx("div", { className: "mt-3 rounded-md border border-dashed border-input px-3 py-2", children: /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
5308
6010
|
/* @__PURE__ */ jsx(Gift, { className: "mr-1 inline h-3.5 w-3.5", "aria-hidden": true }),
|
|
5309
6011
|
"A natureza desta nota \xE9 ",
|
|
@@ -5315,41 +6017,7 @@ function NoteReconcileView({ noteId, onBack, onOpenInvoice, chrome = "page" }) {
|
|
|
5315
6017
|
" ",
|
|
5316
6018
|
/* @__PURE__ */ jsx("span", { className: "rounded-full bg-muted px-1.5 py-0.5 text-[10px]", children: "Em breve" })
|
|
5317
6019
|
] }) }),
|
|
5318
|
-
/* @__PURE__ */
|
|
5319
|
-
/* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: () => {
|
|
5320
|
-
void load();
|
|
5321
|
-
}, children: [
|
|
5322
|
-
/* @__PURE__ */ jsx(RefreshCw, { className: "mr-1.5 h-4 w-4" }),
|
|
5323
|
-
"Atualizar status"
|
|
5324
|
-
] }),
|
|
5325
|
-
note.hasXml ? /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", disabled: baixandoXml, onClick: () => {
|
|
5326
|
-
void baixarXml();
|
|
5327
|
-
}, children: [
|
|
5328
|
-
baixandoXml ? /* @__PURE__ */ jsx(Loader2, { className: "mr-1.5 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx(FileDown, { className: "mr-1.5 h-4 w-4" }),
|
|
5329
|
-
"Baixar XML"
|
|
5330
|
-
] }) : /* @__PURE__ */ jsx(
|
|
5331
|
-
EmBreve,
|
|
5332
|
-
{
|
|
5333
|
-
label: "Baixar XML",
|
|
5334
|
-
o_que: "O arquivo desta nota n\xE3o foi guardado \u2014 ela entrou antes de o est\xE1gio passar a gravar o XML. Reimportar o .xml preenche"
|
|
5335
|
-
}
|
|
5336
|
-
),
|
|
5337
|
-
/* @__PURE__ */ jsx(
|
|
5338
|
-
EmBreve,
|
|
5339
|
-
{
|
|
5340
|
-
label: "DANFE (PDF)",
|
|
5341
|
-
o_que: "O espelho impresso da nota. Tem layout fixado pela SEFAZ e vinha renderizado da PlugNotas no V1 \u2014 n\xE3o sai do XML sozinho"
|
|
5342
|
-
}
|
|
5343
|
-
),
|
|
5344
|
-
/* @__PURE__ */ jsx(
|
|
5345
|
-
EmBreve,
|
|
5346
|
-
{
|
|
5347
|
-
label: "Cadastrar fornecedor",
|
|
5348
|
-
o_que: "Criar a pessoa do fornecedor aqui, sem sair da nota \u2014 \xE9 o que preenche a contraparte do t\xEDtulo",
|
|
5349
|
-
quantas: "a Laissa cadastrou 37 fornecedores no V1 enquanto importava"
|
|
5350
|
-
}
|
|
5351
|
-
)
|
|
5352
|
-
] })
|
|
6020
|
+
!emModal && /* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: ferramentas })
|
|
5353
6021
|
] }),
|
|
5354
6022
|
/* @__PURE__ */ jsxs(Card, { className: "p-4", children: [
|
|
5355
6023
|
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold", children: "Padr\xF5es desta nota" }),
|
|
@@ -5479,11 +6147,11 @@ function NoteReconcileView({ noteId, onBack, onOpenInvoice, chrome = "page" }) {
|
|
|
5479
6147
|
" ",
|
|
5480
6148
|
item.unit ?? "",
|
|
5481
6149
|
" \xB7 ",
|
|
5482
|
-
|
|
6150
|
+
money3(item.unitPrice),
|
|
5483
6151
|
typeLabel ? ` \xB7 ${typeLabel}` : " \xB7 sem tipo"
|
|
5484
6152
|
] })
|
|
5485
6153
|
] }),
|
|
5486
|
-
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-sm tabular-nums", children:
|
|
6154
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-sm tabular-nums", children: money3(item.total) }),
|
|
5487
6155
|
d.suggestedBy && !done && /* @__PURE__ */ jsx(AuthorBadge, { draft: d }),
|
|
5488
6156
|
/* @__PURE__ */ jsx(ItemState, { done: done && ready, ready })
|
|
5489
6157
|
]
|
|
@@ -5499,8 +6167,8 @@ function NoteReconcileView({ noteId, onBack, onOpenInvoice, chrome = "page" }) {
|
|
|
5499
6167
|
] }),
|
|
5500
6168
|
/* @__PURE__ */ jsxs("dl", { className: "mt-2 grid grid-cols-2 gap-x-4 gap-y-1 text-xs sm:grid-cols-4", children: [
|
|
5501
6169
|
/* @__PURE__ */ jsx(Field, { small: true, label: "Qtd", value: `${qty(item.quantity)} ${item.unit ?? ""}` }),
|
|
5502
|
-
/* @__PURE__ */ jsx(Field, { small: true, label: "Vl. unit.", value:
|
|
5503
|
-
/* @__PURE__ */ jsx(Field, { small: true, label: "Total", value:
|
|
6170
|
+
/* @__PURE__ */ jsx(Field, { small: true, label: "Vl. unit.", value: money3(item.unitPrice) }),
|
|
6171
|
+
/* @__PURE__ */ jsx(Field, { small: true, label: "Total", value: money3(item.total) }),
|
|
5504
6172
|
/* @__PURE__ */ jsx(Field, { small: true, label: "C\xF3d", value: item.supplierProductCode || "\u2014", mono: true }),
|
|
5505
6173
|
/* @__PURE__ */ jsx(Field, { small: true, label: "EAN", value: item.eanBarcode ?? "\u2014", mono: true }),
|
|
5506
6174
|
/* @__PURE__ */ jsx(Field, { small: true, label: "NCM", value: item.ncm ?? "\u2014", mono: true }),
|
|
@@ -5617,7 +6285,7 @@ function NoteReconcileView({ noteId, onBack, onOpenInvoice, chrome = "page" }) {
|
|
|
5617
6285
|
] }),
|
|
5618
6286
|
/* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between text-sm", children: [
|
|
5619
6287
|
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "Novo custo unit\xE1rio" }),
|
|
5620
|
-
/* @__PURE__ */ jsx("span", { className: "tabular-nums", children:
|
|
6288
|
+
/* @__PURE__ */ jsx("span", { className: "tabular-nums", children: money3(unitCost) })
|
|
5621
6289
|
] })
|
|
5622
6290
|
] }),
|
|
5623
6291
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
@@ -5720,18 +6388,18 @@ function NoteReconcileView({ noteId, onBack, onOpenInvoice, chrome = "page" }) {
|
|
|
5720
6388
|
instalments.length === 1 ? "parcela" : "parcelas",
|
|
5721
6389
|
" \xB7",
|
|
5722
6390
|
" ",
|
|
5723
|
-
/* @__PURE__ */ jsx("span", { className: "tabular-nums", children:
|
|
6391
|
+
/* @__PURE__ */ jsx("span", { className: "tabular-nums", children: money3(instalmentSum) })
|
|
5724
6392
|
] })
|
|
5725
6393
|
] }),
|
|
5726
6394
|
note.declaredPayments.length > 0 && /* @__PURE__ */ jsxs("p", { className: "mt-1 text-xs text-muted-foreground", children: [
|
|
5727
6395
|
"A nota declarou: ",
|
|
5728
|
-
note.declaredPayments.map((p) => `${p.label ?? p.code} ${
|
|
6396
|
+
note.declaredPayments.map((p) => `${p.label ?? p.code} ${money3(p.value)}`).join(" \xB7 ")
|
|
5729
6397
|
] }),
|
|
5730
6398
|
/* @__PURE__ */ jsx("div", { className: "mt-3 space-y-2", children: instalments.map((inst, i) => /* @__PURE__ */ jsxs("div", { className: "grid items-end gap-2 sm:grid-cols-[2rem_1fr_1fr_1fr_2rem]", children: [
|
|
5731
6399
|
/* @__PURE__ */ jsx("span", { className: "pb-2 text-xs tabular-nums text-muted-foreground", children: inst.index }),
|
|
5732
6400
|
/* @__PURE__ */ jsxs("label", { className: "block", children: [
|
|
5733
6401
|
/* @__PURE__ */ jsx("span", { className: "text-[11px] text-muted-foreground", children: "Vencimento" }),
|
|
5734
|
-
readOnly ? /* @__PURE__ */ jsx("p", { className: "py-2 text-sm tabular-nums", children:
|
|
6402
|
+
readOnly ? /* @__PURE__ */ jsx("p", { className: "py-2 text-sm tabular-nums", children: day3(inst.dueDate) }) : /* @__PURE__ */ jsx(
|
|
5735
6403
|
DatePicker,
|
|
5736
6404
|
{
|
|
5737
6405
|
value: inst.dueDate ?? "",
|
|
@@ -5795,41 +6463,24 @@ function NoteReconcileView({ noteId, onBack, onOpenInvoice, chrome = "page" }) {
|
|
|
5795
6463
|
Math.abs(instalmentSum - note.total) > 0.01 && /* @__PURE__ */ jsx(Hint, { className: "mt-3", children: /* @__PURE__ */ jsxs("span", { children: [
|
|
5796
6464
|
/* @__PURE__ */ jsx(AlertTriangle, { className: "mr-1 inline h-3.5 w-3.5", "aria-hidden": true }),
|
|
5797
6465
|
"A nota diz ",
|
|
5798
|
-
|
|
6466
|
+
money3(note.total),
|
|
5799
6467
|
" e as parcelas somam ",
|
|
5800
|
-
|
|
6468
|
+
money3(instalmentSum),
|
|
5801
6469
|
". O t\xEDtulo vai nascer com ",
|
|
5802
|
-
/* @__PURE__ */ jsx("strong", { children:
|
|
6470
|
+
/* @__PURE__ */ jsx("strong", { children: money3(instalmentSum) }),
|
|
5803
6471
|
" \u2014 \xE9 a soma das parcelas que define o saldo a pagar."
|
|
5804
6472
|
] }) })
|
|
5805
6473
|
] }),
|
|
5806
|
-
/* @__PURE__ */
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
EmBreve,
|
|
5817
|
-
{
|
|
5818
|
-
label: "Anexar boleto",
|
|
5819
|
-
o_que: "Guardar o arquivo no t\xEDtulo que esta nota cria",
|
|
5820
|
-
quantas: "25 anexos no V1, o \xFAltimo hoje"
|
|
5821
|
-
}
|
|
5822
|
-
),
|
|
5823
|
-
/* @__PURE__ */ jsx(
|
|
5824
|
-
EmBreve,
|
|
5825
|
-
{
|
|
5826
|
-
label: "Ler o c\xF3digo de barras do boleto",
|
|
5827
|
-
o_que: "Preencher vencimento e valor da parcela a partir do boleto anexado",
|
|
5828
|
-
quantas: "automa\xE7\xE3o do V1 que ningu\xE9m documentou"
|
|
5829
|
-
}
|
|
5830
|
-
)
|
|
5831
|
-
] })
|
|
5832
|
-
] }),
|
|
6474
|
+
/* @__PURE__ */ jsx(
|
|
6475
|
+
NoteAttachmentsCard,
|
|
6476
|
+
{
|
|
6477
|
+
noteId: note.id,
|
|
6478
|
+
invoiceId: note.invoiceId,
|
|
6479
|
+
readOnly,
|
|
6480
|
+
instalments,
|
|
6481
|
+
onInstalments: setInstalments
|
|
6482
|
+
}
|
|
6483
|
+
),
|
|
5833
6484
|
error && /* @__PURE__ */ jsx(Card, { className: "border-destructive bg-destructive/5 p-4", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error }) })
|
|
5834
6485
|
] }), `Concilia\xE7\xE3o \xB7 NF-e ${note.number}`, rodape);
|
|
5835
6486
|
}
|
|
@@ -5858,8 +6509,8 @@ function Field({ label, value, mono, small }) {
|
|
|
5858
6509
|
/* @__PURE__ */ jsx("dd", { className: `${mono ? "tabular-nums" : ""} ${small ? "text-xs" : "text-sm"}`, children: value })
|
|
5859
6510
|
] });
|
|
5860
6511
|
}
|
|
5861
|
-
var
|
|
5862
|
-
var
|
|
6512
|
+
var money4 = (v) => new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(v || 0);
|
|
6513
|
+
var day4 = (iso) => iso ? iso.slice(0, 10).split("-").reverse().join("/") : "\u2014";
|
|
5863
6514
|
var MANIFEST_TONE = {
|
|
5864
6515
|
confirmada: "bg-success-soft text-success-soft-foreground",
|
|
5865
6516
|
processando: "bg-info-soft text-info-soft-foreground",
|
|
@@ -5869,6 +6520,7 @@ function ManifestView({ onOpenNote, onBack }) {
|
|
|
5869
6520
|
const [notes, setNotes] = useState([]);
|
|
5870
6521
|
const [loading, setLoading] = useState(true);
|
|
5871
6522
|
const [tab, setTab] = useState("pendentes");
|
|
6523
|
+
const [pullOpen, setPullOpen] = useState(false);
|
|
5872
6524
|
const reload = useCallback(async () => {
|
|
5873
6525
|
setLoading(true);
|
|
5874
6526
|
try {
|
|
@@ -5918,12 +6570,19 @@ function ManifestView({ onOpenNote, onBack }) {
|
|
|
5918
6570
|
/* @__PURE__ */ jsx(Hint, { className: "mt-3", children: /* @__PURE__ */ jsx("span", { children: "A manifesta\xE7\xE3o continua sendo feita no sistema antigo por enquanto. Aqui voc\xEA l\xEA a fila e o que a SEFAZ respondeu; a entrada no estoque e a conta a pagar j\xE1 s\xE3o feitas nesta tela nova." }) }),
|
|
5919
6571
|
/* @__PURE__ */ jsxs("div", { className: "mt-3 flex flex-wrap gap-2", children: [
|
|
5920
6572
|
/* @__PURE__ */ jsx(EmBreve, { label: "Aceitar / Recusar", o_que: "Responder \xE0 SEFAZ \u2014 \xE9 obriga\xE7\xE3o com prazo. Hoje a manifesta\xE7\xE3o \xE9 feita no sistema antigo" }),
|
|
5921
|
-
/* @__PURE__ */
|
|
6573
|
+
/* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: () => setPullOpen(true), children: [
|
|
6574
|
+
/* @__PURE__ */ jsx(KeyRound, { className: "mr-1.5 h-4 w-4" }),
|
|
6575
|
+
"Puxar por chave"
|
|
6576
|
+
] }),
|
|
5922
6577
|
/* @__PURE__ */ jsx(EmBreve, { label: "Sincronizar agora", o_que: "Pedir \xE0 SEFAZ o que chegou desde a \xFAltima varredura" }),
|
|
5923
6578
|
/* @__PURE__ */ jsx(EmBreve, { label: "Resincronizar tudo", o_que: "Refazer a varredura inteira do per\xEDodo" }),
|
|
5924
6579
|
/* @__PURE__ */ jsx(EmBreve, { label: "Diagnosticar", o_que: "Por que uma nota n\xE3o chegou: certificado, credencial ou cursor parado" })
|
|
5925
6580
|
] })
|
|
5926
6581
|
] }),
|
|
6582
|
+
/* @__PURE__ */ jsx(PullByKeyDialog, { open: pullOpen, onOpenChange: setPullOpen, onPulled: (r) => {
|
|
6583
|
+
void reload();
|
|
6584
|
+
onOpenNote(r.documentId);
|
|
6585
|
+
} }),
|
|
5927
6586
|
/* @__PURE__ */ jsx(ListFilterBar, { filters, onClear: () => setTab("todas"), activeCount: tab === "todas" ? 0 : 1 }),
|
|
5928
6587
|
loading ? /* @__PURE__ */ jsx("div", { className: "space-y-2", children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx(Skeleton, { className: "h-12 w-full" }, i)) }) : shown.length === 0 ? /* @__PURE__ */ jsxs(Card, { className: "p-10 text-center", children: [
|
|
5929
6588
|
/* @__PURE__ */ jsx(FileText, { className: "mx-auto h-8 w-8 text-muted-foreground", "aria-hidden": true }),
|
|
@@ -5939,10 +6598,10 @@ function ManifestView({ onOpenNote, onBack }) {
|
|
|
5939
6598
|
/* @__PURE__ */ jsx("th", { className: "px-3 py-2 text-right font-medium", children: "A\xE7\xF5es" })
|
|
5940
6599
|
] }) }),
|
|
5941
6600
|
/* @__PURE__ */ jsx("tbody", { children: shown.map((note) => /* @__PURE__ */ jsxs("tr", { className: "border-b last:border-0 hover:bg-muted/30", children: [
|
|
5942
|
-
/* @__PURE__ */ jsx("td", { className: "px-3 py-2 tabular-nums text-muted-foreground", children:
|
|
6601
|
+
/* @__PURE__ */ jsx("td", { className: "px-3 py-2 tabular-nums text-muted-foreground", children: day4(note.issueDate) }),
|
|
5943
6602
|
/* @__PURE__ */ jsx("td", { className: "px-3 py-2 tabular-nums font-medium", children: note.number }),
|
|
5944
6603
|
/* @__PURE__ */ jsx("td", { className: "px-3 py-2", children: note.supplierName || "\u2014" }),
|
|
5945
|
-
/* @__PURE__ */ jsx("td", { className: "px-3 py-2 text-right tabular-nums", children:
|
|
6604
|
+
/* @__PURE__ */ jsx("td", { className: "px-3 py-2 text-right tabular-nums", children: money4(note.total) }),
|
|
5946
6605
|
/* @__PURE__ */ jsx("td", { className: "px-3 py-2 text-right tabular-nums text-muted-foreground", children: note.instalmentCount }),
|
|
5947
6606
|
/* @__PURE__ */ jsx("td", { className: "px-3 py-2 text-center", children: /* @__PURE__ */ jsx("span", { className: `inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium ${MANIFEST_TONE[note.manifestationStatus ?? ""] ?? "bg-muted text-muted-foreground"}`, children: note.manifestationStatus ?? "n\xE3o manifestada" }) }),
|
|
5948
6607
|
/* @__PURE__ */ jsx("td", { className: "px-3 py-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-1.5", children: [
|
|
@@ -6078,9 +6737,9 @@ var COLUMNS = [
|
|
|
6078
6737
|
].join(", ");
|
|
6079
6738
|
var sb2 = () => getSupabaseClientOptional();
|
|
6080
6739
|
function useEmitterSettings(legalEntityId) {
|
|
6081
|
-
const [row, setRow] =
|
|
6082
|
-
const [loading, setLoading] =
|
|
6083
|
-
|
|
6740
|
+
const [row, setRow] = React7.useState(null);
|
|
6741
|
+
const [loading, setLoading] = React7.useState(true);
|
|
6742
|
+
React7.useEffect(() => {
|
|
6084
6743
|
if (!legalEntityId) {
|
|
6085
6744
|
setLoading(false);
|
|
6086
6745
|
return;
|
|
@@ -6096,7 +6755,7 @@ function useEmitterSettings(legalEntityId) {
|
|
|
6096
6755
|
alive = false;
|
|
6097
6756
|
};
|
|
6098
6757
|
}, [legalEntityId]);
|
|
6099
|
-
const save =
|
|
6758
|
+
const save = React7.useCallback(async (tenantId, patch) => {
|
|
6100
6759
|
if (!legalEntityId) return false;
|
|
6101
6760
|
const payload = { ...patch, tenant_id: tenantId, legal_entity_id: legalEntityId, updated_at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
6102
6761
|
const { data, error } = await sb2().from("plg_fiscalbr_emitter_settings").upsert(payload, { onConflict: "legal_entity_id" }).select(COLUMNS).single();
|
|
@@ -6149,7 +6808,7 @@ function SummaryCard({ title, lines, badge, onConfigure }) {
|
|
|
6149
6808
|
return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(CardHeader, { className: "flex-row items-start justify-between gap-3 space-y-0", children: [
|
|
6150
6809
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
6151
6810
|
/* @__PURE__ */ jsx(CardTitle, { className: "text-base", children: title }),
|
|
6152
|
-
/* @__PURE__ */ jsx("dl", { className: "mt-2 grid gap-x-6 gap-y-1 text-sm", style: { gridTemplateColumns: "auto 1fr" }, children: lines.map((l) => /* @__PURE__ */ jsxs(
|
|
6811
|
+
/* @__PURE__ */ jsx("dl", { className: "mt-2 grid gap-x-6 gap-y-1 text-sm", style: { gridTemplateColumns: "auto 1fr" }, children: lines.map((l) => /* @__PURE__ */ jsxs(React7.Fragment, { children: [
|
|
6153
6812
|
/* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: l.label }),
|
|
6154
6813
|
/* @__PURE__ */ jsx("dd", { className: "text-foreground", children: l.value })
|
|
6155
6814
|
] }, l.label)) })
|
|
@@ -6170,7 +6829,7 @@ function SummaryCard({ title, lines, badge, onConfigure }) {
|
|
|
6170
6829
|
var fmtDateTime = (v) => v ? new Date(v).toLocaleString("pt-BR") : null;
|
|
6171
6830
|
function UnitCertificateWidget({ item }) {
|
|
6172
6831
|
const { row, loading, save } = useEmitterSettings(item?.legalEntityId);
|
|
6173
|
-
const [open, setOpen] =
|
|
6832
|
+
const [open, setOpen] = React7.useState(false);
|
|
6174
6833
|
if (!item?.id) return null;
|
|
6175
6834
|
if (!item.legalEntityId) return /* @__PURE__ */ jsx(NeedsLegalEntity, { item, what: "O certificado digital" });
|
|
6176
6835
|
if (loading || !row) return /* @__PURE__ */ jsx(LoadingCard, {});
|
|
@@ -6273,11 +6932,11 @@ function EnvSelect({ value, onChange, disabled }) {
|
|
|
6273
6932
|
}
|
|
6274
6933
|
function UnitFiscalWidget({ item }) {
|
|
6275
6934
|
const { row, loading, save } = useEmitterSettings(item?.legalEntityId);
|
|
6276
|
-
const [draft, setDraft] =
|
|
6277
|
-
const [cscToken, setCscToken] =
|
|
6278
|
-
const [saving, setSaving] =
|
|
6279
|
-
const [open, setOpen] =
|
|
6280
|
-
|
|
6935
|
+
const [draft, setDraft] = React7.useState({});
|
|
6936
|
+
const [cscToken, setCscToken] = React7.useState("");
|
|
6937
|
+
const [saving, setSaving] = React7.useState(false);
|
|
6938
|
+
const [open, setOpen] = React7.useState(false);
|
|
6939
|
+
React7.useEffect(() => {
|
|
6281
6940
|
if (row) setDraft(row);
|
|
6282
6941
|
}, [row]);
|
|
6283
6942
|
if (!item?.id) return null;
|
|
@@ -6645,7 +7304,7 @@ var dayOrDateTime = (v) => {
|
|
|
6645
7304
|
const d = new Date(v);
|
|
6646
7305
|
return d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0 ? d.toLocaleDateString("pt-BR") : dateTime(v);
|
|
6647
7306
|
};
|
|
6648
|
-
var
|
|
7307
|
+
var money5 = (v) => v == null ? "\u2014" : v.toLocaleString("pt-BR", { style: "currency", currency: "BRL" });
|
|
6649
7308
|
function buttonHint(s) {
|
|
6650
7309
|
const parts = [s.hasValid ? "Notas fiscais desta conta \u2014 h\xE1 uma nota v\xE1lida" : "Notas fiscais desta conta"];
|
|
6651
7310
|
if (s.withoutEffect > 0) parts.push(`${s.withoutEffect} cancelada(s), rejeitada(s) ou com erro`);
|
|
@@ -6713,7 +7372,7 @@ function NoteRow({ note, canCancel, onChanged }) {
|
|
|
6713
7372
|
else window.location.assign(url);
|
|
6714
7373
|
} catch (e) {
|
|
6715
7374
|
w?.close();
|
|
6716
|
-
toast.error("PDF indispon\xEDvel", { description:
|
|
7375
|
+
toast.error("PDF indispon\xEDvel", { description: describeError(e) });
|
|
6717
7376
|
} finally {
|
|
6718
7377
|
setBusy(null);
|
|
6719
7378
|
}
|
|
@@ -6725,7 +7384,7 @@ function NoteRow({ note, canCancel, onChanged }) {
|
|
|
6725
7384
|
await onChanged();
|
|
6726
7385
|
toast(status === note.status ? "Ainda em processamento na SEFAZ/prefeitura" : `Nota ${statusLabel({ status, cancelledAt: null }).toLowerCase()}`);
|
|
6727
7386
|
} catch (e) {
|
|
6728
|
-
toast.error("N\xE3o foi poss\xEDvel consultar", { description:
|
|
7387
|
+
toast.error("N\xE3o foi poss\xEDvel consultar", { description: describeError(e) });
|
|
6729
7388
|
} finally {
|
|
6730
7389
|
setBusy(null);
|
|
6731
7390
|
}
|
|
@@ -6813,7 +7472,7 @@ function CancelNotePanel({ note, onClose, onDone }) {
|
|
|
6813
7472
|
else toast("Cancelamento solicitado", { description: "A SEFAZ/prefeitura ainda est\xE1 processando. Use \xABAtualizar\xBB para conferir." });
|
|
6814
7473
|
await onDone();
|
|
6815
7474
|
} catch (e) {
|
|
6816
|
-
setError(
|
|
7475
|
+
setError(describeError(e));
|
|
6817
7476
|
setWorking(null);
|
|
6818
7477
|
}
|
|
6819
7478
|
};
|
|
@@ -6884,7 +7543,7 @@ function NoteDetails({ note }) {
|
|
|
6884
7543
|
["Refer\xEAncia", note.integrationId && /* @__PURE__ */ jsx("span", { className: "break-all font-mono text-xs", children: note.integrationId })],
|
|
6885
7544
|
["Chave de acesso", note.accessKey && /* @__PURE__ */ jsx("span", { className: "break-all font-mono text-xs", children: note.accessKey })],
|
|
6886
7545
|
["C\xF3digo de verifica\xE7\xE3o", note.verificationCode],
|
|
6887
|
-
["Valor",
|
|
7546
|
+
["Valor", money5(note.totalValue)],
|
|
6888
7547
|
["Tomador", recipientLabel(note.recipient)],
|
|
6889
7548
|
["Criada em", dateTime(note.createdAt)],
|
|
6890
7549
|
["Autorizada em", note.authorizedAt && dayOrDateTime(note.authorizedAt)],
|
|
@@ -7099,9 +7758,9 @@ function inboundNotesInventoryView(options = {}) {
|
|
|
7099
7758
|
};
|
|
7100
7759
|
}
|
|
7101
7760
|
function InboundNoteDocumentModal({ movement, onClose }) {
|
|
7102
|
-
const [noteId, setNoteId] =
|
|
7103
|
-
const [erro, setErro] =
|
|
7104
|
-
|
|
7761
|
+
const [noteId, setNoteId] = React7.useState(null);
|
|
7762
|
+
const [erro, setErro] = React7.useState(null);
|
|
7763
|
+
React7.useEffect(() => {
|
|
7105
7764
|
let vivo = true;
|
|
7106
7765
|
const numero = nfeNumberOf(movement);
|
|
7107
7766
|
const busca = movement.operationId ? findInboxNoteByOperation(movement.operationId).then((id) => id ?? (numero ? findInboxNoteByNumber(numero) : null)) : numero ? findInboxNoteByNumber(numero) : Promise.resolve(null);
|
|
@@ -7110,7 +7769,7 @@ function InboundNoteDocumentModal({ movement, onClose }) {
|
|
|
7110
7769
|
if (id) setNoteId(id);
|
|
7111
7770
|
else setErro("N\xE3o achei a nota desta entrada nesta conta.");
|
|
7112
7771
|
}).catch((e) => {
|
|
7113
|
-
if (vivo) setErro(
|
|
7772
|
+
if (vivo) setErro(describeError(e));
|
|
7114
7773
|
});
|
|
7115
7774
|
return () => {
|
|
7116
7775
|
vivo = false;
|
|
@@ -7283,6 +7942,6 @@ function createPlugNotasPlugin(options = {}) {
|
|
|
7283
7942
|
});
|
|
7284
7943
|
}
|
|
7285
7944
|
|
|
7286
|
-
export { EVENT_LABEL, InboundNoteDocumentModal, InboundNotesPage, InboundNotesView, InvoiceNotesButton, IssuedNotesView, MODEL_LABEL, ManifestView, NfeParseError, NoteReconcileView, PLUGNOTAS_CONNECTOR_ID, PLUGNOTAS_FIELDS, PLUGNOTAS_SETTINGS, ReturnedNotesView, STATUS_META, STOCK_BEARING_ENTRY_TYPES, TaxGroupsView, acceptNote, cancelNote, createPlugNotasConnector, createPlugNotasFinancialProvider, createPlugNotasPlugin, eventStatusLabel, explainRejection, fetchNotePdf, findInboxNoteByNumber, findInboxNoteByOperation, getInboxNote, getInboxNoteXml, inboundNoteDocumentModal, inboundNotesInventoryView, isStockBearing, isValidCnpj, isWithoutEffect, listChartAccounts, listInboxNotes, listInvoiceNotes, listMeasurementUnits, listNoteEvents, listProductsByIds, listStockLocations, listSupplierMap, markPlugNotasEmitterReady, notesButtonState, onlyDigits, parseNfeXml, paymentLabel, paymentTypeFromCode, recipientLabel, refreshNote, rejectNote, saveNoteDecision, searchProducts, stageNoteFromXml, statusLabel, suggestNoteItems, summarizeNotes, toStagePayload };
|
|
7945
|
+
export { EVENT_LABEL, InboundNoteDocumentModal, InboundNotesPage, InboundNotesView, InvoiceNotesButton, IssuedNotesView, MODEL_LABEL, ManifestView, NfeParseError, NoteReconcileView, PLUGNOTAS_CONNECTOR_ID, PLUGNOTAS_FIELDS, PLUGNOTAS_SETTINGS, PullByKeyError, ReturnedNotesView, STATUS_META, STOCK_BEARING_ENTRY_TYPES, TaxGroupsView, acceptNote, addNoteAttachment, cancelNote, createPlugNotasConnector, createPlugNotasFinancialProvider, createPlugNotasPlugin, eventStatusLabel, explainRejection, extractPaymentCode, fetchNotePdf, findInboxNoteByNumber, findInboxNoteByOperation, getInboxNote, getInboxNotePdf, getInboxNoteXml, inboundNoteDocumentModal, inboundNotesInventoryView, isStockBearing, isValidCnpj, isWithoutEffect, linkInboxSupplier, listChartAccounts, listInboxNotes, listInvoiceNotes, listMeasurementUnits, listNoteAttachments, listNoteEvents, listProductsByIds, listStockLocations, listSupplierMap, markPlugNotasEmitterReady, moveNoteAttachmentsToInvoice, notesButtonState, onlyDigits, parseBoleto, parseNfeXml, paymentLabel, paymentTypeFromCode, pullNoteByKey, recipientLabel, refreshNote, rejectNote, removeNoteAttachment, saveNoteDecision, searchProducts, stageNoteFromXml, statusLabel, suggestNoteItems, summarizeNotes, toStagePayload };
|
|
7287
7946
|
//# sourceMappingURL=index.js.map
|
|
7288
7947
|
//# sourceMappingURL=index.js.map
|