@baruk/core 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.baruk-provenance.json +4 -4
- package/CHANGELOG.md +42 -0
- package/dist/audit/repository.d.ts +33 -1
- package/dist/audit/repository.d.ts.map +1 -1
- package/dist/audit/repository.js +41 -7
- package/dist/audit/repository.js.map +1 -1
- package/dist/auth/service.d.ts +21 -0
- package/dist/auth/service.d.ts.map +1 -1
- package/dist/auth/service.js +46 -1
- package/dist/auth/service.js.map +1 -1
- package/dist/billing/ar-repository.d.ts +41 -1
- package/dist/billing/ar-repository.d.ts.map +1 -1
- package/dist/billing/ar-repository.js +82 -6
- package/dist/billing/ar-repository.js.map +1 -1
- package/dist/billing/provider-account.d.ts +38 -0
- package/dist/billing/provider-account.d.ts.map +1 -1
- package/dist/billing/provider-account.js +58 -2
- package/dist/billing/provider-account.js.map +1 -1
- package/dist/billing/repository.d.ts +44 -0
- package/dist/billing/repository.d.ts.map +1 -1
- package/dist/billing/repository.js +49 -5
- package/dist/billing/repository.js.map +1 -1
- package/dist/cjs/audit/repository.js +41 -7
- package/dist/cjs/audit/repository.js.map +1 -1
- package/dist/cjs/auth/service.js +46 -1
- package/dist/cjs/auth/service.js.map +1 -1
- package/dist/cjs/billing/ar-repository.js +82 -6
- package/dist/cjs/billing/ar-repository.js.map +1 -1
- package/dist/cjs/billing/provider-account.js +60 -1
- package/dist/cjs/billing/provider-account.js.map +1 -1
- package/dist/cjs/billing/repository.js +51 -5
- package/dist/cjs/billing/repository.js.map +1 -1
- package/dist/cjs/clients/ibge.js +103 -0
- package/dist/cjs/clients/ibge.js.map +1 -0
- package/dist/cjs/clients/repository.js +186 -9
- package/dist/cjs/clients/repository.js.map +1 -1
- package/dist/cjs/collection/branding.js +190 -0
- package/dist/cjs/collection/branding.js.map +1 -1
- package/dist/cjs/collection/clearance-store.js +74 -0
- package/dist/cjs/collection/clearance-store.js.map +1 -0
- package/dist/cjs/collection/communication-runtime.js +65 -2
- package/dist/cjs/collection/communication-runtime.js.map +1 -1
- package/dist/cjs/collection/engine.js +20 -0
- package/dist/cjs/collection/engine.js.map +1 -1
- package/dist/cjs/collection/policy.js +29 -1
- package/dist/cjs/collection/policy.js.map +1 -1
- package/dist/cjs/communication/clearance.js +18 -0
- package/dist/cjs/communication/clearance.js.map +1 -0
- package/dist/cjs/communication/dry-run-scenario.js +5 -0
- package/dist/cjs/communication/dry-run-scenario.js.map +1 -1
- package/dist/cjs/communication/engine.js +12 -0
- package/dist/cjs/communication/engine.js.map +1 -1
- package/dist/cjs/communication/policy.js.map +1 -1
- package/dist/cjs/competence/business-days.js +155 -0
- package/dist/cjs/competence/business-days.js.map +1 -0
- package/dist/cjs/competence/catalog-validation.js +174 -0
- package/dist/cjs/competence/catalog-validation.js.map +1 -0
- package/dist/cjs/competence/obligation-preview.js +190 -0
- package/dist/cjs/competence/obligation-preview.js.map +1 -0
- package/dist/cjs/competence/repository.js +330 -17
- package/dist/cjs/competence/repository.js.map +1 -1
- package/dist/cjs/dashboard/pilot-panel.js +90 -0
- package/dist/cjs/dashboard/pilot-panel.js.map +1 -0
- package/dist/cjs/dashboard/repository.js +11 -1
- package/dist/cjs/dashboard/repository.js.map +1 -1
- package/dist/cjs/db/client.js +17 -11
- package/dist/cjs/db/client.js.map +1 -1
- package/dist/cjs/db/provision-e2e-identity.js +111 -0
- package/dist/cjs/db/provision-e2e-identity.js.map +1 -0
- package/dist/cjs/fiscal/applicability.js +164 -0
- package/dist/cjs/fiscal/applicability.js.map +1 -0
- package/dist/cjs/fiscal/conditions.js +198 -0
- package/dist/cjs/fiscal/conditions.js.map +1 -0
- package/dist/cjs/fiscal/contracts/nfse-adn-contract.js +390 -0
- package/dist/cjs/fiscal/contracts/nfse-adn-contract.js.map +1 -0
- package/dist/cjs/fiscal/contracts/nfse-adn-endpoint.js +108 -0
- package/dist/cjs/fiscal/contracts/nfse-adn-endpoint.js.map +1 -0
- package/dist/cjs/fiscal/contracts/nfse-adn-envelope.js +220 -0
- package/dist/cjs/fiscal/contracts/nfse-adn-envelope.js.map +1 -0
- package/dist/cjs/fiscal/coverage/model.js +127 -0
- package/dist/cjs/fiscal/coverage/model.js.map +1 -0
- package/dist/cjs/fiscal/coverage/requests.js +99 -0
- package/dist/cjs/fiscal/coverage/requests.js.map +1 -0
- package/dist/cjs/fiscal/credentials/material.js +168 -0
- package/dist/cjs/fiscal/credentials/material.js.map +1 -0
- package/dist/cjs/fiscal/credentials/readiness.js +163 -0
- package/dist/cjs/fiscal/credentials/readiness.js.map +1 -0
- package/dist/cjs/fiscal/eligibility.js +199 -0
- package/dist/cjs/fiscal/eligibility.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/__fixtures__/nfse.js +128 -0
- package/dist/cjs/fiscal/ingestion/__fixtures__/nfse.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/adn-transport.js +229 -0
- package/dist/cjs/fiscal/ingestion/adn-transport.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/direction.js +36 -0
- package/dist/cjs/fiscal/ingestion/direction.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/nfse-adn.js +228 -0
- package/dist/cjs/fiscal/ingestion/nfse-adn.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/pipeline.js +704 -0
- package/dist/cjs/fiscal/ingestion/pipeline.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/provider.js +51 -0
- package/dist/cjs/fiscal/ingestion/provider.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/repository.js +132 -0
- package/dist/cjs/fiscal/ingestion/repository.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/synthetic-provider.js +103 -0
- package/dist/cjs/fiscal/ingestion/synthetic-provider.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/synthetic-transport-types.js +13 -0
- package/dist/cjs/fiscal/ingestion/synthetic-transport-types.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/synthetic-transport.js +61 -0
- package/dist/cjs/fiscal/ingestion/synthetic-transport.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/xml-reader.js +121 -0
- package/dist/cjs/fiscal/ingestion/xml-reader.js.map +1 -0
- package/dist/cjs/fiscal/repository.js +470 -0
- package/dist/cjs/fiscal/repository.js.map +1 -0
- package/dist/cjs/fiscal/sync/circuit.js +124 -0
- package/dist/cjs/fiscal/sync/circuit.js.map +1 -0
- package/dist/cjs/fiscal/sync/intervention.js +140 -0
- package/dist/cjs/fiscal/sync/intervention.js.map +1 -0
- package/dist/cjs/fiscal/sync/lease.js +146 -0
- package/dist/cjs/fiscal/sync/lease.js.map +1 -0
- package/dist/cjs/fiscal/sync/observability.js +244 -0
- package/dist/cjs/fiscal/sync/observability.js.map +1 -0
- package/dist/cjs/fiscal/sync/orchestrator.js +490 -0
- package/dist/cjs/fiscal/sync/orchestrator.js.map +1 -0
- package/dist/cjs/fiscal/sync/policy.js +143 -0
- package/dist/cjs/fiscal/sync/policy.js.map +1 -0
- package/dist/cjs/fiscal/sync/reprocess.js +241 -0
- package/dist/cjs/fiscal/sync/reprocess.js.map +1 -0
- package/dist/cjs/fiscal/sync/retry.js +183 -0
- package/dist/cjs/fiscal/sync/retry.js.map +1 -0
- package/dist/cjs/fiscal/sync/secret-boundary.js +123 -0
- package/dist/cjs/fiscal/sync/secret-boundary.js.map +1 -0
- package/dist/cjs/fiscal/transport/https.js +309 -0
- package/dist/cjs/fiscal/transport/https.js.map +1 -0
- package/dist/cjs/fiscal/transport/synthetic-tls.js +328 -0
- package/dist/cjs/fiscal/transport/synthetic-tls.js.map +1 -0
- package/dist/cjs/fiscal/transport/types.js +93 -0
- package/dist/cjs/fiscal/transport/types.js.map +1 -0
- package/dist/cjs/import/br-documents.js +85 -0
- package/dist/cjs/import/br-documents.js.map +1 -0
- package/dist/cjs/import/clients-import.js +347 -40
- package/dist/cjs/import/clients-import.js.map +1 -1
- package/dist/cjs/index.js +316 -11
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/legal/documents.js +100 -15
- package/dist/cjs/legal/documents.js.map +1 -1
- package/dist/cjs/legal/index.js +3 -1
- package/dist/cjs/legal/index.js.map +1 -1
- package/dist/cjs/legal/types.js.map +1 -1
- package/dist/cjs/onboarding/persistence.js +4 -4
- package/dist/cjs/onboarding/persistence.js.map +1 -1
- package/dist/cjs/pilot/go-live-checklist.js +212 -0
- package/dist/cjs/pilot/go-live-checklist.js.map +1 -0
- package/dist/cjs/pilot/milestone.js +79 -0
- package/dist/cjs/pilot/milestone.js.map +1 -0
- package/dist/cjs/platform/capabilities.js +144 -0
- package/dist/cjs/platform/capabilities.js.map +1 -0
- package/dist/cjs/platform/job-contract.js +411 -0
- package/dist/cjs/platform/job-contract.js.map +1 -0
- package/dist/cjs/rbac/catalog.js +34 -0
- package/dist/cjs/rbac/catalog.js.map +1 -1
- package/dist/cjs/subscription-billing/index.js +2 -1
- package/dist/cjs/subscription-billing/index.js.map +1 -1
- package/dist/cjs/subscription-billing/service.js +153 -77
- package/dist/cjs/subscription-billing/service.js.map +1 -1
- package/dist/cjs/tenancy/features.js +131 -0
- package/dist/cjs/tenancy/features.js.map +1 -0
- package/dist/cjs/tenancy/settings.js +224 -0
- package/dist/cjs/tenancy/settings.js.map +1 -0
- package/dist/cjs/users/repository.js +24 -1
- package/dist/cjs/users/repository.js.map +1 -1
- package/dist/clients/ibge.d.ts +17 -0
- package/dist/clients/ibge.d.ts.map +1 -0
- package/dist/clients/ibge.js +98 -0
- package/dist/clients/ibge.js.map +1 -0
- package/dist/clients/repository.d.ts +154 -0
- package/dist/clients/repository.d.ts.map +1 -1
- package/dist/clients/repository.js +182 -9
- package/dist/clients/repository.js.map +1 -1
- package/dist/collection/branding.d.ts +65 -0
- package/dist/collection/branding.d.ts.map +1 -1
- package/dist/collection/branding.js +186 -0
- package/dist/collection/branding.js.map +1 -1
- package/dist/collection/clearance-store.d.ts +39 -0
- package/dist/collection/clearance-store.d.ts.map +1 -0
- package/dist/collection/clearance-store.js +69 -0
- package/dist/collection/clearance-store.js.map +1 -0
- package/dist/collection/communication-runtime.d.ts +37 -0
- package/dist/collection/communication-runtime.d.ts.map +1 -1
- package/dist/collection/communication-runtime.js +63 -1
- package/dist/collection/communication-runtime.js.map +1 -1
- package/dist/collection/engine.d.ts +23 -0
- package/dist/collection/engine.d.ts.map +1 -1
- package/dist/collection/engine.js +20 -0
- package/dist/collection/engine.js.map +1 -1
- package/dist/collection/policy.d.ts +25 -0
- package/dist/collection/policy.d.ts.map +1 -1
- package/dist/collection/policy.js +27 -0
- package/dist/collection/policy.js.map +1 -1
- package/dist/communication/clearance.d.ts +53 -0
- package/dist/communication/clearance.d.ts.map +1 -0
- package/dist/communication/clearance.js +15 -0
- package/dist/communication/clearance.js.map +1 -0
- package/dist/communication/dry-run-scenario.d.ts.map +1 -1
- package/dist/communication/dry-run-scenario.js +5 -0
- package/dist/communication/dry-run-scenario.js.map +1 -1
- package/dist/communication/engine.d.ts +10 -0
- package/dist/communication/engine.d.ts.map +1 -1
- package/dist/communication/engine.js +12 -0
- package/dist/communication/engine.js.map +1 -1
- package/dist/communication/policy.d.ts +16 -0
- package/dist/communication/policy.d.ts.map +1 -1
- package/dist/communication/policy.js.map +1 -1
- package/dist/competence/business-days.d.ts +51 -0
- package/dist/competence/business-days.d.ts.map +1 -0
- package/dist/competence/business-days.js +145 -0
- package/dist/competence/business-days.js.map +1 -0
- package/dist/competence/catalog-validation.d.ts +86 -0
- package/dist/competence/catalog-validation.d.ts.map +1 -0
- package/dist/competence/catalog-validation.js +168 -0
- package/dist/competence/catalog-validation.js.map +1 -0
- package/dist/competence/obligation-preview.d.ts +103 -0
- package/dist/competence/obligation-preview.d.ts.map +1 -0
- package/dist/competence/obligation-preview.js +184 -0
- package/dist/competence/obligation-preview.js.map +1 -0
- package/dist/competence/repository.d.ts +139 -1
- package/dist/competence/repository.d.ts.map +1 -1
- package/dist/competence/repository.js +325 -17
- package/dist/competence/repository.js.map +1 -1
- package/dist/dashboard/pilot-panel.d.ts +100 -0
- package/dist/dashboard/pilot-panel.d.ts.map +1 -0
- package/dist/dashboard/pilot-panel.js +87 -0
- package/dist/dashboard/pilot-panel.js.map +1 -0
- package/dist/dashboard/repository.d.ts.map +1 -1
- package/dist/dashboard/repository.js +11 -1
- package/dist/dashboard/repository.js.map +1 -1
- package/dist/db/client.d.ts +45 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +16 -11
- package/dist/db/client.js.map +1 -1
- package/dist/db/migrate.d.ts +36 -1
- package/dist/db/migrate.d.ts.map +1 -1
- package/dist/db/migrate.js +199 -32
- package/dist/db/migrate.js.map +1 -1
- package/dist/db/provision-e2e-identity.d.ts +2 -0
- package/dist/db/provision-e2e-identity.d.ts.map +1 -0
- package/dist/db/provision-e2e-identity.js +109 -0
- package/dist/db/provision-e2e-identity.js.map +1 -0
- package/dist/fiscal/applicability.d.ts +73 -0
- package/dist/fiscal/applicability.d.ts.map +1 -0
- package/dist/fiscal/applicability.js +160 -0
- package/dist/fiscal/applicability.js.map +1 -0
- package/dist/fiscal/conditions.d.ts +99 -0
- package/dist/fiscal/conditions.d.ts.map +1 -0
- package/dist/fiscal/conditions.js +190 -0
- package/dist/fiscal/conditions.js.map +1 -0
- package/dist/fiscal/contracts/nfse-adn-contract.d.ts +315 -0
- package/dist/fiscal/contracts/nfse-adn-contract.d.ts.map +1 -0
- package/dist/fiscal/contracts/nfse-adn-contract.js +386 -0
- package/dist/fiscal/contracts/nfse-adn-contract.js.map +1 -0
- package/dist/fiscal/contracts/nfse-adn-endpoint.d.ts +13 -0
- package/dist/fiscal/contracts/nfse-adn-endpoint.d.ts.map +1 -0
- package/dist/fiscal/contracts/nfse-adn-endpoint.js +103 -0
- package/dist/fiscal/contracts/nfse-adn-endpoint.js.map +1 -0
- package/dist/fiscal/contracts/nfse-adn-envelope.d.ts +77 -0
- package/dist/fiscal/contracts/nfse-adn-envelope.d.ts.map +1 -0
- package/dist/fiscal/contracts/nfse-adn-envelope.js +215 -0
- package/dist/fiscal/contracts/nfse-adn-envelope.js.map +1 -0
- package/dist/fiscal/coverage/model.d.ts +86 -0
- package/dist/fiscal/coverage/model.d.ts.map +1 -0
- package/dist/fiscal/coverage/model.js +120 -0
- package/dist/fiscal/coverage/model.js.map +1 -0
- package/dist/fiscal/coverage/requests.d.ts +70 -0
- package/dist/fiscal/coverage/requests.d.ts.map +1 -0
- package/dist/fiscal/coverage/requests.js +95 -0
- package/dist/fiscal/coverage/requests.js.map +1 -0
- package/dist/fiscal/credentials/material.d.ts +81 -0
- package/dist/fiscal/credentials/material.d.ts.map +1 -0
- package/dist/fiscal/credentials/material.js +164 -0
- package/dist/fiscal/credentials/material.js.map +1 -0
- package/dist/fiscal/credentials/readiness.d.ts +92 -0
- package/dist/fiscal/credentials/readiness.d.ts.map +1 -0
- package/dist/fiscal/credentials/readiness.js +159 -0
- package/dist/fiscal/credentials/readiness.js.map +1 -0
- package/dist/fiscal/eligibility.d.ts +106 -0
- package/dist/fiscal/eligibility.d.ts.map +1 -0
- package/dist/fiscal/eligibility.js +194 -0
- package/dist/fiscal/eligibility.js.map +1 -0
- package/dist/fiscal/ingestion/__fixtures__/nfse.d.ts +57 -0
- package/dist/fiscal/ingestion/__fixtures__/nfse.d.ts.map +1 -0
- package/dist/fiscal/ingestion/__fixtures__/nfse.js +121 -0
- package/dist/fiscal/ingestion/__fixtures__/nfse.js.map +1 -0
- package/dist/fiscal/ingestion/adn-transport.d.ts +123 -0
- package/dist/fiscal/ingestion/adn-transport.d.ts.map +1 -0
- package/dist/fiscal/ingestion/adn-transport.js +220 -0
- package/dist/fiscal/ingestion/adn-transport.js.map +1 -0
- package/dist/fiscal/ingestion/direction.d.ts +60 -0
- package/dist/fiscal/ingestion/direction.d.ts.map +1 -0
- package/dist/fiscal/ingestion/direction.js +32 -0
- package/dist/fiscal/ingestion/direction.js.map +1 -0
- package/dist/fiscal/ingestion/nfse-adn.d.ts +91 -0
- package/dist/fiscal/ingestion/nfse-adn.d.ts.map +1 -0
- package/dist/fiscal/ingestion/nfse-adn.js +222 -0
- package/dist/fiscal/ingestion/nfse-adn.js.map +1 -0
- package/dist/fiscal/ingestion/pipeline.d.ts +168 -0
- package/dist/fiscal/ingestion/pipeline.d.ts.map +1 -0
- package/dist/fiscal/ingestion/pipeline.js +699 -0
- package/dist/fiscal/ingestion/pipeline.js.map +1 -0
- package/dist/fiscal/ingestion/provider.d.ts +206 -0
- package/dist/fiscal/ingestion/provider.d.ts.map +1 -0
- package/dist/fiscal/ingestion/provider.js +47 -0
- package/dist/fiscal/ingestion/provider.js.map +1 -0
- package/dist/fiscal/ingestion/repository.d.ts +82 -0
- package/dist/fiscal/ingestion/repository.d.ts.map +1 -0
- package/dist/fiscal/ingestion/repository.js +127 -0
- package/dist/fiscal/ingestion/repository.js.map +1 -0
- package/dist/fiscal/ingestion/synthetic-provider.d.ts +92 -0
- package/dist/fiscal/ingestion/synthetic-provider.d.ts.map +1 -0
- package/dist/fiscal/ingestion/synthetic-provider.js +99 -0
- package/dist/fiscal/ingestion/synthetic-provider.js.map +1 -0
- package/dist/fiscal/ingestion/synthetic-transport-types.d.ts +19 -0
- package/dist/fiscal/ingestion/synthetic-transport-types.d.ts.map +1 -0
- package/dist/fiscal/ingestion/synthetic-transport-types.js +9 -0
- package/dist/fiscal/ingestion/synthetic-transport-types.js.map +1 -0
- package/dist/fiscal/ingestion/synthetic-transport.d.ts +55 -0
- package/dist/fiscal/ingestion/synthetic-transport.d.ts.map +1 -0
- package/dist/fiscal/ingestion/synthetic-transport.js +57 -0
- package/dist/fiscal/ingestion/synthetic-transport.js.map +1 -0
- package/dist/fiscal/ingestion/xml-reader.d.ts +55 -0
- package/dist/fiscal/ingestion/xml-reader.d.ts.map +1 -0
- package/dist/fiscal/ingestion/xml-reader.js +112 -0
- package/dist/fiscal/ingestion/xml-reader.js.map +1 -0
- package/dist/fiscal/repository.d.ts +220 -0
- package/dist/fiscal/repository.d.ts.map +1 -0
- package/dist/fiscal/repository.js +449 -0
- package/dist/fiscal/repository.js.map +1 -0
- package/dist/fiscal/sync/circuit.d.ts +86 -0
- package/dist/fiscal/sync/circuit.d.ts.map +1 -0
- package/dist/fiscal/sync/circuit.js +118 -0
- package/dist/fiscal/sync/circuit.js.map +1 -0
- package/dist/fiscal/sync/intervention.d.ts +81 -0
- package/dist/fiscal/sync/intervention.d.ts.map +1 -0
- package/dist/fiscal/sync/intervention.js +135 -0
- package/dist/fiscal/sync/intervention.js.map +1 -0
- package/dist/fiscal/sync/lease.d.ts +118 -0
- package/dist/fiscal/sync/lease.d.ts.map +1 -0
- package/dist/fiscal/sync/lease.js +139 -0
- package/dist/fiscal/sync/lease.js.map +1 -0
- package/dist/fiscal/sync/observability.d.ts +148 -0
- package/dist/fiscal/sync/observability.d.ts.map +1 -0
- package/dist/fiscal/sync/observability.js +239 -0
- package/dist/fiscal/sync/observability.js.map +1 -0
- package/dist/fiscal/sync/orchestrator.d.ts +132 -0
- package/dist/fiscal/sync/orchestrator.d.ts.map +1 -0
- package/dist/fiscal/sync/orchestrator.js +487 -0
- package/dist/fiscal/sync/orchestrator.js.map +1 -0
- package/dist/fiscal/sync/policy.d.ts +87 -0
- package/dist/fiscal/sync/policy.d.ts.map +1 -0
- package/dist/fiscal/sync/policy.js +136 -0
- package/dist/fiscal/sync/policy.js.map +1 -0
- package/dist/fiscal/sync/reprocess.d.ts +76 -0
- package/dist/fiscal/sync/reprocess.d.ts.map +1 -0
- package/dist/fiscal/sync/reprocess.js +237 -0
- package/dist/fiscal/sync/reprocess.js.map +1 -0
- package/dist/fiscal/sync/retry.d.ts +82 -0
- package/dist/fiscal/sync/retry.d.ts.map +1 -0
- package/dist/fiscal/sync/retry.js +176 -0
- package/dist/fiscal/sync/retry.js.map +1 -0
- package/dist/fiscal/sync/secret-boundary.d.ts +169 -0
- package/dist/fiscal/sync/secret-boundary.d.ts.map +1 -0
- package/dist/fiscal/sync/secret-boundary.js +116 -0
- package/dist/fiscal/sync/secret-boundary.js.map +1 -0
- package/dist/fiscal/transport/https.d.ts +86 -0
- package/dist/fiscal/transport/https.d.ts.map +1 -0
- package/dist/fiscal/transport/https.js +303 -0
- package/dist/fiscal/transport/https.js.map +1 -0
- package/dist/fiscal/transport/synthetic-tls.d.ts +80 -0
- package/dist/fiscal/transport/synthetic-tls.d.ts.map +1 -0
- package/dist/fiscal/transport/synthetic-tls.js +323 -0
- package/dist/fiscal/transport/synthetic-tls.js.map +1 -0
- package/dist/fiscal/transport/types.d.ts +134 -0
- package/dist/fiscal/transport/types.d.ts.map +1 -0
- package/dist/fiscal/transport/types.js +88 -0
- package/dist/fiscal/transport/types.js.map +1 -0
- package/dist/import/br-documents.d.ts +26 -0
- package/dist/import/br-documents.d.ts.map +1 -0
- package/dist/import/br-documents.js +78 -0
- package/dist/import/br-documents.js.map +1 -0
- package/dist/import/clients-import.d.ts +122 -4
- package/dist/import/clients-import.d.ts.map +1 -1
- package/dist/import/clients-import.js +341 -41
- package/dist/import/clients-import.js.map +1 -1
- package/dist/index.d.ts +115 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +100 -7
- package/dist/index.js.map +1 -1
- package/dist/legal/documents.d.ts +12 -1
- package/dist/legal/documents.d.ts.map +1 -1
- package/dist/legal/documents.js +98 -14
- package/dist/legal/documents.js.map +1 -1
- package/dist/legal/index.d.ts +1 -1
- package/dist/legal/index.d.ts.map +1 -1
- package/dist/legal/index.js +1 -1
- package/dist/legal/index.js.map +1 -1
- package/dist/legal/types.d.ts +37 -2
- package/dist/legal/types.d.ts.map +1 -1
- package/dist/legal/types.js.map +1 -1
- package/dist/onboarding/persistence.d.ts +10 -1
- package/dist/onboarding/persistence.d.ts.map +1 -1
- package/dist/onboarding/persistence.js +4 -4
- package/dist/onboarding/persistence.js.map +1 -1
- package/dist/pilot/go-live-checklist.d.ts +41 -0
- package/dist/pilot/go-live-checklist.d.ts.map +1 -0
- package/dist/pilot/go-live-checklist.js +209 -0
- package/dist/pilot/go-live-checklist.js.map +1 -0
- package/dist/pilot/milestone.d.ts +56 -0
- package/dist/pilot/milestone.d.ts.map +1 -0
- package/dist/pilot/milestone.js +74 -0
- package/dist/pilot/milestone.js.map +1 -0
- package/dist/platform/capabilities.d.ts +88 -0
- package/dist/platform/capabilities.d.ts.map +1 -0
- package/dist/platform/capabilities.js +140 -0
- package/dist/platform/capabilities.js.map +1 -0
- package/dist/platform/job-contract.d.ts +232 -0
- package/dist/platform/job-contract.d.ts.map +1 -0
- package/dist/platform/job-contract.js +403 -0
- package/dist/platform/job-contract.js.map +1 -0
- package/dist/rbac/catalog.d.ts.map +1 -1
- package/dist/rbac/catalog.js +34 -0
- package/dist/rbac/catalog.js.map +1 -1
- package/dist/subscription-billing/index.d.ts +6 -5
- package/dist/subscription-billing/index.d.ts.map +1 -1
- package/dist/subscription-billing/index.js +3 -3
- package/dist/subscription-billing/index.js.map +1 -1
- package/dist/subscription-billing/service.d.ts +21 -0
- package/dist/subscription-billing/service.d.ts.map +1 -1
- package/dist/subscription-billing/service.js +90 -15
- package/dist/subscription-billing/service.js.map +1 -1
- package/dist/tenancy/features.d.ts +69 -0
- package/dist/tenancy/features.d.ts.map +1 -0
- package/dist/tenancy/features.js +123 -0
- package/dist/tenancy/features.js.map +1 -0
- package/dist/tenancy/settings.d.ts +63 -0
- package/dist/tenancy/settings.d.ts.map +1 -0
- package/dist/tenancy/settings.js +218 -0
- package/dist/tenancy/settings.js.map +1 -0
- package/dist/users/repository.d.ts +16 -1
- package/dist/users/repository.d.ts.map +1 -1
- package/dist/users/repository.js +24 -1
- package/dist/users/repository.js.map +1 -1
- package/package.json +9 -2
- package/src/db/migrations/0045_role_write_scope.sql +122 -0
- package/src/db/migrations/0046_pilot_activation_model.sql +184 -0
- package/src/db/migrations/0047_recipient_clearance.sql +89 -0
- package/src/db/migrations/0048_item_type_note.sql +16 -0
- package/src/db/migrations/0049_national_fiscal_engine.sql +279 -0
- package/src/db/migrations/0050_fiscal_vocabulary_readonly.sql +29 -0
- package/src/db/migrations/0051_seed_rules_from_catalog.sql +72 -0
- package/src/db/migrations/0052_fiscal_rule_delete_scope.sql +57 -0
- package/src/db/migrations/0053_rule_validity_lower_bound.sql +44 -0
- package/src/db/migrations/0054_tenant_profile_and_rule_source.sql +89 -0
- package/src/db/migrations/0055_job_capability_contract.sql +300 -0
- package/src/db/migrations/0056_fiscal_document_ingestion.sql +337 -0
- package/src/db/migrations/0057_fiscal_pending_event_inbox.sql +228 -0
- package/src/db/migrations/0058_fiscal_operational_engine.sql +516 -0
- package/src/db/migrations/0059_fiscal_contract_version.sql +59 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* O transporte, separado do que trafega.
|
|
4
|
+
*
|
|
5
|
+
* ## Por que a fronteira fica exatamente aqui
|
|
6
|
+
*
|
|
7
|
+
* O adapter da NFS-e (`nfse-adn.ts`) recebia um `AdnTransport` cuja assinatura
|
|
8
|
+
* já falava de NSU e de lote — vocabulário FISCAL. Isso funcionou para provar a
|
|
9
|
+
* ingestão, mas amarra duas decisões que mudam por motivos diferentes: como se
|
|
10
|
+
* fala com o servidor (TLS mútuo, timeout, cabeçalho de espera) e o que se pede
|
|
11
|
+
* a ele (NSU, chave de acesso, evento).
|
|
12
|
+
*
|
|
13
|
+
* A prova de que são eixos independentes é o próprio Brasil fiscal: NF-e e CT-e
|
|
14
|
+
* usam SOAP; a NFS-e nacional usa REST; um provedor municipal usaria outra coisa
|
|
15
|
+
* ainda — e os TRÊS apresentam o mesmo certificado ICP-Brasil por TLS mútuo,
|
|
16
|
+
* respeitam a mesma classe de erro de rede e precisam do mesmo teto de espera.
|
|
17
|
+
* Um `if (provedor === 'x')` dentro de um cliente HTTP seria o sintoma da
|
|
18
|
+
* fronteira no lugar errado.
|
|
19
|
+
*
|
|
20
|
+
* Por isso esta camada não conhece NSU, não conhece documento e não conhece
|
|
21
|
+
* cliente. Ela conhece requisição, resposta, prazo e material de TLS.
|
|
22
|
+
*
|
|
23
|
+
* ## O que ela NÃO faz
|
|
24
|
+
*
|
|
25
|
+
* Não retenta. Não classifica erro fiscal. Não decide backoff. Essas decisões
|
|
26
|
+
* dependem do que estava sendo pedido — e um transporte que retentasse sozinho
|
|
27
|
+
* transformaria uma espera obrigatória de uma hora em três requisições, que é o
|
|
28
|
+
* caminho direto para o `cStat 656` e para o CNPJ do cliente bloqueado.
|
|
29
|
+
*/
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
exports.FiscalTransportError = void 0;
|
|
32
|
+
exports.parseRetryAfter = parseRetryAfter;
|
|
33
|
+
/**
|
|
34
|
+
* Falha de transporte.
|
|
35
|
+
*
|
|
36
|
+
* A mensagem é montada por NÓS a partir da classe e de um código curto. O erro
|
|
37
|
+
* original NÃO é encadeado, e isso é deliberado: `Error.message` de TLS cita o
|
|
38
|
+
* caminho do arquivo do certificado e o sujeito do titular, e `err.stack` de um
|
|
39
|
+
* cliente HTTP já carregou a URL inteira com credencial embutida neste
|
|
40
|
+
* ecossistema. Redigir o campo não bastaria — a defesa é não copiar o texto.
|
|
41
|
+
*/
|
|
42
|
+
class FiscalTransportError extends Error {
|
|
43
|
+
errorClass;
|
|
44
|
+
code;
|
|
45
|
+
retryAfter;
|
|
46
|
+
constructor(errorClass,
|
|
47
|
+
/** Código curto e estável (`ETIMEDOUT`, `CERT_HAS_EXPIRED`). Nunca texto livre do sistema. */
|
|
48
|
+
code,
|
|
49
|
+
/** Espera pedida pelo servidor (`Retry-After`), quando houver. */
|
|
50
|
+
retryAfter = null) {
|
|
51
|
+
super(`transporte ${errorClass} (${code})`);
|
|
52
|
+
this.errorClass = errorClass;
|
|
53
|
+
this.code = code;
|
|
54
|
+
this.retryAfter = retryAfter;
|
|
55
|
+
this.name = 'FiscalTransportError';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.FiscalTransportError = FiscalTransportError;
|
|
59
|
+
/**
|
|
60
|
+
* Lê `Retry-After` como a RFC 9110 §10.2.3 o define: segundos OU data HTTP.
|
|
61
|
+
*
|
|
62
|
+
* Existe aqui, e não dentro do cliente HTTP, porque o cabeçalho é a única parte
|
|
63
|
+
* da resposta que o motor de retentativa consulta — e ela precisa ser lida
|
|
64
|
+
* igual venha de onde vier. Valor ausente, negativo ou ilegível devolve `null`:
|
|
65
|
+
* inventar uma espera a partir de lixo é pior do que não ter espera nenhuma,
|
|
66
|
+
* porque a inventada parece autorizada.
|
|
67
|
+
*/
|
|
68
|
+
function parseRetryAfter(raw, now = new Date()) {
|
|
69
|
+
if (!raw)
|
|
70
|
+
return null;
|
|
71
|
+
const trimmed = raw.trim();
|
|
72
|
+
if (trimmed === '')
|
|
73
|
+
return null;
|
|
74
|
+
if (/^\d+$/.test(trimmed)) {
|
|
75
|
+
const seconds = Number(trimmed);
|
|
76
|
+
// Um teto de 24h impede que um cabeçalho absurdo (ou hostil) congele um
|
|
77
|
+
// cliente por semanas. O valor continua sendo do servidor; o teto é nosso.
|
|
78
|
+
if (!Number.isFinite(seconds) || seconds < 0)
|
|
79
|
+
return null;
|
|
80
|
+
const capped = Math.min(seconds, 86_400);
|
|
81
|
+
return new Date(now.getTime() + capped * 1000);
|
|
82
|
+
}
|
|
83
|
+
const asDate = new Date(trimmed);
|
|
84
|
+
if (Number.isNaN(asDate.getTime()))
|
|
85
|
+
return null;
|
|
86
|
+
// Data no passado significa "pode agora". Devolver `null` diz exatamente isso
|
|
87
|
+
// sem obrigar quem chama a comparar de novo.
|
|
88
|
+
if (asDate.getTime() <= now.getTime())
|
|
89
|
+
return null;
|
|
90
|
+
const cap = new Date(now.getTime() + 86_400_000);
|
|
91
|
+
return asDate.getTime() > cap.getTime() ? cap : asDate;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/fiscal/transport/types.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;;;AAiHH,0CAwBC;AA9FD;;;;;;;;GAQG;AACH,MAAa,oBAAqB,SAAQ,KAAK;IAElC;IAEA;IAEA;IALX,YACW,UAAqC;IAC9C,8FAA8F;IACrF,IAAY;IACrB,kEAAkE;IACzD,aAA0B,IAAI;QAEvC,KAAK,CAAC,cAAc,UAAU,KAAK,IAAI,GAAG,CAAC,CAAC;QANnC,eAAU,GAAV,UAAU,CAA2B;QAErC,SAAI,GAAJ,IAAI,CAAQ;QAEZ,eAAU,GAAV,UAAU,CAAoB;QAGvC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAXD,oDAWC;AAyCD;;;;;;;;GAQG;AACH,SAAgB,eAAe,CAC7B,GAA8B,EAC9B,MAAY,IAAI,IAAI,EAAE;IAEtB,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,OAAO,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAEhC,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QAChC,wEAAwE;QACxE,2EAA2E;QAC3E,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACzC,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IAChD,8EAA8E;IAC9E,6CAA6C;IAC7C,IAAI,MAAM,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE;QAAE,OAAO,IAAI,CAAC;IACnD,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,UAAU,CAAC,CAAC;IACjD,OAAO,MAAM,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;AACzD,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CPF e CNPJ — validação por dígito verificador.
|
|
4
|
+
*
|
|
5
|
+
* Contar dígitos não valida documento. `00000000000` tem onze dígitos e não é
|
|
6
|
+
* CPF de ninguém; `11222333000182` tem catorze e não fecha o DV. Num importador
|
|
7
|
+
* de carteira, aceitar por comprimento significa que um erro de digitação vira
|
|
8
|
+
* cliente, e o erro só aparece na primeira cobrança devolvida — quando já há
|
|
9
|
+
* honorário, obrigação e um e-mail enviado ao titular errado.
|
|
10
|
+
*
|
|
11
|
+
* Os dois algoritmos são o módulo 11 oficial da Receita. Ficam no CORE, e não na
|
|
12
|
+
* vertical contábil, pela mesma razão que `client.document_number` está no core:
|
|
13
|
+
* CPF e CNPJ identificam pessoa no Brasil inteiro, não no segmento contábil.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.onlyDigits = void 0;
|
|
17
|
+
exports.isValidCpf = isValidCpf;
|
|
18
|
+
exports.isValidCnpj = isValidCnpj;
|
|
19
|
+
exports.classifyDocument = classifyDocument;
|
|
20
|
+
/** Remove tudo que não é dígito. Aceita máscara, ponto, barra e traço. */
|
|
21
|
+
const onlyDigits = (v) => v.replace(/\D/g, '');
|
|
22
|
+
exports.onlyDigits = onlyDigits;
|
|
23
|
+
function dv(base, pesoInicial) {
|
|
24
|
+
let soma = 0;
|
|
25
|
+
let peso = pesoInicial;
|
|
26
|
+
for (const c of base) {
|
|
27
|
+
soma += Number(c) * peso;
|
|
28
|
+
peso--;
|
|
29
|
+
if (peso < 2)
|
|
30
|
+
peso = 9;
|
|
31
|
+
}
|
|
32
|
+
const resto = soma % 11;
|
|
33
|
+
return resto < 2 ? 0 : 11 - resto;
|
|
34
|
+
}
|
|
35
|
+
function isValidCpf(value) {
|
|
36
|
+
const d = (0, exports.onlyDigits)(value);
|
|
37
|
+
if (d.length !== 11)
|
|
38
|
+
return false;
|
|
39
|
+
// Repetidos passam no módulo 11 por construção — são recusados por regra.
|
|
40
|
+
if (/^(\d)\1{10}$/.test(d))
|
|
41
|
+
return false;
|
|
42
|
+
const base = d.slice(0, 9);
|
|
43
|
+
let soma = 0;
|
|
44
|
+
for (let i = 0; i < 9; i++)
|
|
45
|
+
soma += Number(base[i]) * (10 - i);
|
|
46
|
+
let r = (soma * 10) % 11;
|
|
47
|
+
if (r === 10)
|
|
48
|
+
r = 0;
|
|
49
|
+
if (r !== Number(d[9]))
|
|
50
|
+
return false;
|
|
51
|
+
soma = 0;
|
|
52
|
+
for (let i = 0; i < 10; i++)
|
|
53
|
+
soma += Number(d[i]) * (11 - i);
|
|
54
|
+
r = (soma * 10) % 11;
|
|
55
|
+
if (r === 10)
|
|
56
|
+
r = 0;
|
|
57
|
+
return r === Number(d[10]);
|
|
58
|
+
}
|
|
59
|
+
function isValidCnpj(value) {
|
|
60
|
+
const d = (0, exports.onlyDigits)(value);
|
|
61
|
+
if (d.length !== 14)
|
|
62
|
+
return false;
|
|
63
|
+
if (/^(\d)\1{13}$/.test(d))
|
|
64
|
+
return false;
|
|
65
|
+
const d1 = dv(d.slice(0, 12), 5);
|
|
66
|
+
if (d1 !== Number(d[12]))
|
|
67
|
+
return false;
|
|
68
|
+
const d2 = dv(d.slice(0, 13), 6);
|
|
69
|
+
return d2 === Number(d[13]);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Classifica pelo próprio documento.
|
|
73
|
+
*
|
|
74
|
+
* O comprimento já diz se a linha é pessoa física ou jurídica; uma coluna
|
|
75
|
+
* `tipo` que discorde disso é conflito de dado, não preferência do usuário.
|
|
76
|
+
*/
|
|
77
|
+
function classifyDocument(value) {
|
|
78
|
+
const d = (0, exports.onlyDigits)(value);
|
|
79
|
+
if (d.length === 11)
|
|
80
|
+
return isValidCpf(d) ? 'cpf' : 'invalid';
|
|
81
|
+
if (d.length === 14)
|
|
82
|
+
return isValidCnpj(d) ? 'cnpj' : 'invalid';
|
|
83
|
+
return 'invalid';
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=br-documents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"br-documents.js","sourceRoot":"","sources":["../../../src/import/br-documents.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,23 +1,66 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ImportDigestMismatch = exports.ImportWaveLimitExceeded = exports.CANONICAL_HEADER = void 0;
|
|
4
|
+
exports.canonicalTemplateCsv = canonicalTemplateCsv;
|
|
5
|
+
exports.digestOf = digestOf;
|
|
3
6
|
exports.parseClientsCsv = parseClientsCsv;
|
|
4
7
|
exports.planImport = planImport;
|
|
5
8
|
exports.commitImport = commitImport;
|
|
9
|
+
exports.rollbackImportBatch = rollbackImportBatch;
|
|
10
|
+
exports.listImportBatches = listImportBatches;
|
|
11
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
12
|
const repository_js_1 = require("../clients/repository.js");
|
|
13
|
+
const phone_js_1 = require("../contacts/phone.js");
|
|
14
|
+
const br_documents_js_1 = require("./br-documents.js");
|
|
15
|
+
const shared_1 = require("@baruk/shared");
|
|
7
16
|
const HEADER_ALIASES = {
|
|
8
17
|
nome: 'displayName',
|
|
9
18
|
display_name: 'displayName',
|
|
10
|
-
|
|
19
|
+
nome_fantasia: 'displayName',
|
|
20
|
+
razao_social: 'legalName',
|
|
21
|
+
legal_name: 'legalName',
|
|
11
22
|
documento: 'documentNumber',
|
|
12
23
|
document_number: 'documentNumber',
|
|
13
24
|
cnpj: 'documentNumber',
|
|
14
25
|
cpf: 'documentNumber',
|
|
15
|
-
|
|
16
|
-
|
|
26
|
+
cpf_cnpj: 'documentNumber',
|
|
27
|
+
tipo: 'clientTypeHint',
|
|
28
|
+
client_type: 'clientTypeHint',
|
|
17
29
|
email: 'email',
|
|
30
|
+
'e-mail': 'email',
|
|
18
31
|
telefone: 'phone',
|
|
19
32
|
phone: 'phone',
|
|
33
|
+
celular: 'phone',
|
|
34
|
+
municipio: 'municipality',
|
|
35
|
+
município: 'municipality',
|
|
36
|
+
cidade: 'municipality',
|
|
37
|
+
uf: 'stateUf',
|
|
38
|
+
estado: 'stateUf',
|
|
39
|
+
endereco: 'addressLine',
|
|
40
|
+
endereço: 'addressLine',
|
|
41
|
+
cep: 'postalCode',
|
|
42
|
+
observacoes: 'notes',
|
|
43
|
+
observações: 'notes',
|
|
20
44
|
};
|
|
45
|
+
/** Cabeçalho canônico do template distribuído ao escritório. */
|
|
46
|
+
exports.CANONICAL_HEADER = [
|
|
47
|
+
'nome',
|
|
48
|
+
'razao_social',
|
|
49
|
+
'documento',
|
|
50
|
+
'email',
|
|
51
|
+
'telefone',
|
|
52
|
+
'municipio',
|
|
53
|
+
'uf',
|
|
54
|
+
'endereco',
|
|
55
|
+
'cep',
|
|
56
|
+
'observacoes',
|
|
57
|
+
];
|
|
58
|
+
function canonicalTemplateCsv() {
|
|
59
|
+
return [
|
|
60
|
+
exports.CANONICAL_HEADER.join(','),
|
|
61
|
+
'Padaria Central Ltda,PADARIA CENTRAL LTDA,11.222.333/0001-81,contato@exemplo.com.br,(62) 99988-7766,Goiânia,GO,Rua das Flores 100,74000-000,',
|
|
62
|
+
].join('\n');
|
|
63
|
+
}
|
|
21
64
|
function parseCsvRaw(text) {
|
|
22
65
|
const rows = [];
|
|
23
66
|
let field = '';
|
|
@@ -59,89 +102,353 @@ function parseCsvRaw(text) {
|
|
|
59
102
|
}
|
|
60
103
|
return rows.filter((r) => r.some((cell) => cell.trim() !== ''));
|
|
61
104
|
}
|
|
62
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Aceita o que um e-mail precisa ter para ser endereçável, e nada além.
|
|
107
|
+
*
|
|
108
|
+
* Não é a gramática da RFC 5322 — ela aceita coisas que nenhum provedor entrega
|
|
109
|
+
* e recusá-las cedo é melhor que descobrir no bounce.
|
|
110
|
+
*/
|
|
111
|
+
const EMAIL_RE = /^[^\s@,;]+@[^\s@.,;]+(\.[^\s@.,;]+)+$/;
|
|
112
|
+
function digestOf(text) {
|
|
113
|
+
return (0, node_crypto_1.createHash)('sha256').update(text, 'utf8').digest('hex');
|
|
114
|
+
}
|
|
63
115
|
function parseClientsCsv(text) {
|
|
64
116
|
const raw = parseCsvRaw(text);
|
|
65
117
|
const errors = [];
|
|
118
|
+
const warnings = [];
|
|
66
119
|
if (raw.length === 0)
|
|
67
|
-
return { rows: [], errors: [{ line: 0, message: 'CSV vazio' }] };
|
|
68
|
-
|
|
120
|
+
return { rows: [], errors: [{ line: 0, message: 'CSV vazio' }], warnings };
|
|
121
|
+
// `\uFEFF` escrito como escape, e não como o caractere: um BOM literal no
|
|
122
|
+
// código-fonte é invisível em revisão. Ele aparece de verdade no CSV — todo
|
|
123
|
+
// Excel em português salva com BOM, e sem removê-lo a primeira coluna do
|
|
124
|
+
// cabeçalho nunca casa com nenhum alias.
|
|
125
|
+
const header = raw[0].map((h) => h
|
|
126
|
+
.trim()
|
|
127
|
+
.toLowerCase()
|
|
128
|
+
.replace(/^\uFEFF/, ''));
|
|
69
129
|
const colMap = header.map((h) => HEADER_ALIASES[h]);
|
|
70
130
|
if (!colMap.includes('displayName')) {
|
|
71
|
-
return {
|
|
131
|
+
return {
|
|
132
|
+
rows: [],
|
|
133
|
+
errors: [
|
|
134
|
+
{
|
|
135
|
+
line: 1,
|
|
136
|
+
message: `Cabeçalho sem coluna de nome. Esperado um destes: nome, display_name, nome_fantasia. Recebido: ${header.join(', ')}`,
|
|
137
|
+
field: 'cabecalho',
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
warnings,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
for (const [idx, h] of header.entries()) {
|
|
144
|
+
if (!colMap[idx] && h) {
|
|
145
|
+
warnings.push({ line: 1, message: `Coluna "${h}" não reconhecida e ignorada`, field: h });
|
|
146
|
+
}
|
|
72
147
|
}
|
|
73
148
|
const rows = [];
|
|
74
149
|
for (let i = 1; i < raw.length; i++) {
|
|
75
150
|
const cells = raw[i];
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
rec.clientType = value.toLowerCase() === 'pf' ? 'pf' : 'pj';
|
|
85
|
-
else if (key === 'email')
|
|
86
|
-
rec.email = value || null;
|
|
87
|
-
else if (key === 'phone')
|
|
88
|
-
rec.phone = value || null;
|
|
89
|
-
else if (key === 'displayName')
|
|
90
|
-
rec.displayName = value;
|
|
91
|
-
});
|
|
92
|
-
if (!rec.displayName) {
|
|
93
|
-
errors.push({ line: i + 1, message: 'Nome obrigatório ausente' });
|
|
151
|
+
const line = i + 1;
|
|
152
|
+
const get = (key) => {
|
|
153
|
+
const idx = colMap.indexOf(key);
|
|
154
|
+
return idx >= 0 ? (cells[idx] ?? '').trim() : '';
|
|
155
|
+
};
|
|
156
|
+
const displayName = get('displayName');
|
|
157
|
+
if (!displayName) {
|
|
158
|
+
errors.push({ line, message: 'Nome obrigatório ausente', field: 'nome' });
|
|
94
159
|
continue;
|
|
95
160
|
}
|
|
96
|
-
|
|
97
|
-
|
|
161
|
+
const docRaw = get('documentNumber');
|
|
162
|
+
let documentNumber = null;
|
|
163
|
+
let clientType = null;
|
|
164
|
+
if (docRaw) {
|
|
165
|
+
const kind = (0, br_documents_js_1.classifyDocument)(docRaw);
|
|
166
|
+
if (kind === 'invalid') {
|
|
167
|
+
const d = (0, br_documents_js_1.onlyDigits)(docRaw);
|
|
168
|
+
errors.push({
|
|
169
|
+
line,
|
|
170
|
+
message: d.length === 11 || d.length === 14
|
|
171
|
+
? `Documento com dígito verificador inválido (${docRaw})`
|
|
172
|
+
: `Documento não é CPF nem CNPJ: ${d.length} dígitos`,
|
|
173
|
+
field: 'documento',
|
|
174
|
+
});
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
documentNumber = (0, br_documents_js_1.onlyDigits)(docRaw);
|
|
178
|
+
clientType = kind === 'cpf' ? 'pf' : 'pj';
|
|
179
|
+
}
|
|
180
|
+
// A coluna `tipo` só é consultada quando o documento não decidiu. Quando
|
|
181
|
+
// ambos falam e discordam, isso é conflito de dado: recusar é mais seguro
|
|
182
|
+
// que eleger um vencedor, porque escolher errado grava a pessoa errada.
|
|
183
|
+
const hint = get('clientTypeHint').toLowerCase();
|
|
184
|
+
if (hint === 'pf' || hint === 'pj') {
|
|
185
|
+
if (clientType && clientType !== hint) {
|
|
186
|
+
errors.push({
|
|
187
|
+
line,
|
|
188
|
+
message: `Coluna tipo diz "${hint}" mas o documento é ${clientType === 'pf' ? 'CPF' : 'CNPJ'}`,
|
|
189
|
+
field: 'tipo',
|
|
190
|
+
});
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
clientType ??= hint;
|
|
194
|
+
}
|
|
195
|
+
if (!clientType) {
|
|
196
|
+
clientType = 'pj';
|
|
197
|
+
warnings.push({
|
|
198
|
+
line,
|
|
199
|
+
message: 'Sem documento e sem tipo — assumido PJ',
|
|
200
|
+
field: 'tipo',
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
const email = get('email') || null;
|
|
204
|
+
if (email && !EMAIL_RE.test(email)) {
|
|
205
|
+
errors.push({ line, message: `E-mail malformado: ${email}`, field: 'email' });
|
|
98
206
|
continue;
|
|
99
207
|
}
|
|
208
|
+
if (!email) {
|
|
209
|
+
warnings.push({
|
|
210
|
+
line,
|
|
211
|
+
message: 'Sem e-mail — a automação de cobrança e de pedido de documento não alcança este cliente',
|
|
212
|
+
field: 'email',
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
const phoneRaw = get('phone') || null;
|
|
216
|
+
if (phoneRaw) {
|
|
217
|
+
const p = (0, phone_js_1.parseBrazilPhone)(phoneRaw);
|
|
218
|
+
if (!p.ok) {
|
|
219
|
+
warnings.push({
|
|
220
|
+
line,
|
|
221
|
+
message: `Telefone não discável (${p.reason}) — guardado como texto, sem uso automático`,
|
|
222
|
+
field: 'telefone',
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const ufRaw = get('stateUf') || null;
|
|
227
|
+
const stateUf = (0, repository_js_1.normalizeUf)(ufRaw);
|
|
228
|
+
if (ufRaw && !stateUf) {
|
|
229
|
+
warnings.push({
|
|
230
|
+
line,
|
|
231
|
+
message: `UF "${ufRaw}" fora do formato de duas letras — não gravada`,
|
|
232
|
+
field: 'uf',
|
|
233
|
+
});
|
|
234
|
+
}
|
|
100
235
|
rows.push({
|
|
101
|
-
line
|
|
102
|
-
displayName
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
236
|
+
line,
|
|
237
|
+
displayName,
|
|
238
|
+
legalName: get('legalName') || null,
|
|
239
|
+
documentNumber,
|
|
240
|
+
clientType,
|
|
241
|
+
email,
|
|
242
|
+
phone: phoneRaw,
|
|
243
|
+
municipality: get('municipality') || null,
|
|
244
|
+
stateUf,
|
|
245
|
+
addressLine: get('addressLine') || null,
|
|
246
|
+
postalCode: get('postalCode') || null,
|
|
247
|
+
notes: get('notes') || null,
|
|
107
248
|
});
|
|
108
249
|
}
|
|
109
|
-
return { rows, errors };
|
|
250
|
+
return { rows, errors, warnings };
|
|
110
251
|
}
|
|
111
252
|
async function planImport(tx, text) {
|
|
112
|
-
const { rows, errors } = parseClientsCsv(text);
|
|
253
|
+
const { rows, errors, warnings } = parseClientsCsv(text);
|
|
113
254
|
const toCreate = [];
|
|
114
255
|
const duplicates = [];
|
|
115
256
|
const seen = new Set();
|
|
116
257
|
for (const row of rows) {
|
|
117
258
|
if (row.documentNumber) {
|
|
118
259
|
if (seen.has(row.documentNumber)) {
|
|
119
|
-
duplicates.push({
|
|
260
|
+
duplicates.push({
|
|
261
|
+
line: row.line,
|
|
262
|
+
documentNumber: row.documentNumber,
|
|
263
|
+
reason: 'no_arquivo',
|
|
264
|
+
});
|
|
120
265
|
continue;
|
|
121
266
|
}
|
|
122
267
|
seen.add(row.documentNumber);
|
|
123
268
|
const existing = await (0, repository_js_1.findClientIdByDocument)(tx, row.documentNumber);
|
|
124
269
|
if (existing) {
|
|
125
|
-
duplicates.push({
|
|
270
|
+
duplicates.push({
|
|
271
|
+
line: row.line,
|
|
272
|
+
documentNumber: row.documentNumber,
|
|
273
|
+
reason: 'ja_cadastrado',
|
|
274
|
+
});
|
|
126
275
|
continue;
|
|
127
276
|
}
|
|
128
277
|
}
|
|
129
278
|
toCreate.push(row);
|
|
130
279
|
}
|
|
131
|
-
return {
|
|
280
|
+
return {
|
|
281
|
+
total: rows.length,
|
|
282
|
+
toCreate,
|
|
283
|
+
duplicates,
|
|
284
|
+
errors,
|
|
285
|
+
warnings,
|
|
286
|
+
digest: digestOf(text),
|
|
287
|
+
summary: {
|
|
288
|
+
comEmail: toCreate.filter((r) => r.email).length,
|
|
289
|
+
semEmail: toCreate.filter((r) => !r.email).length,
|
|
290
|
+
comTelefone: toCreate.filter((r) => r.phone).length,
|
|
291
|
+
pf: toCreate.filter((r) => r.clientType === 'pf').length,
|
|
292
|
+
pj: toCreate.filter((r) => r.clientType === 'pj').length,
|
|
293
|
+
comLocalidade: toCreate.filter((r) => r.stateUf && r.municipality).length,
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
class ImportWaveLimitExceeded extends Error {
|
|
298
|
+
planned;
|
|
299
|
+
limit;
|
|
300
|
+
constructor(planned, limit) {
|
|
301
|
+
super(`O plano cria ${planned} cliente(s) e o limite declarado é ${limit}. ` +
|
|
302
|
+
'Nada foi importado. Confira se o arquivo é o esperado ou declare o limite correto.');
|
|
303
|
+
this.planned = planned;
|
|
304
|
+
this.limit = limit;
|
|
305
|
+
this.name = 'ImportWaveLimitExceeded';
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
exports.ImportWaveLimitExceeded = ImportWaveLimitExceeded;
|
|
309
|
+
class ImportDigestMismatch extends Error {
|
|
310
|
+
constructor() {
|
|
311
|
+
super('O conteúdo enviado não confere com o que foi planejado. Refaça a conferência antes de aplicar.');
|
|
312
|
+
this.name = 'ImportDigestMismatch';
|
|
313
|
+
}
|
|
132
314
|
}
|
|
133
|
-
|
|
315
|
+
exports.ImportDigestMismatch = ImportDigestMismatch;
|
|
316
|
+
/**
|
|
317
|
+
* Aplica o plano.
|
|
318
|
+
*
|
|
319
|
+
* `expectedDigest` é obrigatório por desenho: sem ele, o commit poderia aplicar
|
|
320
|
+
* um arquivo que ninguém conferiu. Quem realmente quer pular a conferência passa
|
|
321
|
+
* o digest do próprio conteúdo — e isso fica explícito na chamada, em vez de
|
|
322
|
+
* acontecer por omissão.
|
|
323
|
+
*/
|
|
324
|
+
async function commitImport(tx, text, createdBy, expectedDigest,
|
|
325
|
+
/**
|
|
326
|
+
* Quantos clientes o operador ESPERA criar. Obrigatório, e sem valor padrão.
|
|
327
|
+
*
|
|
328
|
+
* Não existe "sem limite" por omissão, e a ausência de default é a decisão:
|
|
329
|
+
* um teto opcional é um teto que ninguém passa no dia em que importa o
|
|
330
|
+
* arquivo errado. Aqui o compilador obriga a declarar a expectativa antes de
|
|
331
|
+
* escrever, e o importador recusa quando o plano não bate.
|
|
332
|
+
*
|
|
333
|
+
* Isso vale além da Onda 1. O erro que ele pega é o mais banal e o mais caro
|
|
334
|
+
* da importação: apontar para o arquivo da carteira inteira quando se queria
|
|
335
|
+
* uma amostra. Sem o teto, a diferença entre cinco clientes e trezentos é um
|
|
336
|
+
* clique — e o desfazer, embora exista, não recolhe o que a régua de cobrança
|
|
337
|
+
* já tiver alcançado.
|
|
338
|
+
*/
|
|
339
|
+
expectedMax) {
|
|
340
|
+
const digest = digestOf(text);
|
|
341
|
+
if (digest !== expectedDigest)
|
|
342
|
+
throw new ImportDigestMismatch();
|
|
134
343
|
const plan = await planImport(tx, text);
|
|
344
|
+
// ANTES de qualquer escrita: nem o lote é criado se o plano estourar o teto.
|
|
345
|
+
if (plan.toCreate.length > expectedMax) {
|
|
346
|
+
throw new ImportWaveLimitExceeded(plan.toCreate.length, expectedMax);
|
|
347
|
+
}
|
|
348
|
+
const batchId = (0, shared_1.uuidv7)();
|
|
349
|
+
await tx `
|
|
350
|
+
INSERT INTO client_import_batch
|
|
351
|
+
(id, tenant_id, source_digest, row_total, created_count, skipped_count, error_count, created_by)
|
|
352
|
+
VALUES (
|
|
353
|
+
${batchId}, current_setting('app.current_tenant')::uuid, ${digest},
|
|
354
|
+
${plan.total}, 0, ${plan.duplicates.length}, ${plan.errors.length}, ${createdBy ?? null}
|
|
355
|
+
)
|
|
356
|
+
`;
|
|
135
357
|
let created = 0;
|
|
136
358
|
for (const row of plan.toCreate) {
|
|
137
359
|
await (0, repository_js_1.createClient)(tx, {
|
|
138
360
|
displayName: row.displayName,
|
|
361
|
+
legalName: row.legalName,
|
|
139
362
|
clientType: row.clientType,
|
|
140
363
|
documentNumber: row.documentNumber,
|
|
364
|
+
email: row.email,
|
|
365
|
+
phone: row.phone,
|
|
366
|
+
municipality: row.municipality,
|
|
367
|
+
stateUf: row.stateUf,
|
|
368
|
+
addressLine: row.addressLine,
|
|
369
|
+
postalCode: row.postalCode,
|
|
370
|
+
notes: row.notes,
|
|
371
|
+
importBatchId: batchId,
|
|
141
372
|
createdBy: createdBy ?? null,
|
|
142
373
|
});
|
|
143
374
|
created++;
|
|
144
375
|
}
|
|
145
|
-
|
|
376
|
+
await tx `UPDATE client_import_batch SET created_count = ${created} WHERE id = ${batchId}`;
|
|
377
|
+
return {
|
|
378
|
+
batchId,
|
|
379
|
+
created,
|
|
380
|
+
skipped: plan.duplicates.length,
|
|
381
|
+
errors: plan.errors,
|
|
382
|
+
warnings: plan.warnings,
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Desfaz uma importação — logicamente, e só o que ainda é seguro desfazer.
|
|
387
|
+
*
|
|
388
|
+
* Soft-delete, nunca `DELETE`. E não é "desfaz o lote": é "desfaz as linhas do
|
|
389
|
+
* lote que ninguém usou desde então". Um cliente que já recebeu honorário,
|
|
390
|
+
* obrigação, documento ou cobrança deixou de ser uma linha importada — apagá-lo
|
|
391
|
+
* levaria junto trabalho real. Esses ficam, e o relatório diz quais e por quê,
|
|
392
|
+
* em vez de o desfazer falhar inteiro ou apagar demais.
|
|
393
|
+
*/
|
|
394
|
+
async function rollbackImportBatch(tx, batchId, actorId) {
|
|
395
|
+
const [batch] = await tx `
|
|
396
|
+
SELECT id, status FROM client_import_batch WHERE id = ${batchId}
|
|
397
|
+
`;
|
|
398
|
+
if (!batch)
|
|
399
|
+
throw new Error('Lote de importação não encontrado neste escritório.');
|
|
400
|
+
if (batch.status === 'rolled_back')
|
|
401
|
+
return { batchId, reverted: 0, retained: [] };
|
|
402
|
+
const candidatos = await tx `
|
|
403
|
+
SELECT id FROM client WHERE import_batch_id = ${batchId} AND deleted_at IS NULL
|
|
404
|
+
`;
|
|
405
|
+
const retained = [];
|
|
406
|
+
let reverted = 0;
|
|
407
|
+
for (const c of candidatos) {
|
|
408
|
+
const [uso] = await tx `
|
|
409
|
+
SELECT
|
|
410
|
+
(SELECT count(*)::int FROM fee_agreement WHERE client_id = ${c.id} AND deleted_at IS NULL) AS fees,
|
|
411
|
+
(SELECT count(*)::int FROM recurring_instance WHERE client_id = ${c.id} AND deleted_at IS NULL) AS obligations,
|
|
412
|
+
(SELECT count(*)::int FROM document WHERE client_id = ${c.id} AND deleted_at IS NULL) AS docs,
|
|
413
|
+
(SELECT count(*)::int FROM charge WHERE client_id = ${c.id} AND deleted_at IS NULL) AS charges
|
|
414
|
+
`;
|
|
415
|
+
const motivos = [
|
|
416
|
+
(uso?.fees ?? 0) > 0 ? 'honorário' : null,
|
|
417
|
+
(uso?.obligations ?? 0) > 0 ? 'obrigação' : null,
|
|
418
|
+
(uso?.docs ?? 0) > 0 ? 'documento' : null,
|
|
419
|
+
(uso?.charges ?? 0) > 0 ? 'cobrança' : null,
|
|
420
|
+
].filter((m) => m !== null);
|
|
421
|
+
if (motivos.length > 0) {
|
|
422
|
+
retained.push({ clientId: c.id, reason: motivos.join(', ') });
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
await tx `
|
|
426
|
+
UPDATE client SET deleted_at = now(), deleted_by = ${actorId ?? null}, updated_at = now()
|
|
427
|
+
WHERE id = ${c.id} AND deleted_at IS NULL
|
|
428
|
+
`;
|
|
429
|
+
reverted++;
|
|
430
|
+
}
|
|
431
|
+
await tx `
|
|
432
|
+
UPDATE client_import_batch
|
|
433
|
+
SET status = 'rolled_back', rolled_back_at = now(), rolled_back_by = ${actorId ?? null}
|
|
434
|
+
WHERE id = ${batchId}
|
|
435
|
+
`;
|
|
436
|
+
return { batchId, reverted, retained };
|
|
437
|
+
}
|
|
438
|
+
async function listImportBatches(tx) {
|
|
439
|
+
const rows = await tx `
|
|
440
|
+
SELECT id, source_digest, row_total, created_count, skipped_count, error_count, status, created_at
|
|
441
|
+
FROM client_import_batch ORDER BY created_at DESC LIMIT 50
|
|
442
|
+
`;
|
|
443
|
+
return rows.map((r) => ({
|
|
444
|
+
id: r.id,
|
|
445
|
+
sourceDigest: r.source_digest,
|
|
446
|
+
rowTotal: r.row_total,
|
|
447
|
+
createdCount: r.created_count,
|
|
448
|
+
skippedCount: r.skipped_count,
|
|
449
|
+
errorCount: r.error_count,
|
|
450
|
+
status: r.status,
|
|
451
|
+
createdAt: r.created_at.toISOString(),
|
|
452
|
+
}));
|
|
146
453
|
}
|
|
147
454
|
//# sourceMappingURL=clients-import.js.map
|