@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,112 @@
1
+ import { NextResponse } from "next/server";
2
+ import { z } from "zod";
3
+ import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
4
+ import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
5
+ import { KsefDirectReceivedDocument } from "../../../data/entities.js";
6
+ const metadata = {
7
+ path: "/integration-ksef-direct/received-documents",
8
+ GET: { requireAuth: true, requireFeatures: ["integration_ksef_direct.received_documents.view"] }
9
+ };
10
+ const querySchema = z.object({
11
+ page: z.coerce.number().min(1).default(1),
12
+ pageSize: z.coerce.number().min(1).max(100).default(50),
13
+ status: z.string().optional(),
14
+ search: z.string().optional()
15
+ });
16
+ async function GET(req) {
17
+ const auth = await getAuthFromRequest(req);
18
+ if (!auth?.tenantId || !auth.orgId) {
19
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
20
+ }
21
+ const url = new URL(req.url);
22
+ const parsed = querySchema.safeParse(Object.fromEntries(url.searchParams.entries()));
23
+ if (!parsed.success) {
24
+ return NextResponse.json({ error: "Invalid query" }, { status: 400 });
25
+ }
26
+ const query = parsed.data;
27
+ const container = await createRequestContainer();
28
+ const em = container.resolve("em");
29
+ const where = {
30
+ organizationId: auth.orgId,
31
+ tenantId: auth.tenantId
32
+ };
33
+ if (query.status) where.status = query.status;
34
+ if (query.search) {
35
+ const pattern = `%${query.search}%`;
36
+ where.$or = [
37
+ { ksefReferenceNumber: { $ilike: pattern } },
38
+ { invoiceNumber: { $ilike: pattern } },
39
+ { sellerNip: { $ilike: pattern } },
40
+ { sellerName: { $ilike: pattern } }
41
+ ];
42
+ }
43
+ const [docs, total] = await em.findAndCount(
44
+ KsefDirectReceivedDocument,
45
+ where,
46
+ {
47
+ orderBy: { createdAt: "DESC" },
48
+ limit: query.pageSize,
49
+ offset: (query.page - 1) * query.pageSize
50
+ }
51
+ );
52
+ const items = docs.map((doc) => ({
53
+ id: doc.id,
54
+ ksefReferenceNumber: doc.ksefReferenceNumber,
55
+ invoiceNumber: doc.invoiceNumber ?? null,
56
+ sellerNip: doc.sellerNip ?? null,
57
+ sellerName: doc.sellerName ?? null,
58
+ issueDate: doc.issueDate ?? null,
59
+ currency: doc.currency ?? null,
60
+ netAmount: doc.netAmount ?? null,
61
+ vatAmount: doc.vatAmount ?? null,
62
+ grossAmount: doc.grossAmount ?? null,
63
+ status: doc.status,
64
+ errorMessage: doc.errorMessage ?? null,
65
+ syncedAt: doc.syncedAt?.toISOString() ?? null,
66
+ createdAt: doc.createdAt.toISOString()
67
+ }));
68
+ return NextResponse.json({ items, total, page: query.page, pageSize: query.pageSize });
69
+ }
70
+ const openApi = {
71
+ tag: "KSeF Direct",
72
+ summary: "List received KSeF documents",
73
+ methods: {
74
+ GET: {
75
+ summary: "List received KSeF documents",
76
+ description: "Returns a paginated list of received KSeF document records for the current organization.",
77
+ responses: [
78
+ {
79
+ status: 200,
80
+ description: "Paginated list",
81
+ schema: z.object({
82
+ items: z.array(z.object({
83
+ id: z.string().uuid(),
84
+ ksefReferenceNumber: z.string(),
85
+ invoiceNumber: z.string().nullable(),
86
+ sellerNip: z.string().nullable(),
87
+ sellerName: z.string().nullable(),
88
+ issueDate: z.string().nullable(),
89
+ currency: z.string().nullable(),
90
+ netAmount: z.string().nullable(),
91
+ vatAmount: z.string().nullable(),
92
+ grossAmount: z.string().nullable(),
93
+ status: z.string(),
94
+ errorMessage: z.string().nullable(),
95
+ syncedAt: z.string().nullable(),
96
+ createdAt: z.string()
97
+ })),
98
+ total: z.number(),
99
+ page: z.number(),
100
+ pageSize: z.number()
101
+ })
102
+ }
103
+ ]
104
+ }
105
+ }
106
+ };
107
+ export {
108
+ GET,
109
+ metadata,
110
+ openApi
111
+ };
112
+ //# sourceMappingURL=received-documents.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/integration_ksef_direct/api/get/integration-ksef-direct/received-documents.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { KsefDirectReceivedDocument } from '../../../data/entities'\n\nexport const metadata = {\n path: '/integration-ksef-direct/received-documents',\n GET: { requireAuth: true, requireFeatures: ['integration_ksef_direct.received_documents.view'] },\n}\n\nconst querySchema = z.object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n status: z.string().optional(),\n search: z.string().optional(),\n})\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const url = new URL(req.url)\n const parsed = querySchema.safeParse(Object.fromEntries(url.searchParams.entries()))\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid query' }, { status: 400 })\n }\n const query = parsed.data\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as any\n\n const where: Record<string, unknown> = {\n organizationId: auth.orgId,\n tenantId: auth.tenantId,\n }\n\n if (query.status) where.status = query.status\n\n if (query.search) {\n const pattern = `%${query.search}%`\n where.$or = [\n { ksefReferenceNumber: { $ilike: pattern } },\n { invoiceNumber: { $ilike: pattern } },\n { sellerNip: { $ilike: pattern } },\n { sellerName: { $ilike: pattern } },\n ]\n }\n\n const [docs, total] = await em.findAndCount(\n KsefDirectReceivedDocument,\n where,\n {\n orderBy: { createdAt: 'DESC' },\n limit: query.pageSize,\n offset: (query.page - 1) * query.pageSize,\n },\n )\n\n const items = docs.map((doc: KsefDirectReceivedDocument) => ({\n id: doc.id,\n ksefReferenceNumber: doc.ksefReferenceNumber,\n invoiceNumber: doc.invoiceNumber ?? null,\n sellerNip: doc.sellerNip ?? null,\n sellerName: doc.sellerName ?? null,\n issueDate: doc.issueDate ?? null,\n currency: doc.currency ?? null,\n netAmount: doc.netAmount ?? null,\n vatAmount: doc.vatAmount ?? null,\n grossAmount: doc.grossAmount ?? null,\n status: doc.status,\n errorMessage: doc.errorMessage ?? null,\n syncedAt: doc.syncedAt?.toISOString() ?? null,\n createdAt: doc.createdAt.toISOString(),\n }))\n\n return NextResponse.json({ items, total, page: query.page, pageSize: query.pageSize })\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'KSeF Direct',\n summary: 'List received KSeF documents',\n methods: {\n GET: {\n summary: 'List received KSeF documents',\n description: 'Returns a paginated list of received KSeF document records for the current organization.',\n responses: [\n {\n status: 200,\n description: 'Paginated list',\n schema: z.object({\n items: z.array(z.object({\n id: z.string().uuid(),\n ksefReferenceNumber: z.string(),\n invoiceNumber: z.string().nullable(),\n sellerNip: z.string().nullable(),\n sellerName: z.string().nullable(),\n issueDate: z.string().nullable(),\n currency: z.string().nullable(),\n netAmount: z.string().nullable(),\n vatAmount: z.string().nullable(),\n grossAmount: z.string().nullable(),\n status: z.string(),\n errorMessage: z.string().nullable(),\n syncedAt: z.string().nullable(),\n createdAt: z.string(),\n })),\n total: z.number(),\n page: z.number(),\n pageSize: z.number(),\n }),\n },\n ],\n },\n },\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,54 @@
1
+ import { NextResponse } from "next/server";
2
+ import { z } from "zod";
3
+ import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
4
+ import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
5
+ import { KsefDirectCredentialsSchema } from "../../../data/validators.js";
6
+ const metadata = {
7
+ path: "/integration-ksef-direct/seller-info",
8
+ GET: { requireAuth: true, requireFeatures: ["integration_ksef_direct.documents.create"] }
9
+ };
10
+ async function GET(req) {
11
+ const auth = await getAuthFromRequest(req);
12
+ if (!auth?.tenantId || !auth.orgId) {
13
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
14
+ }
15
+ const container = await createRequestContainer();
16
+ const credentialsService = container.resolve("integrationCredentialsService");
17
+ const em = container.resolve("em");
18
+ const rawCredentials = credentialsService ? await credentialsService.resolve("integration_ksef_direct", {
19
+ tenantId: auth.tenantId,
20
+ organizationId: auth.orgId
21
+ }) : null;
22
+ const credentialsParsed = rawCredentials ? KsefDirectCredentialsSchema.safeParse(rawCredentials) : null;
23
+ const sellerNip = credentialsParsed?.success ? credentialsParsed.data.nip : null;
24
+ const { Organization } = await import("@open-mercato/core/modules/directory/data/entities");
25
+ const org = await em.findOne(Organization, { id: auth.orgId });
26
+ const sellerName = org?.name ?? null;
27
+ return NextResponse.json({ sellerNip, sellerName });
28
+ }
29
+ const openApi = {
30
+ tag: "KSeF Direct",
31
+ summary: "Get KSeF Direct seller info",
32
+ methods: {
33
+ GET: {
34
+ summary: "Get seller NIP and name for the current tenant",
35
+ description: "Returns seller NIP from KSeF credentials and seller name from the current Organization.",
36
+ responses: [
37
+ {
38
+ status: 200,
39
+ description: "Seller info",
40
+ schema: z.object({
41
+ sellerNip: z.string().nullable(),
42
+ sellerName: z.string().nullable()
43
+ })
44
+ }
45
+ ]
46
+ }
47
+ }
48
+ };
49
+ export {
50
+ GET,
51
+ metadata,
52
+ openApi
53
+ };
54
+ //# sourceMappingURL=seller-info.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/integration_ksef_direct/api/get/integration-ksef-direct/seller-info.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { KsefDirectCredentialsSchema } from '../../../data/validators'\n\nexport const metadata = {\n path: '/integration-ksef-direct/seller-info',\n GET: { requireAuth: true, requireFeatures: ['integration_ksef_direct.documents.create'] },\n}\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const container = await createRequestContainer()\n const credentialsService = container.resolve('integrationCredentialsService') as any\n const em = container.resolve('em') as any\n\n const rawCredentials = credentialsService\n ? await credentialsService.resolve('integration_ksef_direct', {\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n })\n : null\n\n const credentialsParsed = rawCredentials\n ? KsefDirectCredentialsSchema.safeParse(rawCredentials)\n : null\n\n const sellerNip = credentialsParsed?.success ? credentialsParsed.data.nip : null\n\n const { Organization } = await import('@open-mercato/core/modules/directory/data/entities')\n const org = await em.findOne(Organization, { id: auth.orgId })\n const sellerName = org?.name ?? null\n\n return NextResponse.json({ sellerNip, sellerName })\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'KSeF Direct',\n summary: 'Get KSeF Direct seller info',\n methods: {\n GET: {\n summary: 'Get seller NIP and name for the current tenant',\n description: 'Returns seller NIP from KSeF credentials and seller name from the current Organization.',\n responses: [\n {\n status: 200,\n description: 'Seller info',\n schema: z.object({\n sellerNip: z.string().nullable(),\n sellerName: z.string().nullable(),\n }),\n },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAElB,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AACvC,SAAS,mCAAmC;AAErC,MAAM,WAAW;AAAA,EACtB,MAAM;AAAA,EACN,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,0CAA0C,EAAE;AAC1F;AAEA,eAAsB,IAAI,KAAc;AACtC,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,MAAI,CAAC,MAAM,YAAY,CAAC,KAAK,OAAO;AAClC,WAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACrE;AAEA,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,qBAAqB,UAAU,QAAQ,+BAA+B;AAC5E,QAAM,KAAK,UAAU,QAAQ,IAAI;AAEjC,QAAM,iBAAiB,qBACnB,MAAM,mBAAmB,QAAQ,2BAA2B;AAAA,IAC1D,UAAU,KAAK;AAAA,IACf,gBAAgB,KAAK;AAAA,EACvB,CAAC,IACD;AAEJ,QAAM,oBAAoB,iBACtB,4BAA4B,UAAU,cAAc,IACpD;AAEJ,QAAM,YAAY,mBAAmB,UAAU,kBAAkB,KAAK,MAAM;AAE5E,QAAM,EAAE,aAAa,IAAI,MAAM,OAAO,oDAAoD;AAC1F,QAAM,MAAM,MAAM,GAAG,QAAQ,cAAc,EAAE,IAAI,KAAK,MAAM,CAAC;AAC7D,QAAM,aAAa,KAAK,QAAQ;AAEhC,SAAO,aAAa,KAAK,EAAE,WAAW,WAAW,CAAC;AACpD;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,KAAK;AAAA,MACH,SAAS;AAAA,MACT,aAAa;AAAA,MACb,WAAW;AAAA,QACT;AAAA,UACE,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,EAAE,OAAO;AAAA,YACf,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,YAC/B,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,UAClC,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,64 @@
1
+ import { NextResponse } from "next/server";
2
+ import { z } from "zod";
3
+ import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
4
+ import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
5
+ import {
6
+ enqueueKsefDirectDocument,
7
+ KsefDocumentNotFoundError,
8
+ KsefDocumentNotQueueableError
9
+ } from "../../../../../commands/enqueue-ksef-direct-document.js";
10
+ const metadata = {
11
+ path: "/integration-ksef-direct/documents/[id]/send",
12
+ POST: { requireAuth: true, requireFeatures: ["integration_ksef_direct.documents.send"] }
13
+ };
14
+ async function POST(req, { params }) {
15
+ const auth = await getAuthFromRequest(req);
16
+ if (!auth?.tenantId || !auth.orgId) {
17
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
18
+ }
19
+ const container = await createRequestContainer();
20
+ const em = container.resolve("em");
21
+ try {
22
+ const result = await enqueueKsefDirectDocument(em, auth.tenantId, auth.orgId, params.id);
23
+ return NextResponse.json(result, { status: 200 });
24
+ } catch (err) {
25
+ if (err instanceof KsefDocumentNotFoundError) {
26
+ return NextResponse.json({ error: "Document not found" }, { status: 404 });
27
+ }
28
+ if (err instanceof KsefDocumentNotQueueableError) {
29
+ return NextResponse.json({ error: err.message }, { status: 409 });
30
+ }
31
+ throw err;
32
+ }
33
+ }
34
+ const openApi = {
35
+ tag: "KSeF Direct",
36
+ summary: "Send KSeF Direct document",
37
+ methods: {
38
+ POST: {
39
+ summary: "Queue a KSeF Direct document for sending",
40
+ description: "Transitions a document from draft or failed status to queued and enqueues it for KSeF submission.",
41
+ responses: [
42
+ {
43
+ status: 200,
44
+ description: "Document queued",
45
+ schema: z.object({
46
+ id: z.string().uuid(),
47
+ status: z.literal("queued"),
48
+ invoiceNumber: z.string()
49
+ })
50
+ }
51
+ ],
52
+ errors: [
53
+ { status: 404, description: "Document not found", schema: z.object({ error: z.string() }) },
54
+ { status: 409, description: "Document cannot be queued in current status", schema: z.object({ error: z.string() }) }
55
+ ]
56
+ }
57
+ }
58
+ };
59
+ export {
60
+ POST,
61
+ metadata,
62
+ openApi
63
+ };
64
+ //# sourceMappingURL=send.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../../src/modules/integration_ksef_direct/api/post/integration-ksef-direct/documents/%5Bid%5D/send.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport {\n enqueueKsefDirectDocument,\n KsefDocumentNotFoundError,\n KsefDocumentNotQueueableError,\n} from '../../../../../commands/enqueue-ksef-direct-document'\n\nexport const metadata = {\n path: '/integration-ksef-direct/documents/[id]/send',\n POST: { requireAuth: true, requireFeatures: ['integration_ksef_direct.documents.send'] },\n}\n\nexport async function POST(req: Request, { params }: { params: { id: string } }) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as any\n\n try {\n const result = await enqueueKsefDirectDocument(em, auth.tenantId, auth.orgId, params.id)\n return NextResponse.json(result, { status: 200 })\n } catch (err) {\n if (err instanceof KsefDocumentNotFoundError) {\n return NextResponse.json({ error: 'Document not found' }, { status: 404 })\n }\n if (err instanceof KsefDocumentNotQueueableError) {\n return NextResponse.json({ error: err.message }, { status: 409 })\n }\n throw err\n }\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'KSeF Direct',\n summary: 'Send KSeF Direct document',\n methods: {\n POST: {\n summary: 'Queue a KSeF Direct document for sending',\n description: 'Transitions a document from draft or failed status to queued and enqueues it for KSeF submission.',\n responses: [\n {\n status: 200,\n description: 'Document queued',\n schema: z.object({\n id: z.string().uuid(),\n status: z.literal('queued'),\n invoiceNumber: z.string(),\n }),\n },\n ],\n errors: [\n { status: 404, description: 'Document not found', schema: z.object({ error: z.string() }) },\n { status: 409, description: 'Document cannot be queued in current status', schema: z.object({ error: z.string() }) },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAElB,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AACvC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,MAAM,WAAW;AAAA,EACtB,MAAM;AAAA,EACN,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,wCAAwC,EAAE;AACzF;AAEA,eAAsB,KAAK,KAAc,EAAE,OAAO,GAA+B;AAC/E,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,MAAI,CAAC,MAAM,YAAY,CAAC,KAAK,OAAO;AAClC,WAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACrE;AAEA,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,KAAK,UAAU,QAAQ,IAAI;AAEjC,MAAI;AACF,UAAM,SAAS,MAAM,0BAA0B,IAAI,KAAK,UAAU,KAAK,OAAO,OAAO,EAAE;AACvF,WAAO,aAAa,KAAK,QAAQ,EAAE,QAAQ,IAAI,CAAC;AAAA,EAClD,SAAS,KAAK;AACZ,QAAI,eAAe,2BAA2B;AAC5C,aAAO,aAAa,KAAK,EAAE,OAAO,qBAAqB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC3E;AACA,QAAI,eAAe,+BAA+B;AAChD,aAAO,aAAa,KAAK,EAAE,OAAO,IAAI,QAAQ,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAClE;AACA,UAAM;AAAA,EACR;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,WAAW;AAAA,QACT;AAAA,UACE,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,EAAE,OAAO;AAAA,YACf,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,YACpB,QAAQ,EAAE,QAAQ,QAAQ;AAAA,YAC1B,eAAe,EAAE,OAAO;AAAA,UAC1B,CAAC;AAAA,QACH;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,sBAAsB,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE;AAAA,QAC1F,EAAE,QAAQ,KAAK,aAAa,+CAA+C,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE;AAAA,MACrH;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,104 @@
1
+ import { NextResponse } from "next/server";
2
+ import { z } from "zod";
3
+ import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
4
+ import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
5
+ import { readJsonSafe } from "@open-mercato/shared/lib/http/readJsonSafe";
6
+ import { validateCrudMutationGuard, runCrudMutationGuardAfterSuccess } from "@open-mercato/shared/lib/crud/mutation-guard";
7
+ import { CreateKsefDirectDocumentSchema } from "../../../data/validators.js";
8
+ import { createKsefDirectDocument, KsefDirectNotConfiguredError } from "../../../commands/create-ksef-direct-document.js";
9
+ const metadata = {
10
+ path: "/integration-ksef-direct/documents",
11
+ POST: { requireAuth: true, requireFeatures: ["integration_ksef_direct.documents.create"] }
12
+ };
13
+ async function POST(req) {
14
+ const auth = await getAuthFromRequest(req);
15
+ if (!auth?.tenantId || !auth.orgId) {
16
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
17
+ }
18
+ const body = await readJsonSafe(req, {});
19
+ const parsed = CreateKsefDirectDocumentSchema.safeParse(body);
20
+ if (!parsed.success) {
21
+ return NextResponse.json(
22
+ { error: "Validation failed", fieldErrors: parsed.error.flatten().fieldErrors },
23
+ { status: 400 }
24
+ );
25
+ }
26
+ const container = await createRequestContainer();
27
+ const guardResult = await validateCrudMutationGuard(container, {
28
+ tenantId: auth.tenantId,
29
+ organizationId: auth.orgId,
30
+ userId: auth.sub ?? "",
31
+ resourceKind: "integration_ksef_direct.document",
32
+ resourceId: "new",
33
+ operation: "create",
34
+ requestMethod: "POST",
35
+ requestHeaders: req.headers
36
+ });
37
+ if (guardResult && !guardResult.ok) {
38
+ return NextResponse.json(guardResult.body, { status: guardResult.status });
39
+ }
40
+ const em = container.resolve("em");
41
+ const credentialsService = container.resolve("integrationCredentialsService");
42
+ let result;
43
+ try {
44
+ result = await createKsefDirectDocument(em, auth.tenantId, auth.orgId, parsed.data, credentialsService);
45
+ } catch (err) {
46
+ if (err instanceof KsefDirectNotConfiguredError) {
47
+ return NextResponse.json(
48
+ { error: "KSeF Direct integration is not configured. Set up NIP in integration credentials first." },
49
+ { status: 422 }
50
+ );
51
+ }
52
+ throw err;
53
+ }
54
+ if (guardResult?.shouldRunAfterSuccess) {
55
+ await runCrudMutationGuardAfterSuccess(container, {
56
+ tenantId: auth.tenantId,
57
+ organizationId: auth.orgId,
58
+ userId: auth.sub ?? "",
59
+ resourceKind: "integration_ksef_direct.document",
60
+ resourceId: result.id,
61
+ operation: "create",
62
+ requestMethod: "POST",
63
+ requestHeaders: req.headers,
64
+ metadata: guardResult.metadata
65
+ });
66
+ }
67
+ return NextResponse.json(result, { status: 201 });
68
+ }
69
+ const openApi = {
70
+ tag: "KSeF Direct",
71
+ summary: "Create KSeF Direct document",
72
+ methods: {
73
+ POST: {
74
+ summary: "Create a manual KSeF Direct document",
75
+ description: "Creates a document record in draft status from manually entered invoice data.",
76
+ requestBody: {
77
+ contentType: "application/json",
78
+ schema: CreateKsefDirectDocumentSchema
79
+ },
80
+ responses: [
81
+ {
82
+ status: 201,
83
+ description: "Document created",
84
+ schema: z.object({
85
+ id: z.string().uuid(),
86
+ status: z.literal("draft"),
87
+ invoiceNumber: z.string(),
88
+ sellerNip: z.string()
89
+ })
90
+ }
91
+ ],
92
+ errors: [
93
+ { status: 400, description: "Validation error", schema: z.object({ error: z.string(), fieldErrors: z.record(z.string(), z.array(z.string())).optional() }) },
94
+ { status: 422, description: "Integration not configured", schema: z.object({ error: z.string() }) }
95
+ ]
96
+ }
97
+ }
98
+ };
99
+ export {
100
+ POST,
101
+ metadata,
102
+ openApi
103
+ };
104
+ //# sourceMappingURL=documents.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/integration_ksef_direct/api/post/integration-ksef-direct/documents.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { validateCrudMutationGuard, runCrudMutationGuardAfterSuccess } from '@open-mercato/shared/lib/crud/mutation-guard'\nimport { CreateKsefDirectDocumentSchema } from '../../../data/validators'\nimport { createKsefDirectDocument, KsefDirectNotConfiguredError } from '../../../commands/create-ksef-direct-document'\n\nexport const metadata = {\n path: '/integration-ksef-direct/documents',\n POST: { requireAuth: true, requireFeatures: ['integration_ksef_direct.documents.create'] },\n}\n\nexport async function POST(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const body = await readJsonSafe(req, {})\n const parsed = CreateKsefDirectDocumentSchema.safeParse(body)\n if (!parsed.success) {\n return NextResponse.json(\n { error: 'Validation failed', fieldErrors: parsed.error.flatten().fieldErrors },\n { status: 400 },\n )\n }\n\n const container = await createRequestContainer()\n\n const guardResult = await validateCrudMutationGuard(container, {\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n userId: auth.sub ?? '',\n resourceKind: 'integration_ksef_direct.document',\n resourceId: 'new',\n operation: 'create',\n requestMethod: 'POST',\n requestHeaders: req.headers,\n })\n if (guardResult && !guardResult.ok) {\n return NextResponse.json(guardResult.body, { status: guardResult.status })\n }\n\n const em = container.resolve('em') as any\n const credentialsService = container.resolve('integrationCredentialsService') as any\n\n let result: { id: string; status: string; invoiceNumber: string; sellerNip: string }\n try {\n result = await createKsefDirectDocument(em, auth.tenantId, auth.orgId, parsed.data, credentialsService)\n } catch (err) {\n if (err instanceof KsefDirectNotConfiguredError) {\n return NextResponse.json(\n { error: 'KSeF Direct integration is not configured. Set up NIP in integration credentials first.' },\n { status: 422 },\n )\n }\n throw err\n }\n\n if (guardResult?.shouldRunAfterSuccess) {\n await runCrudMutationGuardAfterSuccess(container, {\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n userId: auth.sub ?? '',\n resourceKind: 'integration_ksef_direct.document',\n resourceId: result.id,\n operation: 'create',\n requestMethod: 'POST',\n requestHeaders: req.headers,\n metadata: guardResult.metadata,\n })\n }\n\n return NextResponse.json(result, { status: 201 })\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'KSeF Direct',\n summary: 'Create KSeF Direct document',\n methods: {\n POST: {\n summary: 'Create a manual KSeF Direct document',\n description: 'Creates a document record in draft status from manually entered invoice data.',\n requestBody: {\n contentType: 'application/json',\n schema: CreateKsefDirectDocumentSchema,\n },\n responses: [\n {\n status: 201,\n description: 'Document created',\n schema: z.object({\n id: z.string().uuid(),\n status: z.literal('draft'),\n invoiceNumber: z.string(),\n sellerNip: z.string(),\n }),\n },\n ],\n errors: [\n { status: 400, description: 'Validation error', schema: z.object({ error: z.string(), fieldErrors: z.record(z.string(), z.array(z.string())).optional() }) },\n { status: 422, description: 'Integration not configured', schema: z.object({ error: z.string() }) },\n ],\n },\n },\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,41 @@
1
+ import { NextResponse } from "next/server";
2
+ import { z } from "zod";
3
+ import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
4
+ import { generateKsefInvoiceNumber } from "../../../lib/invoiceNumberFormat.js";
5
+ const metadata = {
6
+ path: "/integration-ksef-direct/invoice-numbers",
7
+ POST: { requireAuth: true, requireFeatures: ["integration_ksef_direct.documents.create"] }
8
+ };
9
+ async function POST(req) {
10
+ const auth = await getAuthFromRequest(req);
11
+ if (!auth?.tenantId || !auth.orgId) {
12
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
13
+ }
14
+ const number = generateKsefInvoiceNumber();
15
+ return NextResponse.json({ number }, { status: 201 });
16
+ }
17
+ const openApi = {
18
+ tag: "KSeF Direct",
19
+ summary: "Generate KSeF invoice number",
20
+ methods: {
21
+ POST: {
22
+ summary: "Generate a unique KSeF invoice number",
23
+ description: "Returns a unique invoice number in FV/{yyyy}/{mm}/{id} format using a cryptographically random identifier.",
24
+ responses: [
25
+ {
26
+ status: 201,
27
+ description: "Generated invoice number",
28
+ schema: z.object({
29
+ number: z.string()
30
+ })
31
+ }
32
+ ]
33
+ }
34
+ }
35
+ };
36
+ export {
37
+ POST,
38
+ metadata,
39
+ openApi
40
+ };
41
+ //# sourceMappingURL=invoice-numbers.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/integration_ksef_direct/api/post/integration-ksef-direct/invoice-numbers.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { generateKsefInvoiceNumber } from '../../../lib/invoiceNumberFormat'\n\nexport const metadata = {\n path: '/integration-ksef-direct/invoice-numbers',\n POST: { requireAuth: true, requireFeatures: ['integration_ksef_direct.documents.create'] },\n}\n\nexport async function POST(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const number = generateKsefInvoiceNumber()\n return NextResponse.json({ number }, { status: 201 })\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'KSeF Direct',\n summary: 'Generate KSeF invoice number',\n methods: {\n POST: {\n summary: 'Generate a unique KSeF invoice number',\n description: 'Returns a unique invoice number in FV/{yyyy}/{mm}/{id} format using a cryptographically random identifier.',\n responses: [\n {\n status: 201,\n description: 'Generated invoice number',\n schema: z.object({\n number: z.string(),\n }),\n },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAElB,SAAS,0BAA0B;AACnC,SAAS,iCAAiC;AAEnC,MAAM,WAAW;AAAA,EACtB,MAAM;AAAA,EACN,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,0CAA0C,EAAE;AAC3F;AAEA,eAAsB,KAAK,KAAc;AACvC,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,MAAI,CAAC,MAAM,YAAY,CAAC,KAAK,OAAO;AAClC,WAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACrE;AAEA,QAAM,SAAS,0BAA0B;AACzC,SAAO,aAAa,KAAK,EAAE,OAAO,GAAG,EAAE,QAAQ,IAAI,CAAC;AACtD;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,WAAW;AAAA,QACT;AAAA,UACE,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,EAAE,OAAO;AAAA,YACf,QAAQ,EAAE,OAAO;AAAA,UACnB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,172 @@
1
+ import { NextResponse } from "next/server";
2
+ import { z } from "zod";
3
+ import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
4
+ import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
5
+ import { readJsonSafe } from "@open-mercato/shared/lib/http/readJsonSafe";
6
+ import { ReceivedDocumentFetchSchema } from "../../../../data/validators.js";
7
+ import { KsefNetworkError } from "../../../../lib/ksefClient.js";
8
+ const metadata = {
9
+ path: "/integration-ksef-direct/received-documents/fetch",
10
+ POST: { requireAuth: true, requireFeatures: ["integration_ksef_direct.received_documents.sync"] }
11
+ };
12
+ const receivedDocumentResponseSchema = z.object({
13
+ id: z.string().uuid(),
14
+ ksefReferenceNumber: z.string(),
15
+ invoiceNumber: z.string().nullable(),
16
+ sellerNip: z.string().nullable(),
17
+ sellerName: z.string().nullable(),
18
+ issueDate: z.string().nullable(),
19
+ currency: z.string().nullable(),
20
+ netAmount: z.string().nullable(),
21
+ vatAmount: z.string().nullable(),
22
+ grossAmount: z.string().nullable(),
23
+ rawXml: z.string(),
24
+ status: z.literal("downloaded"),
25
+ errorMessage: z.null(),
26
+ syncedAt: z.string(),
27
+ createdAt: z.string(),
28
+ updatedAt: z.string()
29
+ });
30
+ async function POST(req) {
31
+ const auth = await getAuthFromRequest(req);
32
+ if (!auth?.tenantId || !auth.orgId) {
33
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
34
+ }
35
+ const body = await readJsonSafe(req, {});
36
+ const parsed = ReceivedDocumentFetchSchema.safeParse(body);
37
+ if (!parsed.success) {
38
+ return NextResponse.json({ error: "Invalid request" }, { status: 400 });
39
+ }
40
+ const container = await createRequestContainer();
41
+ const credentialsService = container.resolve("integrationCredentialsService");
42
+ const rawCreds = credentialsService ? await credentialsService.resolve("integration_ksef_direct", {
43
+ tenantId: auth.tenantId,
44
+ organizationId: auth.orgId
45
+ }) : null;
46
+ const { KsefDirectCredentialsSchema } = await import("../../../../data/validators.js");
47
+ const credsParsed = KsefDirectCredentialsSchema.safeParse(rawCreds);
48
+ if (!credsParsed.success) {
49
+ return NextResponse.json({ error: "KSeF credentials not configured" }, { status: 409 });
50
+ }
51
+ const credentials = {
52
+ ksefToken: credsParsed.data.ksef_token,
53
+ nip: credsParsed.data.nip,
54
+ environment: credsParsed.data.environment,
55
+ tenantId: auth.tenantId
56
+ };
57
+ const { downloadInvoice } = await import("../../../../lib/ksefClient.js");
58
+ const { parseReceivedInvoiceXml } = await import("../../../../lib/ksefXmlParser.js");
59
+ const { KsefDirectReceivedDocument } = await import("../../../../data/entities.js");
60
+ let rawContent;
61
+ let upoDownloadUrl = null;
62
+ let invoiceDownloadUrl = null;
63
+ try {
64
+ const result = await downloadInvoice(credentials, parsed.data.ksefReferenceNumber);
65
+ rawContent = result.rawContent;
66
+ upoDownloadUrl = result.upoDownloadUrl;
67
+ invoiceDownloadUrl = result.invoiceDownloadUrl;
68
+ } catch (err) {
69
+ if (err instanceof KsefNetworkError) {
70
+ return NextResponse.json({ error: `KSeF API error: ${err.message}` }, { status: 502 });
71
+ }
72
+ if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) {
73
+ return NextResponse.json({ error: "KSeF API request timed out" }, { status: 504 });
74
+ }
75
+ throw err;
76
+ }
77
+ const parsedXml = parseReceivedInvoiceXml(rawContent);
78
+ const em = container.resolve("em");
79
+ const now = /* @__PURE__ */ new Date();
80
+ let record = await em.findOne(KsefDirectReceivedDocument, {
81
+ organizationId: auth.orgId,
82
+ ksefReferenceNumber: parsed.data.ksefReferenceNumber
83
+ });
84
+ if (record) {
85
+ record.rawXml = rawContent;
86
+ if (parsedXml.invoiceNumber) record.invoiceNumber = parsedXml.invoiceNumber;
87
+ if (parsedXml.sellerNip) record.sellerNip = parsedXml.sellerNip;
88
+ if (parsedXml.sellerName) record.sellerName = parsedXml.sellerName;
89
+ if (parsedXml.issueDate) record.issueDate = parsedXml.issueDate;
90
+ if (parsedXml.currency) record.currency = parsedXml.currency;
91
+ if (parsedXml.netAmount) record.netAmount = parsedXml.netAmount;
92
+ if (parsedXml.vatAmount) record.vatAmount = parsedXml.vatAmount;
93
+ if (parsedXml.grossAmount) record.grossAmount = parsedXml.grossAmount;
94
+ if (upoDownloadUrl) record.upoDownloadUrl = upoDownloadUrl;
95
+ if (invoiceDownloadUrl) record.invoiceDownloadUrl = invoiceDownloadUrl;
96
+ record.status = "downloaded";
97
+ record.errorMessage = null;
98
+ record.syncedAt = now;
99
+ record.updatedAt = now;
100
+ } else {
101
+ record = em.create(KsefDirectReceivedDocument, {
102
+ organizationId: auth.orgId,
103
+ tenantId: auth.tenantId,
104
+ ksefReferenceNumber: parsed.data.ksefReferenceNumber,
105
+ rawXml: rawContent,
106
+ invoiceNumber: parsedXml.invoiceNumber ?? null,
107
+ sellerNip: parsedXml.sellerNip ?? null,
108
+ sellerName: parsedXml.sellerName ?? null,
109
+ issueDate: parsedXml.issueDate ?? null,
110
+ currency: parsedXml.currency ?? null,
111
+ netAmount: parsedXml.netAmount ?? null,
112
+ vatAmount: parsedXml.vatAmount ?? null,
113
+ grossAmount: parsedXml.grossAmount ?? null,
114
+ upoDownloadUrl,
115
+ invoiceDownloadUrl,
116
+ status: "downloaded",
117
+ syncedAt: now
118
+ });
119
+ em.persist(record);
120
+ }
121
+ await em.flush();
122
+ return NextResponse.json({
123
+ id: record.id,
124
+ ksefReferenceNumber: record.ksefReferenceNumber,
125
+ invoiceNumber: record.invoiceNumber ?? null,
126
+ sellerNip: record.sellerNip ?? null,
127
+ sellerName: record.sellerName ?? null,
128
+ issueDate: record.issueDate ?? null,
129
+ currency: record.currency ?? null,
130
+ netAmount: record.netAmount ?? null,
131
+ vatAmount: record.vatAmount ?? null,
132
+ grossAmount: record.grossAmount ?? null,
133
+ rawXml: record.rawXml,
134
+ status: "downloaded",
135
+ errorMessage: null,
136
+ syncedAt: record.syncedAt?.toISOString() ?? now.toISOString(),
137
+ createdAt: record.createdAt.toISOString(),
138
+ updatedAt: record.updatedAt.toISOString()
139
+ });
140
+ }
141
+ const openApi = {
142
+ tag: "KSeF Direct",
143
+ summary: "Fetch received document by KSeF reference",
144
+ methods: {
145
+ POST: {
146
+ summary: "Fetch and store a single received KSeF document",
147
+ description: "Downloads the FA(2) XML for a given KSeF reference number and stores it locally. Synchronous \u2014 waits for the download to complete.",
148
+ requestBody: {
149
+ contentType: "application/json",
150
+ schema: ReceivedDocumentFetchSchema
151
+ },
152
+ responses: [
153
+ {
154
+ status: 200,
155
+ description: "Document fetched and stored",
156
+ schema: receivedDocumentResponseSchema
157
+ }
158
+ ],
159
+ errors: [
160
+ { status: 400, description: "Invalid request", schema: z.object({ error: z.string() }) },
161
+ { status: 409, description: "KSeF credentials not configured", schema: z.object({ error: z.string() }) },
162
+ { status: 502, description: "KSeF API error", schema: z.object({ error: z.string() }) }
163
+ ]
164
+ }
165
+ }
166
+ };
167
+ export {
168
+ POST,
169
+ metadata,
170
+ openApi
171
+ };
172
+ //# sourceMappingURL=fetch.js.map