@open-mercato/core 0.6.8-develop.6925.1.cefa200fa4 → 0.6.8-develop.6931.1.4a1e1c786b

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 (405) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/eudr_due_diligence_statement/index.js +47 -0
  3. package/dist/generated/entities/eudr_due_diligence_statement/index.js.map +7 -0
  4. package/dist/generated/entities/eudr_evidence_submission/index.js +51 -0
  5. package/dist/generated/entities/eudr_evidence_submission/index.js.map +7 -0
  6. package/dist/generated/entities/eudr_mitigation_action/index.js +31 -0
  7. package/dist/generated/entities/eudr_mitigation_action/index.js.map +7 -0
  8. package/dist/generated/entities/eudr_plot/index.js +39 -0
  9. package/dist/generated/entities/eudr_plot/index.js.map +7 -0
  10. package/dist/generated/entities/eudr_product_mapping/index.js +31 -0
  11. package/dist/generated/entities/eudr_product_mapping/index.js.map +7 -0
  12. package/dist/generated/entities/eudr_risk_assessment/index.js +35 -0
  13. package/dist/generated/entities/eudr_risk_assessment/index.js.map +7 -0
  14. package/dist/generated/entities.ids.generated.js +9 -0
  15. package/dist/generated/entities.ids.generated.js.map +2 -2
  16. package/dist/generated/entity-fields-registry.js +120 -0
  17. package/dist/generated/entity-fields-registry.js.map +2 -2
  18. package/dist/helpers/integration/ui.js +3 -0
  19. package/dist/helpers/integration/ui.js.map +2 -2
  20. package/dist/modules/attachments/fields/attachment.js +5 -1
  21. package/dist/modules/attachments/fields/attachment.js.map +2 -2
  22. package/dist/modules/attachments/lib/crud.js +3 -1
  23. package/dist/modules/attachments/lib/crud.js.map +2 -2
  24. package/dist/modules/eudr/acl.js +43 -0
  25. package/dist/modules/eudr/acl.js.map +7 -0
  26. package/dist/modules/eudr/ai-agents.js +205 -0
  27. package/dist/modules/eudr/ai-agents.js.map +7 -0
  28. package/dist/modules/eudr/ai-tools/compliance-pack.js +495 -0
  29. package/dist/modules/eudr/ai-tools/compliance-pack.js.map +7 -0
  30. package/dist/modules/eudr/ai-tools/types.js +10 -0
  31. package/dist/modules/eudr/ai-tools/types.js.map +7 -0
  32. package/dist/modules/eudr/ai-tools.js +10 -0
  33. package/dist/modules/eudr/ai-tools.js.map +7 -0
  34. package/dist/modules/eudr/api/dashboard/widgets/compliance-overview/route.js +386 -0
  35. package/dist/modules/eudr/api/dashboard/widgets/compliance-overview/route.js.map +7 -0
  36. package/dist/modules/eudr/api/evidence-submissions/route.js +318 -0
  37. package/dist/modules/eudr/api/evidence-submissions/route.js.map +7 -0
  38. package/dist/modules/eudr/api/mitigation-actions/route.js +249 -0
  39. package/dist/modules/eudr/api/mitigation-actions/route.js.map +7 -0
  40. package/dist/modules/eudr/api/openapi.js +27 -0
  41. package/dist/modules/eudr/api/openapi.js.map +7 -0
  42. package/dist/modules/eudr/api/plots/import/route.js +294 -0
  43. package/dist/modules/eudr/api/plots/import/route.js.map +7 -0
  44. package/dist/modules/eudr/api/plots/route.js +279 -0
  45. package/dist/modules/eudr/api/plots/route.js.map +7 -0
  46. package/dist/modules/eudr/api/product-mappings/route.js +257 -0
  47. package/dist/modules/eudr/api/product-mappings/route.js.map +7 -0
  48. package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js +298 -0
  49. package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js.map +7 -0
  50. package/dist/modules/eudr/api/product-mappings/suggestions/route.js +132 -0
  51. package/dist/modules/eudr/api/product-mappings/suggestions/route.js.map +7 -0
  52. package/dist/modules/eudr/api/reports/annual/route.js +266 -0
  53. package/dist/modules/eudr/api/reports/annual/route.js.map +7 -0
  54. package/dist/modules/eudr/api/risk-assessments/route.js +300 -0
  55. package/dist/modules/eudr/api/risk-assessments/route.js.map +7 -0
  56. package/dist/modules/eudr/api/statements/[id]/export/route.js +631 -0
  57. package/dist/modules/eudr/api/statements/[id]/export/route.js.map +7 -0
  58. package/dist/modules/eudr/api/statements/[id]/readiness/route.js +111 -0
  59. package/dist/modules/eudr/api/statements/[id]/readiness/route.js.map +7 -0
  60. package/dist/modules/eudr/api/statements/route.js +314 -0
  61. package/dist/modules/eudr/api/statements/route.js.map +7 -0
  62. package/dist/modules/eudr/api/suppliers/compliance/route.js +173 -0
  63. package/dist/modules/eudr/api/suppliers/compliance/route.js.map +7 -0
  64. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.js +468 -0
  65. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.js.map +7 -0
  66. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.js +16 -0
  67. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.js.map +7 -0
  68. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.js +351 -0
  69. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.js.map +7 -0
  70. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.js +17 -0
  71. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.js.map +7 -0
  72. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js +313 -0
  73. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js.map +7 -0
  74. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.meta.js +16 -0
  75. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.meta.js.map +7 -0
  76. package/dist/modules/eudr/backend/eudr/page.js +360 -0
  77. package/dist/modules/eudr/backend/eudr/page.js.map +7 -0
  78. package/dist/modules/eudr/backend/eudr/page.meta.js +16 -0
  79. package/dist/modules/eudr/backend/eudr/page.meta.js.map +7 -0
  80. package/dist/modules/eudr/backend/eudr/plots/[id]/page.js +346 -0
  81. package/dist/modules/eudr/backend/eudr/plots/[id]/page.js.map +7 -0
  82. package/dist/modules/eudr/backend/eudr/plots/[id]/page.meta.js +16 -0
  83. package/dist/modules/eudr/backend/eudr/plots/[id]/page.meta.js.map +7 -0
  84. package/dist/modules/eudr/backend/eudr/plots/create/page.js +253 -0
  85. package/dist/modules/eudr/backend/eudr/plots/create/page.js.map +7 -0
  86. package/dist/modules/eudr/backend/eudr/plots/create/page.meta.js +17 -0
  87. package/dist/modules/eudr/backend/eudr/plots/create/page.meta.js.map +7 -0
  88. package/dist/modules/eudr/backend/eudr/plots/page.js +386 -0
  89. package/dist/modules/eudr/backend/eudr/plots/page.js.map +7 -0
  90. package/dist/modules/eudr/backend/eudr/plots/page.meta.js +16 -0
  91. package/dist/modules/eudr/backend/eudr/plots/page.meta.js.map +7 -0
  92. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.js +253 -0
  93. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.js.map +7 -0
  94. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.js +16 -0
  95. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.js.map +7 -0
  96. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.js +174 -0
  97. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.js.map +7 -0
  98. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.meta.js +17 -0
  99. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.meta.js.map +7 -0
  100. package/dist/modules/eudr/backend/eudr/product-mappings/page.js +306 -0
  101. package/dist/modules/eudr/backend/eudr/product-mappings/page.js.map +7 -0
  102. package/dist/modules/eudr/backend/eudr/product-mappings/page.meta.js +16 -0
  103. package/dist/modules/eudr/backend/eudr/product-mappings/page.meta.js.map +7 -0
  104. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.js +335 -0
  105. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.js.map +7 -0
  106. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.js +16 -0
  107. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.js.map +7 -0
  108. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.js +220 -0
  109. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.js.map +7 -0
  110. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.meta.js +17 -0
  111. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.meta.js.map +7 -0
  112. package/dist/modules/eudr/backend/eudr/risk-assessments/page.js +324 -0
  113. package/dist/modules/eudr/backend/eudr/risk-assessments/page.js.map +7 -0
  114. package/dist/modules/eudr/backend/eudr/risk-assessments/page.meta.js +16 -0
  115. package/dist/modules/eudr/backend/eudr/risk-assessments/page.meta.js.map +7 -0
  116. package/dist/modules/eudr/backend/eudr/statements/[id]/page.js +648 -0
  117. package/dist/modules/eudr/backend/eudr/statements/[id]/page.js.map +7 -0
  118. package/dist/modules/eudr/backend/eudr/statements/[id]/page.meta.js +16 -0
  119. package/dist/modules/eudr/backend/eudr/statements/[id]/page.meta.js.map +7 -0
  120. package/dist/modules/eudr/backend/eudr/statements/create/page.js +432 -0
  121. package/dist/modules/eudr/backend/eudr/statements/create/page.js.map +7 -0
  122. package/dist/modules/eudr/backend/eudr/statements/create/page.meta.js +17 -0
  123. package/dist/modules/eudr/backend/eudr/statements/create/page.meta.js.map +7 -0
  124. package/dist/modules/eudr/backend/eudr/statements/page.js +309 -0
  125. package/dist/modules/eudr/backend/eudr/statements/page.js.map +7 -0
  126. package/dist/modules/eudr/backend/eudr/statements/page.meta.js +16 -0
  127. package/dist/modules/eudr/backend/eudr/statements/page.meta.js.map +7 -0
  128. package/dist/modules/eudr/ce.js +56 -0
  129. package/dist/modules/eudr/ce.js.map +7 -0
  130. package/dist/modules/eudr/commands/evidence-submissions.js +571 -0
  131. package/dist/modules/eudr/commands/evidence-submissions.js.map +7 -0
  132. package/dist/modules/eudr/commands/index.js +7 -0
  133. package/dist/modules/eudr/commands/index.js.map +7 -0
  134. package/dist/modules/eudr/commands/lifecycle-events.js +19 -0
  135. package/dist/modules/eudr/commands/lifecycle-events.js.map +7 -0
  136. package/dist/modules/eudr/commands/mitigation-actions.js +488 -0
  137. package/dist/modules/eudr/commands/mitigation-actions.js.map +7 -0
  138. package/dist/modules/eudr/commands/plots.js +517 -0
  139. package/dist/modules/eudr/commands/plots.js.map +7 -0
  140. package/dist/modules/eudr/commands/product-mappings.js +468 -0
  141. package/dist/modules/eudr/commands/product-mappings.js.map +7 -0
  142. package/dist/modules/eudr/commands/risk-assessments.js +599 -0
  143. package/dist/modules/eudr/commands/risk-assessments.js.map +7 -0
  144. package/dist/modules/eudr/commands/statements.js +747 -0
  145. package/dist/modules/eudr/commands/statements.js.map +7 -0
  146. package/dist/modules/eudr/components/CountrySelectField.js +64 -0
  147. package/dist/modules/eudr/components/CountrySelectField.js.map +7 -0
  148. package/dist/modules/eudr/components/GeometryInput.js +133 -0
  149. package/dist/modules/eudr/components/GeometryInput.js.map +7 -0
  150. package/dist/modules/eudr/components/MappingSuggestionsDialog.js +307 -0
  151. package/dist/modules/eudr/components/MappingSuggestionsDialog.js.map +7 -0
  152. package/dist/modules/eudr/components/MitigationActionsSection.js +345 -0
  153. package/dist/modules/eudr/components/MitigationActionsSection.js.map +7 -0
  154. package/dist/modules/eudr/components/OrderSelectField.js +88 -0
  155. package/dist/modules/eudr/components/OrderSelectField.js.map +7 -0
  156. package/dist/modules/eudr/components/PlotImportDialog.js +229 -0
  157. package/dist/modules/eudr/components/PlotImportDialog.js.map +7 -0
  158. package/dist/modules/eudr/components/PlotMapPreview.js +35 -0
  159. package/dist/modules/eudr/components/PlotMapPreview.js.map +7 -0
  160. package/dist/modules/eudr/components/PlotMapPreviewImpl.js +97 -0
  161. package/dist/modules/eudr/components/PlotMapPreviewImpl.js.map +7 -0
  162. package/dist/modules/eudr/components/PlotMultiSelectField.js +198 -0
  163. package/dist/modules/eudr/components/PlotMultiSelectField.js.map +7 -0
  164. package/dist/modules/eudr/components/RiskCriteriaField.js +128 -0
  165. package/dist/modules/eudr/components/RiskCriteriaField.js.map +7 -0
  166. package/dist/modules/eudr/components/StatementLifecycleBar.js +274 -0
  167. package/dist/modules/eudr/components/StatementLifecycleBar.js.map +7 -0
  168. package/dist/modules/eudr/components/StatementReadinessChecklist.js +56 -0
  169. package/dist/modules/eudr/components/StatementReadinessChecklist.js.map +7 -0
  170. package/dist/modules/eudr/components/StatementRiskSection.js +179 -0
  171. package/dist/modules/eudr/components/StatementRiskSection.js.map +7 -0
  172. package/dist/modules/eudr/components/crudErrorI18n.js +31 -0
  173. package/dist/modules/eudr/components/crudErrorI18n.js.map +7 -0
  174. package/dist/modules/eudr/components/formConfig.js +593 -0
  175. package/dist/modules/eudr/components/formConfig.js.map +7 -0
  176. package/dist/modules/eudr/components/plotForm.js +68 -0
  177. package/dist/modules/eudr/components/plotForm.js.map +7 -0
  178. package/dist/modules/eudr/data/enrichers.js +62 -0
  179. package/dist/modules/eudr/data/enrichers.js.map +7 -0
  180. package/dist/modules/eudr/data/entities.js +437 -0
  181. package/dist/modules/eudr/data/entities.js.map +7 -0
  182. package/dist/modules/eudr/data/validators.js +271 -0
  183. package/dist/modules/eudr/data/validators.js.map +7 -0
  184. package/dist/modules/eudr/encryption.js +33 -0
  185. package/dist/modules/eudr/encryption.js.map +7 -0
  186. package/dist/modules/eudr/events.js +38 -0
  187. package/dist/modules/eudr/events.js.map +7 -0
  188. package/dist/modules/eudr/index.js +15 -0
  189. package/dist/modules/eudr/index.js.map +7 -0
  190. package/dist/modules/eudr/lib/annual-report.js +104 -0
  191. package/dist/modules/eudr/lib/annual-report.js.map +7 -0
  192. package/dist/modules/eudr/lib/completeness.js +64 -0
  193. package/dist/modules/eudr/lib/completeness.js.map +7 -0
  194. package/dist/modules/eudr/lib/detail-read-scope.js +16 -0
  195. package/dist/modules/eudr/lib/detail-read-scope.js.map +7 -0
  196. package/dist/modules/eudr/lib/geometry.js +142 -0
  197. package/dist/modules/eudr/lib/geometry.js.map +7 -0
  198. package/dist/modules/eudr/lib/notifications.js +56 -0
  199. package/dist/modules/eudr/lib/notifications.js.map +7 -0
  200. package/dist/modules/eudr/lib/plural.js +26 -0
  201. package/dist/modules/eudr/lib/plural.js.map +7 -0
  202. package/dist/modules/eudr/lib/reference-data.js +240 -0
  203. package/dist/modules/eudr/lib/reference-data.js.map +7 -0
  204. package/dist/modules/eudr/lib/species.js +10 -0
  205. package/dist/modules/eudr/lib/species.js.map +7 -0
  206. package/dist/modules/eudr/lib/statement-lifecycle.js +84 -0
  207. package/dist/modules/eudr/lib/statement-lifecycle.js.map +7 -0
  208. package/dist/modules/eudr/lib/statement-seeding.js +49 -0
  209. package/dist/modules/eudr/lib/statement-seeding.js.map +7 -0
  210. package/dist/modules/eudr/migrations/Migration20260706102002_eudr.js +15 -0
  211. package/dist/modules/eudr/migrations/Migration20260706102002_eudr.js.map +7 -0
  212. package/dist/modules/eudr/migrations/Migration20260706152612_eudr.js +24 -0
  213. package/dist/modules/eudr/migrations/Migration20260706152612_eudr.js.map +7 -0
  214. package/dist/modules/eudr/migrations/Migration20260722100000_eudr.js +15 -0
  215. package/dist/modules/eudr/migrations/Migration20260722100000_eudr.js.map +7 -0
  216. package/dist/modules/eudr/notifications.js +58 -0
  217. package/dist/modules/eudr/notifications.js.map +7 -0
  218. package/dist/modules/eudr/search.js +186 -0
  219. package/dist/modules/eudr/search.js.map +7 -0
  220. package/dist/modules/eudr/setup.js +12 -0
  221. package/dist/modules/eudr/setup.js.map +7 -0
  222. package/dist/modules/eudr/subscribers/notify-mitigation-completed.js +34 -0
  223. package/dist/modules/eudr/subscribers/notify-mitigation-completed.js.map +7 -0
  224. package/dist/modules/eudr/subscribers/notify-risk-concluded.js +35 -0
  225. package/dist/modules/eudr/subscribers/notify-risk-concluded.js.map +7 -0
  226. package/dist/modules/eudr/subscribers/notify-statement-reference-issued.js +37 -0
  227. package/dist/modules/eudr/subscribers/notify-statement-reference-issued.js.map +7 -0
  228. package/dist/modules/eudr/subscribers/notify-statement-submitted.js +34 -0
  229. package/dist/modules/eudr/subscribers/notify-statement-submitted.js.map +7 -0
  230. package/dist/modules/eudr/subscribers/notify-statement-withdrawn.js +34 -0
  231. package/dist/modules/eudr/subscribers/notify-statement-withdrawn.js.map +7 -0
  232. package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-created.js +124 -0
  233. package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-created.js.map +7 -0
  234. package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.js +22 -0
  235. package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.js.map +7 -0
  236. package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.client.js +203 -0
  237. package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.client.js.map +7 -0
  238. package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.js +23 -0
  239. package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.js.map +7 -0
  240. package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.client.js +19 -0
  241. package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.client.js.map +7 -0
  242. package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.js +31 -0
  243. package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.js.map +7 -0
  244. package/dist/modules/eudr/widgets/injection/order-compliance/widget.client.js +100 -0
  245. package/dist/modules/eudr/widgets/injection/order-compliance/widget.client.js.map +7 -0
  246. package/dist/modules/eudr/widgets/injection/order-compliance/widget.js +17 -0
  247. package/dist/modules/eudr/widgets/injection/order-compliance/widget.js.map +7 -0
  248. package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.client.js +116 -0
  249. package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.client.js.map +7 -0
  250. package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.js +17 -0
  251. package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.js.map +7 -0
  252. package/dist/modules/eudr/widgets/injection-table.js +32 -0
  253. package/dist/modules/eudr/widgets/injection-table.js.map +7 -0
  254. package/dist/modules/notifications/lib/notificationService.js +67 -3
  255. package/dist/modules/notifications/lib/notificationService.js.map +2 -2
  256. package/dist/modules/query_index/lib/engine.js +121 -48
  257. package/dist/modules/query_index/lib/engine.js.map +2 -2
  258. package/dist/modules/sales/api/documents/factory.js +17 -0
  259. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  260. package/dist/modules/sales/commands/documents.js +32 -18
  261. package/dist/modules/sales/commands/documents.js.map +2 -2
  262. package/dist/modules/sales/data/entities.js +1 -0
  263. package/dist/modules/sales/data/entities.js.map +2 -2
  264. package/dist/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.js +17 -0
  265. package/dist/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.js.map +7 -0
  266. package/generated/entities/eudr_due_diligence_statement/index.ts +22 -0
  267. package/generated/entities/eudr_evidence_submission/index.ts +24 -0
  268. package/generated/entities/eudr_mitigation_action/index.ts +14 -0
  269. package/generated/entities/eudr_plot/index.ts +18 -0
  270. package/generated/entities/eudr_product_mapping/index.ts +14 -0
  271. package/generated/entities/eudr_risk_assessment/index.ts +16 -0
  272. package/generated/entities.ids.generated.ts +9 -0
  273. package/generated/entity-fields-registry.ts +120 -0
  274. package/package.json +7 -7
  275. package/src/helpers/integration/ui.ts +12 -0
  276. package/src/modules/attachments/fields/attachment.tsx +5 -0
  277. package/src/modules/attachments/lib/crud.ts +2 -0
  278. package/src/modules/eudr/acl.ts +39 -0
  279. package/src/modules/eudr/ai-agents.ts +258 -0
  280. package/src/modules/eudr/ai-tools/compliance-pack.ts +618 -0
  281. package/src/modules/eudr/ai-tools/types.ts +44 -0
  282. package/src/modules/eudr/ai-tools.ts +15 -0
  283. package/src/modules/eudr/api/dashboard/widgets/compliance-overview/route.ts +481 -0
  284. package/src/modules/eudr/api/evidence-submissions/route.ts +335 -0
  285. package/src/modules/eudr/api/mitigation-actions/route.ts +263 -0
  286. package/src/modules/eudr/api/openapi.ts +28 -0
  287. package/src/modules/eudr/api/plots/import/route.ts +369 -0
  288. package/src/modules/eudr/api/plots/route.ts +296 -0
  289. package/src/modules/eudr/api/product-mappings/route.ts +269 -0
  290. package/src/modules/eudr/api/product-mappings/suggestions/apply/route.ts +382 -0
  291. package/src/modules/eudr/api/product-mappings/suggestions/route.ts +169 -0
  292. package/src/modules/eudr/api/reports/annual/route.ts +457 -0
  293. package/src/modules/eudr/api/risk-assessments/route.ts +323 -0
  294. package/src/modules/eudr/api/statements/[id]/export/route.ts +713 -0
  295. package/src/modules/eudr/api/statements/[id]/readiness/route.ts +129 -0
  296. package/src/modules/eudr/api/statements/route.ts +329 -0
  297. package/src/modules/eudr/api/suppliers/compliance/route.ts +241 -0
  298. package/src/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.ts +12 -0
  299. package/src/modules/eudr/backend/eudr/evidence-submissions/[id]/page.tsx +545 -0
  300. package/src/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.ts +13 -0
  301. package/src/modules/eudr/backend/eudr/evidence-submissions/create/page.tsx +383 -0
  302. package/src/modules/eudr/backend/eudr/evidence-submissions/page.meta.ts +12 -0
  303. package/src/modules/eudr/backend/eudr/evidence-submissions/page.tsx +379 -0
  304. package/src/modules/eudr/backend/eudr/page.meta.ts +12 -0
  305. package/src/modules/eudr/backend/eudr/page.tsx +477 -0
  306. package/src/modules/eudr/backend/eudr/plots/[id]/page.meta.ts +12 -0
  307. package/src/modules/eudr/backend/eudr/plots/[id]/page.tsx +404 -0
  308. package/src/modules/eudr/backend/eudr/plots/create/page.meta.ts +13 -0
  309. package/src/modules/eudr/backend/eudr/plots/create/page.tsx +267 -0
  310. package/src/modules/eudr/backend/eudr/plots/page.meta.ts +12 -0
  311. package/src/modules/eudr/backend/eudr/plots/page.tsx +442 -0
  312. package/src/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.ts +12 -0
  313. package/src/modules/eudr/backend/eudr/product-mappings/[id]/page.tsx +311 -0
  314. package/src/modules/eudr/backend/eudr/product-mappings/create/page.meta.ts +13 -0
  315. package/src/modules/eudr/backend/eudr/product-mappings/create/page.tsx +190 -0
  316. package/src/modules/eudr/backend/eudr/product-mappings/page.meta.ts +12 -0
  317. package/src/modules/eudr/backend/eudr/product-mappings/page.tsx +344 -0
  318. package/src/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.ts +12 -0
  319. package/src/modules/eudr/backend/eudr/risk-assessments/[id]/page.tsx +421 -0
  320. package/src/modules/eudr/backend/eudr/risk-assessments/create/page.meta.ts +13 -0
  321. package/src/modules/eudr/backend/eudr/risk-assessments/create/page.tsx +247 -0
  322. package/src/modules/eudr/backend/eudr/risk-assessments/page.meta.ts +12 -0
  323. package/src/modules/eudr/backend/eudr/risk-assessments/page.tsx +383 -0
  324. package/src/modules/eudr/backend/eudr/statements/[id]/page.meta.ts +12 -0
  325. package/src/modules/eudr/backend/eudr/statements/[id]/page.tsx +777 -0
  326. package/src/modules/eudr/backend/eudr/statements/create/page.meta.ts +13 -0
  327. package/src/modules/eudr/backend/eudr/statements/create/page.tsx +511 -0
  328. package/src/modules/eudr/backend/eudr/statements/page.meta.ts +12 -0
  329. package/src/modules/eudr/backend/eudr/statements/page.tsx +372 -0
  330. package/src/modules/eudr/ce.ts +52 -0
  331. package/src/modules/eudr/commands/evidence-submissions.ts +699 -0
  332. package/src/modules/eudr/commands/index.ts +6 -0
  333. package/src/modules/eudr/commands/lifecycle-events.ts +28 -0
  334. package/src/modules/eudr/commands/mitigation-actions.ts +574 -0
  335. package/src/modules/eudr/commands/plots.ts +627 -0
  336. package/src/modules/eudr/commands/product-mappings.ts +556 -0
  337. package/src/modules/eudr/commands/risk-assessments.ts +728 -0
  338. package/src/modules/eudr/commands/statements.ts +933 -0
  339. package/src/modules/eudr/components/CountrySelectField.tsx +77 -0
  340. package/src/modules/eudr/components/GeometryInput.tsx +170 -0
  341. package/src/modules/eudr/components/MappingSuggestionsDialog.tsx +385 -0
  342. package/src/modules/eudr/components/MitigationActionsSection.tsx +417 -0
  343. package/src/modules/eudr/components/OrderSelectField.tsx +116 -0
  344. package/src/modules/eudr/components/PlotImportDialog.tsx +277 -0
  345. package/src/modules/eudr/components/PlotMapPreview.tsx +46 -0
  346. package/src/modules/eudr/components/PlotMapPreviewImpl.tsx +111 -0
  347. package/src/modules/eudr/components/PlotMultiSelectField.tsx +238 -0
  348. package/src/modules/eudr/components/RiskCriteriaField.tsx +173 -0
  349. package/src/modules/eudr/components/StatementLifecycleBar.tsx +363 -0
  350. package/src/modules/eudr/components/StatementReadinessChecklist.tsx +82 -0
  351. package/src/modules/eudr/components/StatementRiskSection.tsx +242 -0
  352. package/src/modules/eudr/components/crudErrorI18n.ts +36 -0
  353. package/src/modules/eudr/components/formConfig.tsx +717 -0
  354. package/src/modules/eudr/components/plotForm.ts +75 -0
  355. package/src/modules/eudr/data/enrichers.ts +82 -0
  356. package/src/modules/eudr/data/entities.ts +369 -0
  357. package/src/modules/eudr/data/validators.ts +357 -0
  358. package/src/modules/eudr/encryption.ts +31 -0
  359. package/src/modules/eudr/events.ts +38 -0
  360. package/src/modules/eudr/i18n/de.json +747 -0
  361. package/src/modules/eudr/i18n/en.json +747 -0
  362. package/src/modules/eudr/i18n/es.json +747 -0
  363. package/src/modules/eudr/i18n/ko.json +747 -0
  364. package/src/modules/eudr/i18n/pl.json +747 -0
  365. package/src/modules/eudr/index.ts +13 -0
  366. package/src/modules/eudr/lib/annual-report.ts +120 -0
  367. package/src/modules/eudr/lib/completeness.ts +90 -0
  368. package/src/modules/eudr/lib/detail-read-scope.ts +44 -0
  369. package/src/modules/eudr/lib/geometry.ts +191 -0
  370. package/src/modules/eudr/lib/notifications.ts +85 -0
  371. package/src/modules/eudr/lib/plural.ts +36 -0
  372. package/src/modules/eudr/lib/reference-data.ts +128 -0
  373. package/src/modules/eudr/lib/species.ts +12 -0
  374. package/src/modules/eudr/lib/statement-lifecycle.ts +109 -0
  375. package/src/modules/eudr/lib/statement-seeding.ts +86 -0
  376. package/src/modules/eudr/migrations/.snapshot-open-mercato.json +2046 -0
  377. package/src/modules/eudr/migrations/Migration20260706102002_eudr.ts +16 -0
  378. package/src/modules/eudr/migrations/Migration20260706152612_eudr.ts +30 -0
  379. package/src/modules/eudr/migrations/Migration20260722100000_eudr.ts +17 -0
  380. package/src/modules/eudr/notifications.ts +56 -0
  381. package/src/modules/eudr/search.ts +212 -0
  382. package/src/modules/eudr/setup.ts +10 -0
  383. package/src/modules/eudr/subscribers/notify-mitigation-completed.ts +56 -0
  384. package/src/modules/eudr/subscribers/notify-risk-concluded.ts +58 -0
  385. package/src/modules/eudr/subscribers/notify-statement-reference-issued.ts +59 -0
  386. package/src/modules/eudr/subscribers/notify-statement-submitted.ts +49 -0
  387. package/src/modules/eudr/subscribers/notify-statement-withdrawn.ts +49 -0
  388. package/src/modules/eudr/subscribers/recompute-completeness-on-attachment-created.ts +189 -0
  389. package/src/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.ts +31 -0
  390. package/src/modules/eudr/widgets/dashboard/compliance-overview/widget.client.tsx +271 -0
  391. package/src/modules/eudr/widgets/dashboard/compliance-overview/widget.ts +24 -0
  392. package/src/modules/eudr/widgets/injection/eudr-product-column/widget.client.tsx +37 -0
  393. package/src/modules/eudr/widgets/injection/eudr-product-column/widget.ts +30 -0
  394. package/src/modules/eudr/widgets/injection/order-compliance/widget.client.tsx +131 -0
  395. package/src/modules/eudr/widgets/injection/order-compliance/widget.ts +16 -0
  396. package/src/modules/eudr/widgets/injection/supplier-compliance/widget.client.tsx +168 -0
  397. package/src/modules/eudr/widgets/injection/supplier-compliance/widget.ts +16 -0
  398. package/src/modules/eudr/widgets/injection-table.ts +31 -0
  399. package/src/modules/notifications/lib/notificationService.ts +83 -4
  400. package/src/modules/query_index/lib/engine.ts +139 -51
  401. package/src/modules/sales/api/documents/factory.ts +29 -0
  402. package/src/modules/sales/commands/documents.ts +65 -18
  403. package/src/modules/sales/data/entities.ts +1 -0
  404. package/src/modules/sales/migrations/.snapshot-open-mercato.json +10 -0
  405. package/src/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.ts +59 -0
@@ -0,0 +1,27 @@
1
+ import {
2
+ createCrudOpenApiFactory,
3
+ createPagedListResponseSchema as createSharedPagedListResponseSchema,
4
+ defaultCreateResponseSchema as sharedDefaultCreateResponseSchema,
5
+ defaultOkResponseSchema as sharedDefaultOkResponseSchema
6
+ } from "@open-mercato/shared/lib/openapi/crud";
7
+ const defaultCreateResponseSchema = sharedDefaultCreateResponseSchema;
8
+ const defaultOkResponseSchema = sharedDefaultOkResponseSchema;
9
+ function createPagedListResponseSchema(itemSchema) {
10
+ return createSharedPagedListResponseSchema(itemSchema, { paginationMetaOptional: true });
11
+ }
12
+ const buildEudrCrudOpenApi = createCrudOpenApiFactory({
13
+ defaultTag: "EUDR",
14
+ defaultCreateResponseSchema,
15
+ defaultOkResponseSchema,
16
+ makeListDescription: ({ pluralLower }) => `Returns a paginated collection of ${pluralLower} scoped to the authenticated organization.`
17
+ });
18
+ function createEudrCrudOpenApi(options) {
19
+ return buildEudrCrudOpenApi(options);
20
+ }
21
+ export {
22
+ createEudrCrudOpenApi,
23
+ createPagedListResponseSchema,
24
+ defaultCreateResponseSchema,
25
+ defaultOkResponseSchema
26
+ };
27
+ //# sourceMappingURL=openapi.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/eudr/api/openapi.ts"],
4
+ "sourcesContent": ["import { type ZodTypeAny } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport {\n createCrudOpenApiFactory,\n createPagedListResponseSchema as createSharedPagedListResponseSchema,\n defaultCreateResponseSchema as sharedDefaultCreateResponseSchema,\n defaultOkResponseSchema as sharedDefaultOkResponseSchema,\n type CrudOpenApiOptions,\n} from '@open-mercato/shared/lib/openapi/crud'\n\nexport const defaultCreateResponseSchema = sharedDefaultCreateResponseSchema\nexport const defaultOkResponseSchema = sharedDefaultOkResponseSchema\n\nexport function createPagedListResponseSchema(itemSchema: ZodTypeAny) {\n return createSharedPagedListResponseSchema(itemSchema, { paginationMetaOptional: true })\n}\n\nconst buildEudrCrudOpenApi = createCrudOpenApiFactory({\n defaultTag: 'EUDR',\n defaultCreateResponseSchema,\n defaultOkResponseSchema,\n makeListDescription: ({ pluralLower }) =>\n `Returns a paginated collection of ${pluralLower} scoped to the authenticated organization.`,\n})\n\nexport function createEudrCrudOpenApi(options: CrudOpenApiOptions): OpenApiRouteDoc {\n return buildEudrCrudOpenApi(options)\n}\n"],
5
+ "mappings": "AAEA;AAAA,EACE;AAAA,EACA,iCAAiC;AAAA,EACjC,+BAA+B;AAAA,EAC/B,2BAA2B;AAAA,OAEtB;AAEA,MAAM,8BAA8B;AACpC,MAAM,0BAA0B;AAEhC,SAAS,8BAA8B,YAAwB;AACpE,SAAO,oCAAoC,YAAY,EAAE,wBAAwB,KAAK,CAAC;AACzF;AAEA,MAAM,uBAAuB,yBAAyB;AAAA,EACpD,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA,qBAAqB,CAAC,EAAE,YAAY,MAClC,qCAAqC,WAAW;AACpD,CAAC;AAEM,SAAS,sBAAsB,SAA8C;AAClF,SAAO,qBAAqB,OAAO;AACrC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,294 @@
1
+ import { z } from "zod";
2
+ import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
3
+ import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
4
+ import { resolveOrganizationScopeForRequest } from "@open-mercato/core/modules/directory/utils/organizationScope";
5
+ import { CrudHttpError, isCrudHttpError } from "@open-mercato/shared/lib/crud/errors";
6
+ import { createLogger } from "@open-mercato/shared/lib/logger";
7
+ import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
8
+ import { getAllMutationGuardInstances } from "@open-mercato/shared/lib/crud/mutation-guard-store";
9
+ import {
10
+ bridgeLegacyGuard,
11
+ runMutationGuards
12
+ } from "@open-mercato/shared/lib/crud/mutation-guard-registry";
13
+ import { E } from "../../../../../generated/entities.ids.generated.js";
14
+ import { collectFeatures } from "../../../lib/geometry.js";
15
+ import { plotCreateSchema } from "../../../data/validators.js";
16
+ const logger = createLogger("eudr").child({ component: "api/plots/import" });
17
+ const metadata = {
18
+ POST: { requireAuth: true, requireFeatures: ["eudr.plots.manage"] }
19
+ };
20
+ const importSchema = z.object({
21
+ supplierEntityId: z.string().uuid(),
22
+ defaultCountry: z.string().regex(/^[A-Za-z]{2}$/).transform((value) => value.toUpperCase()).optional(),
23
+ featureCollection: z.unknown()
24
+ });
25
+ function isRecord(value) {
26
+ return value !== null && typeof value === "object" && !Array.isArray(value);
27
+ }
28
+ function optionalString(value) {
29
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
30
+ }
31
+ function optionalNumber(value) {
32
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
33
+ }
34
+ function resolveUserFeatures(auth) {
35
+ const features = auth?.features;
36
+ if (!Array.isArray(features)) return [];
37
+ return features.filter((value) => typeof value === "string");
38
+ }
39
+ async function runGuards(ctx, input) {
40
+ const legacyGuard = bridgeLegacyGuard(ctx.container);
41
+ const guards = [...getAllMutationGuardInstances(), ...legacyGuard ? [legacyGuard] : []];
42
+ return runMutationGuards(guards, input, {
43
+ userFeatures: resolveUserFeatures(ctx.auth)
44
+ });
45
+ }
46
+ async function runGuardAfterSuccessCallbacks(callbacks, input) {
47
+ for (const callback of callbacks) {
48
+ if (!callback.guard.afterSuccess) continue;
49
+ try {
50
+ await callback.guard.afterSuccess({
51
+ ...input,
52
+ metadata: callback.metadata ?? null
53
+ });
54
+ } catch (err) {
55
+ logger.warn("Mutation guard afterSuccess callback failed", { err });
56
+ }
57
+ }
58
+ }
59
+ async function resolveRequestContext(req) {
60
+ const container = await createRequestContainer();
61
+ const auth = await getAuthFromRequest(req);
62
+ const { translate } = await resolveTranslations();
63
+ if (!auth || !auth.tenantId) {
64
+ throw new CrudHttpError(401, { error: translate("eudr.errors.unauthorized", "Unauthorized") });
65
+ }
66
+ const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req });
67
+ const organizationId = scope?.selectedId ?? auth.orgId ?? null;
68
+ if (!organizationId) {
69
+ throw new CrudHttpError(400, {
70
+ error: translate("eudr.errors.organization_required", "Organization context is required")
71
+ });
72
+ }
73
+ return {
74
+ tenantId: auth.tenantId,
75
+ organizationId,
76
+ ctx: {
77
+ container,
78
+ auth,
79
+ organizationScope: scope,
80
+ selectedOrganizationId: organizationId,
81
+ organizationIds: scope?.filterIds ?? (auth.orgId ? [auth.orgId] : null),
82
+ request: req
83
+ }
84
+ };
85
+ }
86
+ function featureProperties(feature) {
87
+ if (!isRecord(feature)) return {};
88
+ const properties = feature.properties;
89
+ return isRecord(properties) ? properties : {};
90
+ }
91
+ function featureGeometryType(feature) {
92
+ if (!isRecord(feature)) return null;
93
+ if (feature.type === "Feature" && isRecord(feature.geometry) && typeof feature.geometry.type === "string") {
94
+ return feature.geometry.type;
95
+ }
96
+ return typeof feature.type === "string" ? feature.type : null;
97
+ }
98
+ function resolveFeatureName(properties, index) {
99
+ return optionalString(properties.name) ?? optionalString(properties.ProductionPlace) ?? `Plot ${index + 1}`;
100
+ }
101
+ function errorKeyFromError(error) {
102
+ if (isCrudHttpError(error)) {
103
+ const bodyError = error.body?.error;
104
+ return typeof bodyError === "string" && bodyError.length > 0 ? bodyError : "eudr.errors.plot_import_failed";
105
+ }
106
+ if (error instanceof z.ZodError) {
107
+ const firstMessage = error.issues[0]?.message;
108
+ return typeof firstMessage === "string" && firstMessage.length > 0 ? firstMessage : "eudr.errors.plot_import_failed";
109
+ }
110
+ return "eudr.errors.plot_import_failed";
111
+ }
112
+ async function loadSupplierDisplayName(queryEngine, scope, supplierEntityId) {
113
+ try {
114
+ const customersEntityId = E.customers?.customer_entity;
115
+ if (!customersEntityId) return null;
116
+ const result = await queryEngine.query(customersEntityId, {
117
+ fields: ["id", "display_name"],
118
+ filters: { id: { $in: [supplierEntityId] } },
119
+ page: { page: 1, pageSize: 1 },
120
+ tenantId: scope.tenantId,
121
+ organizationId: scope.organizationId
122
+ });
123
+ const rawName = result.items[0]?.display_name ?? result.items[0]?.displayName;
124
+ return typeof rawName === "string" && rawName.length ? rawName : null;
125
+ } catch {
126
+ return null;
127
+ }
128
+ }
129
+ async function createPlotFromFeature(args) {
130
+ const properties = featureProperties(args.feature);
131
+ const name = resolveFeatureName(properties, args.index);
132
+ const originCountry = optionalString(properties.ProducerCountry) ?? args.input.defaultCountry ?? null;
133
+ if (!originCountry) throw new CrudHttpError(400, { error: "eudr.errors.importCountryMissing" });
134
+ const area = optionalNumber(properties.Area);
135
+ const base = {
136
+ supplierEntityId: args.input.supplierEntityId,
137
+ name,
138
+ originCountry,
139
+ geometry: args.feature,
140
+ producerName: optionalString(properties.ProducerName),
141
+ areaHa: featureGeometryType(args.feature) === "Point" && area !== null ? area : void 0,
142
+ supplierSnapshot: args.supplierDisplayName ? { displayName: args.supplierDisplayName } : void 0
143
+ };
144
+ const parsed = plotCreateSchema.parse(base);
145
+ const { result } = await args.commandBus.execute(
146
+ "eudr.plots.create",
147
+ {
148
+ input: {
149
+ ...parsed,
150
+ tenantId: args.scope.tenantId,
151
+ organizationId: args.scope.organizationId
152
+ },
153
+ ctx: args.ctx,
154
+ metadata: {
155
+ tenantId: args.scope.tenantId,
156
+ organizationId: args.scope.organizationId,
157
+ resourceKind: "eudr.plot",
158
+ context: { cacheAliases: ["eudr.plot"] }
159
+ }
160
+ }
161
+ );
162
+ return { id: result?.entityId ?? result?.id ?? null };
163
+ }
164
+ async function POST(req) {
165
+ try {
166
+ const requestContext = await resolveRequestContext(req);
167
+ const { translate } = await resolveTranslations();
168
+ const payload = await req.json().catch(() => ({}));
169
+ const input = importSchema.parse(payload);
170
+ const guardResult = await runGuards(requestContext.ctx, {
171
+ tenantId: requestContext.tenantId,
172
+ organizationId: requestContext.organizationId,
173
+ userId: requestContext.ctx.auth?.sub ?? "",
174
+ resourceKind: "eudr.plot",
175
+ resourceId: null,
176
+ operation: "create",
177
+ requestMethod: req.method,
178
+ requestHeaders: req.headers,
179
+ mutationPayload: {
180
+ supplierEntityId: input.supplierEntityId,
181
+ defaultCountry: input.defaultCountry ?? null
182
+ }
183
+ });
184
+ if (!guardResult.ok) {
185
+ return Response.json(
186
+ guardResult.errorBody ?? { error: translate("eudr.errors.operation_blocked", "Operation blocked by guard") },
187
+ { status: guardResult.errorStatus ?? 422 }
188
+ );
189
+ }
190
+ const guardPatch = guardResult.modifiedPayload ?? null;
191
+ const effectiveSupplierEntityId = typeof guardPatch?.supplierEntityId === "string" && guardPatch.supplierEntityId.length ? guardPatch.supplierEntityId : input.supplierEntityId;
192
+ const effectiveDefaultCountry = typeof guardPatch?.defaultCountry === "string" && guardPatch.defaultCountry.length ? guardPatch.defaultCountry : input.defaultCountry;
193
+ const featureResult = collectFeatures(input.featureCollection);
194
+ if (!featureResult.ok) {
195
+ return Response.json({ errorKey: featureResult.errorKey }, { status: 400 });
196
+ }
197
+ const commandBus = requestContext.ctx.container.resolve("commandBus");
198
+ const failed = [];
199
+ const createdIds = [];
200
+ const effectiveInput = {
201
+ ...input,
202
+ supplierEntityId: effectiveSupplierEntityId,
203
+ defaultCountry: effectiveDefaultCountry
204
+ };
205
+ const importScope = { tenantId: requestContext.tenantId, organizationId: requestContext.organizationId };
206
+ const supplierDisplayName = await loadSupplierDisplayName(
207
+ requestContext.ctx.container.resolve("queryEngine"),
208
+ importScope,
209
+ effectiveSupplierEntityId
210
+ );
211
+ for (const [index, feature] of featureResult.features.entries()) {
212
+ const name = resolveFeatureName(featureProperties(feature), index);
213
+ try {
214
+ const created = await createPlotFromFeature({
215
+ commandBus,
216
+ ctx: requestContext.ctx,
217
+ scope: importScope,
218
+ input: effectiveInput,
219
+ feature,
220
+ index,
221
+ supplierDisplayName
222
+ });
223
+ if (created.id) createdIds.push(created.id);
224
+ } catch (error) {
225
+ failed.push({ index, name, errorKey: errorKeyFromError(error) });
226
+ }
227
+ }
228
+ if (guardResult.afterSuccessCallbacks.length) {
229
+ for (const id of createdIds) {
230
+ await runGuardAfterSuccessCallbacks(guardResult.afterSuccessCallbacks, {
231
+ tenantId: requestContext.tenantId,
232
+ organizationId: requestContext.organizationId,
233
+ userId: requestContext.ctx.auth?.sub ?? "",
234
+ resourceKind: "eudr.plot",
235
+ resourceId: id,
236
+ operation: "create",
237
+ requestMethod: req.method,
238
+ requestHeaders: req.headers
239
+ });
240
+ }
241
+ }
242
+ return Response.json({ created: createdIds.length, failed });
243
+ } catch (error) {
244
+ if (isCrudHttpError(error)) {
245
+ return Response.json(error.body, { status: error.status });
246
+ }
247
+ const { translate } = await resolveTranslations();
248
+ if (error instanceof z.ZodError) {
249
+ return Response.json(
250
+ { error: translate("eudr.errors.plot_import_failed", "Failed to import plots") },
251
+ { status: 400 }
252
+ );
253
+ }
254
+ logger.error("Plot import failed", { err: error });
255
+ return Response.json(
256
+ { error: translate("eudr.errors.plot_import_failed", "Failed to import plots") },
257
+ { status: 500 }
258
+ );
259
+ }
260
+ }
261
+ const importResponseSchema = z.object({
262
+ created: z.number(),
263
+ failed: z.array(z.object({
264
+ index: z.number(),
265
+ name: z.string(),
266
+ errorKey: z.string()
267
+ }))
268
+ });
269
+ const openApi = {
270
+ tag: "EUDR",
271
+ summary: "Import EUDR plots from GeoJSON",
272
+ methods: {
273
+ POST: {
274
+ summary: "Import plots",
275
+ requestBody: {
276
+ contentType: "application/json",
277
+ schema: importSchema
278
+ },
279
+ responses: [
280
+ { status: 200, description: "Import result", schema: importResponseSchema },
281
+ { status: 400, description: "Invalid import payload", schema: z.object({ error: z.string().optional(), errorKey: z.string().optional() }) },
282
+ { status: 401, description: "Unauthorized", schema: z.object({ error: z.string() }) },
283
+ { status: 403, description: "Forbidden", schema: z.object({ error: z.string() }) },
284
+ { status: 500, description: "Plot import failed", schema: z.object({ error: z.string() }) }
285
+ ]
286
+ }
287
+ }
288
+ };
289
+ export {
290
+ POST,
291
+ metadata,
292
+ openApi
293
+ };
294
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/eudr/api/plots/import/route.ts"],
4
+ "sourcesContent": ["import { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { getAllMutationGuardInstances } from '@open-mercato/shared/lib/crud/mutation-guard-store'\nimport {\n bridgeLegacyGuard,\n runMutationGuards,\n type MutationGuard,\n type MutationGuardInput,\n} from '@open-mercato/shared/lib/crud/mutation-guard-registry'\nimport type { QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport { E } from '#generated/entities.ids.generated'\nimport { collectFeatures } from '../../../lib/geometry'\nimport { plotCreateSchema } from '../../../data/validators'\n\nconst logger = createLogger('eudr').child({ component: 'api/plots/import' })\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['eudr.plots.manage'] },\n}\n\nconst importSchema = z.object({\n supplierEntityId: z.string().uuid(),\n defaultCountry: z.string().regex(/^[A-Za-z]{2}$/).transform((value) => value.toUpperCase()).optional(),\n featureCollection: z.unknown(),\n})\n\ntype PlotImportInput = z.infer<typeof importSchema>\ntype PlotImportFailure = { index: number; name: string; errorKey: string }\ntype RequestContext = { ctx: CommandRuntimeContext; organizationId: string; tenantId: string }\ntype CommandCreateResult = { entityId?: string; id?: string }\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction optionalString(value: unknown): string | null {\n return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null\n}\n\nfunction optionalNumber(value: unknown): number | null {\n return typeof value === 'number' && Number.isFinite(value) ? value : null\n}\n\nfunction resolveUserFeatures(auth: unknown): string[] {\n const features = (auth as { features?: unknown })?.features\n if (!Array.isArray(features)) return []\n return features.filter((value): value is string => typeof value === 'string')\n}\n\nasync function runGuards(\n ctx: CommandRuntimeContext,\n input: MutationGuardInput,\n): Promise<{\n ok: boolean\n errorBody?: Record<string, unknown>\n errorStatus?: number\n modifiedPayload?: Record<string, unknown>\n afterSuccessCallbacks: Array<{ guard: MutationGuard; metadata: Record<string, unknown> | null }>\n}> {\n const legacyGuard = bridgeLegacyGuard(ctx.container)\n const guards = [...getAllMutationGuardInstances(), ...(legacyGuard ? [legacyGuard] : [])]\n return runMutationGuards(guards, input, {\n userFeatures: resolveUserFeatures(ctx.auth),\n })\n}\n\nasync function runGuardAfterSuccessCallbacks(\n callbacks: Array<{ guard: MutationGuard; metadata: Record<string, unknown> | null }>,\n input: {\n tenantId: string\n organizationId: string\n userId: string\n resourceKind: string\n resourceId: string\n operation: 'create'\n requestMethod: string\n requestHeaders: Headers\n },\n): Promise<void> {\n for (const callback of callbacks) {\n if (!callback.guard.afterSuccess) continue\n try {\n await callback.guard.afterSuccess({\n ...input,\n metadata: callback.metadata ?? null,\n })\n } catch (err) {\n logger.warn('Mutation guard afterSuccess callback failed', { err })\n }\n }\n}\n\nasync function resolveRequestContext(req: Request): Promise<RequestContext> {\n const container = await createRequestContainer()\n const auth = await getAuthFromRequest(req)\n const { translate } = await resolveTranslations()\n\n if (!auth || !auth.tenantId) {\n throw new CrudHttpError(401, { error: translate('eudr.errors.unauthorized', 'Unauthorized') })\n }\n\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req })\n const organizationId = scope?.selectedId ?? auth.orgId ?? null\n if (!organizationId) {\n throw new CrudHttpError(400, {\n error: translate('eudr.errors.organization_required', 'Organization context is required'),\n })\n }\n\n return {\n tenantId: auth.tenantId,\n organizationId,\n ctx: {\n container,\n auth,\n organizationScope: scope,\n selectedOrganizationId: organizationId,\n organizationIds: scope?.filterIds ?? (auth.orgId ? [auth.orgId] : null),\n request: req,\n },\n }\n}\n\nfunction featureProperties(feature: unknown): Record<string, unknown> {\n if (!isRecord(feature)) return {}\n const properties = feature.properties\n return isRecord(properties) ? properties : {}\n}\n\nfunction featureGeometryType(feature: unknown): string | null {\n if (!isRecord(feature)) return null\n if (feature.type === 'Feature' && isRecord(feature.geometry) && typeof feature.geometry.type === 'string') {\n return feature.geometry.type\n }\n return typeof feature.type === 'string' ? feature.type : null\n}\n\nfunction resolveFeatureName(properties: Record<string, unknown>, index: number): string {\n return optionalString(properties.name)\n ?? optionalString(properties.ProductionPlace)\n ?? `Plot ${index + 1}`\n}\n\nfunction errorKeyFromError(error: unknown): string {\n if (isCrudHttpError(error)) {\n const bodyError = error.body?.error\n return typeof bodyError === 'string' && bodyError.length > 0 ? bodyError : 'eudr.errors.plot_import_failed'\n }\n if (error instanceof z.ZodError) {\n const firstMessage = error.issues[0]?.message\n return typeof firstMessage === 'string' && firstMessage.length > 0 ? firstMessage : 'eudr.errors.plot_import_failed'\n }\n return 'eudr.errors.plot_import_failed'\n}\n\nasync function loadSupplierDisplayName(\n queryEngine: QueryEngine,\n scope: { tenantId: string; organizationId: string },\n supplierEntityId: string,\n): Promise<string | null> {\n // Soft cross-module read (FK-id convention) via the query engine \u2014 no direct\n // customers entity import; degrades to null when the peer is absent so the\n // import still succeeds without a snapshot.\n try {\n const customersEntityId = (E as Record<string, Record<string, string>>).customers?.customer_entity\n if (!customersEntityId) return null\n const result = await queryEngine.query<Record<string, unknown>>(customersEntityId, {\n fields: ['id', 'display_name'],\n filters: { id: { $in: [supplierEntityId] } },\n page: { page: 1, pageSize: 1 },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n const rawName = result.items[0]?.display_name ?? result.items[0]?.displayName\n return typeof rawName === 'string' && rawName.length ? rawName : null\n } catch {\n return null\n }\n}\n\nasync function createPlotFromFeature(args: {\n commandBus: CommandBus\n ctx: CommandRuntimeContext\n scope: { tenantId: string; organizationId: string }\n input: PlotImportInput\n feature: unknown\n index: number\n supplierDisplayName: string | null\n}): Promise<{ id: string | null }> {\n const properties = featureProperties(args.feature)\n const name = resolveFeatureName(properties, args.index)\n const originCountry = optionalString(properties.ProducerCountry) ?? args.input.defaultCountry ?? null\n if (!originCountry) throw new CrudHttpError(400, { error: 'eudr.errors.importCountryMissing' })\n\n const area = optionalNumber(properties.Area)\n const base = {\n supplierEntityId: args.input.supplierEntityId,\n name,\n originCountry,\n geometry: args.feature,\n producerName: optionalString(properties.ProducerName),\n areaHa: featureGeometryType(args.feature) === 'Point' && area !== null ? area : undefined,\n supplierSnapshot: args.supplierDisplayName ? { displayName: args.supplierDisplayName } : undefined,\n }\n const parsed = plotCreateSchema.parse(base)\n const { result } = await args.commandBus.execute<typeof parsed & { tenantId: string; organizationId: string }, CommandCreateResult>(\n 'eudr.plots.create',\n {\n input: {\n ...parsed,\n tenantId: args.scope.tenantId,\n organizationId: args.scope.organizationId,\n },\n ctx: args.ctx,\n metadata: {\n tenantId: args.scope.tenantId,\n organizationId: args.scope.organizationId,\n resourceKind: 'eudr.plot',\n context: { cacheAliases: ['eudr.plot'] },\n },\n },\n )\n return { id: result?.entityId ?? result?.id ?? null }\n}\n\nexport async function POST(req: Request) {\n try {\n const requestContext = await resolveRequestContext(req)\n const { translate } = await resolveTranslations()\n const payload = await req.json().catch(() => ({}))\n const input = importSchema.parse(payload)\n const guardResult = await runGuards(requestContext.ctx, {\n tenantId: requestContext.tenantId,\n organizationId: requestContext.organizationId,\n userId: requestContext.ctx.auth?.sub ?? '',\n resourceKind: 'eudr.plot',\n resourceId: null,\n operation: 'create',\n requestMethod: req.method,\n requestHeaders: req.headers,\n mutationPayload: {\n supplierEntityId: input.supplierEntityId,\n defaultCountry: input.defaultCountry ?? null,\n },\n })\n if (!guardResult.ok) {\n return Response.json(\n guardResult.errorBody ?? { error: translate('eudr.errors.operation_blocked', 'Operation blocked by guard') },\n { status: guardResult.errorStatus ?? 422 },\n )\n }\n const guardPatch = guardResult.modifiedPayload ?? null\n const effectiveSupplierEntityId = typeof guardPatch?.supplierEntityId === 'string' && guardPatch.supplierEntityId.length\n ? guardPatch.supplierEntityId\n : input.supplierEntityId\n const effectiveDefaultCountry = typeof guardPatch?.defaultCountry === 'string' && guardPatch.defaultCountry.length\n ? guardPatch.defaultCountry\n : input.defaultCountry\n\n const featureResult = collectFeatures(input.featureCollection)\n if (!featureResult.ok) {\n return Response.json({ errorKey: featureResult.errorKey }, { status: 400 })\n }\n\n const commandBus = requestContext.ctx.container.resolve('commandBus') as CommandBus\n const failed: PlotImportFailure[] = []\n const createdIds: string[] = []\n const effectiveInput: PlotImportInput = {\n ...input,\n supplierEntityId: effectiveSupplierEntityId,\n defaultCountry: effectiveDefaultCountry,\n }\n\n const importScope = { tenantId: requestContext.tenantId, organizationId: requestContext.organizationId }\n const supplierDisplayName = await loadSupplierDisplayName(\n requestContext.ctx.container.resolve('queryEngine') as QueryEngine,\n importScope,\n effectiveSupplierEntityId,\n )\n\n for (const [index, feature] of featureResult.features.entries()) {\n const name = resolveFeatureName(featureProperties(feature), index)\n try {\n const created = await createPlotFromFeature({\n commandBus,\n ctx: requestContext.ctx,\n scope: importScope,\n input: effectiveInput,\n feature,\n index,\n supplierDisplayName,\n })\n if (created.id) createdIds.push(created.id)\n } catch (error) {\n failed.push({ index, name, errorKey: errorKeyFromError(error) })\n }\n }\n\n if (guardResult.afterSuccessCallbacks.length) {\n for (const id of createdIds) {\n await runGuardAfterSuccessCallbacks(guardResult.afterSuccessCallbacks, {\n tenantId: requestContext.tenantId,\n organizationId: requestContext.organizationId,\n userId: requestContext.ctx.auth?.sub ?? '',\n resourceKind: 'eudr.plot',\n resourceId: id,\n operation: 'create',\n requestMethod: req.method,\n requestHeaders: req.headers,\n })\n }\n }\n\n return Response.json({ created: createdIds.length, failed })\n } catch (error) {\n if (isCrudHttpError(error)) {\n return Response.json(error.body, { status: error.status })\n }\n const { translate } = await resolveTranslations()\n if (error instanceof z.ZodError) {\n return Response.json(\n { error: translate('eudr.errors.plot_import_failed', 'Failed to import plots') },\n { status: 400 },\n )\n }\n logger.error('Plot import failed', { err: error })\n return Response.json(\n { error: translate('eudr.errors.plot_import_failed', 'Failed to import plots') },\n { status: 500 },\n )\n }\n}\n\nconst importResponseSchema = z.object({\n created: z.number(),\n failed: z.array(z.object({\n index: z.number(),\n name: z.string(),\n errorKey: z.string(),\n })),\n})\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'EUDR',\n summary: 'Import EUDR plots from GeoJSON',\n methods: {\n POST: {\n summary: 'Import plots',\n requestBody: {\n contentType: 'application/json',\n schema: importSchema,\n },\n responses: [\n { status: 200, description: 'Import result', schema: importResponseSchema },\n { status: 400, description: 'Invalid import payload', schema: z.object({ error: z.string().optional(), errorKey: z.string().optional() }) },\n { status: 401, description: 'Unauthorized', schema: z.object({ error: z.string() }) },\n { status: 403, description: 'Forbidden', schema: z.object({ error: z.string() }) },\n { status: 500, description: 'Plot import failed', schema: z.object({ error: z.string() }) },\n ],\n },\n },\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,279 @@
1
+ import { z } from "zod";
2
+ import { makeCrudRoute } from "@open-mercato/shared/lib/crud/factory";
3
+ import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
4
+ import { splitCustomFieldPayload } from "@open-mercato/shared/lib/crud/custom-fields";
5
+ import { buildIlikeTerm } from "@open-mercato/shared/lib/db/buildIlikeTerm";
6
+ import { parseBooleanToken } from "@open-mercato/shared/lib/boolean";
7
+ import { withScopedPayload } from "@open-mercato/shared/lib/api/scoped";
8
+ import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
9
+ import { findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
10
+ import { E } from "../../../../generated/entities.ids.generated.js";
11
+ import { EudrPlot } from "../../data/entities.js";
12
+ import { resolveDetailReadScope } from "../../lib/detail-read-scope.js";
13
+ import {
14
+ EUDR_PLOT_TYPES,
15
+ plotCreateSchema,
16
+ plotUpdateSchema
17
+ } from "../../data/validators.js";
18
+ import {
19
+ createEudrCrudOpenApi,
20
+ createPagedListResponseSchema,
21
+ defaultOkResponseSchema
22
+ } from "../openapi.js";
23
+ const rawBodySchema = z.object({}).passthrough();
24
+ const listSchema = z.object({
25
+ page: z.coerce.number().min(1).default(1),
26
+ pageSize: z.coerce.number().min(1).max(100).default(50),
27
+ search: z.string().optional(),
28
+ supplierEntityId: z.string().uuid().optional(),
29
+ plotType: z.enum(EUDR_PLOT_TYPES).optional(),
30
+ isActive: z.string().optional(),
31
+ originCountry: z.string().length(2).optional(),
32
+ id: z.string().uuid().optional(),
33
+ ids: z.string().optional(),
34
+ sortField: z.string().optional(),
35
+ sortDir: z.enum(["asc", "desc"]).optional()
36
+ });
37
+ const routeMetadata = {
38
+ GET: { requireAuth: true, requireFeatures: ["eudr.plots.view"] },
39
+ POST: { requireAuth: true, requireFeatures: ["eudr.plots.manage"] },
40
+ PUT: { requireAuth: true, requireFeatures: ["eudr.plots.manage"] },
41
+ DELETE: { requireAuth: true, requireFeatures: ["eudr.plots.manage"] }
42
+ };
43
+ const metadata = routeMetadata;
44
+ function toIsoString(value) {
45
+ if (value instanceof Date) return value.toISOString();
46
+ if (typeof value !== "string" || value.length === 0) return null;
47
+ const date = new Date(value);
48
+ return Number.isNaN(date.getTime()) ? value : date.toISOString();
49
+ }
50
+ function asStringOrNull(value) {
51
+ return typeof value === "string" ? value : null;
52
+ }
53
+ function stringArray(value) {
54
+ if (!Array.isArray(value)) return [];
55
+ return value.filter((entry) => typeof entry === "string");
56
+ }
57
+ function resolveDeleteInput(parsed, ctx, translate) {
58
+ const record = parsed && typeof parsed === "object" ? recordFrom(parsed) : {};
59
+ const body = record.body && typeof record.body === "object" ? recordFrom(record.body) : null;
60
+ const query = record.query && typeof record.query === "object" ? recordFrom(record.query) : null;
61
+ const requestId = ctx.request ? new URL(ctx.request.url).searchParams.get("id") : null;
62
+ const id = asStringOrNull(body?.id) ?? asStringOrNull(record.id) ?? asStringOrNull(query?.id) ?? requestId;
63
+ if (!id) throw new CrudHttpError(400, { error: translate("eudr.errors.plot_required", "Plot id is required") });
64
+ return { id };
65
+ }
66
+ function recordFrom(value) {
67
+ return value;
68
+ }
69
+ function buildFilters(query) {
70
+ const filters = {};
71
+ if (query.id) filters.id = { $eq: query.id };
72
+ if (query.supplierEntityId) filters.supplier_entity_id = { $eq: query.supplierEntityId };
73
+ if (query.plotType) filters.plot_type = { $eq: query.plotType };
74
+ if (query.originCountry) filters.origin_country = { $eq: query.originCountry.toUpperCase() };
75
+ const isActive = parseBooleanToken(query.isActive);
76
+ if (isActive !== null) filters.is_active = { $eq: isActive };
77
+ const search = typeof query.search === "string" ? query.search.trim() : "";
78
+ if (search) {
79
+ const searchPattern = buildIlikeTerm(search);
80
+ filters.$or = [
81
+ { name: { $ilike: searchPattern } },
82
+ { external_id: { $ilike: searchPattern } }
83
+ ];
84
+ }
85
+ return filters;
86
+ }
87
+ function transformPlotItem(item) {
88
+ if (!item || typeof item !== "object") return item;
89
+ const record = item;
90
+ return {
91
+ id: record.id,
92
+ supplierEntityId: record.supplier_entity_id ?? null,
93
+ supplierSnapshot: record.supplier_snapshot ?? null,
94
+ name: record.name ?? null,
95
+ externalId: record.external_id ?? null,
96
+ originCountry: record.origin_country ?? null,
97
+ plotType: record.plot_type ?? null,
98
+ areaHa: record.area_ha ?? null,
99
+ validationWarnings: stringArray(record.validation_warnings),
100
+ producerName: record.producer_name ?? null,
101
+ isActive: typeof record.is_active === "boolean" ? record.is_active : parseBooleanToken(typeof record.is_active === "string" ? record.is_active : null),
102
+ createdAt: toIsoString(record.created_at),
103
+ updatedAt: toIsoString(record.updated_at)
104
+ };
105
+ }
106
+ const listFields = [
107
+ "id",
108
+ "supplier_entity_id",
109
+ "supplier_snapshot",
110
+ "name",
111
+ "external_id",
112
+ "origin_country",
113
+ "plot_type",
114
+ "area_ha",
115
+ "validation_warnings",
116
+ "is_active",
117
+ "created_at",
118
+ "updated_at"
119
+ ];
120
+ const crud = makeCrudRoute({
121
+ metadata: routeMetadata,
122
+ orm: {
123
+ entity: EudrPlot,
124
+ idField: "id",
125
+ orgField: "organizationId",
126
+ tenantField: "tenantId",
127
+ softDeleteField: "deletedAt"
128
+ },
129
+ indexer: { entityType: E.eudr.eudr_plot },
130
+ list: {
131
+ schema: listSchema,
132
+ entityId: E.eudr.eudr_plot,
133
+ fields: listFields,
134
+ sortFieldMap: {
135
+ created_at: "created_at",
136
+ createdAt: "created_at",
137
+ updated_at: "updated_at",
138
+ updatedAt: "updated_at",
139
+ name: "name",
140
+ area_ha: "area_ha",
141
+ areaHa: "area_ha"
142
+ },
143
+ buildFilters,
144
+ transformItem: transformPlotItem
145
+ },
146
+ actions: {
147
+ create: {
148
+ commandId: "eudr.plots.create",
149
+ schema: rawBodySchema,
150
+ mapInput: async ({ raw, ctx }) => {
151
+ const { translate } = await resolveTranslations();
152
+ const scoped = withScopedPayload(raw ?? {}, ctx, translate);
153
+ const { base, custom } = splitCustomFieldPayload(scoped);
154
+ const parsed = plotCreateSchema.parse(base);
155
+ const input = { ...parsed, tenantId: scoped.tenantId, organizationId: scoped.organizationId };
156
+ return Object.keys(custom).length ? { ...input, customFields: custom } : input;
157
+ },
158
+ response: ({ result }) => ({ id: result?.entityId ?? result?.id ?? null }),
159
+ status: 201
160
+ },
161
+ update: {
162
+ commandId: "eudr.plots.update",
163
+ schema: rawBodySchema,
164
+ mapInput: async ({ raw, ctx }) => {
165
+ const { translate } = await resolveTranslations();
166
+ const scoped = withScopedPayload(raw ?? {}, ctx, translate);
167
+ const { base, custom } = splitCustomFieldPayload(scoped);
168
+ const parsed = plotUpdateSchema.parse(base);
169
+ const input = { ...parsed, tenantId: scoped.tenantId, organizationId: scoped.organizationId };
170
+ return Object.keys(custom).length ? { ...input, customFields: custom } : input;
171
+ },
172
+ response: ({ result }) => {
173
+ const updatedAt = result?.updatedAt;
174
+ return {
175
+ ok: true,
176
+ updatedAt: updatedAt instanceof Date ? updatedAt.toISOString() : typeof updatedAt === "string" ? updatedAt : null
177
+ };
178
+ }
179
+ },
180
+ delete: {
181
+ commandId: "eudr.plots.delete",
182
+ schema: rawBodySchema,
183
+ mapInput: async ({ parsed, ctx }) => {
184
+ const { translate } = await resolveTranslations();
185
+ return resolveDeleteInput(parsed, ctx, translate);
186
+ },
187
+ response: () => ({ ok: true })
188
+ }
189
+ },
190
+ hooks: {
191
+ afterList: async (payload, ctx) => {
192
+ const detailRead = typeof ctx.query.id === "string" && ctx.query.id.length > 0 || typeof ctx.query.ids === "string" && ctx.query.ids.length > 0;
193
+ if (!detailRead) return;
194
+ const items = Array.isArray(payload?.items) ? payload.items : [];
195
+ if (!items.length) return;
196
+ const scope = resolveDetailReadScope(ctx);
197
+ if (!scope) return;
198
+ const ids = items.map((item) => item && typeof item === "object" ? asStringOrNull(item.id) : null).filter((id) => id !== null);
199
+ if (!ids.length) return;
200
+ const em = ctx.container.resolve("em");
201
+ const where = {
202
+ id: { $in: ids },
203
+ deletedAt: null,
204
+ tenantId: scope.tenantId,
205
+ organizationId: scope.organizationFilter
206
+ };
207
+ const decrypted = await findWithDecryption(
208
+ em,
209
+ EudrPlot,
210
+ where,
211
+ {},
212
+ { tenantId: scope.tenantId, organizationId: scope.decryptionOrganizationId }
213
+ );
214
+ const byId = new Map(decrypted.map((plot) => [plot.id, plot]));
215
+ for (const item of items) {
216
+ if (!item || typeof item !== "object") continue;
217
+ const record = item;
218
+ const id = asStringOrNull(record.id);
219
+ const plot = id ? byId.get(id) : null;
220
+ if (!plot) continue;
221
+ record.geometry = plot.geometry ?? null;
222
+ record.producerName = plot.producerName ?? null;
223
+ record.description = plot.description ?? null;
224
+ }
225
+ }
226
+ }
227
+ });
228
+ const GET = crud.GET;
229
+ const POST = crud.POST;
230
+ const PUT = crud.PUT;
231
+ const DELETE = crud.DELETE;
232
+ const plotListItemSchema = z.object({
233
+ id: z.string().uuid(),
234
+ supplierEntityId: z.string().uuid().nullable().optional(),
235
+ supplierSnapshot: z.object({
236
+ displayName: z.string().nullable().optional()
237
+ }).nullable().optional(),
238
+ name: z.string().nullable().optional(),
239
+ externalId: z.string().nullable().optional(),
240
+ originCountry: z.string().nullable().optional(),
241
+ plotType: z.enum(EUDR_PLOT_TYPES).nullable().optional(),
242
+ areaHa: z.union([z.string(), z.number()]).nullable().optional(),
243
+ geometry: z.unknown().nullable().optional().describe(
244
+ "Present only on detail reads requested with id or ids; omitted from bare paginated list reads."
245
+ ),
246
+ validationWarnings: z.array(z.string()),
247
+ producerName: z.string().nullable().optional(),
248
+ isActive: z.boolean().nullable().optional(),
249
+ createdAt: z.string().nullable().optional(),
250
+ updatedAt: z.string().nullable().optional()
251
+ });
252
+ const openApi = createEudrCrudOpenApi({
253
+ resourceName: "Plot",
254
+ querySchema: listSchema,
255
+ listResponseSchema: createPagedListResponseSchema(plotListItemSchema),
256
+ create: {
257
+ schema: plotCreateSchema,
258
+ description: "Creates an EUDR supplier plot for the scoped organization."
259
+ },
260
+ update: {
261
+ schema: plotUpdateSchema,
262
+ responseSchema: defaultOkResponseSchema,
263
+ description: "Updates an EUDR supplier plot."
264
+ },
265
+ del: {
266
+ schema: z.object({ id: z.string().uuid() }),
267
+ responseSchema: defaultOkResponseSchema,
268
+ description: "Deletes an EUDR supplier plot by id. Request body or query may provide the identifier."
269
+ }
270
+ });
271
+ export {
272
+ DELETE,
273
+ GET,
274
+ POST,
275
+ PUT,
276
+ metadata,
277
+ openApi
278
+ };
279
+ //# sourceMappingURL=route.js.map