@open-mercato/core 0.6.8-develop.6924.1.a8d208fcdc → 0.6.8-develop.6930.1.1e5976efc3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +2 -2
- package/dist/generated/entities/eudr_due_diligence_statement/index.js +47 -0
- package/dist/generated/entities/eudr_due_diligence_statement/index.js.map +7 -0
- package/dist/generated/entities/eudr_evidence_submission/index.js +51 -0
- package/dist/generated/entities/eudr_evidence_submission/index.js.map +7 -0
- package/dist/generated/entities/eudr_mitigation_action/index.js +31 -0
- package/dist/generated/entities/eudr_mitigation_action/index.js.map +7 -0
- package/dist/generated/entities/eudr_plot/index.js +39 -0
- package/dist/generated/entities/eudr_plot/index.js.map +7 -0
- package/dist/generated/entities/eudr_product_mapping/index.js +31 -0
- package/dist/generated/entities/eudr_product_mapping/index.js.map +7 -0
- package/dist/generated/entities/eudr_risk_assessment/index.js +35 -0
- package/dist/generated/entities/eudr_risk_assessment/index.js.map +7 -0
- package/dist/generated/entities/role/index.js +2 -0
- package/dist/generated/entities/role/index.js.map +2 -2
- package/dist/generated/entities.ids.generated.js +9 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +121 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/api.js +4 -0
- package/dist/helpers/integration/api.js.map +2 -2
- package/dist/modules/attachments/fields/attachment.js +5 -1
- package/dist/modules/attachments/fields/attachment.js.map +2 -2
- package/dist/modules/attachments/lib/crud.js +3 -1
- package/dist/modules/attachments/lib/crud.js.map +2 -2
- package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js +5 -0
- package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js.map +2 -2
- package/dist/modules/audit_logs/api/audit-logs/actions/undo/route.js +5 -0
- package/dist/modules/audit_logs/api/audit-logs/actions/undo/route.js.map +2 -2
- package/dist/modules/audit_logs/backend/audit-logs/page.js +4 -4
- package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
- package/dist/modules/audit_logs/components/AuditLogsActions.js +9 -2
- package/dist/modules/audit_logs/components/AuditLogsActions.js.map +2 -2
- package/dist/modules/auth/api/login.js +5 -2
- package/dist/modules/auth/api/login.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +8 -5
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/users/[id]/edit/page.js +15 -1
- package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/users/page.js +7 -1
- package/dist/modules/auth/backend/users/page.js.map +2 -2
- package/dist/modules/auth/commands/users.js +175 -76
- package/dist/modules/auth/commands/users.js.map +2 -2
- package/dist/modules/auth/data/entities.js +4 -0
- package/dist/modules/auth/data/entities.js.map +2 -2
- package/dist/modules/auth/lib/sessionIntegrity.js +1 -1
- package/dist/modules/auth/lib/sessionIntegrity.js.map +2 -2
- package/dist/modules/auth/lib/setup-app.js +1 -1
- package/dist/modules/auth/lib/setup-app.js.map +2 -2
- package/dist/modules/auth/migrations/Migration20260728134212_auth.js +14 -0
- package/dist/modules/auth/migrations/Migration20260728134212_auth.js.map +7 -0
- package/dist/modules/eudr/acl.js +43 -0
- package/dist/modules/eudr/acl.js.map +7 -0
- package/dist/modules/eudr/ai-agents.js +205 -0
- package/dist/modules/eudr/ai-agents.js.map +7 -0
- package/dist/modules/eudr/ai-tools/compliance-pack.js +495 -0
- package/dist/modules/eudr/ai-tools/compliance-pack.js.map +7 -0
- package/dist/modules/eudr/ai-tools/types.js +10 -0
- package/dist/modules/eudr/ai-tools/types.js.map +7 -0
- package/dist/modules/eudr/ai-tools.js +10 -0
- package/dist/modules/eudr/ai-tools.js.map +7 -0
- package/dist/modules/eudr/api/dashboard/widgets/compliance-overview/route.js +386 -0
- package/dist/modules/eudr/api/dashboard/widgets/compliance-overview/route.js.map +7 -0
- package/dist/modules/eudr/api/evidence-submissions/route.js +318 -0
- package/dist/modules/eudr/api/evidence-submissions/route.js.map +7 -0
- package/dist/modules/eudr/api/mitigation-actions/route.js +249 -0
- package/dist/modules/eudr/api/mitigation-actions/route.js.map +7 -0
- package/dist/modules/eudr/api/openapi.js +27 -0
- package/dist/modules/eudr/api/openapi.js.map +7 -0
- package/dist/modules/eudr/api/plots/import/route.js +294 -0
- package/dist/modules/eudr/api/plots/import/route.js.map +7 -0
- package/dist/modules/eudr/api/plots/route.js +279 -0
- package/dist/modules/eudr/api/plots/route.js.map +7 -0
- package/dist/modules/eudr/api/product-mappings/route.js +257 -0
- package/dist/modules/eudr/api/product-mappings/route.js.map +7 -0
- package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js +298 -0
- package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js.map +7 -0
- package/dist/modules/eudr/api/product-mappings/suggestions/route.js +132 -0
- package/dist/modules/eudr/api/product-mappings/suggestions/route.js.map +7 -0
- package/dist/modules/eudr/api/reports/annual/route.js +266 -0
- package/dist/modules/eudr/api/reports/annual/route.js.map +7 -0
- package/dist/modules/eudr/api/risk-assessments/route.js +300 -0
- package/dist/modules/eudr/api/risk-assessments/route.js.map +7 -0
- package/dist/modules/eudr/api/statements/[id]/export/route.js +631 -0
- package/dist/modules/eudr/api/statements/[id]/export/route.js.map +7 -0
- package/dist/modules/eudr/api/statements/[id]/readiness/route.js +111 -0
- package/dist/modules/eudr/api/statements/[id]/readiness/route.js.map +7 -0
- package/dist/modules/eudr/api/statements/route.js +314 -0
- package/dist/modules/eudr/api/statements/route.js.map +7 -0
- package/dist/modules/eudr/api/suppliers/compliance/route.js +173 -0
- package/dist/modules/eudr/api/suppliers/compliance/route.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.js +468 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.js +351 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.js +17 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js +313 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/page.js +360 -0
- package/dist/modules/eudr/backend/eudr/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/plots/[id]/page.js +346 -0
- package/dist/modules/eudr/backend/eudr/plots/[id]/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/plots/[id]/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/plots/[id]/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/plots/create/page.js +253 -0
- package/dist/modules/eudr/backend/eudr/plots/create/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/plots/create/page.meta.js +17 -0
- package/dist/modules/eudr/backend/eudr/plots/create/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/plots/page.js +386 -0
- package/dist/modules/eudr/backend/eudr/plots/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/plots/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/plots/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.js +253 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/create/page.js +174 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/create/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/create/page.meta.js +17 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/create/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/page.js +306 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.js +335 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.js +220 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.meta.js +17 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.js +324 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/statements/[id]/page.js +648 -0
- package/dist/modules/eudr/backend/eudr/statements/[id]/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/statements/[id]/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/statements/[id]/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/statements/create/page.js +432 -0
- package/dist/modules/eudr/backend/eudr/statements/create/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/statements/create/page.meta.js +17 -0
- package/dist/modules/eudr/backend/eudr/statements/create/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/statements/page.js +309 -0
- package/dist/modules/eudr/backend/eudr/statements/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/statements/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/statements/page.meta.js.map +7 -0
- package/dist/modules/eudr/ce.js +56 -0
- package/dist/modules/eudr/ce.js.map +7 -0
- package/dist/modules/eudr/commands/evidence-submissions.js +571 -0
- package/dist/modules/eudr/commands/evidence-submissions.js.map +7 -0
- package/dist/modules/eudr/commands/index.js +7 -0
- package/dist/modules/eudr/commands/index.js.map +7 -0
- package/dist/modules/eudr/commands/lifecycle-events.js +19 -0
- package/dist/modules/eudr/commands/lifecycle-events.js.map +7 -0
- package/dist/modules/eudr/commands/mitigation-actions.js +488 -0
- package/dist/modules/eudr/commands/mitigation-actions.js.map +7 -0
- package/dist/modules/eudr/commands/plots.js +517 -0
- package/dist/modules/eudr/commands/plots.js.map +7 -0
- package/dist/modules/eudr/commands/product-mappings.js +468 -0
- package/dist/modules/eudr/commands/product-mappings.js.map +7 -0
- package/dist/modules/eudr/commands/risk-assessments.js +599 -0
- package/dist/modules/eudr/commands/risk-assessments.js.map +7 -0
- package/dist/modules/eudr/commands/statements.js +747 -0
- package/dist/modules/eudr/commands/statements.js.map +7 -0
- package/dist/modules/eudr/components/CountrySelectField.js +64 -0
- package/dist/modules/eudr/components/CountrySelectField.js.map +7 -0
- package/dist/modules/eudr/components/GeometryInput.js +133 -0
- package/dist/modules/eudr/components/GeometryInput.js.map +7 -0
- package/dist/modules/eudr/components/MappingSuggestionsDialog.js +307 -0
- package/dist/modules/eudr/components/MappingSuggestionsDialog.js.map +7 -0
- package/dist/modules/eudr/components/MitigationActionsSection.js +345 -0
- package/dist/modules/eudr/components/MitigationActionsSection.js.map +7 -0
- package/dist/modules/eudr/components/OrderSelectField.js +88 -0
- package/dist/modules/eudr/components/OrderSelectField.js.map +7 -0
- package/dist/modules/eudr/components/PlotImportDialog.js +229 -0
- package/dist/modules/eudr/components/PlotImportDialog.js.map +7 -0
- package/dist/modules/eudr/components/PlotMapPreview.js +35 -0
- package/dist/modules/eudr/components/PlotMapPreview.js.map +7 -0
- package/dist/modules/eudr/components/PlotMapPreviewImpl.js +97 -0
- package/dist/modules/eudr/components/PlotMapPreviewImpl.js.map +7 -0
- package/dist/modules/eudr/components/PlotMultiSelectField.js +198 -0
- package/dist/modules/eudr/components/PlotMultiSelectField.js.map +7 -0
- package/dist/modules/eudr/components/RiskCriteriaField.js +128 -0
- package/dist/modules/eudr/components/RiskCriteriaField.js.map +7 -0
- package/dist/modules/eudr/components/StatementLifecycleBar.js +274 -0
- package/dist/modules/eudr/components/StatementLifecycleBar.js.map +7 -0
- package/dist/modules/eudr/components/StatementReadinessChecklist.js +56 -0
- package/dist/modules/eudr/components/StatementReadinessChecklist.js.map +7 -0
- package/dist/modules/eudr/components/StatementRiskSection.js +179 -0
- package/dist/modules/eudr/components/StatementRiskSection.js.map +7 -0
- package/dist/modules/eudr/components/crudErrorI18n.js +31 -0
- package/dist/modules/eudr/components/crudErrorI18n.js.map +7 -0
- package/dist/modules/eudr/components/formConfig.js +593 -0
- package/dist/modules/eudr/components/formConfig.js.map +7 -0
- package/dist/modules/eudr/components/plotForm.js +68 -0
- package/dist/modules/eudr/components/plotForm.js.map +7 -0
- package/dist/modules/eudr/data/enrichers.js +62 -0
- package/dist/modules/eudr/data/enrichers.js.map +7 -0
- package/dist/modules/eudr/data/entities.js +437 -0
- package/dist/modules/eudr/data/entities.js.map +7 -0
- package/dist/modules/eudr/data/validators.js +271 -0
- package/dist/modules/eudr/data/validators.js.map +7 -0
- package/dist/modules/eudr/encryption.js +33 -0
- package/dist/modules/eudr/encryption.js.map +7 -0
- package/dist/modules/eudr/events.js +38 -0
- package/dist/modules/eudr/events.js.map +7 -0
- package/dist/modules/eudr/index.js +15 -0
- package/dist/modules/eudr/index.js.map +7 -0
- package/dist/modules/eudr/lib/annual-report.js +104 -0
- package/dist/modules/eudr/lib/annual-report.js.map +7 -0
- package/dist/modules/eudr/lib/completeness.js +64 -0
- package/dist/modules/eudr/lib/completeness.js.map +7 -0
- package/dist/modules/eudr/lib/detail-read-scope.js +16 -0
- package/dist/modules/eudr/lib/detail-read-scope.js.map +7 -0
- package/dist/modules/eudr/lib/geometry.js +142 -0
- package/dist/modules/eudr/lib/geometry.js.map +7 -0
- package/dist/modules/eudr/lib/notifications.js +56 -0
- package/dist/modules/eudr/lib/notifications.js.map +7 -0
- package/dist/modules/eudr/lib/plural.js +26 -0
- package/dist/modules/eudr/lib/plural.js.map +7 -0
- package/dist/modules/eudr/lib/reference-data.js +240 -0
- package/dist/modules/eudr/lib/reference-data.js.map +7 -0
- package/dist/modules/eudr/lib/species.js +10 -0
- package/dist/modules/eudr/lib/species.js.map +7 -0
- package/dist/modules/eudr/lib/statement-lifecycle.js +84 -0
- package/dist/modules/eudr/lib/statement-lifecycle.js.map +7 -0
- package/dist/modules/eudr/lib/statement-seeding.js +49 -0
- package/dist/modules/eudr/lib/statement-seeding.js.map +7 -0
- package/dist/modules/eudr/migrations/Migration20260706102002_eudr.js +15 -0
- package/dist/modules/eudr/migrations/Migration20260706102002_eudr.js.map +7 -0
- package/dist/modules/eudr/migrations/Migration20260706152612_eudr.js +24 -0
- package/dist/modules/eudr/migrations/Migration20260706152612_eudr.js.map +7 -0
- package/dist/modules/eudr/migrations/Migration20260722100000_eudr.js +15 -0
- package/dist/modules/eudr/migrations/Migration20260722100000_eudr.js.map +7 -0
- package/dist/modules/eudr/notifications.js +58 -0
- package/dist/modules/eudr/notifications.js.map +7 -0
- package/dist/modules/eudr/search.js +186 -0
- package/dist/modules/eudr/search.js.map +7 -0
- package/dist/modules/eudr/setup.js +12 -0
- package/dist/modules/eudr/setup.js.map +7 -0
- package/dist/modules/eudr/subscribers/notify-mitigation-completed.js +34 -0
- package/dist/modules/eudr/subscribers/notify-mitigation-completed.js.map +7 -0
- package/dist/modules/eudr/subscribers/notify-risk-concluded.js +35 -0
- package/dist/modules/eudr/subscribers/notify-risk-concluded.js.map +7 -0
- package/dist/modules/eudr/subscribers/notify-statement-reference-issued.js +37 -0
- package/dist/modules/eudr/subscribers/notify-statement-reference-issued.js.map +7 -0
- package/dist/modules/eudr/subscribers/notify-statement-submitted.js +34 -0
- package/dist/modules/eudr/subscribers/notify-statement-submitted.js.map +7 -0
- package/dist/modules/eudr/subscribers/notify-statement-withdrawn.js +34 -0
- package/dist/modules/eudr/subscribers/notify-statement-withdrawn.js.map +7 -0
- package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-created.js +124 -0
- package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-created.js.map +7 -0
- package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.js +22 -0
- package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.js.map +7 -0
- package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.client.js +203 -0
- package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.client.js.map +7 -0
- package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.js +23 -0
- package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.js.map +7 -0
- package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.client.js +19 -0
- package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.client.js.map +7 -0
- package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.js +31 -0
- package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.js.map +7 -0
- package/dist/modules/eudr/widgets/injection/order-compliance/widget.client.js +100 -0
- package/dist/modules/eudr/widgets/injection/order-compliance/widget.client.js.map +7 -0
- package/dist/modules/eudr/widgets/injection/order-compliance/widget.js +17 -0
- package/dist/modules/eudr/widgets/injection/order-compliance/widget.js.map +7 -0
- package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.client.js +116 -0
- package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.client.js.map +7 -0
- package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.js +17 -0
- package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.js.map +7 -0
- package/dist/modules/eudr/widgets/injection-table.js +32 -0
- package/dist/modules/eudr/widgets/injection-table.js.map +7 -0
- package/dist/modules/notifications/lib/notificationService.js +67 -3
- package/dist/modules/notifications/lib/notificationService.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +121 -48
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/sales/api/documents/factory.js +17 -0
- package/dist/modules/sales/api/documents/factory.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +32 -18
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/data/entities.js +1 -0
- package/dist/modules/sales/data/entities.js.map +2 -2
- package/dist/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.js +17 -0
- package/dist/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.js.map +7 -0
- package/generated/entities/eudr_due_diligence_statement/index.ts +22 -0
- package/generated/entities/eudr_evidence_submission/index.ts +24 -0
- package/generated/entities/eudr_mitigation_action/index.ts +14 -0
- package/generated/entities/eudr_plot/index.ts +18 -0
- package/generated/entities/eudr_product_mapping/index.ts +14 -0
- package/generated/entities/eudr_risk_assessment/index.ts +16 -0
- package/generated/entities/role/index.ts +1 -0
- package/generated/entities.ids.generated.ts +9 -0
- package/generated/entity-fields-registry.ts +121 -0
- package/package.json +7 -7
- package/src/helpers/integration/api.ts +13 -0
- package/src/modules/attachments/fields/attachment.tsx +5 -0
- package/src/modules/attachments/lib/crud.ts +2 -0
- package/src/modules/audit_logs/api/audit-logs/actions/redo/route.ts +7 -0
- package/src/modules/audit_logs/api/audit-logs/actions/undo/route.ts +9 -0
- package/src/modules/audit_logs/backend/audit-logs/page.tsx +4 -4
- package/src/modules/audit_logs/components/AuditLogsActions.tsx +20 -4
- package/src/modules/auth/api/login.ts +9 -2
- package/src/modules/auth/api/users/route.ts +8 -4
- package/src/modules/auth/backend/users/[id]/edit/page.tsx +17 -1
- package/src/modules/auth/backend/users/page.tsx +11 -0
- package/src/modules/auth/commands/users.ts +251 -85
- package/src/modules/auth/data/entities.ts +3 -0
- package/src/modules/auth/i18n/de.json +6 -0
- package/src/modules/auth/i18n/en.json +6 -0
- package/src/modules/auth/i18n/es.json +6 -0
- package/src/modules/auth/i18n/ko.json +6 -0
- package/src/modules/auth/i18n/pl.json +6 -0
- package/src/modules/auth/lib/sessionIntegrity.ts +1 -1
- package/src/modules/auth/lib/setup-app.ts +1 -1
- package/src/modules/auth/migrations/.snapshot-open-mercato.json +16 -0
- package/src/modules/auth/migrations/Migration20260728134212_auth.ts +14 -0
- package/src/modules/eudr/acl.ts +39 -0
- package/src/modules/eudr/ai-agents.ts +258 -0
- package/src/modules/eudr/ai-tools/compliance-pack.ts +618 -0
- package/src/modules/eudr/ai-tools/types.ts +44 -0
- package/src/modules/eudr/ai-tools.ts +15 -0
- package/src/modules/eudr/api/dashboard/widgets/compliance-overview/route.ts +481 -0
- package/src/modules/eudr/api/evidence-submissions/route.ts +335 -0
- package/src/modules/eudr/api/mitigation-actions/route.ts +263 -0
- package/src/modules/eudr/api/openapi.ts +28 -0
- package/src/modules/eudr/api/plots/import/route.ts +369 -0
- package/src/modules/eudr/api/plots/route.ts +296 -0
- package/src/modules/eudr/api/product-mappings/route.ts +269 -0
- package/src/modules/eudr/api/product-mappings/suggestions/apply/route.ts +382 -0
- package/src/modules/eudr/api/product-mappings/suggestions/route.ts +169 -0
- package/src/modules/eudr/api/reports/annual/route.ts +457 -0
- package/src/modules/eudr/api/risk-assessments/route.ts +323 -0
- package/src/modules/eudr/api/statements/[id]/export/route.ts +713 -0
- package/src/modules/eudr/api/statements/[id]/readiness/route.ts +129 -0
- package/src/modules/eudr/api/statements/route.ts +329 -0
- package/src/modules/eudr/api/suppliers/compliance/route.ts +241 -0
- package/src/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/evidence-submissions/[id]/page.tsx +545 -0
- package/src/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.ts +13 -0
- package/src/modules/eudr/backend/eudr/evidence-submissions/create/page.tsx +383 -0
- package/src/modules/eudr/backend/eudr/evidence-submissions/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/evidence-submissions/page.tsx +379 -0
- package/src/modules/eudr/backend/eudr/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/page.tsx +477 -0
- package/src/modules/eudr/backend/eudr/plots/[id]/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/plots/[id]/page.tsx +404 -0
- package/src/modules/eudr/backend/eudr/plots/create/page.meta.ts +13 -0
- package/src/modules/eudr/backend/eudr/plots/create/page.tsx +267 -0
- package/src/modules/eudr/backend/eudr/plots/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/plots/page.tsx +442 -0
- package/src/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/product-mappings/[id]/page.tsx +311 -0
- package/src/modules/eudr/backend/eudr/product-mappings/create/page.meta.ts +13 -0
- package/src/modules/eudr/backend/eudr/product-mappings/create/page.tsx +190 -0
- package/src/modules/eudr/backend/eudr/product-mappings/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/product-mappings/page.tsx +344 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/[id]/page.tsx +421 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/create/page.meta.ts +13 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/create/page.tsx +247 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/page.tsx +383 -0
- package/src/modules/eudr/backend/eudr/statements/[id]/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/statements/[id]/page.tsx +777 -0
- package/src/modules/eudr/backend/eudr/statements/create/page.meta.ts +13 -0
- package/src/modules/eudr/backend/eudr/statements/create/page.tsx +511 -0
- package/src/modules/eudr/backend/eudr/statements/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/statements/page.tsx +372 -0
- package/src/modules/eudr/ce.ts +52 -0
- package/src/modules/eudr/commands/evidence-submissions.ts +699 -0
- package/src/modules/eudr/commands/index.ts +6 -0
- package/src/modules/eudr/commands/lifecycle-events.ts +28 -0
- package/src/modules/eudr/commands/mitigation-actions.ts +574 -0
- package/src/modules/eudr/commands/plots.ts +627 -0
- package/src/modules/eudr/commands/product-mappings.ts +556 -0
- package/src/modules/eudr/commands/risk-assessments.ts +728 -0
- package/src/modules/eudr/commands/statements.ts +933 -0
- package/src/modules/eudr/components/CountrySelectField.tsx +77 -0
- package/src/modules/eudr/components/GeometryInput.tsx +170 -0
- package/src/modules/eudr/components/MappingSuggestionsDialog.tsx +385 -0
- package/src/modules/eudr/components/MitigationActionsSection.tsx +417 -0
- package/src/modules/eudr/components/OrderSelectField.tsx +116 -0
- package/src/modules/eudr/components/PlotImportDialog.tsx +277 -0
- package/src/modules/eudr/components/PlotMapPreview.tsx +46 -0
- package/src/modules/eudr/components/PlotMapPreviewImpl.tsx +111 -0
- package/src/modules/eudr/components/PlotMultiSelectField.tsx +238 -0
- package/src/modules/eudr/components/RiskCriteriaField.tsx +173 -0
- package/src/modules/eudr/components/StatementLifecycleBar.tsx +363 -0
- package/src/modules/eudr/components/StatementReadinessChecklist.tsx +82 -0
- package/src/modules/eudr/components/StatementRiskSection.tsx +242 -0
- package/src/modules/eudr/components/crudErrorI18n.ts +36 -0
- package/src/modules/eudr/components/formConfig.tsx +717 -0
- package/src/modules/eudr/components/plotForm.ts +75 -0
- package/src/modules/eudr/data/enrichers.ts +82 -0
- package/src/modules/eudr/data/entities.ts +369 -0
- package/src/modules/eudr/data/validators.ts +357 -0
- package/src/modules/eudr/encryption.ts +31 -0
- package/src/modules/eudr/events.ts +38 -0
- package/src/modules/eudr/i18n/de.json +747 -0
- package/src/modules/eudr/i18n/en.json +747 -0
- package/src/modules/eudr/i18n/es.json +747 -0
- package/src/modules/eudr/i18n/ko.json +747 -0
- package/src/modules/eudr/i18n/pl.json +747 -0
- package/src/modules/eudr/index.ts +13 -0
- package/src/modules/eudr/lib/annual-report.ts +120 -0
- package/src/modules/eudr/lib/completeness.ts +90 -0
- package/src/modules/eudr/lib/detail-read-scope.ts +44 -0
- package/src/modules/eudr/lib/geometry.ts +191 -0
- package/src/modules/eudr/lib/notifications.ts +85 -0
- package/src/modules/eudr/lib/plural.ts +36 -0
- package/src/modules/eudr/lib/reference-data.ts +128 -0
- package/src/modules/eudr/lib/species.ts +12 -0
- package/src/modules/eudr/lib/statement-lifecycle.ts +109 -0
- package/src/modules/eudr/lib/statement-seeding.ts +86 -0
- package/src/modules/eudr/migrations/.snapshot-open-mercato.json +2046 -0
- package/src/modules/eudr/migrations/Migration20260706102002_eudr.ts +16 -0
- package/src/modules/eudr/migrations/Migration20260706152612_eudr.ts +30 -0
- package/src/modules/eudr/migrations/Migration20260722100000_eudr.ts +17 -0
- package/src/modules/eudr/notifications.ts +56 -0
- package/src/modules/eudr/search.ts +212 -0
- package/src/modules/eudr/setup.ts +10 -0
- package/src/modules/eudr/subscribers/notify-mitigation-completed.ts +56 -0
- package/src/modules/eudr/subscribers/notify-risk-concluded.ts +58 -0
- package/src/modules/eudr/subscribers/notify-statement-reference-issued.ts +59 -0
- package/src/modules/eudr/subscribers/notify-statement-submitted.ts +49 -0
- package/src/modules/eudr/subscribers/notify-statement-withdrawn.ts +49 -0
- package/src/modules/eudr/subscribers/recompute-completeness-on-attachment-created.ts +189 -0
- package/src/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.ts +31 -0
- package/src/modules/eudr/widgets/dashboard/compliance-overview/widget.client.tsx +271 -0
- package/src/modules/eudr/widgets/dashboard/compliance-overview/widget.ts +24 -0
- package/src/modules/eudr/widgets/injection/eudr-product-column/widget.client.tsx +37 -0
- package/src/modules/eudr/widgets/injection/eudr-product-column/widget.ts +30 -0
- package/src/modules/eudr/widgets/injection/order-compliance/widget.client.tsx +131 -0
- package/src/modules/eudr/widgets/injection/order-compliance/widget.ts +16 -0
- package/src/modules/eudr/widgets/injection/supplier-compliance/widget.client.tsx +168 -0
- package/src/modules/eudr/widgets/injection/supplier-compliance/widget.ts +16 -0
- package/src/modules/eudr/widgets/injection-table.ts +31 -0
- package/src/modules/notifications/lib/notificationService.ts +83 -4
- package/src/modules/query_index/lib/engine.ts +139 -51
- package/src/modules/sales/api/documents/factory.ts +29 -0
- package/src/modules/sales/commands/documents.ts +65 -18
- package/src/modules/sales/data/entities.ts +1 -0
- package/src/modules/sales/migrations/.snapshot-open-mercato.json +10 -0
- package/src/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.ts +59 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/eudr/lib/completeness.ts"],
|
|
4
|
+
"sourcesContent": ["import { GEOJSON_TYPES } from '../data/validators'\n\nexport const COMPLETENESS_DIMENSIONS = ['origin_country', 'geolocation', 'quantity', 'harvest_period', 'producer', 'documents'] as const\nexport const REQUIRED_DIMENSIONS = COMPLETENESS_DIMENSIONS\nexport type CompletenessDimension = (typeof COMPLETENESS_DIMENSIONS)[number]\n\nexport type CompletenessInput = {\n originCountry?: string | null\n geolocation?: unknown\n quantityKg?: string | number | null\n harvestFrom?: Date | string | null\n harvestTo?: Date | string | null\n producerName?: string | null\n attachmentIds?: string[] | null\n}\n\nexport type CompletenessContext = {\n linkedAttachmentCount?: number\n activePlotCount?: number\n}\n\nexport type CompletenessResult = { score: number; missingFields: CompletenessDimension[] }\n\nfunction isOriginCountryComplete(value: string | null | undefined): boolean {\n return typeof value === 'string' && /^[A-Za-z]{2}$/.test(value.trim())\n}\n\nfunction isGeolocationComplete(value: unknown): boolean {\n if (value === null || typeof value !== 'object') return false\n const candidate = value as { type?: unknown }\n return typeof candidate.type === 'string' && GEOJSON_TYPES.includes(candidate.type as (typeof GEOJSON_TYPES)[number])\n}\n\nfunction isQuantityComplete(value: string | number | null | undefined): boolean {\n if (typeof value !== 'string' && typeof value !== 'number') return false\n const quantity = Number(value)\n return Number.isFinite(quantity) && quantity > 0\n}\n\nfunction parseDate(value: Date | string | null | undefined): Date | null {\n if (value == null) return null\n const date = value instanceof Date ? value : new Date(value)\n return Number.isNaN(date.getTime()) ? null : date\n}\n\nfunction isHarvestPeriodComplete(harvestFrom: Date | string | null | undefined, harvestTo: Date | string | null | undefined): boolean {\n const parsedHarvestFrom = parseDate(harvestFrom)\n const parsedHarvestTo = parseDate(harvestTo)\n return parsedHarvestFrom !== null && parsedHarvestTo !== null && parsedHarvestFrom <= parsedHarvestTo\n}\n\nfunction isProducerComplete(value: string | null | undefined): boolean {\n return typeof value === 'string' && value.trim().length > 0\n}\n\nfunction isDocumentsComplete(value: string[] | null | undefined): boolean {\n return Array.isArray(value) && value.length >= 1\n}\n\nexport function computeCompleteness(input: CompletenessInput, context: CompletenessContext = {}): CompletenessResult {\n const completionByDimension: Record<CompletenessDimension, boolean> = {\n origin_country: isOriginCountryComplete(input.originCountry),\n geolocation: isGeolocationComplete(input.geolocation) || (context.activePlotCount ?? 0) > 0,\n quantity: isQuantityComplete(input.quantityKg),\n harvest_period: isHarvestPeriodComplete(input.harvestFrom, input.harvestTo),\n producer: isProducerComplete(input.producerName),\n documents: isDocumentsComplete(input.attachmentIds) || (context.linkedAttachmentCount ?? 0) > 0,\n }\n\n const missingFields = COMPLETENESS_DIMENSIONS.filter((dimension) => !completionByDimension[dimension])\n const metCount = COMPLETENESS_DIMENSIONS.length - missingFields.length\n const score = Math.round((metCount / COMPLETENESS_DIMENSIONS.length) * 100)\n\n return { score, missingFields }\n}\n\nexport function computeSubmissionCompleteness(input: CompletenessInput, context?: CompletenessContext): CompletenessResult {\n return computeCompleteness(input, context)\n}\n\nexport const HARVEST_CUTOFF_DATE = new Date('2020-12-31T23:59:59.999Z')\n\nexport function computeHarvestCutoffWarning(\n harvestFrom: Date | string | null | undefined,\n harvestTo: Date | string | null | undefined,\n): 'harvest_before_cutoff' | null {\n const windowEnd = parseDate(harvestTo) ?? parseDate(harvestFrom)\n if (!windowEnd) return null\n return windowEnd.getTime() <= HARVEST_CUTOFF_DATE.getTime() ? 'harvest_before_cutoff' : null\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,qBAAqB;AAEvB,MAAM,0BAA0B,CAAC,kBAAkB,eAAe,YAAY,kBAAkB,YAAY,WAAW;AACvH,MAAM,sBAAsB;AAoBnC,SAAS,wBAAwB,OAA2C;AAC1E,SAAO,OAAO,UAAU,YAAY,gBAAgB,KAAK,MAAM,KAAK,CAAC;AACvE;AAEA,SAAS,sBAAsB,OAAyB;AACtD,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,QAAM,YAAY;AAClB,SAAO,OAAO,UAAU,SAAS,YAAY,cAAc,SAAS,UAAU,IAAsC;AACtH;AAEA,SAAS,mBAAmB,OAAoD;AAC9E,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,SAAU,QAAO;AACnE,QAAM,WAAW,OAAO,KAAK;AAC7B,SAAO,OAAO,SAAS,QAAQ,KAAK,WAAW;AACjD;AAEA,SAAS,UAAU,OAAsD;AACvE,MAAI,SAAS,KAAM,QAAO;AAC1B,QAAM,OAAO,iBAAiB,OAAO,QAAQ,IAAI,KAAK,KAAK;AAC3D,SAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,IAAI,OAAO;AAC/C;AAEA,SAAS,wBAAwB,aAA+C,WAAsD;AACpI,QAAM,oBAAoB,UAAU,WAAW;AAC/C,QAAM,kBAAkB,UAAU,SAAS;AAC3C,SAAO,sBAAsB,QAAQ,oBAAoB,QAAQ,qBAAqB;AACxF;AAEA,SAAS,mBAAmB,OAA2C;AACrE,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS;AAC5D;AAEA,SAAS,oBAAoB,OAA6C;AACxE,SAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,UAAU;AACjD;AAEO,SAAS,oBAAoB,OAA0B,UAA+B,CAAC,GAAuB;AACnH,QAAM,wBAAgE;AAAA,IACpE,gBAAgB,wBAAwB,MAAM,aAAa;AAAA,IAC3D,aAAa,sBAAsB,MAAM,WAAW,MAAM,QAAQ,mBAAmB,KAAK;AAAA,IAC1F,UAAU,mBAAmB,MAAM,UAAU;AAAA,IAC7C,gBAAgB,wBAAwB,MAAM,aAAa,MAAM,SAAS;AAAA,IAC1E,UAAU,mBAAmB,MAAM,YAAY;AAAA,IAC/C,WAAW,oBAAoB,MAAM,aAAa,MAAM,QAAQ,yBAAyB,KAAK;AAAA,EAChG;AAEA,QAAM,gBAAgB,wBAAwB,OAAO,CAAC,cAAc,CAAC,sBAAsB,SAAS,CAAC;AACrG,QAAM,WAAW,wBAAwB,SAAS,cAAc;AAChE,QAAM,QAAQ,KAAK,MAAO,WAAW,wBAAwB,SAAU,GAAG;AAE1E,SAAO,EAAE,OAAO,cAAc;AAChC;AAEO,SAAS,8BAA8B,OAA0B,SAAmD;AACzH,SAAO,oBAAoB,OAAO,OAAO;AAC3C;AAEO,MAAM,sBAAsB,oBAAI,KAAK,0BAA0B;AAE/D,SAAS,4BACd,aACA,WACgC;AAChC,QAAM,YAAY,UAAU,SAAS,KAAK,UAAU,WAAW;AAC/D,MAAI,CAAC,UAAW,QAAO;AACvB,SAAO,UAAU,QAAQ,KAAK,oBAAoB,QAAQ,IAAI,0BAA0B;AAC1F;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
function resolveDetailReadScope(ctx) {
|
|
2
|
+
const tenantId = ctx.auth?.tenantId ?? null;
|
|
3
|
+
if (!tenantId) return null;
|
|
4
|
+
const scopedOrganizationIds = Array.isArray(ctx.organizationIds) && ctx.organizationIds.length ? Array.from(new Set(ctx.organizationIds)) : null;
|
|
5
|
+
const singleOrganizationId = ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null;
|
|
6
|
+
if (!scopedOrganizationIds && !singleOrganizationId) return null;
|
|
7
|
+
return {
|
|
8
|
+
tenantId,
|
|
9
|
+
organizationFilter: scopedOrganizationIds ? { $in: scopedOrganizationIds } : singleOrganizationId,
|
|
10
|
+
decryptionOrganizationId: singleOrganizationId
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
resolveDetailReadScope
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=detail-read-scope.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/eudr/lib/detail-read-scope.ts"],
|
|
4
|
+
"sourcesContent": ["export type DetailReadScope = {\n tenantId: string\n /** Matches the organization scope the list query itself used. */\n organizationFilter: string | { $in: string[] }\n /**\n * Fallback organization for decryption only. `decryptEntitiesWithFallbackScope`\n * prefers each record's own tenant/organization and consults this only when the\n * record carries none, so a single value stays correct for multi-org reads.\n */\n decryptionOrganizationId: string | null\n}\n\ntype DetailReadScopeContext = {\n auth?: { tenantId?: string | null; orgId?: string | null } | null\n organizationIds?: string[] | null\n selectedOrganizationId?: string | null\n}\n\n/**\n * Resolves the scope for an `afterList` detail re-fetch (the decryption pass).\n *\n * The list query is scoped by the full `organizationIds` array, so re-fetching by\n * a single organization silently drops decrypted fields for a multi-org user who\n * has not selected one. Returns null when no scope can be established, so callers\n * fail closed rather than reading across the tenant.\n */\nexport function resolveDetailReadScope(ctx: DetailReadScopeContext): DetailReadScope | null {\n const tenantId = ctx.auth?.tenantId ?? null\n if (!tenantId) return null\n\n const scopedOrganizationIds = Array.isArray(ctx.organizationIds) && ctx.organizationIds.length\n ? Array.from(new Set(ctx.organizationIds))\n : null\n const singleOrganizationId = ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null\n if (!scopedOrganizationIds && !singleOrganizationId) return null\n\n return {\n tenantId,\n organizationFilter: scopedOrganizationIds\n ? { $in: scopedOrganizationIds }\n : (singleOrganizationId as string),\n decryptionOrganizationId: singleOrganizationId,\n }\n}\n"],
|
|
5
|
+
"mappings": "AA0BO,SAAS,uBAAuB,KAAqD;AAC1F,QAAM,WAAW,IAAI,MAAM,YAAY;AACvC,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,wBAAwB,MAAM,QAAQ,IAAI,eAAe,KAAK,IAAI,gBAAgB,SACpF,MAAM,KAAK,IAAI,IAAI,IAAI,eAAe,CAAC,IACvC;AACJ,QAAM,uBAAuB,IAAI,0BAA0B,IAAI,MAAM,SAAS;AAC9E,MAAI,CAAC,yBAAyB,CAAC,qBAAsB,QAAO;AAE5D,SAAO;AAAA,IACL;AAAA,IACA,oBAAoB,wBAChB,EAAE,KAAK,sBAAsB,IAC5B;AAAA,IACL,0BAA0B;AAAA,EAC5B;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
const MAX_GEOMETRY_SIZE = 262144;
|
|
2
|
+
const MAX_IMPORT_SIZE = 1048576;
|
|
3
|
+
const MAX_FEATURE_COLLECTION_FEATURES = 500;
|
|
4
|
+
const EARTH_RADIUS_METERS = 63710088e-1;
|
|
5
|
+
const POINT_MAX_AREA_HA = 4;
|
|
6
|
+
function isRecord(value) {
|
|
7
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
8
|
+
}
|
|
9
|
+
function serializedLength(value) {
|
|
10
|
+
try {
|
|
11
|
+
const serialized = JSON.stringify(value);
|
|
12
|
+
return typeof serialized === "string" ? serialized.length : null;
|
|
13
|
+
} catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function decimalPlaces(value) {
|
|
18
|
+
const decimal = String(value).split(/[eE]/)[0]?.split(".")[1];
|
|
19
|
+
return decimal?.length ?? 0;
|
|
20
|
+
}
|
|
21
|
+
function validatePosition(input) {
|
|
22
|
+
if (!Array.isArray(input) || input.length < 2) return { ok: false, errorKey: "geometryOutOfRange" };
|
|
23
|
+
const [longitude, latitude] = input;
|
|
24
|
+
if (typeof longitude !== "number" || typeof latitude !== "number") return { ok: false, errorKey: "geometryOutOfRange" };
|
|
25
|
+
if (!Number.isFinite(longitude) || !Number.isFinite(latitude)) return { ok: false, errorKey: "geometryOutOfRange" };
|
|
26
|
+
if (longitude < -180 || longitude > 180 || latitude < -90 || latitude > 90) return { ok: false, errorKey: "geometryOutOfRange" };
|
|
27
|
+
return {
|
|
28
|
+
ok: true,
|
|
29
|
+
position: [longitude, latitude],
|
|
30
|
+
lowPrecision: decimalPlaces(longitude) < 6 || decimalPlaces(latitude) < 6
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function positionsEqual(left, right) {
|
|
34
|
+
return left[0] === right[0] && left[1] === right[1];
|
|
35
|
+
}
|
|
36
|
+
function validateRing(input) {
|
|
37
|
+
if (!Array.isArray(input)) return { ok: false, errorKey: "geometryInvalid" };
|
|
38
|
+
if (input.length < 4) return { ok: false, errorKey: "geometryRingNotClosed" };
|
|
39
|
+
const ring = [];
|
|
40
|
+
let lowPrecision = false;
|
|
41
|
+
for (const candidate of input) {
|
|
42
|
+
const result = validatePosition(candidate);
|
|
43
|
+
if (!result.ok) return result;
|
|
44
|
+
ring.push(result.position);
|
|
45
|
+
lowPrecision = lowPrecision || result.lowPrecision;
|
|
46
|
+
}
|
|
47
|
+
if (!positionsEqual(ring[0], ring[ring.length - 1])) return { ok: false, errorKey: "geometryRingNotClosed" };
|
|
48
|
+
return { ok: true, ring, lowPrecision };
|
|
49
|
+
}
|
|
50
|
+
function validatePolygonCoordinates(input) {
|
|
51
|
+
if (!Array.isArray(input) || input.length === 0) return { ok: false, errorKey: "geometryInvalid" };
|
|
52
|
+
const rings = [];
|
|
53
|
+
let lowPrecision = false;
|
|
54
|
+
for (const candidate of input) {
|
|
55
|
+
const result = validateRing(candidate);
|
|
56
|
+
if (!result.ok) return result;
|
|
57
|
+
rings.push(result.ring);
|
|
58
|
+
lowPrecision = lowPrecision || result.lowPrecision;
|
|
59
|
+
}
|
|
60
|
+
return { ok: true, rings, lowPrecision };
|
|
61
|
+
}
|
|
62
|
+
function validateGeometry(input) {
|
|
63
|
+
if (!isRecord(input) || typeof input.type !== "string") return { ok: false, errorKey: "geometryInvalid" };
|
|
64
|
+
if (input.type === "Point") {
|
|
65
|
+
const result = validatePosition(input.coordinates);
|
|
66
|
+
if (!result.ok) return result;
|
|
67
|
+
return { ok: true, geometry: { type: "Point", coordinates: result.position }, lowPrecision: result.lowPrecision };
|
|
68
|
+
}
|
|
69
|
+
if (input.type === "Polygon") {
|
|
70
|
+
const result = validatePolygonCoordinates(input.coordinates);
|
|
71
|
+
if (!result.ok) return result;
|
|
72
|
+
return { ok: true, geometry: { type: "Polygon", coordinates: result.rings }, lowPrecision: result.lowPrecision };
|
|
73
|
+
}
|
|
74
|
+
if (input.type === "MultiPolygon") {
|
|
75
|
+
if (!Array.isArray(input.coordinates) || input.coordinates.length === 0) return { ok: false, errorKey: "geometryInvalid" };
|
|
76
|
+
const polygons = [];
|
|
77
|
+
let lowPrecision = false;
|
|
78
|
+
for (const candidate of input.coordinates) {
|
|
79
|
+
const result = validatePolygonCoordinates(candidate);
|
|
80
|
+
if (!result.ok) return result;
|
|
81
|
+
polygons.push(result.rings);
|
|
82
|
+
lowPrecision = lowPrecision || result.lowPrecision;
|
|
83
|
+
}
|
|
84
|
+
return { ok: true, geometry: { type: "MultiPolygon", coordinates: polygons }, lowPrecision };
|
|
85
|
+
}
|
|
86
|
+
return { ok: false, errorKey: "geometryInvalid" };
|
|
87
|
+
}
|
|
88
|
+
function toRadians(value) {
|
|
89
|
+
return value * Math.PI / 180;
|
|
90
|
+
}
|
|
91
|
+
function ringAreaSquareMeters(ring) {
|
|
92
|
+
let total = 0;
|
|
93
|
+
for (let index = 0; index < ring.length - 1; index += 1) {
|
|
94
|
+
const [longitude1, latitude1] = ring[index];
|
|
95
|
+
const [longitude2, latitude2] = ring[index + 1];
|
|
96
|
+
total += (toRadians(longitude2) - toRadians(longitude1)) * (2 + Math.sin(toRadians(latitude1)) + Math.sin(toRadians(latitude2)));
|
|
97
|
+
}
|
|
98
|
+
return Math.abs(total * EARTH_RADIUS_METERS * EARTH_RADIUS_METERS / 2);
|
|
99
|
+
}
|
|
100
|
+
function polygonAreaSquareMeters(rings) {
|
|
101
|
+
const [exterior, ...holes] = rings;
|
|
102
|
+
const holesArea = holes.reduce((sum, ring) => sum + ringAreaSquareMeters(ring), 0);
|
|
103
|
+
return Math.max(0, ringAreaSquareMeters(exterior) - holesArea);
|
|
104
|
+
}
|
|
105
|
+
function areaHa(geometry) {
|
|
106
|
+
const squareMeters = geometry.type === "Polygon" ? polygonAreaSquareMeters(geometry.coordinates) : geometry.coordinates.reduce((sum, polygon) => sum + polygonAreaSquareMeters(polygon), 0);
|
|
107
|
+
return Math.round(squareMeters / 1e4 * 1e4) / 1e4;
|
|
108
|
+
}
|
|
109
|
+
function validatePlotGeometry(input) {
|
|
110
|
+
const length = serializedLength(input);
|
|
111
|
+
if (length === null) return { ok: false, errorKey: "geometryInvalid" };
|
|
112
|
+
if (length > MAX_GEOMETRY_SIZE) return { ok: false, errorKey: "geometryTooLarge" };
|
|
113
|
+
const isFeature = isRecord(input) && input.type === "Feature";
|
|
114
|
+
const geometryInput = isFeature ? input.geometry : input;
|
|
115
|
+
const properties = isFeature && isRecord(input.properties) ? input.properties : {};
|
|
116
|
+
const result = validateGeometry(geometryInput);
|
|
117
|
+
if (!result.ok) return result;
|
|
118
|
+
const plotType = result.geometry.type === "Point" ? "point" : "polygon";
|
|
119
|
+
return {
|
|
120
|
+
ok: true,
|
|
121
|
+
feature: { type: "Feature", properties, geometry: result.geometry },
|
|
122
|
+
plotType,
|
|
123
|
+
computedAreaHa: result.geometry.type === "Point" ? null : areaHa(result.geometry),
|
|
124
|
+
warnings: result.lowPrecision ? ["low_precision"] : []
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function collectFeatures(featureCollection) {
|
|
128
|
+
const length = serializedLength(featureCollection);
|
|
129
|
+
if (length === null) return { ok: false, errorKey: "geometryInvalid" };
|
|
130
|
+
if (length > MAX_IMPORT_SIZE) return { ok: false, errorKey: "importTooLarge" };
|
|
131
|
+
if (!isRecord(featureCollection) || featureCollection.type !== "FeatureCollection" || !Array.isArray(featureCollection.features)) {
|
|
132
|
+
return { ok: false, errorKey: "geometryInvalid" };
|
|
133
|
+
}
|
|
134
|
+
if (featureCollection.features.length > MAX_FEATURE_COLLECTION_FEATURES) return { ok: false, errorKey: "importTooManyFeatures" };
|
|
135
|
+
return { ok: true, features: featureCollection.features };
|
|
136
|
+
}
|
|
137
|
+
export {
|
|
138
|
+
POINT_MAX_AREA_HA,
|
|
139
|
+
collectFeatures,
|
|
140
|
+
validatePlotGeometry
|
|
141
|
+
};
|
|
142
|
+
//# sourceMappingURL=geometry.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/eudr/lib/geometry.ts"],
|
|
4
|
+
"sourcesContent": ["export type EudrPlotGeometryType = 'point' | 'polygon'\n\ntype GeoJsonPosition = [number, number]\ntype GeoJsonPoint = { type: 'Point'; coordinates: GeoJsonPosition }\ntype GeoJsonPolygon = { type: 'Polygon'; coordinates: GeoJsonPosition[][] }\ntype GeoJsonMultiPolygon = { type: 'MultiPolygon'; coordinates: GeoJsonPosition[][][] }\ntype GeoJsonSupportedGeometry = GeoJsonPoint | GeoJsonPolygon | GeoJsonMultiPolygon\n\nexport type GeoJsonFeature = {\n type: 'Feature'\n properties: Record<string, unknown>\n geometry: GeoJsonSupportedGeometry\n}\n\nexport type GeometryValidationResult =\n | { ok: true; feature: GeoJsonFeature; plotType: EudrPlotGeometryType; computedAreaHa: number | null; warnings: string[] }\n | { ok: false; errorKey: string }\n\ntype PositionValidationResult =\n | { ok: true; position: GeoJsonPosition; lowPrecision: boolean }\n | { ok: false; errorKey: 'geometryOutOfRange' }\n\nconst MAX_GEOMETRY_SIZE = 262_144\nconst MAX_IMPORT_SIZE = 1_048_576\nconst MAX_FEATURE_COLLECTION_FEATURES = 500\nconst EARTH_RADIUS_METERS = 6_371_008.8\n\nexport const POINT_MAX_AREA_HA = 4\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction serializedLength(value: unknown): number | null {\n try {\n const serialized = JSON.stringify(value)\n return typeof serialized === 'string' ? serialized.length : null\n } catch {\n return null\n }\n}\n\nfunction decimalPlaces(value: number): number {\n const decimal = String(value).split(/[eE]/)[0]?.split('.')[1]\n return decimal?.length ?? 0\n}\n\nfunction validatePosition(input: unknown): PositionValidationResult {\n if (!Array.isArray(input) || input.length < 2) return { ok: false, errorKey: 'geometryOutOfRange' }\n const [longitude, latitude] = input\n if (typeof longitude !== 'number' || typeof latitude !== 'number') return { ok: false, errorKey: 'geometryOutOfRange' }\n if (!Number.isFinite(longitude) || !Number.isFinite(latitude)) return { ok: false, errorKey: 'geometryOutOfRange' }\n if (longitude < -180 || longitude > 180 || latitude < -90 || latitude > 90) return { ok: false, errorKey: 'geometryOutOfRange' }\n\n return {\n ok: true,\n position: [longitude, latitude],\n lowPrecision: decimalPlaces(longitude) < 6 || decimalPlaces(latitude) < 6,\n }\n}\n\nfunction positionsEqual(left: GeoJsonPosition, right: GeoJsonPosition): boolean {\n return left[0] === right[0] && left[1] === right[1]\n}\n\nfunction validateRing(input: unknown): { ok: true; ring: GeoJsonPosition[]; lowPrecision: boolean } | { ok: false; errorKey: string } {\n if (!Array.isArray(input)) return { ok: false, errorKey: 'geometryInvalid' }\n if (input.length < 4) return { ok: false, errorKey: 'geometryRingNotClosed' }\n\n const ring: GeoJsonPosition[] = []\n let lowPrecision = false\n for (const candidate of input) {\n const result = validatePosition(candidate)\n if (!result.ok) return result\n ring.push(result.position)\n lowPrecision = lowPrecision || result.lowPrecision\n }\n\n if (!positionsEqual(ring[0], ring[ring.length - 1])) return { ok: false, errorKey: 'geometryRingNotClosed' }\n return { ok: true, ring, lowPrecision }\n}\n\nfunction validatePolygonCoordinates(input: unknown): { ok: true; rings: GeoJsonPosition[][]; lowPrecision: boolean } | { ok: false; errorKey: string } {\n if (!Array.isArray(input) || input.length === 0) return { ok: false, errorKey: 'geometryInvalid' }\n\n const rings: GeoJsonPosition[][] = []\n let lowPrecision = false\n for (const candidate of input) {\n const result = validateRing(candidate)\n if (!result.ok) return result\n rings.push(result.ring)\n lowPrecision = lowPrecision || result.lowPrecision\n }\n\n return { ok: true, rings, lowPrecision }\n}\n\nfunction validateGeometry(input: unknown): { ok: true; geometry: GeoJsonSupportedGeometry; lowPrecision: boolean } | { ok: false; errorKey: string } {\n if (!isRecord(input) || typeof input.type !== 'string') return { ok: false, errorKey: 'geometryInvalid' }\n\n if (input.type === 'Point') {\n const result = validatePosition(input.coordinates)\n if (!result.ok) return result\n return { ok: true, geometry: { type: 'Point', coordinates: result.position }, lowPrecision: result.lowPrecision }\n }\n\n if (input.type === 'Polygon') {\n const result = validatePolygonCoordinates(input.coordinates)\n if (!result.ok) return result\n return { ok: true, geometry: { type: 'Polygon', coordinates: result.rings }, lowPrecision: result.lowPrecision }\n }\n\n if (input.type === 'MultiPolygon') {\n if (!Array.isArray(input.coordinates) || input.coordinates.length === 0) return { ok: false, errorKey: 'geometryInvalid' }\n const polygons: GeoJsonPosition[][][] = []\n let lowPrecision = false\n for (const candidate of input.coordinates) {\n const result = validatePolygonCoordinates(candidate)\n if (!result.ok) return result\n polygons.push(result.rings)\n lowPrecision = lowPrecision || result.lowPrecision\n }\n return { ok: true, geometry: { type: 'MultiPolygon', coordinates: polygons }, lowPrecision }\n }\n\n return { ok: false, errorKey: 'geometryInvalid' }\n}\n\nfunction toRadians(value: number): number {\n return (value * Math.PI) / 180\n}\n\nfunction ringAreaSquareMeters(ring: GeoJsonPosition[]): number {\n let total = 0\n for (let index = 0; index < ring.length - 1; index += 1) {\n const [longitude1, latitude1] = ring[index]\n const [longitude2, latitude2] = ring[index + 1]\n total += (toRadians(longitude2) - toRadians(longitude1)) * (2 + Math.sin(toRadians(latitude1)) + Math.sin(toRadians(latitude2)))\n }\n return Math.abs((total * EARTH_RADIUS_METERS * EARTH_RADIUS_METERS) / 2)\n}\n\nfunction polygonAreaSquareMeters(rings: GeoJsonPosition[][]): number {\n const [exterior, ...holes] = rings\n const holesArea = holes.reduce((sum, ring) => sum + ringAreaSquareMeters(ring), 0)\n return Math.max(0, ringAreaSquareMeters(exterior) - holesArea)\n}\n\nfunction areaHa(geometry: GeoJsonPolygon | GeoJsonMultiPolygon): number {\n // Spherical-excess area is approximate, but is within about 0.5% at normal\n // plot scale and sufficient for the 4-ha EUDR threshold hinting flow.\n const squareMeters = geometry.type === 'Polygon'\n ? polygonAreaSquareMeters(geometry.coordinates)\n : geometry.coordinates.reduce((sum, polygon) => sum + polygonAreaSquareMeters(polygon), 0)\n\n return Math.round((squareMeters / 10_000) * 10_000) / 10_000\n}\n\nexport function validatePlotGeometry(input: unknown): GeometryValidationResult {\n const length = serializedLength(input)\n if (length === null) return { ok: false, errorKey: 'geometryInvalid' }\n if (length > MAX_GEOMETRY_SIZE) return { ok: false, errorKey: 'geometryTooLarge' }\n\n const isFeature = isRecord(input) && input.type === 'Feature'\n const geometryInput = isFeature ? input.geometry : input\n const properties = isFeature && isRecord(input.properties) ? input.properties : {}\n const result = validateGeometry(geometryInput)\n if (!result.ok) return result\n\n const plotType: EudrPlotGeometryType = result.geometry.type === 'Point' ? 'point' : 'polygon'\n return {\n ok: true,\n feature: { type: 'Feature', properties, geometry: result.geometry },\n plotType,\n computedAreaHa: result.geometry.type === 'Point' ? null : areaHa(result.geometry),\n warnings: result.lowPrecision ? ['low_precision'] : [],\n }\n}\n\nexport function collectFeatures(featureCollection: unknown): { ok: true; features: unknown[] } | { ok: false; errorKey: string } {\n const length = serializedLength(featureCollection)\n if (length === null) return { ok: false, errorKey: 'geometryInvalid' }\n if (length > MAX_IMPORT_SIZE) return { ok: false, errorKey: 'importTooLarge' }\n\n if (!isRecord(featureCollection) || featureCollection.type !== 'FeatureCollection' || !Array.isArray(featureCollection.features)) {\n return { ok: false, errorKey: 'geometryInvalid' }\n }\n\n if (featureCollection.features.length > MAX_FEATURE_COLLECTION_FEATURES) return { ok: false, errorKey: 'importTooManyFeatures' }\n return { ok: true, features: featureCollection.features }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
2
|
+
import { buildFeatureNotificationFromType } from "../../notifications/lib/notificationBuilder.js";
|
|
3
|
+
import { resolveNotificationService } from "../../notifications/lib/notificationService.js";
|
|
4
|
+
import { notificationTypes } from "../notifications.js";
|
|
5
|
+
const logger = createLogger("eudr").child({ component: "notifications" });
|
|
6
|
+
const REQUIRED_FEATURE_BY_TYPE = {
|
|
7
|
+
"eudr.statement.submitted": "eudr.statements.manage",
|
|
8
|
+
"eudr.statement.reference_issued": "eudr.statements.manage",
|
|
9
|
+
"eudr.statement.withdrawn": "eudr.statements.manage",
|
|
10
|
+
"eudr.risk.non_negligible": "eudr.risk.manage",
|
|
11
|
+
"eudr.mitigation.completed": "eudr.risk.manage"
|
|
12
|
+
};
|
|
13
|
+
async function deliverEudrNotification({
|
|
14
|
+
container,
|
|
15
|
+
typeId,
|
|
16
|
+
payload
|
|
17
|
+
}) {
|
|
18
|
+
let notificationService;
|
|
19
|
+
try {
|
|
20
|
+
notificationService = resolveNotificationService(container);
|
|
21
|
+
} catch (err) {
|
|
22
|
+
logger.debug("Notification service unavailable; skipping EUDR notification", {
|
|
23
|
+
typeId,
|
|
24
|
+
entityId: payload.entityId,
|
|
25
|
+
err
|
|
26
|
+
});
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const typeDef = notificationTypes.find((candidate) => candidate.type === typeId);
|
|
30
|
+
if (!typeDef) {
|
|
31
|
+
throw new Error(`[internal] EUDR notification type is not registered: ${typeId}`);
|
|
32
|
+
}
|
|
33
|
+
const requiredFeature = REQUIRED_FEATURE_BY_TYPE[typeId];
|
|
34
|
+
const content = buildFeatureNotificationFromType(typeDef, {
|
|
35
|
+
requiredFeature,
|
|
36
|
+
bodyVariables: payload.bodyVariables,
|
|
37
|
+
sourceEntityType: payload.sourceEntityType,
|
|
38
|
+
sourceEntityId: payload.entityId,
|
|
39
|
+
linkHref: payload.linkHref,
|
|
40
|
+
groupKey: `${typeId}:${payload.entityId}:${payload.occurredAt}`
|
|
41
|
+
});
|
|
42
|
+
await notificationService.createForFeature(
|
|
43
|
+
{
|
|
44
|
+
...content,
|
|
45
|
+
restrictRecipientsToOrganization: true
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
tenantId: payload.tenantId,
|
|
49
|
+
organizationId: payload.organizationId
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
deliverEudrNotification
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=notifications.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/eudr/lib/notifications.ts"],
|
|
4
|
+
"sourcesContent": ["import { createLogger } from '@open-mercato/shared/lib/logger'\nimport { buildFeatureNotificationFromType } from '../../notifications/lib/notificationBuilder'\nimport { resolveNotificationService } from '../../notifications/lib/notificationService'\nimport { notificationTypes } from '../notifications'\n\nconst logger = createLogger('eudr').child({ component: 'notifications' })\n\nexport type EudrNotificationTypeId =\n | 'eudr.statement.submitted'\n | 'eudr.statement.reference_issued'\n | 'eudr.statement.withdrawn'\n | 'eudr.risk.non_negligible'\n | 'eudr.mitigation.completed'\n\nexport type EudrNotificationContainer = {\n resolve: (name: string) => unknown\n}\n\ntype EudrNotificationPayload = {\n tenantId: string\n organizationId: string | null\n entityId: string\n occurredAt: string\n bodyVariables: Record<string, string>\n linkHref: string\n sourceEntityType: string\n}\n\ntype DeliverEudrNotificationInput = {\n container: EudrNotificationContainer\n typeId: EudrNotificationTypeId\n payload: EudrNotificationPayload\n}\n\nconst REQUIRED_FEATURE_BY_TYPE: Record<EudrNotificationTypeId, string> = {\n 'eudr.statement.submitted': 'eudr.statements.manage',\n 'eudr.statement.reference_issued': 'eudr.statements.manage',\n 'eudr.statement.withdrawn': 'eudr.statements.manage',\n 'eudr.risk.non_negligible': 'eudr.risk.manage',\n 'eudr.mitigation.completed': 'eudr.risk.manage',\n}\n\nexport async function deliverEudrNotification({\n container,\n typeId,\n payload,\n}: DeliverEudrNotificationInput): Promise<void> {\n let notificationService: ReturnType<typeof resolveNotificationService>\n try {\n notificationService = resolveNotificationService(container)\n } catch (err) {\n logger.debug('Notification service unavailable; skipping EUDR notification', {\n typeId,\n entityId: payload.entityId,\n err,\n })\n return\n }\n\n const typeDef = notificationTypes.find((candidate) => candidate.type === typeId)\n if (!typeDef) {\n throw new Error(`[internal] EUDR notification type is not registered: ${typeId}`)\n }\n\n const requiredFeature = REQUIRED_FEATURE_BY_TYPE[typeId]\n const content = buildFeatureNotificationFromType(typeDef, {\n requiredFeature,\n bodyVariables: payload.bodyVariables,\n sourceEntityType: payload.sourceEntityType,\n sourceEntityId: payload.entityId,\n linkHref: payload.linkHref,\n groupKey: `${typeId}:${payload.entityId}:${payload.occurredAt}`,\n })\n\n await notificationService.createForFeature(\n {\n ...content,\n restrictRecipientsToOrganization: true,\n },\n {\n tenantId: payload.tenantId,\n organizationId: payload.organizationId,\n },\n )\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,wCAAwC;AACjD,SAAS,kCAAkC;AAC3C,SAAS,yBAAyB;AAElC,MAAM,SAAS,aAAa,MAAM,EAAE,MAAM,EAAE,WAAW,gBAAgB,CAAC;AA6BxE,MAAM,2BAAmE;AAAA,EACvE,4BAA4B;AAAA,EAC5B,mCAAmC;AAAA,EACnC,4BAA4B;AAAA,EAC5B,4BAA4B;AAAA,EAC5B,6BAA6B;AAC/B;AAEA,eAAsB,wBAAwB;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AACF,GAAgD;AAC9C,MAAI;AACJ,MAAI;AACF,0BAAsB,2BAA2B,SAAS;AAAA,EAC5D,SAAS,KAAK;AACZ,WAAO,MAAM,gEAAgE;AAAA,MAC3E;AAAA,MACA,UAAU,QAAQ;AAAA,MAClB;AAAA,IACF,CAAC;AACD;AAAA,EACF;AAEA,QAAM,UAAU,kBAAkB,KAAK,CAAC,cAAc,UAAU,SAAS,MAAM;AAC/E,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,wDAAwD,MAAM,EAAE;AAAA,EAClF;AAEA,QAAM,kBAAkB,yBAAyB,MAAM;AACvD,QAAM,UAAU,iCAAiC,SAAS;AAAA,IACxD;AAAA,IACA,eAAe,QAAQ;AAAA,IACvB,kBAAkB,QAAQ;AAAA,IAC1B,gBAAgB,QAAQ;AAAA,IACxB,UAAU,QAAQ;AAAA,IAClB,UAAU,GAAG,MAAM,IAAI,QAAQ,QAAQ,IAAI,QAAQ,UAAU;AAAA,EAC/D,CAAC;AAED,QAAM,oBAAoB;AAAA,IACxB;AAAA,MACE,GAAG;AAAA,MACH,kCAAkC;AAAA,IACpC;AAAA,IACA;AAAA,MACE,UAAU,QAAQ;AAAA,MAClB,gBAAgB,QAAQ;AAAA,IAC1B;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const pluralRulesCache = /* @__PURE__ */ new Map();
|
|
2
|
+
function pluralRulesFor(locale) {
|
|
3
|
+
const cached = pluralRulesCache.get(locale);
|
|
4
|
+
if (cached) return cached;
|
|
5
|
+
let rules;
|
|
6
|
+
try {
|
|
7
|
+
rules = new Intl.PluralRules(locale);
|
|
8
|
+
} catch {
|
|
9
|
+
rules = new Intl.PluralRules("en");
|
|
10
|
+
}
|
|
11
|
+
pluralRulesCache.set(locale, rules);
|
|
12
|
+
return rules;
|
|
13
|
+
}
|
|
14
|
+
function translatePlural(translate, locale, baseKey, count, params) {
|
|
15
|
+
const category = pluralRulesFor(locale).select(count);
|
|
16
|
+
const mergedParams = { count, ...params ?? {} };
|
|
17
|
+
for (const key of [`${baseKey}.${category}`, `${baseKey}.other`, baseKey]) {
|
|
18
|
+
const result = translate(key, mergedParams);
|
|
19
|
+
if (result !== key) return result;
|
|
20
|
+
}
|
|
21
|
+
return translate(baseKey, mergedParams);
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
translatePlural
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=plural.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/eudr/lib/plural.ts"],
|
|
4
|
+
"sourcesContent": ["type Translator = (\n key: string,\n fallbackOrParams?: string | Record<string, string | number>,\n params?: Record<string, string | number>,\n) => string\n\nconst pluralRulesCache = new Map<string, Intl.PluralRules>()\n\nfunction pluralRulesFor(locale: string): Intl.PluralRules {\n const cached = pluralRulesCache.get(locale)\n if (cached) return cached\n let rules: Intl.PluralRules\n try {\n rules = new Intl.PluralRules(locale)\n } catch {\n rules = new Intl.PluralRules('en')\n }\n pluralRulesCache.set(locale, rules)\n return rules\n}\n\nexport function translatePlural(\n translate: Translator,\n locale: string,\n baseKey: string,\n count: number,\n params?: Record<string, string | number>,\n): string {\n const category = pluralRulesFor(locale).select(count)\n const mergedParams = { count, ...(params ?? {}) }\n for (const key of [`${baseKey}.${category}`, `${baseKey}.other`, baseKey]) {\n const result = translate(key, mergedParams)\n if (result !== key) return result\n }\n return translate(baseKey, mergedParams)\n}\n"],
|
|
5
|
+
"mappings": "AAMA,MAAM,mBAAmB,oBAAI,IAA8B;AAE3D,SAAS,eAAe,QAAkC;AACxD,QAAM,SAAS,iBAAiB,IAAI,MAAM;AAC1C,MAAI,OAAQ,QAAO;AACnB,MAAI;AACJ,MAAI;AACF,YAAQ,IAAI,KAAK,YAAY,MAAM;AAAA,EACrC,QAAQ;AACN,YAAQ,IAAI,KAAK,YAAY,IAAI;AAAA,EACnC;AACA,mBAAiB,IAAI,QAAQ,KAAK;AAClC,SAAO;AACT;AAEO,SAAS,gBACd,WACA,QACA,SACA,OACA,QACQ;AACR,QAAM,WAAW,eAAe,MAAM,EAAE,OAAO,KAAK;AACpD,QAAM,eAAe,EAAE,OAAO,GAAI,UAAU,CAAC,EAAG;AAChD,aAAW,OAAO,CAAC,GAAG,OAAO,IAAI,QAAQ,IAAI,GAAG,OAAO,UAAU,OAAO,GAAG;AACzE,UAAM,SAAS,UAAU,KAAK,YAAY;AAC1C,QAAI,WAAW,IAAK,QAAO;AAAA,EAC7B;AACA,SAAO,UAAU,SAAS,YAAY;AACxC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
const EUDR_HIGH_RISK_COUNTRIES = ["BY", "KP", "MM", "RU"];
|
|
2
|
+
const EUDR_LOW_RISK_COUNTRIES = [
|
|
3
|
+
"AD",
|
|
4
|
+
"AE",
|
|
5
|
+
"AF",
|
|
6
|
+
"AG",
|
|
7
|
+
"AL",
|
|
8
|
+
"AM",
|
|
9
|
+
"AT",
|
|
10
|
+
"AU",
|
|
11
|
+
"AZ",
|
|
12
|
+
"BA",
|
|
13
|
+
"BB",
|
|
14
|
+
"BD",
|
|
15
|
+
"BE",
|
|
16
|
+
"BG",
|
|
17
|
+
"BH",
|
|
18
|
+
"BI",
|
|
19
|
+
"BN",
|
|
20
|
+
"BS",
|
|
21
|
+
"BT",
|
|
22
|
+
"CA",
|
|
23
|
+
"CF",
|
|
24
|
+
"CG",
|
|
25
|
+
"CH",
|
|
26
|
+
"CL",
|
|
27
|
+
"CN",
|
|
28
|
+
"CR",
|
|
29
|
+
"CU",
|
|
30
|
+
"CV",
|
|
31
|
+
"CY",
|
|
32
|
+
"CZ",
|
|
33
|
+
"DE",
|
|
34
|
+
"DJ",
|
|
35
|
+
"DK",
|
|
36
|
+
"DM",
|
|
37
|
+
"DO",
|
|
38
|
+
"DZ",
|
|
39
|
+
"EE",
|
|
40
|
+
"EG",
|
|
41
|
+
"ES",
|
|
42
|
+
"FI",
|
|
43
|
+
"FJ",
|
|
44
|
+
"FM",
|
|
45
|
+
"FR",
|
|
46
|
+
"GA",
|
|
47
|
+
"GB",
|
|
48
|
+
"GD",
|
|
49
|
+
"GE",
|
|
50
|
+
"GH",
|
|
51
|
+
"GR",
|
|
52
|
+
"GY",
|
|
53
|
+
"HR",
|
|
54
|
+
"HU",
|
|
55
|
+
"IE",
|
|
56
|
+
"IN",
|
|
57
|
+
"IQ",
|
|
58
|
+
"IR",
|
|
59
|
+
"IS",
|
|
60
|
+
"IT",
|
|
61
|
+
"JM",
|
|
62
|
+
"JO",
|
|
63
|
+
"JP",
|
|
64
|
+
"KE",
|
|
65
|
+
"KG",
|
|
66
|
+
"KI",
|
|
67
|
+
"KM",
|
|
68
|
+
"KN",
|
|
69
|
+
"KR",
|
|
70
|
+
"KW",
|
|
71
|
+
"KZ",
|
|
72
|
+
"LA",
|
|
73
|
+
"LB",
|
|
74
|
+
"LC",
|
|
75
|
+
"LI",
|
|
76
|
+
"LK",
|
|
77
|
+
"LS",
|
|
78
|
+
"LT",
|
|
79
|
+
"LU",
|
|
80
|
+
"LV",
|
|
81
|
+
"LY",
|
|
82
|
+
"MA",
|
|
83
|
+
"MC",
|
|
84
|
+
"MD",
|
|
85
|
+
"ME",
|
|
86
|
+
"MG",
|
|
87
|
+
"MH",
|
|
88
|
+
"MK",
|
|
89
|
+
"ML",
|
|
90
|
+
"MN",
|
|
91
|
+
"MT",
|
|
92
|
+
"MU",
|
|
93
|
+
"MV",
|
|
94
|
+
"NL",
|
|
95
|
+
"NO",
|
|
96
|
+
"NP",
|
|
97
|
+
"NR",
|
|
98
|
+
"NZ",
|
|
99
|
+
"OM",
|
|
100
|
+
"PG",
|
|
101
|
+
"PH",
|
|
102
|
+
"PL",
|
|
103
|
+
"PS",
|
|
104
|
+
"PT",
|
|
105
|
+
"PW",
|
|
106
|
+
"QA",
|
|
107
|
+
"RO",
|
|
108
|
+
"RS",
|
|
109
|
+
"RW",
|
|
110
|
+
"SA",
|
|
111
|
+
"SB",
|
|
112
|
+
"SC",
|
|
113
|
+
"SE",
|
|
114
|
+
"SG",
|
|
115
|
+
"SI",
|
|
116
|
+
"SK",
|
|
117
|
+
"SM",
|
|
118
|
+
"SR",
|
|
119
|
+
"SS",
|
|
120
|
+
"ST",
|
|
121
|
+
"SY",
|
|
122
|
+
"SZ",
|
|
123
|
+
"TG",
|
|
124
|
+
"TH",
|
|
125
|
+
"TJ",
|
|
126
|
+
"TL",
|
|
127
|
+
"TM",
|
|
128
|
+
"TN",
|
|
129
|
+
"TO",
|
|
130
|
+
"TR",
|
|
131
|
+
"TT",
|
|
132
|
+
"TV",
|
|
133
|
+
"UA",
|
|
134
|
+
"UG",
|
|
135
|
+
"US",
|
|
136
|
+
"UY",
|
|
137
|
+
"UZ",
|
|
138
|
+
"VC",
|
|
139
|
+
"VN",
|
|
140
|
+
"VU",
|
|
141
|
+
"WS",
|
|
142
|
+
"YE",
|
|
143
|
+
"ZA"
|
|
144
|
+
];
|
|
145
|
+
function getCountryRiskTier(code) {
|
|
146
|
+
const normalized = code?.trim().toUpperCase() ?? "";
|
|
147
|
+
if (!/^[A-Z]{2}$/.test(normalized)) return "unknown";
|
|
148
|
+
if (EUDR_HIGH_RISK_COUNTRIES.includes(normalized)) return "high";
|
|
149
|
+
if (EUDR_LOW_RISK_COUNTRIES.includes(normalized)) return "low";
|
|
150
|
+
return "standard";
|
|
151
|
+
}
|
|
152
|
+
const EUDR_APPLICATION_DATES = {
|
|
153
|
+
largeAndMedium: "2026-12-30",
|
|
154
|
+
microAndSmallNonTimber: "2027-06-30"
|
|
155
|
+
};
|
|
156
|
+
const EUDR_SUPPLEMENTARY_UNIT_HS_PREFIXES = [
|
|
157
|
+
"4011",
|
|
158
|
+
"4013",
|
|
159
|
+
"4104",
|
|
160
|
+
"4403",
|
|
161
|
+
"4406",
|
|
162
|
+
"4408",
|
|
163
|
+
"4410",
|
|
164
|
+
"4411",
|
|
165
|
+
"4412",
|
|
166
|
+
"4413",
|
|
167
|
+
"4701",
|
|
168
|
+
"4702",
|
|
169
|
+
"4704",
|
|
170
|
+
"4705"
|
|
171
|
+
];
|
|
172
|
+
const EUDR_ANNEX1_HS_PREFIXES = {
|
|
173
|
+
cattle: ["0102", "0201", "0202", "0206", "1602"],
|
|
174
|
+
cocoa: ["1801", "1802", "1803", "1804", "1805", "1806"],
|
|
175
|
+
coffee: ["0901", "2101"],
|
|
176
|
+
oil_palm: ["1511", "1513", "2306", "1207", "3823", "2905"],
|
|
177
|
+
rubber: ["4001", "4005", "4006", "4007", "4008", "4009", "4010", "4011", "4012", "4013", "4015", "4016", "4017"],
|
|
178
|
+
soya: ["1201", "1208", "1507", "2304"],
|
|
179
|
+
wood: [
|
|
180
|
+
"4401",
|
|
181
|
+
"4402",
|
|
182
|
+
"4403",
|
|
183
|
+
"4404",
|
|
184
|
+
"4405",
|
|
185
|
+
"4406",
|
|
186
|
+
"4407",
|
|
187
|
+
"4408",
|
|
188
|
+
"4409",
|
|
189
|
+
"4410",
|
|
190
|
+
"4411",
|
|
191
|
+
"4412",
|
|
192
|
+
"4413",
|
|
193
|
+
"4414",
|
|
194
|
+
"4415",
|
|
195
|
+
"4416",
|
|
196
|
+
"4417",
|
|
197
|
+
"4418",
|
|
198
|
+
"4419",
|
|
199
|
+
"4420",
|
|
200
|
+
"4421",
|
|
201
|
+
"9401",
|
|
202
|
+
"9403",
|
|
203
|
+
"9406",
|
|
204
|
+
"44",
|
|
205
|
+
"47",
|
|
206
|
+
"48"
|
|
207
|
+
]
|
|
208
|
+
};
|
|
209
|
+
function suggestCommodityForHsCode(hsCode) {
|
|
210
|
+
const digits = hsCode?.replace(/\D/g, "") ?? "";
|
|
211
|
+
if (digits.length === 0) return null;
|
|
212
|
+
let match = null;
|
|
213
|
+
for (const [commodity, prefixes] of Object.entries(EUDR_ANNEX1_HS_PREFIXES)) {
|
|
214
|
+
for (const prefix of prefixes) {
|
|
215
|
+
if (!digits.startsWith(prefix)) continue;
|
|
216
|
+
if (match !== null && prefix.length <= match.prefixLength) continue;
|
|
217
|
+
match = { commodity, prefixLength: prefix.length };
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return match?.commodity ?? null;
|
|
221
|
+
}
|
|
222
|
+
const EUDR_RISK_CRITERIA_GROUPS = [
|
|
223
|
+
{ key: "country", criteria: ["deforestation_trend", "environmental_governance", "corruption_land_use"] },
|
|
224
|
+
{ key: "supply_chain", criteria: ["chain_complexity", "intermediaries_count", "mixing_risk", "prior_noncompliance"] },
|
|
225
|
+
{ key: "plot_supplier", criteria: ["land_title_permits", "indigenous_rights", "protected_areas", "labor_human_rights", "plot_deforestation_history"] },
|
|
226
|
+
{ key: "documentation", criteria: ["document_completeness", "document_verifiability", "supplier_transparency"] }
|
|
227
|
+
];
|
|
228
|
+
const EUDR_RISK_CRITERIA_KEYS = EUDR_RISK_CRITERIA_GROUPS.flatMap((group) => [...group.criteria]);
|
|
229
|
+
export {
|
|
230
|
+
EUDR_ANNEX1_HS_PREFIXES,
|
|
231
|
+
EUDR_APPLICATION_DATES,
|
|
232
|
+
EUDR_HIGH_RISK_COUNTRIES,
|
|
233
|
+
EUDR_LOW_RISK_COUNTRIES,
|
|
234
|
+
EUDR_RISK_CRITERIA_GROUPS,
|
|
235
|
+
EUDR_RISK_CRITERIA_KEYS,
|
|
236
|
+
EUDR_SUPPLEMENTARY_UNIT_HS_PREFIXES,
|
|
237
|
+
getCountryRiskTier,
|
|
238
|
+
suggestCommodityForHsCode
|
|
239
|
+
};
|
|
240
|
+
//# sourceMappingURL=reference-data.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/eudr/lib/reference-data.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EudrCommodity } from '../data/validators'\n\n/**\n * EUDR reference data.\n *\n * Source: Commission Implementing Regulation (EU) 2025/1093 country\n * benchmarking (22 May 2025; in force \u2014 the July 2025 EP objection was\n * non-binding \u2014 subject to the Commission's 2026 review), the Commission\n * Green Forum country-classification list (cross-checked against independent\n * reproductions; 141 low-risk + 4 high-risk entries), EUDR application dates,\n * and Annex-I/Appendix-I HS data. Effective as of 2026-07. Keep this file as\n * the single update point when the legal reference data changes. Unlisted\n * countries (~48 standard-risk, e.g. BR, ID, MY, and IL per corroborated\n * sources) default to `standard` so full due diligence remains the\n * conservative fallback. Note: CD (DR Congo) is standard; CG (Congo) is low.\n */\n\nexport type EudrCountryRiskTier = 'low' | 'standard' | 'high' | 'unknown'\n\nexport const EUDR_HIGH_RISK_COUNTRIES = ['BY', 'KP', 'MM', 'RU'] as const\n\nexport const EUDR_LOW_RISK_COUNTRIES = [\n 'AD', 'AE', 'AF', 'AG', 'AL', 'AM', 'AT', 'AU', 'AZ', 'BA', 'BB', 'BD',\n 'BE', 'BG', 'BH', 'BI', 'BN', 'BS', 'BT', 'CA', 'CF', 'CG', 'CH', 'CL',\n 'CN', 'CR', 'CU', 'CV', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM', 'DO', 'DZ',\n 'EE', 'EG', 'ES', 'FI', 'FJ', 'FM', 'FR', 'GA', 'GB', 'GD', 'GE', 'GH',\n 'GR', 'GY', 'HR', 'HU', 'IE', 'IN', 'IQ', 'IR', 'IS', 'IT', 'JM', 'JO',\n 'JP', 'KE', 'KG', 'KI', 'KM', 'KN', 'KR', 'KW', 'KZ', 'LA', 'LB', 'LC',\n 'LI', 'LK', 'LS', 'LT', 'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'ME', 'MG',\n 'MH', 'MK', 'ML', 'MN', 'MT', 'MU', 'MV', 'NL', 'NO', 'NP', 'NR', 'NZ',\n 'OM', 'PG', 'PH', 'PL', 'PS', 'PT', 'PW', 'QA', 'RO', 'RS', 'RW', 'SA',\n 'SB', 'SC', 'SE', 'SG', 'SI', 'SK', 'SM', 'SR', 'SS', 'ST', 'SY', 'SZ',\n 'TG', 'TH', 'TJ', 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV', 'UA', 'UG',\n 'US', 'UY', 'UZ', 'VC', 'VN', 'VU', 'WS', 'YE', 'ZA',\n] as const\n\nexport function getCountryRiskTier(code: string | null | undefined): EudrCountryRiskTier {\n const normalized = code?.trim().toUpperCase() ?? ''\n if (!/^[A-Z]{2}$/.test(normalized)) return 'unknown'\n if ((EUDR_HIGH_RISK_COUNTRIES as readonly string[]).includes(normalized)) return 'high'\n if ((EUDR_LOW_RISK_COUNTRIES as readonly string[]).includes(normalized)) return 'low'\n return 'standard'\n}\n\nexport const EUDR_APPLICATION_DATES = {\n largeAndMedium: '2026-12-30',\n microAndSmallNonTimber: '2027-06-30',\n} as const\n\nexport const EUDR_SUPPLEMENTARY_UNIT_HS_PREFIXES = [\n '4011',\n '4013',\n '4104',\n '4403',\n '4406',\n '4408',\n '4410',\n '4411',\n '4412',\n '4413',\n '4701',\n '4702',\n '4704',\n '4705',\n] as const\n\nexport const EUDR_ANNEX1_HS_PREFIXES: Record<EudrCommodity, readonly string[]> = {\n cattle: ['0102', '0201', '0202', '0206', '1602'],\n cocoa: ['1801', '1802', '1803', '1804', '1805', '1806'],\n coffee: ['0901', '2101'],\n oil_palm: ['1511', '1513', '2306', '1207', '3823', '2905'],\n rubber: ['4001', '4005', '4006', '4007', '4008', '4009', '4010', '4011', '4012', '4013', '4015', '4016', '4017'],\n soya: ['1201', '1208', '1507', '2304'],\n wood: [\n '4401',\n '4402',\n '4403',\n '4404',\n '4405',\n '4406',\n '4407',\n '4408',\n '4409',\n '4410',\n '4411',\n '4412',\n '4413',\n '4414',\n '4415',\n '4416',\n '4417',\n '4418',\n '4419',\n '4420',\n '4421',\n '9401',\n '9403',\n '9406',\n '44',\n '47',\n '48',\n ],\n} as const\n\nexport function suggestCommodityForHsCode(hsCode: string | null | undefined): EudrCommodity | null {\n const digits = hsCode?.replace(/\\D/g, '') ?? ''\n if (digits.length === 0) return null\n\n let match: { commodity: EudrCommodity; prefixLength: number } | null = null\n for (const [commodity, prefixes] of Object.entries(EUDR_ANNEX1_HS_PREFIXES) as Array<[EudrCommodity, readonly string[]]>) {\n for (const prefix of prefixes) {\n if (!digits.startsWith(prefix)) continue\n if (match !== null && prefix.length <= match.prefixLength) continue\n match = { commodity, prefixLength: prefix.length }\n }\n }\n\n return match?.commodity ?? null\n}\n\nexport const EUDR_RISK_CRITERIA_GROUPS = [\n { key: 'country', criteria: ['deforestation_trend', 'environmental_governance', 'corruption_land_use'] },\n { key: 'supply_chain', criteria: ['chain_complexity', 'intermediaries_count', 'mixing_risk', 'prior_noncompliance'] },\n { key: 'plot_supplier', criteria: ['land_title_permits', 'indigenous_rights', 'protected_areas', 'labor_human_rights', 'plot_deforestation_history'] },\n { key: 'documentation', criteria: ['document_completeness', 'document_verifiability', 'supplier_transparency'] },\n] as const\n\nexport const EUDR_RISK_CRITERIA_KEYS: readonly string[] = EUDR_RISK_CRITERIA_GROUPS.flatMap((group) => [...group.criteria])\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const WOOD_COMMODITY = "wood";
|
|
2
|
+
function hasMissingSpecies(mapping) {
|
|
3
|
+
if (mapping.commodity !== WOOD_COMMODITY) return false;
|
|
4
|
+
return !mapping.speciesScientificName?.trim() || !mapping.speciesCommonName?.trim();
|
|
5
|
+
}
|
|
6
|
+
export {
|
|
7
|
+
WOOD_COMMODITY,
|
|
8
|
+
hasMissingSpecies
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=species.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/eudr/lib/species.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EudrCommodity } from '../data/validators'\n\nexport const WOOD_COMMODITY = 'wood' satisfies EudrCommodity\n\nexport function hasMissingSpecies(mapping: {\n commodity: string\n speciesScientificName?: string | null\n speciesCommonName?: string | null\n}): boolean {\n if (mapping.commodity !== WOOD_COMMODITY) return false\n return !mapping.speciesScientificName?.trim() || !mapping.speciesCommonName?.trim()\n}\n"],
|
|
5
|
+
"mappings": "AAEO,MAAM,iBAAiB;AAEvB,SAAS,kBAAkB,SAItB;AACV,MAAI,QAAQ,cAAc,eAAgB,QAAO;AACjD,SAAO,CAAC,QAAQ,uBAAuB,KAAK,KAAK,CAAC,QAAQ,mBAAmB,KAAK;AACpF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|