@fast-white-cat/integration-ksef-direct 0.1.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.
Files changed (140) hide show
  1. package/README.md +36 -0
  2. package/dist/index.js +2 -0
  3. package/dist/index.js.map +7 -0
  4. package/dist/modules/integration_ksef_direct/acl.js +13 -0
  5. package/dist/modules/integration_ksef_direct/acl.js.map +7 -0
  6. package/dist/modules/integration_ksef_direct/api/get/integration-ksef-direct/documents/[id].js +92 -0
  7. package/dist/modules/integration_ksef_direct/api/get/integration-ksef-direct/documents/[id].js.map +7 -0
  8. package/dist/modules/integration_ksef_direct/api/get/integration-ksef-direct/documents.js +105 -0
  9. package/dist/modules/integration_ksef_direct/api/get/integration-ksef-direct/documents.js.map +7 -0
  10. package/dist/modules/integration_ksef_direct/api/get/integration-ksef-direct/health.js +158 -0
  11. package/dist/modules/integration_ksef_direct/api/get/integration-ksef-direct/health.js.map +7 -0
  12. package/dist/modules/integration_ksef_direct/api/get/integration-ksef-direct/received-documents/[id].js +86 -0
  13. package/dist/modules/integration_ksef_direct/api/get/integration-ksef-direct/received-documents/[id].js.map +7 -0
  14. package/dist/modules/integration_ksef_direct/api/get/integration-ksef-direct/received-documents.js +112 -0
  15. package/dist/modules/integration_ksef_direct/api/get/integration-ksef-direct/received-documents.js.map +7 -0
  16. package/dist/modules/integration_ksef_direct/api/get/integration-ksef-direct/seller-info.js +54 -0
  17. package/dist/modules/integration_ksef_direct/api/get/integration-ksef-direct/seller-info.js.map +7 -0
  18. package/dist/modules/integration_ksef_direct/api/post/integration-ksef-direct/documents/[id]/send.js +64 -0
  19. package/dist/modules/integration_ksef_direct/api/post/integration-ksef-direct/documents/[id]/send.js.map +7 -0
  20. package/dist/modules/integration_ksef_direct/api/post/integration-ksef-direct/documents.js +104 -0
  21. package/dist/modules/integration_ksef_direct/api/post/integration-ksef-direct/documents.js.map +7 -0
  22. package/dist/modules/integration_ksef_direct/api/post/integration-ksef-direct/invoice-numbers.js +41 -0
  23. package/dist/modules/integration_ksef_direct/api/post/integration-ksef-direct/invoice-numbers.js.map +7 -0
  24. package/dist/modules/integration_ksef_direct/api/post/integration-ksef-direct/received-documents/fetch.js +172 -0
  25. package/dist/modules/integration_ksef_direct/api/post/integration-ksef-direct/received-documents/fetch.js.map +7 -0
  26. package/dist/modules/integration_ksef_direct/api/post/integration-ksef-direct/received-documents/sync.js +80 -0
  27. package/dist/modules/integration_ksef_direct/api/post/integration-ksef-direct/received-documents/sync.js.map +7 -0
  28. package/dist/modules/integration_ksef_direct/backend/integration-ksef-direct/documents/new/page.js +441 -0
  29. package/dist/modules/integration_ksef_direct/backend/integration-ksef-direct/documents/new/page.js.map +7 -0
  30. package/dist/modules/integration_ksef_direct/backend/integration-ksef-direct/documents/new/page.meta.js +8 -0
  31. package/dist/modules/integration_ksef_direct/backend/integration-ksef-direct/documents/new/page.meta.js.map +7 -0
  32. package/dist/modules/integration_ksef_direct/backend/integration-ksef-direct/documents/page.js +193 -0
  33. package/dist/modules/integration_ksef_direct/backend/integration-ksef-direct/documents/page.js.map +7 -0
  34. package/dist/modules/integration_ksef_direct/backend/integration-ksef-direct/received-documents/page.js +314 -0
  35. package/dist/modules/integration_ksef_direct/backend/integration-ksef-direct/received-documents/page.js.map +7 -0
  36. package/dist/modules/integration_ksef_direct/backend/page.js +154 -0
  37. package/dist/modules/integration_ksef_direct/backend/page.js.map +7 -0
  38. package/dist/modules/integration_ksef_direct/commands/create-ksef-direct-document.js +80 -0
  39. package/dist/modules/integration_ksef_direct/commands/create-ksef-direct-document.js.map +7 -0
  40. package/dist/modules/integration_ksef_direct/commands/enqueue-ksef-direct-document.js +43 -0
  41. package/dist/modules/integration_ksef_direct/commands/enqueue-ksef-direct-document.js.map +7 -0
  42. package/dist/modules/integration_ksef_direct/data/entities.js +224 -0
  43. package/dist/modules/integration_ksef_direct/data/entities.js.map +7 -0
  44. package/dist/modules/integration_ksef_direct/data/validators.js +103 -0
  45. package/dist/modules/integration_ksef_direct/data/validators.js.map +7 -0
  46. package/dist/modules/integration_ksef_direct/di.js +11 -0
  47. package/dist/modules/integration_ksef_direct/di.js.map +7 -0
  48. package/dist/modules/integration_ksef_direct/events.js +21 -0
  49. package/dist/modules/integration_ksef_direct/events.js.map +7 -0
  50. package/dist/modules/integration_ksef_direct/index.js +10 -0
  51. package/dist/modules/integration_ksef_direct/index.js.map +7 -0
  52. package/dist/modules/integration_ksef_direct/integration.js +56 -0
  53. package/dist/modules/integration_ksef_direct/integration.js.map +7 -0
  54. package/dist/modules/integration_ksef_direct/lib/health.js +32 -0
  55. package/dist/modules/integration_ksef_direct/lib/health.js.map +7 -0
  56. package/dist/modules/integration_ksef_direct/lib/invoiceNumberFormat.js +23 -0
  57. package/dist/modules/integration_ksef_direct/lib/invoiceNumberFormat.js.map +7 -0
  58. package/dist/modules/integration_ksef_direct/lib/ksefClient.js +523 -0
  59. package/dist/modules/integration_ksef_direct/lib/ksefClient.js.map +7 -0
  60. package/dist/modules/integration_ksef_direct/lib/ksefCrypto.js +103 -0
  61. package/dist/modules/integration_ksef_direct/lib/ksefCrypto.js.map +7 -0
  62. package/dist/modules/integration_ksef_direct/lib/ksefFa2Xml.js +123 -0
  63. package/dist/modules/integration_ksef_direct/lib/ksefFa2Xml.js.map +7 -0
  64. package/dist/modules/integration_ksef_direct/lib/ksefXmlParser.js +76 -0
  65. package/dist/modules/integration_ksef_direct/lib/ksefXmlParser.js.map +7 -0
  66. package/dist/modules/integration_ksef_direct/migrations/Migration20260519210000_integration_ksef_direct.js +15 -0
  67. package/dist/modules/integration_ksef_direct/migrations/Migration20260519210000_integration_ksef_direct.js.map +7 -0
  68. package/dist/modules/integration_ksef_direct/migrations/Migration20260520120000_ksef_direct_documents.js +17 -0
  69. package/dist/modules/integration_ksef_direct/migrations/Migration20260520120000_ksef_direct_documents.js.map +7 -0
  70. package/dist/modules/integration_ksef_direct/migrations/Migration20260520220000_ksef_direct_send_queue.js +15 -0
  71. package/dist/modules/integration_ksef_direct/migrations/Migration20260520220000_ksef_direct_send_queue.js.map +7 -0
  72. package/dist/modules/integration_ksef_direct/migrations/Migration20260520230000_ksef_direct_seller_per_document.js +17 -0
  73. package/dist/modules/integration_ksef_direct/migrations/Migration20260520230000_ksef_direct_seller_per_document.js.map +7 -0
  74. package/dist/modules/integration_ksef_direct/migrations/Migration20260521120000_ksef_direct_received_documents.js +16 -0
  75. package/dist/modules/integration_ksef_direct/migrations/Migration20260521120000_ksef_direct_received_documents.js.map +7 -0
  76. package/dist/modules/integration_ksef_direct/migrations/Migration20260521130000_ksef_received_download_urls.js +15 -0
  77. package/dist/modules/integration_ksef_direct/migrations/Migration20260521130000_ksef_received_download_urls.js.map +7 -0
  78. package/dist/modules/integration_ksef_direct/setup.js +11 -0
  79. package/dist/modules/integration_ksef_direct/setup.js.map +7 -0
  80. package/dist/modules/integration_ksef_direct/subscribers/auto-enqueue-ksef-document.js +19 -0
  81. package/dist/modules/integration_ksef_direct/subscribers/auto-enqueue-ksef-document.js.map +7 -0
  82. package/dist/modules/integration_ksef_direct/workers/check-ksef-document-status.js +103 -0
  83. package/dist/modules/integration_ksef_direct/workers/check-ksef-document-status.js.map +7 -0
  84. package/dist/modules/integration_ksef_direct/workers/send-ksef-document.js +104 -0
  85. package/dist/modules/integration_ksef_direct/workers/send-ksef-document.js.map +7 -0
  86. package/dist/modules/integration_ksef_direct/workers/sync-received-documents.js +137 -0
  87. package/dist/modules/integration_ksef_direct/workers/sync-received-documents.js.map +7 -0
  88. package/dist/types/declarations.d.js +1 -0
  89. package/dist/types/declarations.d.js.map +7 -0
  90. package/package.json +98 -0
  91. package/src/index.ts +1 -0
  92. package/src/modules/integration_ksef_direct/__tests__/invoiceNumberFormat.test.ts +42 -0
  93. package/src/modules/integration_ksef_direct/__tests__/ksefFa2Xml.test.ts +407 -0
  94. package/src/modules/integration_ksef_direct/__tests__/ksefXmlParser.test.ts +230 -0
  95. package/src/modules/integration_ksef_direct/acl.ts +9 -0
  96. package/src/modules/integration_ksef_direct/api/get/integration-ksef-direct/documents/[id].ts +94 -0
  97. package/src/modules/integration_ksef_direct/api/get/integration-ksef-direct/documents.ts +111 -0
  98. package/src/modules/integration_ksef_direct/api/get/integration-ksef-direct/health.ts +194 -0
  99. package/src/modules/integration_ksef_direct/api/get/integration-ksef-direct/received-documents/[id].ts +88 -0
  100. package/src/modules/integration_ksef_direct/api/get/integration-ksef-direct/received-documents.ts +119 -0
  101. package/src/modules/integration_ksef_direct/api/get/integration-ksef-direct/seller-info.ts +62 -0
  102. package/src/modules/integration_ksef_direct/api/post/integration-ksef-direct/documents/[id]/send.ts +64 -0
  103. package/src/modules/integration_ksef_direct/api/post/integration-ksef-direct/documents.ts +109 -0
  104. package/src/modules/integration_ksef_direct/api/post/integration-ksef-direct/invoice-numbers.ts +40 -0
  105. package/src/modules/integration_ksef_direct/api/post/integration-ksef-direct/received-documents/fetch.ts +185 -0
  106. package/src/modules/integration_ksef_direct/api/post/integration-ksef-direct/received-documents/sync.ts +86 -0
  107. package/src/modules/integration_ksef_direct/backend/integration-ksef-direct/documents/new/page.meta.ts +4 -0
  108. package/src/modules/integration_ksef_direct/backend/integration-ksef-direct/documents/new/page.tsx +470 -0
  109. package/src/modules/integration_ksef_direct/backend/integration-ksef-direct/documents/page.tsx +233 -0
  110. package/src/modules/integration_ksef_direct/backend/integration-ksef-direct/received-documents/page.tsx +415 -0
  111. package/src/modules/integration_ksef_direct/backend/page.tsx +183 -0
  112. package/src/modules/integration_ksef_direct/commands/create-ksef-direct-document.ts +93 -0
  113. package/src/modules/integration_ksef_direct/commands/enqueue-ksef-direct-document.ts +57 -0
  114. package/src/modules/integration_ksef_direct/data/entities.ts +195 -0
  115. package/src/modules/integration_ksef_direct/data/validators.ts +115 -0
  116. package/src/modules/integration_ksef_direct/di.ts +9 -0
  117. package/src/modules/integration_ksef_direct/events.ts +18 -0
  118. package/src/modules/integration_ksef_direct/i18n/en.json +115 -0
  119. package/src/modules/integration_ksef_direct/i18n/pl.json +115 -0
  120. package/src/modules/integration_ksef_direct/index.ts +6 -0
  121. package/src/modules/integration_ksef_direct/integration.ts +54 -0
  122. package/src/modules/integration_ksef_direct/lib/health.ts +43 -0
  123. package/src/modules/integration_ksef_direct/lib/invoiceNumberFormat.ts +23 -0
  124. package/src/modules/integration_ksef_direct/lib/ksefClient.ts +668 -0
  125. package/src/modules/integration_ksef_direct/lib/ksefCrypto.ts +138 -0
  126. package/src/modules/integration_ksef_direct/lib/ksefFa2Xml.ts +147 -0
  127. package/src/modules/integration_ksef_direct/lib/ksefXmlParser.ts +97 -0
  128. package/src/modules/integration_ksef_direct/migrations/.snapshot-open-mercato.json +1028 -0
  129. package/src/modules/integration_ksef_direct/migrations/Migration20260519210000_integration_ksef_direct.ts +15 -0
  130. package/src/modules/integration_ksef_direct/migrations/Migration20260520120000_ksef_direct_documents.ts +17 -0
  131. package/src/modules/integration_ksef_direct/migrations/Migration20260520220000_ksef_direct_send_queue.ts +15 -0
  132. package/src/modules/integration_ksef_direct/migrations/Migration20260520230000_ksef_direct_seller_per_document.ts +17 -0
  133. package/src/modules/integration_ksef_direct/migrations/Migration20260521120000_ksef_direct_received_documents.ts +16 -0
  134. package/src/modules/integration_ksef_direct/migrations/Migration20260521130000_ksef_received_download_urls.ts +15 -0
  135. package/src/modules/integration_ksef_direct/setup.ts +9 -0
  136. package/src/modules/integration_ksef_direct/subscribers/auto-enqueue-ksef-document.ts +21 -0
  137. package/src/modules/integration_ksef_direct/workers/check-ksef-document-status.ts +129 -0
  138. package/src/modules/integration_ksef_direct/workers/send-ksef-document.ts +137 -0
  139. package/src/modules/integration_ksef_direct/workers/sync-received-documents.ts +171 -0
  140. package/src/types/declarations.d.ts +1 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../src/modules/integration_ksef_direct/backend/integration-ksef-direct/documents/new/page.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Plus, RefreshCw, Trash2 } from 'lucide-react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { SectionHeader } from '@open-mercato/ui/backend/SectionHeader'\nimport { FormField } from '@open-mercato/ui/primitives/form-field'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\nexport const pageMetadata = { features: ['integration_ksef_direct.documents.create'], navHidden: true }\n\nconst VAT_RATES = ['0', '5', '8', '23', 'ZW', 'NP'] as const\nconst CURRENCIES = ['PLN', 'EUR', 'USD', 'GBP'] as const\nconst VAT_RATE_MULTIPLIERS: Record<string, number> = { '0': 0, '5': 5, '8': 8, '23': 23, ZW: 0, NP: 0 }\n\ntype LineItemState = {\n description: string\n quantity: string\n unit: string\n unitNetPrice: string\n vatRate: string\n}\n\ntype Totals = { net: number; vat: number; gross: number }\n\nfunction round2(v: number) { return Math.round(v * 100) / 100 }\n\nfunction computeTotals(items: LineItemState[]): Totals {\n let net = 0, vat = 0\n for (const item of items) {\n const qty = parseFloat(item.quantity) || 0\n const price = parseFloat(item.unitNetPrice) || 0\n const lineNet = round2(qty * price)\n const rate = VAT_RATE_MULTIPLIERS[item.vatRate] ?? 0\n const lineVat = round2(lineNet * rate / 100)\n net += lineNet\n vat += lineVat\n }\n net = round2(net)\n vat = round2(vat)\n return { net, vat, gross: round2(net + vat) }\n}\n\nfunction emptyLine(): LineItemState {\n return { description: '', quantity: '1', unit: 'szt', unitNetPrice: '0.00', vatRate: '23' }\n}\n\nexport default function NewKsefDirectDocumentPage() {\n const t = useT()\n const router = useRouter()\n\n const [buyerNip, setBuyerNip] = React.useState('')\n const [buyerName, setBuyerName] = React.useState('')\n const [invoiceNumber, setInvoiceNumber] = React.useState('')\n const today = new Date().toISOString().split('T')[0]\n const [issueDate, setIssueDate] = React.useState(today)\n const [saleDate, setSaleDate] = React.useState(today)\n const [currency, setCurrency] = React.useState('PLN')\n const [lineItems, setLineItems] = React.useState<LineItemState[]>([emptyLine()])\n const [notes, setNotes] = React.useState('')\n const [sellerNip, setSellerNip] = React.useState<string | null>(null)\n const [sellerName, setSellerName] = React.useState('')\n const [isGeneratingNumber, setIsGeneratingNumber] = React.useState(false)\n const [sellerAddressL1, setSellerAddressL1] = React.useState('')\n const [sellerCity, setSellerCity] = React.useState('')\n const [sellerCountry, setSellerCountry] = React.useState('PL')\n const [submitError, setSubmitError] = React.useState<string | null>(null)\n const [isMutating, setIsMutating] = React.useState(false)\n\n const { runMutation } = useGuardedMutation<{ entityType: string }>({\n contextId: 'integration_ksef_direct:new-document',\n })\n\n React.useEffect(() => {\n apiCall('/api/integration-ksef-direct/seller-info')\n .then((res) => {\n if (!res.ok) return\n const data = res.result as { sellerNip: string | null; sellerName: string | null }\n if (data.sellerNip !== undefined) setSellerNip(data.sellerNip)\n if (data.sellerName && !sellerName) setSellerName(data.sellerName)\n })\n .catch(() => {\n flash(t('integration_ksef_direct.documents.form.seller_info_error', 'Failed to load seller info'), 'error')\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const totals = React.useMemo(() => computeTotals(lineItems), [lineItems])\n\n React.useEffect(() => {\n function onKeyDown(e: KeyboardEvent) {\n if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n e.preventDefault()\n void handleSubmit()\n }\n if (e.key === 'Escape') router.back()\n }\n window.addEventListener('keydown', onKeyDown)\n return () => window.removeEventListener('keydown', onKeyDown)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [router, buyerNip, buyerName, invoiceNumber, issueDate, saleDate, currency, lineItems, notes, sellerName, sellerAddressL1, sellerCity, sellerCountry])\n\n function addLine() {\n setLineItems((prev) => [...prev, emptyLine()])\n }\n\n function removeLine(index: number) {\n if (lineItems.length <= 1) return\n setLineItems((prev) => prev.filter((_, i) => i !== index))\n }\n\n function updateLine(index: number, field: keyof LineItemState, value: string) {\n setLineItems((prev) => prev.map((item, i) => i === index ? { ...item, [field]: value } : item))\n }\n\n async function handleGenerateNumber() {\n setIsGeneratingNumber(true)\n try {\n const result = await apiCall('/api/integration-ksef-direct/invoice-numbers', { method: 'POST' })\n if (result.ok) {\n const data = result.result as { number: string }\n setInvoiceNumber(data.number)\n } else {\n flash(t('integration_ksef_direct.documents.form.generate_number_error', 'Failed to generate invoice number'), 'error')\n }\n } catch {\n flash(t('integration_ksef_direct.documents.form.generate_number_error', 'Failed to generate invoice number'), 'error')\n } finally {\n setIsGeneratingNumber(false)\n }\n }\n\n async function handleSubmit() {\n setSubmitError(null)\n if (!sellerAddressL1.trim() || !sellerCity.trim()) {\n setSubmitError(t('integration_ksef_direct.documents.form.error_seller_address_required', 'Seller street and city are required.'))\n return\n }\n setIsMutating(true)\n const body = {\n buyerNip,\n buyerName: buyerName || undefined,\n invoiceNumber,\n issueDate,\n saleDate: saleDate || undefined,\n currency,\n lineItems: lineItems.map((item) => ({\n description: item.description,\n quantity: parseFloat(item.quantity) || 0,\n unit: item.unit,\n unitNetPrice: parseFloat(item.unitNetPrice) || 0,\n vatRate: item.vatRate,\n })),\n notes: notes || undefined,\n sellerName: sellerName || undefined,\n sellerAddressL1,\n sellerCity,\n sellerCountry: sellerCountry || undefined,\n }\n\n try {\n await runMutation({\n operation: async () => {\n const result = await apiCall('/api/integration-ksef-direct/documents', {\n method: 'POST',\n body: JSON.stringify(body),\n headers: { 'Content-Type': 'application/json' },\n })\n if (!result.ok) {\n const err = (result.result as Record<string, unknown>)?.error\n throw new Error(typeof err === 'string' ? err : t('integration_ksef_direct.documents.form.error', 'Submission failed'))\n }\n return result.result\n },\n context: { entityType: 'integration_ksef_direct.document' },\n mutationPayload: { entityType: 'integration_ksef_direct.document' },\n })\n flash(t('integration_ksef_direct.documents.form.success', 'Document created successfully.'), 'success')\n router.push('/backend/integration-ksef-direct/documents')\n } catch (err) {\n setSubmitError(err instanceof Error ? err.message : t('integration_ksef_direct.documents.form.error', 'Submission failed'))\n } finally {\n setIsMutating(false)\n }\n }\n\n return (\n <Page>\n <PageBody>\n <h1 className=\"text-xl font-semibold mb-6\">\n {t('integration_ksef_direct.documents.form.title_new', 'New KSeF Document')}\n </h1>\n\n {submitError && (\n <Alert variant=\"destructive\" className=\"mb-6\">\n <AlertDescription>{submitError}</AlertDescription>\n </Alert>\n )}\n\n <SectionHeader title={t('integration_ksef_direct.documents.form.section.buyer', 'Buyer')} />\n <div className=\"grid grid-cols-2 gap-4 mb-6\">\n <FormField label={t('integration_ksef_direct.documents.form.buyer_nip', 'Buyer NIP')} required>\n <input\n type=\"text\"\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm\"\n value={buyerNip}\n onChange={(e) => setBuyerNip(e.target.value)}\n placeholder=\"1234567890\"\n maxLength={10}\n />\n </FormField>\n <FormField label={t('integration_ksef_direct.documents.form.buyer_name', 'Buyer Name')}>\n <input\n type=\"text\"\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm\"\n value={buyerName}\n onChange={(e) => setBuyerName(e.target.value)}\n />\n </FormField>\n </div>\n\n <SectionHeader title={t('integration_ksef_direct.documents.form.section.invoice', 'Invoice Details')} />\n <div className=\"grid grid-cols-2 gap-4 mb-6\">\n <FormField label={t('integration_ksef_direct.documents.form.invoice_number', 'Invoice Number')} required>\n <div className=\"flex gap-2 items-center\">\n <input\n type=\"text\"\n className=\"flex-1 border border-input rounded-md px-3 py-2 text-sm\"\n value={invoiceNumber}\n onChange={(e) => setInvoiceNumber(e.target.value)}\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void handleGenerateNumber()}\n disabled={isGeneratingNumber}\n className=\"shrink-0\"\n >\n {isGeneratingNumber\n ? <><Spinner className=\"size-4 mr-2\" />{t('integration_ksef_direct.documents.form.generating', 'Generating...')}</>\n : <><RefreshCw className=\"size-4 mr-2\" aria-hidden />{t('integration_ksef_direct.documents.form.generate_number', 'Generate number')}</>\n }\n </Button>\n </div>\n </FormField>\n <FormField label={t('integration_ksef_direct.documents.form.currency', 'Currency')}>\n <select\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm\"\n value={currency}\n onChange={(e) => setCurrency(e.target.value)}\n >\n {CURRENCIES.map((c) => <option key={c} value={c}>{c}</option>)}\n </select>\n </FormField>\n <FormField label={t('integration_ksef_direct.documents.form.issue_date', 'Issue Date')} required>\n <input\n type=\"date\"\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm\"\n value={issueDate}\n onChange={(e) => setIssueDate(e.target.value)}\n />\n </FormField>\n <FormField label={t('integration_ksef_direct.documents.form.sale_date', 'Sale Date')}>\n <input\n type=\"date\"\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm\"\n value={saleDate}\n onChange={(e) => setSaleDate(e.target.value)}\n />\n </FormField>\n </div>\n\n <SectionHeader\n title={`${t('integration_ksef_direct.documents.form.line_items', 'Line Items')} (${lineItems.length})`}\n className=\"mt-6\"\n />\n <div className=\"space-y-3 mb-4\">\n {lineItems.map((item, index) => (\n <div key={index} className=\"grid grid-cols-12 gap-2 items-end border border-border rounded-md p-3\">\n <div className=\"col-span-4\">\n <FormField label={t('integration_ksef_direct.documents.form.line_items.description', 'Description')} required>\n <input\n type=\"text\"\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm\"\n value={item.description}\n onChange={(e) => updateLine(index, 'description', e.target.value)}\n />\n </FormField>\n </div>\n <div className=\"col-span-2\">\n <FormField label={t('integration_ksef_direct.documents.form.line_items.quantity', 'Qty')}>\n <input\n type=\"number\"\n min=\"0.001\"\n step=\"any\"\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm\"\n value={item.quantity}\n onChange={(e) => updateLine(index, 'quantity', e.target.value)}\n />\n </FormField>\n </div>\n <div className=\"col-span-1\">\n <FormField label={t('integration_ksef_direct.documents.form.line_items.unit', 'Unit')}>\n <input\n type=\"text\"\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm\"\n value={item.unit}\n onChange={(e) => updateLine(index, 'unit', e.target.value)}\n />\n </FormField>\n </div>\n <div className=\"col-span-2\">\n <FormField label={t('integration_ksef_direct.documents.form.line_items.unit_net_price', 'Net Price')}>\n <input\n type=\"number\"\n min=\"0\"\n step=\"0.01\"\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm\"\n value={item.unitNetPrice}\n onChange={(e) => updateLine(index, 'unitNetPrice', e.target.value)}\n />\n </FormField>\n </div>\n <div className=\"col-span-2\">\n <FormField label={t('integration_ksef_direct.documents.form.line_items.vat_rate', 'VAT')}>\n <select\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm\"\n value={item.vatRate}\n onChange={(e) => updateLine(index, 'vatRate', e.target.value)}\n >\n {VAT_RATES.map((r) => <option key={r} value={r}>{r}%</option>)}\n </select>\n </FormField>\n </div>\n <div className=\"col-span-1 flex justify-end pb-1\">\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n aria-label={t('integration_ksef_direct.documents.form.line_items.remove', 'Remove line')}\n onClick={() => removeLine(index)}\n disabled={lineItems.length <= 1}\n >\n <Trash2 className=\"size-4\" />\n </IconButton>\n </div>\n </div>\n ))}\n </div>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={addLine} className=\"mb-6\">\n <Plus className=\"size-4 mr-2\" aria-hidden />\n {t('integration_ksef_direct.documents.form.line_items.add', 'Add Line')}\n </Button>\n\n <SectionHeader title={t('integration_ksef_direct.documents.form.section.summary', 'Summary')} />\n <div className=\"grid grid-cols-3 gap-4 mb-6\">\n <FormField label={t('integration_ksef_direct.documents.form.net_amount', 'Net Amount')}>\n <input\n type=\"text\"\n readOnly\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm bg-muted\"\n value={`${totals.net.toFixed(2)} ${currency}`}\n />\n </FormField>\n <FormField label={t('integration_ksef_direct.documents.form.vat_amount', 'VAT Amount')}>\n <input\n type=\"text\"\n readOnly\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm bg-muted\"\n value={`${totals.vat.toFixed(2)} ${currency}`}\n />\n </FormField>\n <FormField label={t('integration_ksef_direct.documents.form.gross_amount', 'Gross Amount')}>\n <input\n type=\"text\"\n readOnly\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm bg-muted font-semibold\"\n value={`${totals.gross.toFixed(2)} ${currency}`}\n />\n </FormField>\n </div>\n\n <SectionHeader title={t('integration_ksef_direct.documents.form.section.seller', 'Seller')} className=\"mt-6\" />\n <div className=\"grid grid-cols-2 gap-4 mb-4\">\n <FormField label={t('integration_ksef_direct.documents.form.seller_nip', 'Seller NIP')}>\n <input\n type=\"text\"\n disabled\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm bg-muted text-muted-foreground cursor-not-allowed\"\n value={sellerNip ?? ''}\n placeholder={sellerNip === null ? t('integration_ksef_direct.documents.form.seller_nip_placeholder', 'KSeF not configured') : ''}\n />\n </FormField>\n <FormField label={t('integration_ksef_direct.documents.form.seller_name', 'Seller Name')} required>\n <input\n type=\"text\"\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm\"\n value={sellerName}\n onChange={(e) => setSellerName(e.target.value)}\n maxLength={512}\n />\n </FormField>\n </div>\n\n <SectionHeader title={t('integration_ksef_direct.documents.form.section.seller_address', 'Seller Address')} className=\"mt-0\" />\n <div className=\"grid grid-cols-2 gap-4 mb-6\">\n <FormField label={t('integration_ksef_direct.documents.form.seller_address_l1', 'Street and number')} required>\n <input\n type=\"text\"\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm\"\n value={sellerAddressL1}\n onChange={(e) => setSellerAddressL1(e.target.value)}\n maxLength={512}\n />\n </FormField>\n <FormField label={t('integration_ksef_direct.documents.form.seller_city', 'City')} required>\n <input\n type=\"text\"\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm\"\n value={sellerCity}\n onChange={(e) => setSellerCity(e.target.value)}\n maxLength={256}\n />\n </FormField>\n <FormField label={t('integration_ksef_direct.documents.form.seller_country', 'Country')}>\n <input\n type=\"text\"\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm\"\n value={sellerCountry}\n onChange={(e) => setSellerCountry(e.target.value)}\n maxLength={2}\n placeholder=\"PL\"\n />\n </FormField>\n </div>\n\n <FormField label={t('integration_ksef_direct.documents.form.notes', 'Notes')} className=\"mb-6\">\n <textarea\n rows={3}\n className=\"w-full border border-input rounded-md px-3 py-2 text-sm\"\n value={notes}\n onChange={(e) => setNotes(e.target.value)}\n />\n </FormField>\n\n <div className=\"flex gap-3\">\n <Button\n type=\"button\"\n onClick={() => void handleSubmit()}\n disabled={isMutating}\n >\n {t('integration_ksef_direct.documents.form.submit', 'Save Document')}\n </Button>\n <Button type=\"button\" variant=\"outline\" onClick={() => router.back()}>\n {t('common.cancel', 'Cancel')}\n </Button>\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,8 @@
1
+ const metadata = {
2
+ navHidden: true,
3
+ requireFeatures: ["integration_ksef_direct.documents.create"]
4
+ };
5
+ export {
6
+ metadata
7
+ };
8
+ //# sourceMappingURL=page.meta.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../src/modules/integration_ksef_direct/backend/integration-ksef-direct/documents/new/page.meta.ts"],
4
+ "sourcesContent": ["export const metadata = {\n navHidden: true,\n requireFeatures: ['integration_ksef_direct.documents.create'],\n}\n"],
5
+ "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,WAAW;AAAA,EACX,iBAAiB,CAAC,0CAA0C;AAC9D;",
6
+ "names": []
7
+ }
@@ -0,0 +1,193 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import Link from "next/link";
5
+ import { Plus, Send, RefreshCw } from "lucide-react";
6
+ import { Page, PageBody } from "@open-mercato/ui/backend/Page";
7
+ import { DataTable } from "@open-mercato/ui/backend/DataTable";
8
+ import { StatusBadge } from "@open-mercato/ui/primitives/status-badge";
9
+ import { Button } from "@open-mercato/ui/primitives/button";
10
+ import { flash } from "@open-mercato/ui/backend/FlashMessages";
11
+ import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
12
+ import { useGuardedMutation } from "@open-mercato/ui/backend/injection/useGuardedMutation";
13
+ import { useOrganizationScopeVersion } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
14
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
15
+ import { useAppEvent } from "@open-mercato/ui/backend/injection/useAppEvent";
16
+ const PAGE_SIZE = 50;
17
+ const STATUS_VARIANT = {
18
+ draft: "neutral",
19
+ queued: "warning",
20
+ sending: "warning",
21
+ sent: "success",
22
+ failed: "error"
23
+ };
24
+ const pageMetadata = {
25
+ features: ["integration_ksef_direct.documents.view"]
26
+ };
27
+ function KsefDirectDocumentsPage() {
28
+ const t = useT();
29
+ const scopeVersion = useOrganizationScopeVersion();
30
+ const [rows, setRows] = React.useState([]);
31
+ const [page, setPage] = React.useState(1);
32
+ const [total, setTotal] = React.useState(0);
33
+ const [totalPages, setTotalPages] = React.useState(1);
34
+ const [isLoading, setLoading] = React.useState(false);
35
+ const [sendingId, setSendingId] = React.useState(null);
36
+ const { runMutation } = useGuardedMutation({
37
+ contextId: "integration_ksef_direct:send-document"
38
+ });
39
+ const fetchData = React.useCallback(async () => {
40
+ setLoading(true);
41
+ try {
42
+ const result = await apiCall(
43
+ `/api/integration-ksef-direct/documents?page=${page}&pageSize=${PAGE_SIZE}`
44
+ );
45
+ if (result.ok && result.result) {
46
+ setRows(result.result.items);
47
+ setTotal(result.result.total);
48
+ setTotalPages(Math.max(1, Math.ceil(result.result.total / PAGE_SIZE)));
49
+ } else {
50
+ setRows([]);
51
+ setTotal(0);
52
+ setTotalPages(1);
53
+ }
54
+ } catch {
55
+ setRows([]);
56
+ setTotal(0);
57
+ setTotalPages(1);
58
+ } finally {
59
+ setLoading(false);
60
+ }
61
+ }, [page]);
62
+ React.useEffect(() => {
63
+ void fetchData();
64
+ }, [fetchData, scopeVersion]);
65
+ useAppEvent("ksef_direct.document.*", () => {
66
+ void fetchData();
67
+ }, [fetchData]);
68
+ const handleSend = React.useCallback(async (documentId) => {
69
+ setSendingId(documentId);
70
+ try {
71
+ await runMutation({
72
+ operation: async () => {
73
+ const result = await apiCall(`/api/integration-ksef-direct/documents/${documentId}/send`, {
74
+ method: "POST"
75
+ });
76
+ if (!result.ok) {
77
+ const err = result.result?.error;
78
+ throw new Error(typeof err === "string" ? err : t("integration_ksef_direct.documents.errors.send_failed", "Send failed"));
79
+ }
80
+ return result.result;
81
+ },
82
+ context: { entityType: "integration_ksef_direct.document" },
83
+ mutationPayload: { entityType: "integration_ksef_direct.document" }
84
+ });
85
+ flash(t("integration_ksef_direct.documents.send_success", "Document queued for sending"), "success");
86
+ void fetchData();
87
+ } catch (err) {
88
+ flash(err instanceof Error ? err.message : t("integration_ksef_direct.documents.errors.send_failed", "Send failed"), "error");
89
+ } finally {
90
+ setSendingId(null);
91
+ }
92
+ }, [runMutation, t, fetchData]);
93
+ const columns = React.useMemo(() => [
94
+ {
95
+ id: "invoiceNumber",
96
+ accessorKey: "invoiceNumber",
97
+ header: t("integration_ksef_direct.documents.columns.invoiceNumber", "Invoice Number"),
98
+ cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "font-medium", children: row.original.invoiceNumber })
99
+ },
100
+ {
101
+ id: "buyer",
102
+ header: t("integration_ksef_direct.documents.columns.buyer", "Buyer"),
103
+ cell: ({ row }) => /* @__PURE__ */ jsx("span", { children: row.original.buyerName ? `${row.original.buyerName} (${row.original.buyerNip})` : row.original.buyerNip })
104
+ },
105
+ {
106
+ id: "issueDate",
107
+ accessorKey: "issueDate",
108
+ header: t("integration_ksef_direct.documents.columns.issueDate", "Issue Date"),
109
+ cell: ({ row }) => new Date(row.original.issueDate).toLocaleDateString()
110
+ },
111
+ {
112
+ id: "grossAmount",
113
+ accessorKey: "grossAmount",
114
+ header: t("integration_ksef_direct.documents.columns.grossAmount", "Gross Amount"),
115
+ cell: ({ row }) => /* @__PURE__ */ jsxs("span", { className: "tabular-nums", children: [
116
+ parseFloat(row.original.grossAmount).toLocaleString("pl-PL", { minimumFractionDigits: 2 }),
117
+ " ",
118
+ row.original.currency
119
+ ] })
120
+ },
121
+ {
122
+ id: "status",
123
+ accessorKey: "status",
124
+ header: t("integration_ksef_direct.documents.columns.status", "Status"),
125
+ cell: ({ row }) => /* @__PURE__ */ jsx(StatusBadge, { variant: STATUS_VARIANT[row.original.status] ?? "neutral", children: t(`integration_ksef_direct.documents.status.${row.original.status}`, row.original.status) })
126
+ },
127
+ {
128
+ id: "ksefReferenceNumber",
129
+ header: t("integration_ksef_direct.documents.ksef_reference_number", "KSeF Number"),
130
+ cell: ({ row }) => row.original.ksefReferenceNumber ? /* @__PURE__ */ jsx("span", { className: "font-mono text-sm", children: row.original.ksefReferenceNumber }) : null
131
+ },
132
+ {
133
+ id: "actions",
134
+ header: "",
135
+ cell: ({ row }) => {
136
+ const { id, status } = row.original;
137
+ const isSending = sendingId === id;
138
+ if (status === "draft") {
139
+ return /* @__PURE__ */ jsxs(
140
+ Button,
141
+ {
142
+ size: "sm",
143
+ variant: "ghost",
144
+ disabled: isSending,
145
+ onClick: () => void handleSend(id),
146
+ "aria-label": t("integration_ksef_direct.documents.send_button", "Send to KSeF"),
147
+ children: [
148
+ /* @__PURE__ */ jsx(Send, { className: "h-4 w-4 mr-1" }),
149
+ t("integration_ksef_direct.documents.send_button", "Send to KSeF")
150
+ ]
151
+ }
152
+ );
153
+ }
154
+ if (status === "failed") {
155
+ return /* @__PURE__ */ jsxs(
156
+ Button,
157
+ {
158
+ size: "sm",
159
+ variant: "ghost",
160
+ disabled: isSending,
161
+ onClick: () => void handleSend(id),
162
+ "aria-label": t("integration_ksef_direct.documents.retry_button", "Retry send"),
163
+ children: [
164
+ /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4 mr-1" }),
165
+ t("integration_ksef_direct.documents.retry_button", "Retry")
166
+ ]
167
+ }
168
+ );
169
+ }
170
+ return null;
171
+ }
172
+ }
173
+ ], [t, sendingId, handleSend]);
174
+ return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
175
+ DataTable,
176
+ {
177
+ columns,
178
+ data: rows,
179
+ isLoading,
180
+ actions: /* @__PURE__ */ jsx(Button, { asChild: true, children: /* @__PURE__ */ jsxs(Link, { href: "/backend/integration-ksef-direct/documents/new", children: [
181
+ /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
182
+ t("integration_ksef_direct.documents.list.actions.new", "New Document")
183
+ ] }) }),
184
+ emptyState: t("integration_ksef_direct.documents.empty.title", "No KSeF documents yet"),
185
+ pagination: { page, pageSize: PAGE_SIZE, total, totalPages, onPageChange: setPage }
186
+ }
187
+ ) }) });
188
+ }
189
+ export {
190
+ KsefDirectDocumentsPage as default,
191
+ pageMetadata
192
+ };
193
+ //# sourceMappingURL=page.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/integration_ksef_direct/backend/integration-ksef-direct/documents/page.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { Plus, Send, RefreshCw } from 'lucide-react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport { StatusBadge } from '@open-mercato/ui/primitives/status-badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useAppEvent } from '@open-mercato/ui/backend/injection/useAppEvent'\n\nconst PAGE_SIZE = 50\n\nconst STATUS_VARIANT: Record<string, 'success' | 'error' | 'warning' | 'neutral'> = {\n draft: 'neutral',\n queued: 'warning',\n sending: 'warning',\n sent: 'success',\n failed: 'error',\n}\n\nexport const pageMetadata = {\n features: ['integration_ksef_direct.documents.view'],\n}\n\ntype DocumentRow = {\n id: string\n source: string\n status: string\n invoiceNumber: string\n buyerNip: string\n buyerName: string | null\n issueDate: string\n grossAmount: string\n currency: string\n ksefReferenceNumber: string | null\n createdAt: string\n}\n\ntype ApiResponse = {\n items: DocumentRow[]\n total: number\n page: number\n pageSize: number\n}\n\nexport default function KsefDirectDocumentsPage() {\n const t = useT()\n const scopeVersion = useOrganizationScopeVersion()\n const [rows, setRows] = React.useState<DocumentRow[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [isLoading, setLoading] = React.useState(false)\n const [sendingId, setSendingId] = React.useState<string | null>(null)\n\n const { runMutation } = useGuardedMutation<{ entityType: string }>({\n contextId: 'integration_ksef_direct:send-document',\n })\n\n const fetchData = React.useCallback(async () => {\n setLoading(true)\n try {\n const result = await apiCall<ApiResponse>(\n `/api/integration-ksef-direct/documents?page=${page}&pageSize=${PAGE_SIZE}`,\n )\n if (result.ok && result.result) {\n setRows(result.result.items)\n setTotal(result.result.total)\n setTotalPages(Math.max(1, Math.ceil(result.result.total / PAGE_SIZE)))\n } else {\n setRows([])\n setTotal(0)\n setTotalPages(1)\n }\n } catch {\n setRows([])\n setTotal(0)\n setTotalPages(1)\n } finally {\n setLoading(false)\n }\n }, [page])\n\n React.useEffect(() => { void fetchData() }, [fetchData, scopeVersion])\n\n useAppEvent('ksef_direct.document.*', () => { void fetchData() }, [fetchData])\n\n const handleSend = React.useCallback(async (documentId: string) => {\n setSendingId(documentId)\n try {\n await runMutation({\n operation: async () => {\n const result = await apiCall(`/api/integration-ksef-direct/documents/${documentId}/send`, {\n method: 'POST',\n })\n if (!result.ok) {\n const err = (result.result as Record<string, unknown>)?.error\n throw new Error(typeof err === 'string' ? err : t('integration_ksef_direct.documents.errors.send_failed', 'Send failed'))\n }\n return result.result\n },\n context: { entityType: 'integration_ksef_direct.document' },\n mutationPayload: { entityType: 'integration_ksef_direct.document' },\n })\n flash(t('integration_ksef_direct.documents.send_success', 'Document queued for sending'), 'success')\n void fetchData()\n } catch (err) {\n flash(err instanceof Error ? err.message : t('integration_ksef_direct.documents.errors.send_failed', 'Send failed'), 'error')\n } finally {\n setSendingId(null)\n }\n }, [runMutation, t, fetchData])\n\n const columns = React.useMemo<ColumnDef<DocumentRow, unknown>[]>(() => [\n {\n id: 'invoiceNumber',\n accessorKey: 'invoiceNumber',\n header: t('integration_ksef_direct.documents.columns.invoiceNumber', 'Invoice Number'),\n cell: ({ row }) => <span className=\"font-medium\">{row.original.invoiceNumber}</span>,\n },\n {\n id: 'buyer',\n header: t('integration_ksef_direct.documents.columns.buyer', 'Buyer'),\n cell: ({ row }) => (\n <span>\n {row.original.buyerName\n ? `${row.original.buyerName} (${row.original.buyerNip})`\n : row.original.buyerNip}\n </span>\n ),\n },\n {\n id: 'issueDate',\n accessorKey: 'issueDate',\n header: t('integration_ksef_direct.documents.columns.issueDate', 'Issue Date'),\n cell: ({ row }) => new Date(row.original.issueDate).toLocaleDateString(),\n },\n {\n id: 'grossAmount',\n accessorKey: 'grossAmount',\n header: t('integration_ksef_direct.documents.columns.grossAmount', 'Gross Amount'),\n cell: ({ row }) => (\n <span className=\"tabular-nums\">\n {parseFloat(row.original.grossAmount).toLocaleString('pl-PL', { minimumFractionDigits: 2 })}{' '}\n {row.original.currency}\n </span>\n ),\n },\n {\n id: 'status',\n accessorKey: 'status',\n header: t('integration_ksef_direct.documents.columns.status', 'Status'),\n cell: ({ row }) => (\n <StatusBadge variant={STATUS_VARIANT[row.original.status] ?? 'neutral'}>\n {t(`integration_ksef_direct.documents.status.${row.original.status}`, row.original.status)}\n </StatusBadge>\n ),\n },\n {\n id: 'ksefReferenceNumber',\n header: t('integration_ksef_direct.documents.ksef_reference_number', 'KSeF Number'),\n cell: ({ row }) => row.original.ksefReferenceNumber\n ? <span className=\"font-mono text-sm\">{row.original.ksefReferenceNumber}</span>\n : null,\n },\n {\n id: 'actions',\n header: '',\n cell: ({ row }) => {\n const { id, status } = row.original\n const isSending = sendingId === id\n if (status === 'draft') {\n return (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n disabled={isSending}\n onClick={() => void handleSend(id)}\n aria-label={t('integration_ksef_direct.documents.send_button', 'Send to KSeF')}\n >\n <Send className=\"h-4 w-4 mr-1\" />\n {t('integration_ksef_direct.documents.send_button', 'Send to KSeF')}\n </Button>\n )\n }\n if (status === 'failed') {\n return (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n disabled={isSending}\n onClick={() => void handleSend(id)}\n aria-label={t('integration_ksef_direct.documents.retry_button', 'Retry send')}\n >\n <RefreshCw className=\"h-4 w-4 mr-1\" />\n {t('integration_ksef_direct.documents.retry_button', 'Retry')}\n </Button>\n )\n }\n return null\n },\n },\n ], [t, sendingId, handleSend])\n\n return (\n <Page>\n <PageBody>\n <DataTable<DocumentRow>\n columns={columns}\n data={rows}\n isLoading={isLoading}\n actions={(\n <Button asChild>\n <Link href=\"/backend/integration-ksef-direct/documents/new\">\n <Plus className=\"h-4 w-4 mr-2\" />\n {t('integration_ksef_direct.documents.list.actions.new', 'New Document')}\n </Link>\n </Button>\n )}\n emptyState={t('integration_ksef_direct.documents.empty.title', 'No KSeF documents yet')}\n pagination={{ page, pageSize: PAGE_SIZE, total, totalPages, onPageChange: setPage }}\n />\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,314 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Copy, Search } from "lucide-react";
5
+ import { Page, PageBody } from "@open-mercato/ui/backend/Page";
6
+ import { DataTable } from "@open-mercato/ui/backend/DataTable";
7
+ import { StatusBadge } from "@open-mercato/ui/primitives/status-badge";
8
+ import { Button } from "@open-mercato/ui/primitives/button";
9
+ import { Input } from "@open-mercato/ui/primitives/input";
10
+ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@open-mercato/ui/primitives/dialog";
11
+ import { FormField } from "@open-mercato/ui/primitives/form-field";
12
+ import { Alert, AlertDescription } from "@open-mercato/ui/primitives/alert";
13
+ import { flash } from "@open-mercato/ui/backend/FlashMessages";
14
+ import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
15
+ import { useGuardedMutation } from "@open-mercato/ui/backend/injection/useGuardedMutation";
16
+ import { useOrganizationScopeVersion } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
17
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
18
+ const pageMetadata = {
19
+ requireAuth: true,
20
+ requireFeatures: ["integration_ksef_direct.received_documents.view"],
21
+ pageTitleKey: "integration_ksef_direct.received_documents.title"
22
+ };
23
+ const PAGE_SIZE = 50;
24
+ const STATUS_VARIANT = {
25
+ pending_download: "warning",
26
+ downloaded: "success",
27
+ failed: "error"
28
+ };
29
+ function DetailModal({
30
+ documentId,
31
+ onClose
32
+ }) {
33
+ const t = useT();
34
+ const [doc, setDoc] = React.useState(null);
35
+ const [loading, setLoading] = React.useState(true);
36
+ const [copied, setCopied] = React.useState(false);
37
+ React.useEffect(() => {
38
+ let cancelled = false;
39
+ setLoading(true);
40
+ apiCall(`/api/integration-ksef-direct/received-documents/${documentId}`).then((res) => {
41
+ if (!cancelled && res.ok && res.result) setDoc(res.result);
42
+ }).catch(() => {
43
+ }).finally(() => {
44
+ if (!cancelled) setLoading(false);
45
+ });
46
+ return () => {
47
+ cancelled = true;
48
+ };
49
+ }, [documentId]);
50
+ React.useEffect(() => {
51
+ const handler = (e) => {
52
+ if (e.key === "Escape") onClose();
53
+ };
54
+ window.addEventListener("keydown", handler);
55
+ return () => window.removeEventListener("keydown", handler);
56
+ }, [onClose]);
57
+ async function handleCopy() {
58
+ if (!doc?.rawXml) return;
59
+ try {
60
+ await navigator.clipboard.writeText(doc.rawXml);
61
+ setCopied(true);
62
+ setTimeout(() => setCopied(false), 2e3);
63
+ } catch {
64
+ }
65
+ }
66
+ return /* @__PURE__ */ jsx(Dialog, { open: true, onOpenChange: (open) => {
67
+ if (!open) onClose();
68
+ }, children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-3xl max-h-[90vh] flex flex-col", children: [
69
+ /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: doc?.invoiceNumber ?? doc?.ksefReferenceNumber ?? t("integration_ksef_direct.received_documents.title", "Received Document") }) }),
70
+ loading && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground py-4", children: t("integration_ksef_direct.received_documents.loading", "Loading...") }),
71
+ doc && !loading && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 overflow-y-auto", children: [
72
+ /* @__PURE__ */ jsxs("dl", { className: "grid grid-cols-2 gap-x-6 gap-y-2 text-sm", children: [
73
+ /* @__PURE__ */ jsxs("div", { children: [
74
+ /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: t("integration_ksef_direct.received_documents.column.ksef_reference", "KSeF Ref.") }),
75
+ /* @__PURE__ */ jsx("dd", { className: "font-mono break-all", children: doc.ksefReferenceNumber })
76
+ ] }),
77
+ /* @__PURE__ */ jsxs("div", { children: [
78
+ /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: t("integration_ksef_direct.received_documents.column.invoice_number", "Invoice No.") }),
79
+ /* @__PURE__ */ jsx("dd", { children: doc.invoiceNumber ?? "\u2014" })
80
+ ] }),
81
+ /* @__PURE__ */ jsxs("div", { children: [
82
+ /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: t("integration_ksef_direct.received_documents.column.seller_nip", "Seller NIP") }),
83
+ /* @__PURE__ */ jsx("dd", { children: doc.sellerNip ?? "\u2014" })
84
+ ] }),
85
+ /* @__PURE__ */ jsxs("div", { children: [
86
+ /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: t("integration_ksef_direct.received_documents.column.seller_name", "Seller") }),
87
+ /* @__PURE__ */ jsx("dd", { children: doc.sellerName ?? "\u2014" })
88
+ ] }),
89
+ /* @__PURE__ */ jsxs("div", { children: [
90
+ /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: t("integration_ksef_direct.received_documents.column.issue_date", "Issue Date") }),
91
+ /* @__PURE__ */ jsx("dd", { children: doc.issueDate ?? "\u2014" })
92
+ ] }),
93
+ /* @__PURE__ */ jsxs("div", { children: [
94
+ /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: t("integration_ksef_direct.received_documents.column.gross_amount", "Gross Amount") }),
95
+ /* @__PURE__ */ jsx("dd", { children: doc.grossAmount != null ? `${parseFloat(doc.grossAmount).toLocaleString("pl-PL", { minimumFractionDigits: 2 })} ${doc.currency ?? "PLN"}` : "\u2014" })
96
+ ] }),
97
+ /* @__PURE__ */ jsxs("div", { children: [
98
+ /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: t("integration_ksef_direct.received_documents.column.status", "Status") }),
99
+ /* @__PURE__ */ jsx("dd", { children: /* @__PURE__ */ jsx(StatusBadge, { variant: STATUS_VARIANT[doc.status] ?? "warning", children: t(`integration_ksef_direct.received_documents.status.${doc.status}`, doc.status) }) })
100
+ ] }),
101
+ doc.errorMessage && /* @__PURE__ */ jsxs("div", { className: "col-span-2", children: [
102
+ /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: "Error" }),
103
+ /* @__PURE__ */ jsx("dd", { className: "text-status-destructive-text", children: doc.errorMessage })
104
+ ] })
105
+ ] }),
106
+ doc.rawXml && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
107
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
108
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "XML" }),
109
+ /* @__PURE__ */ jsxs(Button, { size: "sm", variant: "ghost", onClick: handleCopy, "aria-label": "Copy XML", children: [
110
+ /* @__PURE__ */ jsx(Copy, { className: "size-4 mr-1" }),
111
+ copied ? t("integration_ksef_direct.received_documents.xml_copied", "Copied") : t("integration_ksef_direct.received_documents.copy_xml", "Copy XML")
112
+ ] })
113
+ ] }),
114
+ /* @__PURE__ */ jsx("pre", { className: "text-xs font-mono bg-muted rounded p-3 overflow-auto max-h-64 whitespace-pre-wrap break-all", children: doc.rawXml })
115
+ ] })
116
+ ] })
117
+ ] }) });
118
+ }
119
+ function FetchDialog({ onClose, onSuccess }) {
120
+ const t = useT();
121
+ const [reference, setReference] = React.useState("");
122
+ const [error, setError] = React.useState(null);
123
+ const [isSubmitting, setSubmitting] = React.useState(false);
124
+ const { runMutation } = useGuardedMutation({
125
+ contextId: "integration_ksef_direct:fetch-received-document"
126
+ });
127
+ React.useEffect(() => {
128
+ const handler = (e) => {
129
+ if (e.key === "Escape") onClose();
130
+ if ((e.metaKey || e.ctrlKey) && e.key === "Enter") void handleSubmit();
131
+ };
132
+ window.addEventListener("keydown", handler);
133
+ return () => window.removeEventListener("keydown", handler);
134
+ });
135
+ async function handleSubmit() {
136
+ setError(null);
137
+ setSubmitting(true);
138
+ try {
139
+ await runMutation({
140
+ operation: async () => {
141
+ const result = await apiCall("/api/integration-ksef-direct/received-documents/fetch", {
142
+ method: "POST",
143
+ body: JSON.stringify({ ksefReferenceNumber: reference })
144
+ });
145
+ if (!result.ok) {
146
+ const body = result.result;
147
+ throw new Error(typeof body?.error === "string" ? body.error : "Error");
148
+ }
149
+ return result.result;
150
+ },
151
+ context: { entityType: "integration_ksef_direct.received_document" },
152
+ mutationPayload: { entityType: "integration_ksef_direct.received_document" }
153
+ });
154
+ flash(t("integration_ksef_direct.received_documents.fetch_success", "Document fetched successfully."), "success");
155
+ onClose();
156
+ onSuccess();
157
+ } catch (err) {
158
+ setError(err instanceof Error ? err.message : "Error");
159
+ } finally {
160
+ setSubmitting(false);
161
+ }
162
+ }
163
+ return /* @__PURE__ */ jsx(Dialog, { open: true, onOpenChange: (open) => {
164
+ if (!open) onClose();
165
+ }, children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-md", children: [
166
+ /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: t("integration_ksef_direct.received_documents.dialog_fetch.title", "Fetch Document by KSeF Reference") }) }),
167
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
168
+ error && /* @__PURE__ */ jsx(Alert, { variant: "destructive", children: /* @__PURE__ */ jsx(AlertDescription, { children: error }) }),
169
+ /* @__PURE__ */ jsx(FormField, { label: t("integration_ksef_direct.received_documents.column.ksef_reference", "KSeF Reference Number"), required: true, children: /* @__PURE__ */ jsx(
170
+ Input,
171
+ {
172
+ value: reference,
173
+ onChange: (e) => setReference(e.target.value),
174
+ placeholder: "e.g. 1234567890...",
175
+ className: "font-mono"
176
+ }
177
+ ) })
178
+ ] }),
179
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
180
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: onClose, type: "button", children: t("integration_ksef_direct.received_documents.cancel", "Cancel") }),
181
+ /* @__PURE__ */ jsx(Button, { onClick: handleSubmit, disabled: isSubmitting || !reference.trim(), type: "button", children: t("integration_ksef_direct.received_documents.dialog_fetch.submit", "Fetch") })
182
+ ] })
183
+ ] }) });
184
+ }
185
+ function ReceivedDocumentsPage() {
186
+ const t = useT();
187
+ const scopeVersion = useOrganizationScopeVersion();
188
+ const [rows, setRows] = React.useState([]);
189
+ const [page, setPage] = React.useState(1);
190
+ const [total, setTotal] = React.useState(0);
191
+ const [totalPages, setTotalPages] = React.useState(1);
192
+ const [isLoading, setLoading] = React.useState(false);
193
+ const [fetchDialogOpen, setFetchDialogOpen] = React.useState(false);
194
+ const [detailId, setDetailId] = React.useState(null);
195
+ const fetchData = React.useCallback(async () => {
196
+ setLoading(true);
197
+ try {
198
+ const result = await apiCall(
199
+ `/api/integration-ksef-direct/received-documents?page=${page}&pageSize=${PAGE_SIZE}`
200
+ );
201
+ if (result.ok && result.result) {
202
+ setRows(result.result.items);
203
+ setTotal(result.result.total);
204
+ setTotalPages(Math.max(1, Math.ceil(result.result.total / PAGE_SIZE)));
205
+ } else {
206
+ setRows([]);
207
+ setTotal(0);
208
+ setTotalPages(1);
209
+ }
210
+ } catch {
211
+ setRows([]);
212
+ setTotal(0);
213
+ setTotalPages(1);
214
+ } finally {
215
+ setLoading(false);
216
+ }
217
+ }, [page]);
218
+ React.useEffect(() => {
219
+ void fetchData();
220
+ }, [fetchData, scopeVersion]);
221
+ const columns = React.useMemo(() => [
222
+ {
223
+ id: "sellerNip",
224
+ accessorKey: "sellerNip",
225
+ header: t("integration_ksef_direct.received_documents.column.seller_nip", "Seller NIP"),
226
+ cell: ({ row }) => row.original.sellerNip ?? "\u2014"
227
+ },
228
+ {
229
+ id: "sellerName",
230
+ accessorKey: "sellerName",
231
+ header: t("integration_ksef_direct.received_documents.column.seller_name", "Seller"),
232
+ cell: ({ row }) => row.original.sellerName ?? "\u2014"
233
+ },
234
+ {
235
+ id: "invoiceNumber",
236
+ accessorKey: "invoiceNumber",
237
+ header: t("integration_ksef_direct.received_documents.column.invoice_number", "Invoice No."),
238
+ cell: ({ row }) => row.original.invoiceNumber ?? "\u2014"
239
+ },
240
+ {
241
+ id: "issueDate",
242
+ accessorKey: "issueDate",
243
+ header: t("integration_ksef_direct.received_documents.column.issue_date", "Issue Date"),
244
+ cell: ({ row }) => row.original.issueDate ?? "\u2014"
245
+ },
246
+ {
247
+ id: "grossAmount",
248
+ header: t("integration_ksef_direct.received_documents.column.gross_amount", "Gross Amount"),
249
+ cell: ({ row }) => row.original.grossAmount != null ? /* @__PURE__ */ jsxs("span", { className: "tabular-nums", children: [
250
+ parseFloat(row.original.grossAmount).toLocaleString("pl-PL", { minimumFractionDigits: 2 }),
251
+ " ",
252
+ row.original.currency ?? "PLN"
253
+ ] }) : "\u2014"
254
+ },
255
+ {
256
+ id: "status",
257
+ accessorKey: "status",
258
+ header: t("integration_ksef_direct.received_documents.column.status", "Status"),
259
+ cell: ({ row }) => /* @__PURE__ */ jsx(StatusBadge, { variant: STATUS_VARIANT[row.original.status] ?? "warning", children: t(`integration_ksef_direct.received_documents.status.${row.original.status}`, row.original.status) })
260
+ },
261
+ {
262
+ id: "ksefReferenceNumber",
263
+ accessorKey: "ksefReferenceNumber",
264
+ header: t("integration_ksef_direct.received_documents.column.ksef_reference", "KSeF Ref."),
265
+ cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "font-mono text-sm truncate max-w-48 block", title: row.original.ksefReferenceNumber, children: row.original.ksefReferenceNumber })
266
+ }
267
+ ], [t]);
268
+ const toolbar = /* @__PURE__ */ jsxs(
269
+ Button,
270
+ {
271
+ variant: "outline",
272
+ size: "sm",
273
+ onClick: () => setFetchDialogOpen(true),
274
+ children: [
275
+ /* @__PURE__ */ jsx(Search, { className: "size-4 mr-2" }),
276
+ t("integration_ksef_direct.received_documents.fetch_button", "Fetch by reference")
277
+ ]
278
+ }
279
+ );
280
+ return /* @__PURE__ */ jsxs(Page, { children: [
281
+ /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
282
+ DataTable,
283
+ {
284
+ entityId: "ksef_direct_received_document",
285
+ columns,
286
+ data: rows,
287
+ isLoading,
288
+ actions: toolbar,
289
+ emptyState: t("integration_ksef_direct.received_documents.empty", "No received documents found."),
290
+ pagination: { page, pageSize: PAGE_SIZE, total, totalPages, onPageChange: setPage },
291
+ onRowClick: (row) => setDetailId(row.id)
292
+ }
293
+ ) }),
294
+ fetchDialogOpen && /* @__PURE__ */ jsx(
295
+ FetchDialog,
296
+ {
297
+ onClose: () => setFetchDialogOpen(false),
298
+ onSuccess: () => void fetchData()
299
+ }
300
+ ),
301
+ detailId && /* @__PURE__ */ jsx(
302
+ DetailModal,
303
+ {
304
+ documentId: detailId,
305
+ onClose: () => setDetailId(null)
306
+ }
307
+ )
308
+ ] });
309
+ }
310
+ export {
311
+ ReceivedDocumentsPage as default,
312
+ pageMetadata
313
+ };
314
+ //# sourceMappingURL=page.js.map