@baruk/core 0.1.0 → 0.3.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/CHANGELOG.md +59 -0
- package/dist/auth/password-reset.d.ts.map +1 -1
- package/dist/auth/password-reset.js +2 -4
- package/dist/auth/password-reset.js.map +1 -1
- package/dist/auth/password.d.ts +2 -18
- package/dist/auth/password.d.ts.map +1 -1
- package/dist/auth/password.js +12 -51
- package/dist/auth/password.js.map +1 -1
- package/dist/auth/service.d.ts +0 -12
- package/dist/auth/service.d.ts.map +1 -1
- package/dist/auth/service.js +3 -36
- package/dist/auth/service.js.map +1 -1
- package/dist/auth/session-token.d.ts +5 -2
- package/dist/auth/session-token.d.ts.map +1 -1
- package/dist/auth/session-token.js +7 -12
- package/dist/auth/session-token.js.map +1 -1
- package/dist/billing/dunning.d.ts +33 -0
- package/dist/billing/dunning.d.ts.map +1 -0
- package/dist/billing/dunning.js +49 -0
- package/dist/billing/dunning.js.map +1 -0
- package/dist/billing/provider/asaas.d.ts +15 -0
- package/dist/billing/provider/asaas.d.ts.map +1 -0
- package/dist/billing/provider/asaas.js +121 -0
- package/dist/billing/provider/asaas.js.map +1 -0
- package/dist/billing/provider/manual.d.ts +14 -0
- package/dist/billing/provider/manual.d.ts.map +1 -0
- package/dist/billing/provider/manual.js +24 -0
- package/dist/billing/provider/manual.js.map +1 -0
- package/dist/billing/provider/registry.d.ts +12 -0
- package/dist/billing/provider/registry.d.ts.map +1 -0
- package/dist/billing/provider/registry.js +22 -0
- package/dist/billing/provider/registry.js.map +1 -0
- package/dist/billing/provider/types.d.ts +76 -0
- package/dist/billing/provider/types.d.ts.map +1 -0
- package/dist/billing/provider/types.js +9 -0
- package/dist/billing/provider/types.js.map +1 -0
- package/dist/billing/receivable.d.ts +108 -0
- package/dist/billing/receivable.d.ts.map +1 -0
- package/dist/billing/receivable.js +2 -0
- package/dist/billing/receivable.js.map +1 -0
- package/dist/billing/repository.d.ts +97 -0
- package/dist/billing/repository.d.ts.map +1 -0
- package/dist/billing/repository.js +167 -0
- package/dist/billing/repository.js.map +1 -0
- package/dist/cjs/audit/audit.js +31 -0
- package/dist/cjs/audit/audit.js.map +1 -0
- package/dist/cjs/audit/repository.js +32 -0
- package/dist/cjs/audit/repository.js.map +1 -0
- package/dist/cjs/auth/password-reset.js +58 -0
- package/dist/cjs/auth/password-reset.js.map +1 -0
- package/dist/cjs/auth/password.js +32 -0
- package/dist/cjs/auth/password.js.map +1 -0
- package/dist/cjs/auth/service.js +191 -0
- package/dist/cjs/auth/service.js.map +1 -0
- package/dist/cjs/auth/session-token.js +18 -0
- package/dist/cjs/auth/session-token.js.map +1 -0
- package/dist/cjs/billing/dunning.js +54 -0
- package/dist/cjs/billing/dunning.js.map +1 -0
- package/dist/cjs/billing/provider/asaas.js +125 -0
- package/dist/cjs/billing/provider/asaas.js.map +1 -0
- package/dist/cjs/billing/provider/manual.js +28 -0
- package/dist/cjs/billing/provider/manual.js.map +1 -0
- package/dist/cjs/billing/provider/registry.js +27 -0
- package/dist/cjs/billing/provider/registry.js.map +1 -0
- package/dist/cjs/billing/provider/types.js +10 -0
- package/dist/cjs/billing/provider/types.js.map +1 -0
- package/dist/cjs/billing/receivable.js +3 -0
- package/dist/cjs/billing/receivable.js.map +1 -0
- package/dist/cjs/billing/repository.js +180 -0
- package/dist/cjs/billing/repository.js.map +1 -0
- package/dist/cjs/clients/repository.js +123 -0
- package/dist/cjs/clients/repository.js.map +1 -0
- package/dist/cjs/commercial-catalog/catalog.js +108 -0
- package/dist/cjs/commercial-catalog/catalog.js.map +1 -0
- package/dist/cjs/commercial-catalog/consumption-contracts.js +10 -0
- package/dist/cjs/commercial-catalog/consumption-contracts.js.map +1 -0
- package/dist/cjs/commercial-catalog/coupon.js +63 -0
- package/dist/cjs/commercial-catalog/coupon.js.map +1 -0
- package/dist/cjs/commercial-catalog/index.js +16 -0
- package/dist/cjs/commercial-catalog/index.js.map +1 -0
- package/dist/cjs/commercial-catalog/offer-application.js +53 -0
- package/dist/cjs/commercial-catalog/offer-application.js.map +1 -0
- package/dist/cjs/commercial-catalog/types.js +26 -0
- package/dist/cjs/commercial-catalog/types.js.map +1 -0
- package/dist/cjs/crm/repository.js +195 -0
- package/dist/cjs/crm/repository.js.map +1 -0
- package/dist/cjs/dashboard/repository.js +39 -0
- package/dist/cjs/dashboard/repository.js.map +1 -0
- package/dist/cjs/db/client.js +27 -0
- package/dist/cjs/db/client.js.map +1 -0
- package/dist/cjs/db/context.js +43 -0
- package/dist/cjs/db/context.js.map +1 -0
- package/dist/cjs/db/load-env.js +47 -0
- package/dist/cjs/db/load-env.js.map +1 -0
- package/dist/cjs/db/seed.js +69 -0
- package/dist/cjs/db/seed.js.map +1 -0
- package/dist/cjs/entitlements/decision.js +203 -0
- package/dist/cjs/entitlements/decision.js.map +1 -0
- package/dist/cjs/entitlements/derive.js +46 -0
- package/dist/cjs/entitlements/derive.js.map +1 -0
- package/dist/cjs/entitlements/index.js +23 -0
- package/dist/cjs/entitlements/index.js.map +1 -0
- package/dist/cjs/entitlements/sources.js +60 -0
- package/dist/cjs/entitlements/sources.js.map +1 -0
- package/dist/cjs/entitlements/standing.js +42 -0
- package/dist/cjs/entitlements/standing.js.map +1 -0
- package/dist/cjs/entitlements/types.js +16 -0
- package/dist/cjs/entitlements/types.js.map +1 -0
- package/dist/cjs/import/clients-import.js +147 -0
- package/dist/cjs/import/clients-import.js.map +1 -0
- package/dist/cjs/index.js +335 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/mail/dedup-store.js +56 -0
- package/dist/cjs/mail/dedup-store.js.map +1 -0
- package/dist/cjs/mail/index.js +24 -0
- package/dist/cjs/mail/index.js.map +1 -0
- package/dist/cjs/mail/provider.js +251 -0
- package/dist/cjs/mail/provider.js.map +1 -0
- package/dist/cjs/mail/resend-client.js +103 -0
- package/dist/cjs/mail/resend-client.js.map +1 -0
- package/dist/cjs/mail/resend.js +21 -0
- package/dist/cjs/mail/resend.js.map +1 -0
- package/dist/cjs/mail/sanitize.js +56 -0
- package/dist/cjs/mail/sanitize.js.map +1 -0
- package/dist/cjs/mail/sender-resolver.js +15 -0
- package/dist/cjs/mail/sender-resolver.js.map +1 -0
- package/dist/cjs/mail/template-renderer.js +21 -0
- package/dist/cjs/mail/template-renderer.js.map +1 -0
- package/dist/cjs/mail/types.js +38 -0
- package/dist/cjs/mail/types.js.map +1 -0
- package/dist/cjs/notifications/repository.js +49 -0
- package/dist/cjs/notifications/repository.js.map +1 -0
- package/dist/cjs/onboarding/domain.js +370 -0
- package/dist/cjs/onboarding/domain.js.map +1 -0
- package/dist/cjs/onboarding/interaction-review.js +425 -0
- package/dist/cjs/onboarding/interaction-review.js.map +1 -0
- package/dist/cjs/onboarding/persistence.js +444 -0
- package/dist/cjs/onboarding/persistence.js.map +1 -0
- package/dist/cjs/onboarding/portal-actions.js +157 -0
- package/dist/cjs/onboarding/portal-actions.js.map +1 -0
- package/dist/cjs/onboarding/portal.js +177 -0
- package/dist/cjs/onboarding/portal.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/portal/repository.js +37 -0
- package/dist/cjs/portal/repository.js.map +1 -0
- package/dist/cjs/pricing-engine/bundle.js +49 -0
- package/dist/cjs/pricing-engine/bundle.js.map +1 -0
- package/dist/cjs/pricing-engine/errors.js +48 -0
- package/dist/cjs/pricing-engine/errors.js.map +1 -0
- package/dist/cjs/pricing-engine/index.js +30 -0
- package/dist/cjs/pricing-engine/index.js.map +1 -0
- package/dist/cjs/pricing-engine/money.js +69 -0
- package/dist/cjs/pricing-engine/money.js.map +1 -0
- package/dist/cjs/pricing-engine/pipeline.js +330 -0
- package/dist/cjs/pricing-engine/pipeline.js.map +1 -0
- package/dist/cjs/pricing-engine/proration.js +53 -0
- package/dist/cjs/pricing-engine/proration.js.map +1 -0
- package/dist/cjs/pricing-engine/shadow.js +58 -0
- package/dist/cjs/pricing-engine/shadow.js.map +1 -0
- package/dist/cjs/pricing-engine/types.js +34 -0
- package/dist/cjs/pricing-engine/types.js.map +1 -0
- package/dist/cjs/products/catalog.js +10 -0
- package/dist/cjs/products/catalog.js.map +1 -0
- package/dist/cjs/products/repository.js +61 -0
- package/dist/cjs/products/repository.js.map +1 -0
- package/dist/cjs/rbac/authorize.js +36 -0
- package/dist/cjs/rbac/authorize.js.map +1 -0
- package/dist/cjs/rbac/catalog.js +455 -0
- package/dist/cjs/rbac/catalog.js.map +1 -0
- package/dist/cjs/requests/repository.js +114 -0
- package/dist/cjs/requests/repository.js.map +1 -0
- package/dist/cjs/subscription-billing/dunning.js +26 -0
- package/dist/cjs/subscription-billing/dunning.js.map +1 -0
- package/dist/cjs/subscription-billing/events.js +45 -0
- package/dist/cjs/subscription-billing/events.js.map +1 -0
- package/dist/cjs/subscription-billing/index.js +62 -0
- package/dist/cjs/subscription-billing/index.js.map +1 -0
- package/dist/cjs/subscription-billing/plans.js +88 -0
- package/dist/cjs/subscription-billing/plans.js.map +1 -0
- package/dist/cjs/subscription-billing/product-config.js +54 -0
- package/dist/cjs/subscription-billing/product-config.js.map +1 -0
- package/dist/cjs/subscription-billing/provider/asaas.js +233 -0
- package/dist/cjs/subscription-billing/provider/asaas.js.map +1 -0
- package/dist/cjs/subscription-billing/provider/disabled.js +46 -0
- package/dist/cjs/subscription-billing/provider/disabled.js.map +1 -0
- package/dist/cjs/subscription-billing/provider/registry.js +29 -0
- package/dist/cjs/subscription-billing/provider/registry.js.map +1 -0
- package/dist/cjs/subscription-billing/reconcile.js +198 -0
- package/dist/cjs/subscription-billing/reconcile.js.map +1 -0
- package/dist/cjs/subscription-billing/repository.js +359 -0
- package/dist/cjs/subscription-billing/repository.js.map +1 -0
- package/dist/cjs/subscription-billing/service.js +838 -0
- package/dist/cjs/subscription-billing/service.js.map +1 -0
- package/dist/cjs/subscription-billing/types.js +28 -0
- package/dist/cjs/subscription-billing/types.js.map +1 -0
- package/dist/cjs/tenancy/provisioning.js +126 -0
- package/dist/cjs/tenancy/provisioning.js.map +1 -0
- package/dist/cjs/users/repository.js +83 -0
- package/dist/cjs/users/repository.js.map +1 -0
- package/dist/cjs/vault/crypto.js +94 -0
- package/dist/cjs/vault/crypto.js.map +1 -0
- package/dist/cjs/vault/repository.js +120 -0
- package/dist/cjs/vault/repository.js.map +1 -0
- package/dist/commercial-catalog/catalog.d.ts +27 -0
- package/dist/commercial-catalog/catalog.d.ts.map +1 -0
- package/dist/commercial-catalog/catalog.js +104 -0
- package/dist/commercial-catalog/catalog.js.map +1 -0
- package/dist/commercial-catalog/consumption-contracts.d.ts +33 -0
- package/dist/commercial-catalog/consumption-contracts.d.ts.map +1 -0
- package/dist/commercial-catalog/consumption-contracts.js +9 -0
- package/dist/commercial-catalog/consumption-contracts.js.map +1 -0
- package/dist/commercial-catalog/coupon.d.ts +43 -0
- package/dist/commercial-catalog/coupon.d.ts.map +1 -0
- package/dist/commercial-catalog/coupon.js +57 -0
- package/dist/commercial-catalog/coupon.js.map +1 -0
- package/dist/commercial-catalog/index.d.ts +10 -0
- package/dist/commercial-catalog/index.d.ts.map +1 -0
- package/dist/commercial-catalog/index.js +5 -0
- package/dist/commercial-catalog/index.js.map +1 -0
- package/dist/commercial-catalog/offer-application.d.ts +39 -0
- package/dist/commercial-catalog/offer-application.d.ts.map +1 -0
- package/dist/commercial-catalog/offer-application.js +50 -0
- package/dist/commercial-catalog/offer-application.js.map +1 -0
- package/dist/commercial-catalog/types.d.ts +175 -0
- package/dist/commercial-catalog/types.d.ts.map +1 -0
- package/dist/commercial-catalog/types.js +23 -0
- package/dist/commercial-catalog/types.js.map +1 -0
- package/dist/crm/repository.d.ts +109 -0
- package/dist/crm/repository.d.ts.map +1 -0
- package/dist/crm/repository.js +181 -0
- package/dist/crm/repository.js.map +1 -0
- package/dist/db/context.d.ts +2 -0
- package/dist/db/context.d.ts.map +1 -1
- package/dist/db/context.js +3 -0
- package/dist/db/context.js.map +1 -1
- package/dist/db/migrate.js +7 -2
- package/dist/db/migrate.js.map +1 -1
- package/dist/db/seed.js +4 -1
- package/dist/db/seed.js.map +1 -1
- package/dist/entitlements/decision.d.ts +86 -0
- package/dist/entitlements/decision.d.ts.map +1 -0
- package/dist/entitlements/decision.js +196 -0
- package/dist/entitlements/decision.js.map +1 -0
- package/dist/entitlements/derive.d.ts +30 -0
- package/dist/entitlements/derive.d.ts.map +1 -0
- package/dist/entitlements/derive.js +42 -0
- package/dist/entitlements/derive.js.map +1 -0
- package/dist/entitlements/index.d.ts +10 -0
- package/dist/entitlements/index.d.ts.map +1 -0
- package/dist/entitlements/index.js +7 -0
- package/dist/entitlements/index.js.map +1 -0
- package/dist/entitlements/sources.d.ts +30 -0
- package/dist/entitlements/sources.d.ts.map +1 -0
- package/dist/entitlements/sources.js +55 -0
- package/dist/entitlements/sources.js.map +1 -0
- package/dist/entitlements/standing.d.ts +22 -0
- package/dist/entitlements/standing.d.ts.map +1 -0
- package/dist/entitlements/standing.js +38 -0
- package/dist/entitlements/standing.js.map +1 -0
- package/dist/entitlements/types.d.ts +26 -0
- package/dist/entitlements/types.d.ts.map +1 -0
- package/dist/entitlements/types.js +15 -0
- package/dist/entitlements/types.js.map +1 -0
- package/dist/index.d.ts +74 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +51 -4
- package/dist/index.js.map +1 -1
- package/dist/mail/dedup-store.d.ts +25 -0
- package/dist/mail/dedup-store.d.ts.map +1 -0
- package/dist/mail/dedup-store.js +51 -0
- package/dist/mail/dedup-store.js.map +1 -0
- package/dist/mail/index.d.ts +10 -0
- package/dist/mail/index.d.ts.map +1 -0
- package/dist/mail/index.js +9 -0
- package/dist/mail/index.js.map +1 -0
- package/dist/mail/provider.d.ts +31 -0
- package/dist/mail/provider.d.ts.map +1 -0
- package/dist/mail/provider.js +248 -0
- package/dist/mail/provider.js.map +1 -0
- package/dist/mail/resend-client.d.ts +16 -0
- package/dist/mail/resend-client.d.ts.map +1 -0
- package/dist/mail/resend-client.js +100 -0
- package/dist/mail/resend-client.js.map +1 -0
- package/dist/mail/resend.d.ts.map +1 -1
- package/dist/mail/resend.js +2 -0
- package/dist/mail/resend.js.map +1 -1
- package/dist/mail/sanitize.d.ts +17 -0
- package/dist/mail/sanitize.d.ts.map +1 -0
- package/dist/mail/sanitize.js +51 -0
- package/dist/mail/sanitize.js.map +1 -0
- package/dist/mail/sender-resolver.d.ts +8 -0
- package/dist/mail/sender-resolver.d.ts.map +1 -0
- package/dist/mail/sender-resolver.js +11 -0
- package/dist/mail/sender-resolver.js.map +1 -0
- package/dist/mail/template-renderer.d.ts +10 -0
- package/dist/mail/template-renderer.d.ts.map +1 -0
- package/dist/mail/template-renderer.js +17 -0
- package/dist/mail/template-renderer.js.map +1 -0
- package/dist/mail/types.d.ts +143 -0
- package/dist/mail/types.d.ts.map +1 -0
- package/dist/mail/types.js +34 -0
- package/dist/mail/types.js.map +1 -0
- package/dist/onboarding/domain.d.ts +146 -0
- package/dist/onboarding/domain.d.ts.map +1 -0
- package/dist/onboarding/domain.js +348 -0
- package/dist/onboarding/domain.js.map +1 -0
- package/dist/onboarding/interaction-review.d.ts +123 -0
- package/dist/onboarding/interaction-review.d.ts.map +1 -0
- package/dist/onboarding/interaction-review.js +413 -0
- package/dist/onboarding/interaction-review.js.map +1 -0
- package/dist/onboarding/persistence.d.ts +106 -0
- package/dist/onboarding/persistence.d.ts.map +1 -0
- package/dist/onboarding/persistence.js +430 -0
- package/dist/onboarding/persistence.js.map +1 -0
- package/dist/onboarding/portal-actions.d.ts +48 -0
- package/dist/onboarding/portal-actions.d.ts.map +1 -0
- package/dist/onboarding/portal-actions.js +153 -0
- package/dist/onboarding/portal-actions.js.map +1 -0
- package/dist/onboarding/portal.d.ts +58 -0
- package/dist/onboarding/portal.d.ts.map +1 -0
- package/dist/onboarding/portal.js +170 -0
- package/dist/onboarding/portal.js.map +1 -0
- package/dist/pricing-engine/bundle.d.ts +22 -0
- package/dist/pricing-engine/bundle.d.ts.map +1 -0
- package/dist/pricing-engine/bundle.js +44 -0
- package/dist/pricing-engine/bundle.js.map +1 -0
- package/dist/pricing-engine/errors.d.ts +32 -0
- package/dist/pricing-engine/errors.d.ts.map +1 -0
- package/dist/pricing-engine/errors.js +44 -0
- package/dist/pricing-engine/errors.js.map +1 -0
- package/dist/pricing-engine/index.d.ts +12 -0
- package/dist/pricing-engine/index.d.ts.map +1 -0
- package/dist/pricing-engine/index.js +8 -0
- package/dist/pricing-engine/index.js.map +1 -0
- package/dist/pricing-engine/money.d.ts +32 -0
- package/dist/pricing-engine/money.d.ts.map +1 -0
- package/dist/pricing-engine/money.js +58 -0
- package/dist/pricing-engine/money.js.map +1 -0
- package/dist/pricing-engine/pipeline.d.ts +3 -0
- package/dist/pricing-engine/pipeline.d.ts.map +1 -0
- package/dist/pricing-engine/pipeline.js +327 -0
- package/dist/pricing-engine/pipeline.js.map +1 -0
- package/dist/pricing-engine/proration.d.ts +3 -0
- package/dist/pricing-engine/proration.d.ts.map +1 -0
- package/dist/pricing-engine/proration.js +50 -0
- package/dist/pricing-engine/proration.js.map +1 -0
- package/dist/pricing-engine/shadow.d.ts +51 -0
- package/dist/pricing-engine/shadow.d.ts.map +1 -0
- package/dist/pricing-engine/shadow.js +54 -0
- package/dist/pricing-engine/shadow.js.map +1 -0
- package/dist/pricing-engine/types.d.ts +184 -0
- package/dist/pricing-engine/types.d.ts.map +1 -0
- package/dist/pricing-engine/types.js +31 -0
- package/dist/pricing-engine/types.js.map +1 -0
- package/dist/rbac/authorize.d.ts +3 -6
- package/dist/rbac/authorize.d.ts.map +1 -1
- package/dist/rbac/authorize.js +4 -8
- package/dist/rbac/authorize.js.map +1 -1
- package/dist/rbac/catalog.d.ts.map +1 -1
- package/dist/rbac/catalog.js +414 -21
- package/dist/rbac/catalog.js.map +1 -1
- package/dist/subscription-billing/dunning.d.ts +18 -0
- package/dist/subscription-billing/dunning.d.ts.map +1 -0
- package/dist/subscription-billing/dunning.js +28 -0
- package/dist/subscription-billing/dunning.js.map +1 -0
- package/dist/subscription-billing/events.d.ts +58 -0
- package/dist/subscription-billing/events.d.ts.map +1 -0
- package/dist/subscription-billing/events.js +38 -0
- package/dist/subscription-billing/events.js.map +1 -0
- package/dist/subscription-billing/index.d.ts +18 -0
- package/dist/subscription-billing/index.d.ts.map +1 -0
- package/dist/subscription-billing/index.js +16 -0
- package/dist/subscription-billing/index.js.map +1 -0
- package/dist/subscription-billing/plans.d.ts +34 -0
- package/dist/subscription-billing/plans.d.ts.map +1 -0
- package/dist/subscription-billing/plans.js +85 -0
- package/dist/subscription-billing/plans.js.map +1 -0
- package/dist/subscription-billing/product-config.d.ts +61 -0
- package/dist/subscription-billing/product-config.d.ts.map +1 -0
- package/dist/subscription-billing/product-config.js +50 -0
- package/dist/subscription-billing/product-config.js.map +1 -0
- package/dist/subscription-billing/provider/asaas.d.ts +26 -0
- package/dist/subscription-billing/provider/asaas.d.ts.map +1 -0
- package/dist/subscription-billing/provider/asaas.js +229 -0
- package/dist/subscription-billing/provider/asaas.js.map +1 -0
- package/dist/subscription-billing/provider/disabled.d.ts +30 -0
- package/dist/subscription-billing/provider/disabled.d.ts.map +1 -0
- package/dist/subscription-billing/provider/disabled.js +42 -0
- package/dist/subscription-billing/provider/disabled.js.map +1 -0
- package/dist/subscription-billing/provider/registry.d.ts +10 -0
- package/dist/subscription-billing/provider/registry.d.ts.map +1 -0
- package/dist/subscription-billing/provider/registry.js +26 -0
- package/dist/subscription-billing/provider/registry.js.map +1 -0
- package/dist/subscription-billing/reconcile.d.ts +45 -0
- package/dist/subscription-billing/reconcile.d.ts.map +1 -0
- package/dist/subscription-billing/reconcile.js +192 -0
- package/dist/subscription-billing/reconcile.js.map +1 -0
- package/dist/subscription-billing/repository.d.ts +168 -0
- package/dist/subscription-billing/repository.d.ts.map +1 -0
- package/dist/subscription-billing/repository.js +336 -0
- package/dist/subscription-billing/repository.js.map +1 -0
- package/dist/subscription-billing/service.d.ts +175 -0
- package/dist/subscription-billing/service.d.ts.map +1 -0
- package/dist/subscription-billing/service.js +818 -0
- package/dist/subscription-billing/service.js.map +1 -0
- package/dist/subscription-billing/types.d.ts +161 -0
- package/dist/subscription-billing/types.d.ts.map +1 -0
- package/dist/subscription-billing/types.js +24 -0
- package/dist/subscription-billing/types.js.map +1 -0
- package/dist/vault/crypto.d.ts +22 -0
- package/dist/vault/crypto.d.ts.map +1 -0
- package/dist/vault/crypto.js +88 -0
- package/dist/vault/crypto.js.map +1 -0
- package/dist/vault/repository.d.ts +45 -0
- package/dist/vault/repository.d.ts.map +1 -0
- package/dist/vault/repository.js +111 -0
- package/dist/vault/repository.js.map +1 -0
- package/package.json +23 -13
- package/src/db/migrations/0012_vault.sql +51 -0
- package/src/db/migrations/0013_crm.sql +67 -0
- package/src/db/migrations/0014_billing.sql +146 -0
- package/src/db/migrations/0015_merchant_billing_ar.sql +201 -0
- package/src/db/migrations/0016_office_onboarding.sql +162 -0
- package/src/db/migrations/0017_office_onboarding_api.sql +21 -0
- package/src/db/migrations/0018_office_onboarding_portal_actions.sql +60 -0
- package/src/db/migrations/0019_office_onboarding_interaction_review.sql +134 -0
- package/src/db/migrations/0020_saas_billing.sql +157 -0
- package/src/db/migrations/0021_saas_billing_indexes.sql +23 -0
- package/src/db/migrations/0022_saas_billing_multi_product.sql +75 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.computePricingQuote = computePricingQuote;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const money_js_1 = require("./money.js");
|
|
6
|
+
const errors_js_1 = require("./errors.js");
|
|
7
|
+
const bundle_js_1 = require("./bundle.js");
|
|
8
|
+
const types_js_1 = require("./types.js");
|
|
9
|
+
/**
|
|
10
|
+
* Pipeline determinístico do Pricing Engine (RFC-CAPABILITY-PRICING-ENGINE-001
|
|
11
|
+
* §8, ETAPA 5). A ordem abaixo é a ORDEM OFICIAL DA RFC (não a restatada na
|
|
12
|
+
* ETAPA 5 do prompt de implementação, que diverge em 2 pontos — ver
|
|
13
|
+
* correspondência documentada em RFC-CAPABILITY-PRICING-ENGINE-001 §8 e no
|
|
14
|
+
* relatório de entrega): 1.plano 2.módulo 3.quantidade 4.add-on 5.bundle
|
|
15
|
+
* 6.desconto negociado (percentual, cumulativo) 7.cupom 8.campanha
|
|
16
|
+
* 9.crédito promocional (reservado) 10.contrato negociado/grandfathering
|
|
17
|
+
* (FIXA/SOBREPÕE) 11.impostos 12.arredondamento.
|
|
18
|
+
*
|
|
19
|
+
* Cada etapa 5-8 opera SEQUENCIALMENTE sobre o total corrente ("sobre o
|
|
20
|
+
* resultado até aqui", RFC §8 passo 7) — não sobre a base original — porque
|
|
21
|
+
* a ordem já é fixa e explícita (a RFC elimina ambiguidade por ORDEM, não por
|
|
22
|
+
* uma base comum). Erros de contrato são sempre RETORNADOS
|
|
23
|
+
* (`EngineResult`), nunca lançados na fronteira pública (RFC §2/§7) —
|
|
24
|
+
* internamente usamos `throw PricingEngineError` e capturamos em
|
|
25
|
+
* `computePricingQuote`.
|
|
26
|
+
*/
|
|
27
|
+
function fingerprintOf(request) {
|
|
28
|
+
const basis = {
|
|
29
|
+
tenantId: request.tenantId,
|
|
30
|
+
productLine: request.productLine,
|
|
31
|
+
offerCode: request.offer.code,
|
|
32
|
+
planCode: request.plan.code,
|
|
33
|
+
moduleCodes: [...request.offer.moduleCodes].sort(),
|
|
34
|
+
bundleCodes: [...request.offer.bundleCodes].sort(),
|
|
35
|
+
addonCodes: [...request.offer.addonCodes].sort(),
|
|
36
|
+
priceTableCode: request.priceTable.code,
|
|
37
|
+
priceTableVersion: request.priceTable.version,
|
|
38
|
+
billingCycle: request.billingCycle,
|
|
39
|
+
extraSeats: request.extraSeats ?? 0,
|
|
40
|
+
addonQuantities: request.addonQuantities ?? {},
|
|
41
|
+
couponCode: request.coupon?.code ?? null,
|
|
42
|
+
campaignCode: request.campaign?.code ?? null,
|
|
43
|
+
negotiatedContractTenantId: request.negotiatedContract?.tenantId ?? null,
|
|
44
|
+
negotiatedDiscountPercent: request.negotiatedContract?.discountPercent ?? null,
|
|
45
|
+
negotiatedFixedTotalCents: request.negotiatedContract?.fixedTotalCents ?? null,
|
|
46
|
+
trialActive: request.trial?.active ?? false,
|
|
47
|
+
now: request.now,
|
|
48
|
+
};
|
|
49
|
+
return (0, node_crypto_1.createHash)('sha256').update(JSON.stringify(basis)).digest('hex');
|
|
50
|
+
}
|
|
51
|
+
function catalogFingerprint(plan, modules, bundles) {
|
|
52
|
+
const basis = {
|
|
53
|
+
plan: { code: plan.code, tier: plan.tier, franchises: plan.franchises },
|
|
54
|
+
modules: modules.map((m) => ({ code: m.code, class: m.class })).sort((a, b) => a.code.localeCompare(b.code)),
|
|
55
|
+
bundles: bundles
|
|
56
|
+
.map((b) => ({ code: b.code, moduleCodes: [...b.moduleCodes].sort() }))
|
|
57
|
+
.sort((a, b) => a.code.localeCompare(b.code)),
|
|
58
|
+
};
|
|
59
|
+
return (0, node_crypto_1.createHash)('sha256').update(JSON.stringify(basis)).digest('hex');
|
|
60
|
+
}
|
|
61
|
+
function addHours(iso, hours) {
|
|
62
|
+
const d = /^\d{4}-\d{2}-\d{2}$/.test(iso) ? new Date(`${iso}T00:00:00Z`) : new Date(iso);
|
|
63
|
+
d.setUTCHours(d.getUTCHours() + hours);
|
|
64
|
+
return d.toISOString();
|
|
65
|
+
}
|
|
66
|
+
function itemOf(origin, targetCode, quantity, unitPriceCents, subtotalCents) {
|
|
67
|
+
return { origin, targetCode, quantity, unitPriceCents, subtotalCents: subtotalCents ?? unitPriceCents * quantity };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Busca o preço por `targetType`+`targetCode` **filtrado pelo `billingCycle`**
|
|
71
|
+
* (mensal/anual) — o mesmo `targetCode` pode ter duas entradas na tabela
|
|
72
|
+
* (`interval: 'monthly'` e `interval: 'yearly'`), e ignorar `interval` faria
|
|
73
|
+
* o lookup pegar a primeira entrada arbitrária (bug real corrigido antes dos
|
|
74
|
+
* cenários Rep/Ind da ETAPA 12, que exigem cotação mensal E anual).
|
|
75
|
+
*/
|
|
76
|
+
function findPriceItemReais(table, targetType, targetCode, billingCycle) {
|
|
77
|
+
const item = table.items.find((i) => i.targetType === targetType && i.targetCode === targetCode && i.interval === billingCycle);
|
|
78
|
+
if (!item) {
|
|
79
|
+
throw new errors_js_1.PricingEngineError('price-rule-missing', `Sem preço para ${targetType}:${targetCode} (ciclo=${billingCycle}) na tabela "${table.code}" v${table.version}.`);
|
|
80
|
+
}
|
|
81
|
+
return item.amount;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Aplicabilidade de escopo (RFC §16.1 divergência #1 — o que `resolvePriceQuote`
|
|
85
|
+
* mínimo do Catálogo NÃO faz). `scopes` é declarado na TABELA (não por item —
|
|
86
|
+
* `CommercialPriceItem` não tem campo de escopo); interpretação: tabela sem
|
|
87
|
+
* `scopes` = ALL (compatível com o resolvedor mínimo); com `scopes`, aplica-se
|
|
88
|
+
* se QUALQUER escopo casar (TENANT por `tenantId`, PRODUCT_LINE por
|
|
89
|
+
* `productLine`, ALL sempre casa). SEGMENT nunca casa nesta fase (sem contexto
|
|
90
|
+
* de segmento no `PricingRequest` — decisão explícita, não um bug silencioso).
|
|
91
|
+
*/
|
|
92
|
+
function isTableApplicable(table, tenantId, productLine) {
|
|
93
|
+
if (!table.scopes || table.scopes.length === 0)
|
|
94
|
+
return true;
|
|
95
|
+
return table.scopes.some((s) => {
|
|
96
|
+
if (s.scopeType === 'ALL')
|
|
97
|
+
return true;
|
|
98
|
+
if (s.scopeType === 'TENANT')
|
|
99
|
+
return s.matchValue === tenantId;
|
|
100
|
+
if (s.scopeType === 'PRODUCT_LINE')
|
|
101
|
+
return s.matchValue === productLine;
|
|
102
|
+
return false;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function mustFindModule(modules, code) {
|
|
106
|
+
const mod = modules.find((m) => m.code === code);
|
|
107
|
+
if (!mod)
|
|
108
|
+
throw new errors_js_1.PricingEngineError('price-rule-missing', `Módulo "${code}" não existe no catálogo recebido.`);
|
|
109
|
+
return mod;
|
|
110
|
+
}
|
|
111
|
+
function mustFindBundle(bundles, code) {
|
|
112
|
+
const bundle = bundles.find((b) => b.code === code);
|
|
113
|
+
if (!bundle)
|
|
114
|
+
throw new errors_js_1.PricingEngineError('invalid-bundle', `Bundle "${code}" não existe no catálogo recebido.`);
|
|
115
|
+
return bundle;
|
|
116
|
+
}
|
|
117
|
+
function computePricingQuote(request) {
|
|
118
|
+
try {
|
|
119
|
+
return { ok: true, value: computeInternal(request) };
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
if (err instanceof errors_js_1.PricingEngineError)
|
|
123
|
+
return { ok: false, error: err.toJSON() };
|
|
124
|
+
throw err;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function computeInternal(request) {
|
|
128
|
+
const { tenantId, productLine, offer, plan, modules, bundles, priceTable, bundleRules = [], extraSeats = 0, addonQuantities = {}, negotiatedContract, coupon, campaign, trial, now, billingCycle, quoteValidityHours = 24, } = request;
|
|
129
|
+
if (priceTable.code !== offer.priceTableCode) {
|
|
130
|
+
throw new errors_js_1.PricingEngineError('price-rule-missing', `Offer "${offer.code}" referencia a tabela "${offer.priceTableCode}", recebida "${priceTable.code}".`);
|
|
131
|
+
}
|
|
132
|
+
if (priceTable.status !== 'active') {
|
|
133
|
+
throw new errors_js_1.PricingEngineError('catalog-version-not-found', `Tabela "${priceTable.code}" não está ativa (status="${priceTable.status}").`);
|
|
134
|
+
}
|
|
135
|
+
if (now < priceTable.effectiveFrom || (priceTable.effectiveTo != null && now > priceTable.effectiveTo)) {
|
|
136
|
+
throw new errors_js_1.PricingEngineError('invalid-effective-date', `Tabela "${priceTable.code}" fora de vigência em ${now}.`);
|
|
137
|
+
}
|
|
138
|
+
if (!isTableApplicable(priceTable, tenantId, productLine)) {
|
|
139
|
+
throw new errors_js_1.PricingEngineError('catalog-version-not-found', `Tabela "${priceTable.code}" não se aplica ao escopo tenant="${tenantId}"/productLine="${productLine}".`);
|
|
140
|
+
}
|
|
141
|
+
if (negotiatedContract && (now < negotiatedContract.validFrom || (negotiatedContract.validTo != null && now > negotiatedContract.validTo))) {
|
|
142
|
+
throw new errors_js_1.PricingEngineError('negotiated-contract-invalid', `Contrato negociado do tenant "${negotiatedContract.tenantId}" fora de vigência em ${now}.`);
|
|
143
|
+
}
|
|
144
|
+
const warnings = [];
|
|
145
|
+
const appliedRules = [];
|
|
146
|
+
const items = [];
|
|
147
|
+
// Passo 1 — BASE_PLAN_PRICE
|
|
148
|
+
items.push(itemOf('plan', offer.planCode, 1, (0, money_js_1.reaisToCents)(findPriceItemReais(priceTable, 'PLAN', offer.planCode, billingCycle))));
|
|
149
|
+
appliedRules.push('BASE_PLAN_PRICE');
|
|
150
|
+
// Módulos free_module de bundle precisam ser conhecidos ANTES de precificar (passo 2 não pode cobrar 2x depois descontar).
|
|
151
|
+
const freeModuleCodes = new Set();
|
|
152
|
+
for (const bundleCode of offer.bundleCodes) {
|
|
153
|
+
const bundle = mustFindBundle(bundles, bundleCode);
|
|
154
|
+
const rule = bundleRules.find((r) => r.bundleCode === bundleCode);
|
|
155
|
+
for (const code of (0, bundle_js_1.freeModuleCodesForBundle)(bundle, rule))
|
|
156
|
+
freeModuleCodes.add(code);
|
|
157
|
+
}
|
|
158
|
+
// Passo 2 — MODULE_PRICE
|
|
159
|
+
const chargedModuleCodes = new Set();
|
|
160
|
+
for (const moduleCode of offer.moduleCodes) {
|
|
161
|
+
mustFindModule(modules, moduleCode);
|
|
162
|
+
if (chargedModuleCodes.has(moduleCode)) {
|
|
163
|
+
throw new errors_js_1.PricingEngineError('duplicate-charge-item', `Módulo "${moduleCode}" duplicado na oferta "${offer.code}".`);
|
|
164
|
+
}
|
|
165
|
+
chargedModuleCodes.add(moduleCode);
|
|
166
|
+
const unitCents = freeModuleCodes.has(moduleCode) ? 0 : (0, money_js_1.reaisToCents)(findPriceItemReais(priceTable, 'MODULE', moduleCode, billingCycle));
|
|
167
|
+
items.push(itemOf('module', moduleCode, 1, unitCents));
|
|
168
|
+
}
|
|
169
|
+
if (offer.moduleCodes.length > 0)
|
|
170
|
+
appliedRules.push('MODULE_PRICE');
|
|
171
|
+
// Passo 3 — QUANTITY_PRICE (assentos excedentes da franquia — delta já calculado pelo consumidor)
|
|
172
|
+
if (extraSeats > 0) {
|
|
173
|
+
const unitCents = (0, money_js_1.reaisToCents)(findPriceItemReais(priceTable, 'SEAT', 'extra_seat', billingCycle));
|
|
174
|
+
items.push(itemOf('seat', 'extra_seat', extraSeats, unitCents, (0, money_js_1.multiplyByQuantity)(unitCents, extraSeats)));
|
|
175
|
+
appliedRules.push('QUANTITY_PRICE');
|
|
176
|
+
}
|
|
177
|
+
// Passo 4 — ADDON_PRICE
|
|
178
|
+
for (const addonCode of offer.addonCodes) {
|
|
179
|
+
const qty = addonQuantities[addonCode] ?? 1;
|
|
180
|
+
const unitCents = (0, money_js_1.reaisToCents)(findPriceItemReais(priceTable, 'ADDON', addonCode, billingCycle));
|
|
181
|
+
items.push(itemOf('addon', addonCode, qty, unitCents, (0, money_js_1.multiplyByQuantity)(unitCents, qty)));
|
|
182
|
+
}
|
|
183
|
+
if (offer.addonCodes.length > 0)
|
|
184
|
+
appliedRules.push('ADDON_PRICE');
|
|
185
|
+
const subtotalCents = (0, money_js_1.addCents)(...items.map((i) => i.subtotalCents));
|
|
186
|
+
const discounts = [];
|
|
187
|
+
let runningCents = subtotalCents;
|
|
188
|
+
// Exclusividade (§8): cupom/campanha `exclusive` suprime bundle+desconto negociado (passos 5/6).
|
|
189
|
+
// Dois exclusivos → prioridade explícita decide; empate → erro (nunca escolha silenciosa).
|
|
190
|
+
const exclusiveCandidates = [];
|
|
191
|
+
if (coupon?.exclusive)
|
|
192
|
+
exclusiveCandidates.push({ key: 'coupon', priority: coupon.priority ?? 0, code: coupon.code });
|
|
193
|
+
if (campaign?.exclusive)
|
|
194
|
+
exclusiveCandidates.push({ key: 'campaign', priority: campaign.priority ?? 0, code: campaign.code });
|
|
195
|
+
let suppressBundleAndNegotiated = false;
|
|
196
|
+
let ignoredExclusiveKey = null;
|
|
197
|
+
if (exclusiveCandidates.length === 1) {
|
|
198
|
+
suppressBundleAndNegotiated = true;
|
|
199
|
+
}
|
|
200
|
+
else if (exclusiveCandidates.length === 2) {
|
|
201
|
+
const a = exclusiveCandidates[0];
|
|
202
|
+
const b = exclusiveCandidates[1];
|
|
203
|
+
if (a.priority === b.priority) {
|
|
204
|
+
throw new errors_js_1.PricingEngineError('conflicting-rules', `Cupom "${a.code}" e campanha "${b.code}" são ambos exclusivos com a mesma prioridade (${a.priority}) — conflito não resolvível automaticamente.`, [a.code, b.code]);
|
|
205
|
+
}
|
|
206
|
+
suppressBundleAndNegotiated = true;
|
|
207
|
+
ignoredExclusiveKey = a.priority > b.priority ? 'campaign' : 'coupon';
|
|
208
|
+
}
|
|
209
|
+
// Passo 5 — BUNDLE_DISCOUNT
|
|
210
|
+
if (offer.bundleCodes.length > 0) {
|
|
211
|
+
for (const bundleCode of offer.bundleCodes) {
|
|
212
|
+
(0, bundle_js_1.assertBundleModulesCovered)(mustFindBundle(bundles, bundleCode), chargedModuleCodes);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (!suppressBundleAndNegotiated) {
|
|
216
|
+
for (const bundleCode of offer.bundleCodes) {
|
|
217
|
+
const bundle = mustFindBundle(bundles, bundleCode);
|
|
218
|
+
const rule = bundleRules.find((r) => r.bundleCode === bundleCode);
|
|
219
|
+
const amount = (0, bundle_js_1.resolveBundleDiscount)(bundle, rule, items);
|
|
220
|
+
if (amount != null && amount > 0) {
|
|
221
|
+
const applied = Math.min(amount, runningCents);
|
|
222
|
+
discounts.push({ ruleId: bundleCode, step: 'BUNDLE_DISCOUNT', kind: 'bundle', amountCents: applied, appliesTo: bundle.moduleCodes });
|
|
223
|
+
runningCents = (0, money_js_1.subtractCents)(runningCents, applied);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (offer.bundleCodes.length > 0)
|
|
227
|
+
appliedRules.push('BUNDLE_DISCOUNT');
|
|
228
|
+
}
|
|
229
|
+
else if (offer.bundleCodes.length > 0) {
|
|
230
|
+
warnings.push('Desconto de bundle suprimido: regra exclusiva de cupom/campanha está ativa.');
|
|
231
|
+
}
|
|
232
|
+
// Passo 6 — NEGOTIATED_DISCOUNT (percentual, cumulativo — distinto do override do passo 10)
|
|
233
|
+
if (negotiatedContract?.discountPercent != null) {
|
|
234
|
+
if (!suppressBundleAndNegotiated) {
|
|
235
|
+
const amount = (0, money_js_1.applyPercent)(runningCents, negotiatedContract.discountPercent);
|
|
236
|
+
const applied = Math.min(amount, runningCents);
|
|
237
|
+
discounts.push({
|
|
238
|
+
ruleId: `negotiated:${tenantId}`,
|
|
239
|
+
step: 'NEGOTIATED_DISCOUNT',
|
|
240
|
+
kind: 'negotiated_percent',
|
|
241
|
+
amountCents: applied,
|
|
242
|
+
appliesTo: ['*'],
|
|
243
|
+
});
|
|
244
|
+
runningCents = (0, money_js_1.subtractCents)(runningCents, applied);
|
|
245
|
+
appliedRules.push('NEGOTIATED_DISCOUNT');
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
warnings.push('Desconto negociado (percentual) suprimido por regra exclusiva de cupom/campanha.');
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// Passo 7 — COUPON (sobre o resultado até aqui — RFC §8)
|
|
252
|
+
if (coupon) {
|
|
253
|
+
if (ignoredExclusiveKey !== 'coupon') {
|
|
254
|
+
const raw = coupon.effectType === 'percent_off' ? (0, money_js_1.applyPercent)(runningCents, coupon.percentOff ?? 0) : (coupon.amountOffCents ?? 0);
|
|
255
|
+
const applied = Math.min(Math.max(raw, 0), runningCents);
|
|
256
|
+
discounts.push({ ruleId: coupon.code, step: 'COUPON', kind: coupon.effectType, amountCents: applied, appliesTo: ['*'] });
|
|
257
|
+
runningCents = (0, money_js_1.subtractCents)(runningCents, applied);
|
|
258
|
+
appliedRules.push('COUPON');
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
warnings.push(`Cupom "${coupon.code}" ignorado: campanha exclusiva de maior prioridade está ativa.`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Passo 8 — CAMPAIGN
|
|
265
|
+
if (campaign) {
|
|
266
|
+
if (ignoredExclusiveKey !== 'campaign') {
|
|
267
|
+
const raw = campaign.effectType === 'percent_off' ? (0, money_js_1.applyPercent)(runningCents, campaign.percentOff ?? 0) : (campaign.amountOffCents ?? 0);
|
|
268
|
+
const applied = Math.min(Math.max(raw, 0), runningCents);
|
|
269
|
+
discounts.push({ ruleId: campaign.code, step: 'CAMPAIGN', kind: campaign.effectType, amountCents: applied, appliesTo: ['*'] });
|
|
270
|
+
runningCents = (0, money_js_1.subtractCents)(runningCents, applied);
|
|
271
|
+
appliedRules.push('CAMPAIGN');
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
warnings.push(`Campanha "${campaign.code}" ignorada: cupom exclusivo de maior prioridade está ativa.`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// Passo 9 — PROMOTIONAL_CREDIT (reservado — só preenchido quando Wallet/Rating existirem, RFC §12)
|
|
278
|
+
const promotionalCreditsCents = 0;
|
|
279
|
+
appliedRules.push('PROMOTIONAL_CREDIT');
|
|
280
|
+
// Passo 10 — CONTRACT_OVERRIDE_OR_GRANDFATHERING (fixa/sobrepõe o total — nunca um desconto adicional)
|
|
281
|
+
if (negotiatedContract?.fixedTotalCents != null) {
|
|
282
|
+
runningCents = negotiatedContract.fixedTotalCents;
|
|
283
|
+
appliedRules.push('CONTRACT_OVERRIDE_OR_GRANDFATHERING');
|
|
284
|
+
}
|
|
285
|
+
runningCents = (0, money_js_1.clampNonNegative)(runningCents);
|
|
286
|
+
const totalDiscountCents = (0, money_js_1.clampNonNegative)((0, money_js_1.subtractCents)(subtotalCents, runningCents));
|
|
287
|
+
// Passo 11 — TAX (MVP: passthrough/zero configurável — política fiscal fora do escopo, RFC §5)
|
|
288
|
+
const taxes = [];
|
|
289
|
+
const totalTaxCents = 0;
|
|
290
|
+
appliedRules.push('TAX');
|
|
291
|
+
// Passo 12 — ROUNDING (cada etapa já arredondou half-even no ponto de uso — nada fracionário resta a arredondar)
|
|
292
|
+
const totalBeforeTrial = (0, money_js_1.addCents)(runningCents, totalTaxCents);
|
|
293
|
+
appliedRules.push('ROUNDING');
|
|
294
|
+
const trialActive = trial?.active ?? false;
|
|
295
|
+
const totalCents = trialActive ? 0 : totalBeforeTrial;
|
|
296
|
+
const postTrialTotalCents = trialActive ? totalBeforeTrial : null;
|
|
297
|
+
const fingerprint = fingerprintOf(request);
|
|
298
|
+
const quoteId = `pq_${fingerprint.slice(0, 24)}`;
|
|
299
|
+
return {
|
|
300
|
+
quoteId,
|
|
301
|
+
engineVersion: types_js_1.PRICING_ENGINE_VERSION,
|
|
302
|
+
tenantId,
|
|
303
|
+
productLine,
|
|
304
|
+
offerCode: offer.code,
|
|
305
|
+
priceTableCode: priceTable.code,
|
|
306
|
+
priceTableVersion: priceTable.version,
|
|
307
|
+
catalogVersion: catalogFingerprint(plan, modules, bundles),
|
|
308
|
+
pricingPolicyVersion: types_js_1.PRICING_ENGINE_VERSION,
|
|
309
|
+
currency: priceTable.currency,
|
|
310
|
+
now,
|
|
311
|
+
effectiveAt: now,
|
|
312
|
+
expiresAt: addHours(now, quoteValidityHours),
|
|
313
|
+
items,
|
|
314
|
+
discounts,
|
|
315
|
+
taxes,
|
|
316
|
+
promotionalCreditsCents,
|
|
317
|
+
subtotalCents,
|
|
318
|
+
totalDiscountCents,
|
|
319
|
+
totalTaxCents,
|
|
320
|
+
totalCents,
|
|
321
|
+
postTrialTotalCents,
|
|
322
|
+
trial: trial ?? null,
|
|
323
|
+
appliedRules,
|
|
324
|
+
warnings,
|
|
325
|
+
fingerprint,
|
|
326
|
+
auditMetadata: {},
|
|
327
|
+
proration: null,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
//# sourceMappingURL=pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../../src/pricing-engine/pipeline.ts"],"names":[],"mappings":";;AAkIA,kDAOC;AAzID,6CAAyC;AAEzC,yCAAmI;AACnI,2CAAiD;AACjD,2CAA0G;AAC1G,yCASoB;AAEpB;;;;;;;;;;;;;;;;;GAiBG;AAEH,SAAS,aAAa,CAAC,OAAuB;IAC5C,MAAM,KAAK,GAAG;QACZ,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI;QAC7B,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI;QAC3B,WAAW,EAAE,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE;QAClD,WAAW,EAAE,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE;QAClD,UAAU,EAAE,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE;QAChD,cAAc,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI;QACvC,iBAAiB,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO;QAC7C,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,CAAC;QACnC,eAAe,EAAE,OAAO,CAAC,eAAe,IAAI,EAAE;QAC9C,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,IAAI,IAAI,IAAI;QACxC,YAAY,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,IAAI,IAAI;QAC5C,0BAA0B,EAAE,OAAO,CAAC,kBAAkB,EAAE,QAAQ,IAAI,IAAI;QACxE,yBAAyB,EAAE,OAAO,CAAC,kBAAkB,EAAE,eAAe,IAAI,IAAI;QAC9E,yBAAyB,EAAE,OAAO,CAAC,kBAAkB,EAAE,eAAe,IAAI,IAAI;QAC9E,WAAW,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,IAAI,KAAK;QAC3C,GAAG,EAAE,OAAO,CAAC,GAAG;KACjB,CAAC;IACF,OAAO,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,kBAAkB,CAAC,IAA4B,EAAE,OAAuB,EAAE,OAAuB;IACxG,MAAM,KAAK,GAAG;QACZ,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE;QACvE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5G,OAAO,EAAE,OAAO;aACb,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;aACtE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;KAChD,CAAC;IACF,OAAO,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW,EAAE,KAAa;IAC1C,MAAM,CAAC,GAAG,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;IACzF,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,CAAC;IACvC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;AACzB,CAAC;AAED,SAAS,MAAM,CAAC,MAAkB,EAAE,UAAkB,EAAE,QAAgB,EAAE,cAAqB,EAAE,aAAqB;IACpH,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,IAAI,cAAc,GAAG,QAAQ,EAAE,CAAC;AACrH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,kBAAkB,CAAC,KAAmC,EAAE,UAAkB,EAAE,UAAkB,EAAE,YAAkC;IACzI,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,IAAI,CAAC,CAAC,UAAU,KAAK,UAAU,IAAI,CAAC,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC;IAChI,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,8BAAkB,CAC1B,oBAAoB,EACpB,kBAAkB,UAAU,IAAI,UAAU,WAAW,YAAY,gBAAgB,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC,OAAO,GAAG,CAClH,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC;AACrB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,iBAAiB,CAAC,KAAmC,EAAE,QAAgB,EAAE,WAAmB;IACnG,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5D,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;QAC7B,IAAI,CAAC,CAAC,SAAS,KAAK,KAAK;YAAE,OAAO,IAAI,CAAC;QACvC,IAAI,CAAC,CAAC,SAAS,KAAK,QAAQ;YAAE,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC;QAC/D,IAAI,CAAC,CAAC,SAAS,KAAK,cAAc;YAAE,OAAO,CAAC,CAAC,UAAU,KAAK,WAAW,CAAC;QACxE,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,cAAc,CAAC,OAAuB,EAAE,IAAY;IAC3D,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACjD,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,8BAAkB,CAAC,oBAAoB,EAAE,WAAW,IAAI,oCAAoC,CAAC,CAAC;IAClH,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,cAAc,CAAC,OAAuB,EAAE,IAAY;IAC3D,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACpD,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,8BAAkB,CAAC,gBAAgB,EAAE,WAAW,IAAI,oCAAoC,CAAC,CAAC;IACjH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAgB,mBAAmB,CAAC,OAAuB;IACzD,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;IACvD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,8BAAkB;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;QACjF,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,OAAuB;IAC9C,MAAM,EACJ,QAAQ,EACR,WAAW,EACX,KAAK,EACL,IAAI,EACJ,OAAO,EACP,OAAO,EACP,UAAU,EACV,WAAW,GAAG,EAAE,EAChB,UAAU,GAAG,CAAC,EACd,eAAe,GAAG,EAAE,EACpB,kBAAkB,EAClB,MAAM,EACN,QAAQ,EACR,KAAK,EACL,GAAG,EACH,YAAY,EACZ,kBAAkB,GAAG,EAAE,GACxB,GAAG,OAAO,CAAC;IAEZ,IAAI,UAAU,CAAC,IAAI,KAAK,KAAK,CAAC,cAAc,EAAE,CAAC;QAC7C,MAAM,IAAI,8BAAkB,CAC1B,oBAAoB,EACpB,UAAU,KAAK,CAAC,IAAI,0BAA0B,KAAK,CAAC,cAAc,gBAAgB,UAAU,CAAC,IAAI,IAAI,CACtG,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACnC,MAAM,IAAI,8BAAkB,CAAC,2BAA2B,EAAE,WAAW,UAAU,CAAC,IAAI,6BAA6B,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC;IAC3I,CAAC;IACD,IAAI,GAAG,GAAG,UAAU,CAAC,aAAa,IAAI,CAAC,UAAU,CAAC,WAAW,IAAI,IAAI,IAAI,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QACvG,MAAM,IAAI,8BAAkB,CAAC,wBAAwB,EAAE,WAAW,UAAU,CAAC,IAAI,yBAAyB,GAAG,GAAG,CAAC,CAAC;IACpH,CAAC;IACD,IAAI,CAAC,iBAAiB,CAAC,UAAU,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,8BAAkB,CAC1B,2BAA2B,EAC3B,WAAW,UAAU,CAAC,IAAI,qCAAqC,QAAQ,kBAAkB,WAAW,IAAI,CACzG,CAAC;IACJ,CAAC;IACD,IAAI,kBAAkB,IAAI,CAAC,GAAG,GAAG,kBAAkB,CAAC,SAAS,IAAI,CAAC,kBAAkB,CAAC,OAAO,IAAI,IAAI,IAAI,GAAG,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QAC3I,MAAM,IAAI,8BAAkB,CAC1B,6BAA6B,EAC7B,iCAAiC,kBAAkB,CAAC,QAAQ,yBAAyB,GAAG,GAAG,CAC5F,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,YAAY,GAAsB,EAAE,CAAC;IAC3C,MAAM,KAAK,GAAuB,EAAE,CAAC;IAErC,4BAA4B;IAC5B,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,EAAE,IAAA,uBAAY,EAAC,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IAClI,YAAY,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAErC,2HAA2H;IAC3H,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;IAC1C,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;QAClE,KAAK,MAAM,IAAI,IAAI,IAAA,oCAAwB,EAAC,MAAM,EAAE,IAAI,CAAC;YAAE,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACvF,CAAC;IAED,yBAAyB;IACzB,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAU,CAAC;IAC7C,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QAC3C,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACpC,IAAI,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,8BAAkB,CAAC,uBAAuB,EAAE,WAAW,UAAU,0BAA0B,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC;QACvH,CAAC;QACD,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACnC,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAA,uBAAY,EAAC,kBAAkB,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC;QACzI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;QAAE,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAEpE,kGAAkG;IAClG,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACnB,MAAM,SAAS,GAAG,IAAA,uBAAY,EAAC,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC;QACnG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,IAAA,6BAAkB,EAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;QAC3G,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACtC,CAAC;IAED,wBAAwB;IACxB,KAAK,MAAM,SAAS,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,SAAS,GAAG,IAAA,uBAAY,EAAC,kBAAkB,CAAC,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;QACjG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,IAAA,6BAAkB,EAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7F,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAElE,MAAM,aAAa,GAAG,IAAA,mBAAQ,EAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;IACrE,MAAM,SAAS,GAA2B,EAAE,CAAC;IAC7C,IAAI,YAAY,GAAG,aAAa,CAAC;IAEjC,iGAAiG;IACjG,2FAA2F;IAC3F,MAAM,mBAAmB,GAA0E,EAAE,CAAC;IACtG,IAAI,MAAM,EAAE,SAAS;QAAE,mBAAmB,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACtH,IAAI,QAAQ,EAAE,SAAS;QAAE,mBAAmB,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAE9H,IAAI,2BAA2B,GAAG,KAAK,CAAC;IACxC,IAAI,mBAAmB,GAAiC,IAAI,CAAC;IAC7D,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,2BAA2B,GAAG,IAAI,CAAC;IACrC,CAAC;SAAM,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5C,MAAM,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAE,CAAC;QAClC,MAAM,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAE,CAAC;QAClC,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAI,8BAAkB,CAC1B,mBAAmB,EACnB,UAAU,CAAC,CAAC,IAAI,iBAAiB,CAAC,CAAC,IAAI,kDAAkD,CAAC,CAAC,QAAQ,8CAA8C,EACjJ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CACjB,CAAC;QACJ,CAAC;QACD,2BAA2B,GAAG,IAAI,CAAC;QACnC,mBAAmB,GAAG,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC;IACxE,CAAC;IAED,4BAA4B;IAC5B,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YAC3C,IAAA,sCAA0B,EAAC,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,kBAAkB,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;IACD,IAAI,CAAC,2BAA2B,EAAE,CAAC;QACjC,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YAC3C,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;YACnD,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;YAClE,MAAM,MAAM,GAAG,IAAA,iCAAqB,EAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YAC1D,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;gBAC/C,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;gBACrI,YAAY,GAAG,IAAA,wBAAa,EAAC,YAAY,EAAE,OAAO,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;QACD,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;YAAE,YAAY,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACzE,CAAC;SAAM,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxC,QAAQ,CAAC,IAAI,CAAC,6EAA6E,CAAC,CAAC;IAC/F,CAAC;IAED,4FAA4F;IAC5F,IAAI,kBAAkB,EAAE,eAAe,IAAI,IAAI,EAAE,CAAC;QAChD,IAAI,CAAC,2BAA2B,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,IAAA,uBAAY,EAAC,YAAY,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAC;YAC9E,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YAC/C,SAAS,CAAC,IAAI,CAAC;gBACb,MAAM,EAAE,cAAc,QAAQ,EAAE;gBAChC,IAAI,EAAE,qBAAqB;gBAC3B,IAAI,EAAE,oBAAoB;gBAC1B,WAAW,EAAE,OAAO;gBACpB,SAAS,EAAE,CAAC,GAAG,CAAC;aACjB,CAAC,CAAC;YACH,YAAY,GAAG,IAAA,wBAAa,EAAC,YAAY,EAAE,OAAO,CAAC,CAAC;YACpD,YAAY,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,IAAI,CAAC,kFAAkF,CAAC,CAAC;QACpG,CAAC;IACH,CAAC;IAED,yDAAyD;IACzD,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,mBAAmB,KAAK,QAAQ,EAAE,CAAC;YACrC,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,KAAK,aAAa,CAAC,CAAC,CAAC,IAAA,uBAAY,EAAC,YAAY,EAAE,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,IAAI,CAAC,CAAC,CAAC;YACpI,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;YACzD,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACzH,YAAY,GAAG,IAAA,wBAAa,EAAC,YAAY,EAAE,OAAO,CAAC,CAAC;YACpD,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,IAAI,CAAC,UAAU,MAAM,CAAC,IAAI,gEAAgE,CAAC,CAAC;QACvG,CAAC;IACH,CAAC;IAED,qBAAqB;IACrB,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,mBAAmB,KAAK,UAAU,EAAE,CAAC;YACvC,MAAM,GAAG,GAAG,QAAQ,CAAC,UAAU,KAAK,aAAa,CAAC,CAAC,CAAC,IAAA,uBAAY,EAAC,YAAY,EAAE,QAAQ,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,IAAI,CAAC,CAAC,CAAC;YAC1I,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;YACzD,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC/H,YAAY,GAAG,IAAA,wBAAa,EAAC,YAAY,EAAE,OAAO,CAAC,CAAC;YACpD,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,IAAI,CAAC,aAAa,QAAQ,CAAC,IAAI,6DAA6D,CAAC,CAAC;QACzG,CAAC;IACH,CAAC;IAED,mGAAmG;IACnG,MAAM,uBAAuB,GAAG,CAAC,CAAC;IAClC,YAAY,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAExC,uGAAuG;IACvG,IAAI,kBAAkB,EAAE,eAAe,IAAI,IAAI,EAAE,CAAC;QAChD,YAAY,GAAG,kBAAkB,CAAC,eAAe,CAAC;QAClD,YAAY,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;IAC3D,CAAC;IAED,YAAY,GAAG,IAAA,2BAAgB,EAAC,YAAY,CAAC,CAAC;IAC9C,MAAM,kBAAkB,GAAG,IAAA,2BAAgB,EAAC,IAAA,wBAAa,EAAC,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC;IAExF,+FAA+F;IAC/F,MAAM,KAAK,GAA0B,EAAE,CAAC;IACxC,MAAM,aAAa,GAAG,CAAC,CAAC;IACxB,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEzB,iHAAiH;IACjH,MAAM,gBAAgB,GAAG,IAAA,mBAAQ,EAAC,YAAY,EAAE,aAAa,CAAC,CAAC;IAC/D,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAE9B,MAAM,WAAW,GAAG,KAAK,EAAE,MAAM,IAAI,KAAK,CAAC;IAC3C,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC;IACtD,MAAM,mBAAmB,GAAG,WAAW,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC;IAElE,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;IAEjD,OAAO;QACL,OAAO;QACP,aAAa,EAAE,iCAAsB;QACrC,QAAQ;QACR,WAAW;QACX,SAAS,EAAE,KAAK,CAAC,IAAI;QACrB,cAAc,EAAE,UAAU,CAAC,IAAI;QAC/B,iBAAiB,EAAE,UAAU,CAAC,OAAO;QACrC,cAAc,EAAE,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC;QAC1D,oBAAoB,EAAE,iCAAsB;QAC5C,QAAQ,EAAE,UAAU,CAAC,QAAQ;QAC7B,GAAG;QACH,WAAW,EAAE,GAAG;QAChB,SAAS,EAAE,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAC;QAC5C,KAAK;QACL,SAAS;QACT,KAAK;QACL,uBAAuB;QACvB,aAAa;QACb,kBAAkB;QAClB,aAAa;QACb,UAAU;QACV,mBAAmB;QACnB,KAAK,EAAE,KAAK,IAAI,IAAI;QACpB,YAAY;QACZ,QAAQ;QACR,WAAW;QACX,aAAa,EAAE,EAAE;QACjB,SAAS,EAAE,IAAI;KAChB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.computeProration = computeProration;
|
|
4
|
+
const errors_js_1 = require("./errors.js");
|
|
5
|
+
const money_js_1 = require("./money.js");
|
|
6
|
+
/**
|
|
7
|
+
* Proração (RFC §11, ETAPA 9) — PURA e determinística. Datas são sempre
|
|
8
|
+
* comparadas via `Date`/epoch-ms (nunca comparação frágil de string — mesma
|
|
9
|
+
* disciplina de `parseIso` do subscription-billing), o que resolve
|
|
10
|
+
* corretamente meses com dias diferentes, fim de mês e ano bissexto sem
|
|
11
|
+
* lógica de calendário adicional (a diferença em ms já contém isso).
|
|
12
|
+
*/
|
|
13
|
+
/** Aceita data pura (`YYYY-MM-DD`) ou datetime ISO completo (mesma normalização do subscription-billing/commercial-catalog). */
|
|
14
|
+
function parseIso(iso) {
|
|
15
|
+
return /^\d{4}-\d{2}-\d{2}$/.test(iso) ? new Date(`${iso}T00:00:00Z`) : new Date(iso);
|
|
16
|
+
}
|
|
17
|
+
function daysBetween(a, b) {
|
|
18
|
+
return Math.round((parseIso(b).getTime() - parseIso(a).getTime()) / 86_400_000);
|
|
19
|
+
}
|
|
20
|
+
const DEFAULT_TIMING = {
|
|
21
|
+
upgrade: 'immediate',
|
|
22
|
+
add_module: 'immediate',
|
|
23
|
+
seats_up: 'immediate',
|
|
24
|
+
cycle_change: 'immediate',
|
|
25
|
+
reactivate: 'immediate',
|
|
26
|
+
downgrade: 'next_renewal',
|
|
27
|
+
remove_module: 'next_renewal',
|
|
28
|
+
seats_down: 'next_renewal',
|
|
29
|
+
cancel: 'immediate',
|
|
30
|
+
};
|
|
31
|
+
function computeProration(input) {
|
|
32
|
+
const { reason, cycleStart, cycleEnd, now, oldValueCents, newValueCents } = input;
|
|
33
|
+
const daysInCycle = daysBetween(cycleStart, cycleEnd);
|
|
34
|
+
if (daysInCycle <= 0) {
|
|
35
|
+
throw new errors_js_1.PricingEngineError('proration-invalid', `Ciclo inválido: "${cycleStart}" a "${cycleEnd}" não é um intervalo positivo.`);
|
|
36
|
+
}
|
|
37
|
+
const daysSinceStart = daysBetween(cycleStart, now);
|
|
38
|
+
if (daysSinceStart < 0) {
|
|
39
|
+
throw new errors_js_1.PricingEngineError('proration-invalid', `Proração retroativa proibida: "now" (${now}) é anterior ao início do ciclo (${cycleStart}).`);
|
|
40
|
+
}
|
|
41
|
+
const timing = input.timingPolicy ?? DEFAULT_TIMING[reason];
|
|
42
|
+
const daysElapsed = Math.min(daysInCycle, daysSinceStart);
|
|
43
|
+
const daysRemaining = daysInCycle - daysElapsed;
|
|
44
|
+
if (timing === 'next_renewal') {
|
|
45
|
+
// Mudança só produz efeito no próximo ciclo — nenhum ajuste financeiro agora.
|
|
46
|
+
return { reason, effective: timing, daysRemaining, daysInCycle, creditCents: 0, debitCents: 0, netCents: 0 };
|
|
47
|
+
}
|
|
48
|
+
const creditCents = (0, money_js_1.prorateByDays)(oldValueCents, daysRemaining, daysInCycle);
|
|
49
|
+
const debitCents = reason === 'cancel' ? 0 : (0, money_js_1.prorateByDays)(newValueCents, daysRemaining, daysInCycle);
|
|
50
|
+
const netCents = (0, money_js_1.subtractCents)(debitCents, creditCents);
|
|
51
|
+
return { reason, effective: timing, daysRemaining, daysInCycle, creditCents, debitCents, netCents };
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=proration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proration.js","sourceRoot":"","sources":["../../../src/pricing-engine/proration.ts"],"names":[],"mappings":";;AAiCA,4CA6BC;AA9DD,2CAAiD;AACjD,yCAA0D;AAG1D;;;;;;GAMG;AAEH,gIAAgI;AAChI,SAAS,QAAQ,CAAC,GAAW;IAC3B,OAAO,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;AACxF,CAAC;AAED,SAAS,WAAW,CAAC,CAAS,EAAE,CAAS;IACvC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC;AAClF,CAAC;AAED,MAAM,cAAc,GAAsD;IACxE,OAAO,EAAE,WAAW;IACpB,UAAU,EAAE,WAAW;IACvB,QAAQ,EAAE,WAAW;IACrB,YAAY,EAAE,WAAW;IACzB,UAAU,EAAE,WAAW;IACvB,SAAS,EAAE,cAAc;IACzB,aAAa,EAAE,cAAc;IAC7B,UAAU,EAAE,cAAc;IAC1B,MAAM,EAAE,WAAW;CACpB,CAAC;AAEF,SAAgB,gBAAgB,CAAC,KAAqB;IACpD,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC;IAElF,MAAM,WAAW,GAAG,WAAW,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACtD,IAAI,WAAW,IAAI,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,8BAAkB,CAAC,mBAAmB,EAAE,oBAAoB,UAAU,QAAQ,QAAQ,gCAAgC,CAAC,CAAC;IACpI,CAAC;IACD,MAAM,cAAc,GAAG,WAAW,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACpD,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,8BAAkB,CAC1B,mBAAmB,EACnB,wCAAwC,GAAG,oCAAoC,UAAU,IAAI,CAC9F,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,YAAY,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;IAC5D,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAC1D,MAAM,aAAa,GAAG,WAAW,GAAG,WAAW,CAAC;IAEhD,IAAI,MAAM,KAAK,cAAc,EAAE,CAAC;QAC9B,8EAA8E;QAC9E,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IAC/G,CAAC;IAED,MAAM,WAAW,GAAG,IAAA,wBAAa,EAAC,aAAa,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;IAC7E,MAAM,UAAU,GAAG,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAA,wBAAa,EAAC,aAAa,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;IACtG,MAAM,QAAQ,GAAG,IAAA,wBAAa,EAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IAExD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;AACtG,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeCanonicalQuote = normalizeCanonicalQuote;
|
|
4
|
+
exports.compareQuotes = compareQuotes;
|
|
5
|
+
const errors_js_1 = require("./errors.js");
|
|
6
|
+
function normalizeCanonicalQuote(quote) {
|
|
7
|
+
return {
|
|
8
|
+
currency: quote.currency,
|
|
9
|
+
items: quote.items.map((i) => ({ targetCode: i.targetCode, amountCents: i.subtotalCents })),
|
|
10
|
+
totalDiscountCents: quote.totalDiscountCents,
|
|
11
|
+
totalCents: quote.totalCents,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Compara canônico vs shadow. `toleranceCents` (default 0 — igualdade exata
|
|
16
|
+
* em centavos, RFC §13 "igualdade exata em centavos no total") permite uma
|
|
17
|
+
* folga configurável para cenários de arredondamento de terceiros ainda não
|
|
18
|
+
* alinhados. Divergência de decomposição é logada mesmo com total igual
|
|
19
|
+
* (`itemDiffs`), para achar regra faltante sem esperar o total divergir.
|
|
20
|
+
*/
|
|
21
|
+
function compareQuotes(quoteId, canonical, shadow, toleranceCents = 0) {
|
|
22
|
+
if (canonical.currency !== shadow.currency) {
|
|
23
|
+
const err = new errors_js_1.PricingEngineError('currency-mismatch', `Moedas incompatíveis: canônico="${canonical.currency}", shadow="${shadow.currency}".`);
|
|
24
|
+
return {
|
|
25
|
+
status: 'not-comparable',
|
|
26
|
+
quoteId,
|
|
27
|
+
toleranceCents,
|
|
28
|
+
subtotalDiffCents: 0,
|
|
29
|
+
discountDiffCents: 0,
|
|
30
|
+
totalDiffCents: 0,
|
|
31
|
+
itemDiffs: [],
|
|
32
|
+
divergentRules: [],
|
|
33
|
+
errorCode: err.code,
|
|
34
|
+
errorMessage: err.message,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const targetCodes = new Set([...canonical.items.map((i) => i.targetCode), ...shadow.items.map((i) => i.targetCode)]);
|
|
38
|
+
const itemDiffs = [];
|
|
39
|
+
const divergentRules = [];
|
|
40
|
+
for (const targetCode of targetCodes) {
|
|
41
|
+
const canonicalItem = canonical.items.find((i) => i.targetCode === targetCode) ?? null;
|
|
42
|
+
const shadowItem = shadow.items.find((i) => i.targetCode === targetCode) ?? null;
|
|
43
|
+
const canonicalCents = canonicalItem?.amountCents ?? null;
|
|
44
|
+
const shadowCents = shadowItem?.amountCents ?? null;
|
|
45
|
+
const diffCents = (canonicalCents ?? 0) - (shadowCents ?? 0);
|
|
46
|
+
itemDiffs.push({ targetCode, canonicalCents, shadowCents, diffCents });
|
|
47
|
+
if (Math.abs(diffCents) > toleranceCents)
|
|
48
|
+
divergentRules.push(targetCode);
|
|
49
|
+
}
|
|
50
|
+
const subtotalCanonical = canonical.items.reduce((s, i) => s + i.amountCents, 0);
|
|
51
|
+
const subtotalShadow = shadow.items.reduce((s, i) => s + i.amountCents, 0);
|
|
52
|
+
const subtotalDiffCents = subtotalCanonical - subtotalShadow;
|
|
53
|
+
const discountDiffCents = canonical.totalDiscountCents - shadow.totalDiscountCents;
|
|
54
|
+
const totalDiffCents = canonical.totalCents - shadow.totalCents;
|
|
55
|
+
const status = Math.abs(totalDiffCents) <= toleranceCents && divergentRules.length === 0 ? 'match' : 'mismatch';
|
|
56
|
+
return { status, quoteId, toleranceCents, subtotalDiffCents, discountDiffCents, totalDiffCents, itemDiffs, divergentRules };
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=shadow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shadow.js","sourceRoot":"","sources":["../../../src/pricing-engine/shadow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pricing Engine — contratos canônicos (RFC-CAPABILITY-PRICING-ENGINE-001,
|
|
4
|
+
* Track A P1-P3). Domínio PURO — sem DB, sem HTTP, sem `Date.now()` interno,
|
|
5
|
+
* sem aleatório (§3 "determinismo": mesmo input → mesmo output, bit a bit).
|
|
6
|
+
*
|
|
7
|
+
* Fronteira dura (§1): o Engine CALCULA, não POSSUI o catálogo (isso é
|
|
8
|
+
* `commercial-catalog/`) — recebe Plan/Module/Bundle/Offer/PriceTable já
|
|
9
|
+
* resolvidos pelo consumidor. Não mede consumo (Usage), não converte consumo
|
|
10
|
+
* em crédito (Rating), não guarda saldo (Wallet), não cobra (Provider) — ver
|
|
11
|
+
* §12. `PricingQuote` aqui é DISTINTO do `PriceQuote` minimalista de
|
|
12
|
+
* `commercial-catalog/types.ts` (aquele é o "resolvedor mínimo", explicitamente
|
|
13
|
+
* superado por este — RFC-Catalog §16.1/§16.7); nomeado `PricingQuote`
|
|
14
|
+
* (não `PriceQuote`) para não colidir no barrel do pacote.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.PRICING_RULE_STEPS_IN_ORDER = exports.PRICING_ENGINE_VERSION = void 0;
|
|
18
|
+
exports.PRICING_ENGINE_VERSION = '0.1.0';
|
|
19
|
+
/** As 12 etapas, na ordem oficial — usado para validar/auditar `appliedRules` (nunca reordenado em runtime). */
|
|
20
|
+
exports.PRICING_RULE_STEPS_IN_ORDER = [
|
|
21
|
+
'BASE_PLAN_PRICE',
|
|
22
|
+
'MODULE_PRICE',
|
|
23
|
+
'QUANTITY_PRICE',
|
|
24
|
+
'ADDON_PRICE',
|
|
25
|
+
'BUNDLE_DISCOUNT',
|
|
26
|
+
'NEGOTIATED_DISCOUNT',
|
|
27
|
+
'COUPON',
|
|
28
|
+
'CAMPAIGN',
|
|
29
|
+
'PROMOTIONAL_CREDIT',
|
|
30
|
+
'CONTRACT_OVERRIDE_OR_GRANDFATHERING',
|
|
31
|
+
'TAX',
|
|
32
|
+
'ROUNDING',
|
|
33
|
+
];
|
|
34
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/pricing-engine/types.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;;AAaU,QAAA,sBAAsB,GAAG,OAAO,CAAC;AA0B9C,gHAAgH;AACnG,QAAA,2BAA2B,GAA+B;IACrE,iBAAiB;IACjB,cAAc;IACd,gBAAgB;IAChB,aAAa;IACb,iBAAiB;IACjB,qBAAqB;IACrB,QAAQ;IACR,UAAU;IACV,oBAAoB;IACpB,qCAAqC;IACrC,KAAK;IACL,UAAU;CACX,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PRODUCTS = void 0;
|
|
4
|
+
exports.PRODUCTS = [
|
|
5
|
+
{ key: 'contabil', name: 'Baruk Contábil', kind: 'internal', isActive: true },
|
|
6
|
+
{ key: 'rep', name: 'Baruk Rep', kind: 'external', baseUrl: 'https://baruk.app', isActive: true },
|
|
7
|
+
{ key: 'ind', name: 'Baruk Ind', kind: 'external', baseUrl: 'https://baruk.app', isActive: true },
|
|
8
|
+
{ key: 'varejo', name: 'Baruk Varejo', kind: 'external', baseUrl: 'https://baruk.app', isActive: false },
|
|
9
|
+
];
|
|
10
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../../src/products/catalog.ts"],"names":[],"mappings":";;;AAaa,QAAA,QAAQ,GAA0B;IAC7C,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC7E,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,IAAI,EAAE;IACjG,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,IAAI,EAAE;IACjG,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,KAAK,EAAE;CACzG,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listProductsForUser = listProductsForUser;
|
|
4
|
+
exports.ensureProductCatalog = ensureProductCatalog;
|
|
5
|
+
exports.ensureTenantProduct = ensureTenantProduct;
|
|
6
|
+
const shared_1 = require("@baruk/shared");
|
|
7
|
+
const context_js_1 = require("../db/context.js");
|
|
8
|
+
const catalog_js_1 = require("./catalog.js");
|
|
9
|
+
/**
|
|
10
|
+
* Produtos acessíveis ao usuário: cruza suas memberships ativas com os
|
|
11
|
+
* entitlements (tenant_product) ativos. Rode dentro de `withContext({ userId })`
|
|
12
|
+
* — é assim que o Hub sabe a que produtos a pessoa tem direito. Sem entitlement
|
|
13
|
+
* = sem acesso (bloqueio no Hub).
|
|
14
|
+
*/
|
|
15
|
+
async function listProductsForUser(tx, userId) {
|
|
16
|
+
const rows = await tx `
|
|
17
|
+
SELECT DISTINCT t.id AS tenant_id, t.display_name AS tenant_name, t.code AS tenant_code,
|
|
18
|
+
p.key AS product_key, p.name AS product_name, p.kind, p.base_url
|
|
19
|
+
FROM membership m
|
|
20
|
+
JOIN tenant t ON t.id = m.tenant_id
|
|
21
|
+
JOIN tenant_product tp ON tp.tenant_id = m.tenant_id AND tp.status = 'active'
|
|
22
|
+
JOIN product p ON p.id = tp.product_id AND p.is_active
|
|
23
|
+
WHERE m.user_id = ${userId} AND m.status = 'active' AND m.deleted_at IS NULL
|
|
24
|
+
ORDER BY t.display_name, p.name
|
|
25
|
+
`;
|
|
26
|
+
return rows.map((r) => ({
|
|
27
|
+
tenantId: r.tenant_id,
|
|
28
|
+
tenantName: r.tenant_name,
|
|
29
|
+
tenantCode: r.tenant_code,
|
|
30
|
+
productKey: r.product_key,
|
|
31
|
+
productName: r.product_name,
|
|
32
|
+
kind: r.kind,
|
|
33
|
+
baseUrl: r.base_url,
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
/** Materializa o catálogo global de produtos (idempotente). */
|
|
37
|
+
async function ensureProductCatalog(db) {
|
|
38
|
+
for (const p of catalog_js_1.PRODUCTS) {
|
|
39
|
+
await db `
|
|
40
|
+
INSERT INTO product (id, key, name, kind, base_url, is_active)
|
|
41
|
+
VALUES (${(0, shared_1.uuidv7)()}, ${p.key}, ${p.name}, ${p.kind}, ${p.baseUrl ?? null}, ${p.isActive ?? true})
|
|
42
|
+
ON CONFLICT (key) DO UPDATE
|
|
43
|
+
SET name = EXCLUDED.name, kind = EXCLUDED.kind,
|
|
44
|
+
base_url = EXCLUDED.base_url, is_active = EXCLUDED.is_active
|
|
45
|
+
`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** Concede (ou reativa) um produto a um tenant. */
|
|
49
|
+
async function ensureTenantProduct(db, tenantId, productKey) {
|
|
50
|
+
await (0, context_js_1.withContext)(db, { tenantId }, async (tx) => {
|
|
51
|
+
const prod = await tx `SELECT id FROM product WHERE key = ${productKey}`;
|
|
52
|
+
if (!prod[0])
|
|
53
|
+
throw new Error(`Produto desconhecido: ${productKey}`);
|
|
54
|
+
await tx `
|
|
55
|
+
INSERT INTO tenant_product (id, tenant_id, product_id, status)
|
|
56
|
+
VALUES (${(0, shared_1.uuidv7)()}, current_setting('app.current_tenant')::uuid, ${prod[0].id}, 'active')
|
|
57
|
+
ON CONFLICT (tenant_id, product_id) DO UPDATE SET status = 'active'
|
|
58
|
+
`;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository.js","sourceRoot":"","sources":["../../../src/products/repository.ts"],"names":[],"mappings":";;AAqBA,kDA8BC;AAGD,oDAUC;AAGD,kDAUC;AA7ED,0CAAuC;AAEvC,iDAA+C;AAC/C,6CAAwC;AAYxC;;;;;GAKG;AACI,KAAK,UAAU,mBAAmB,CAAC,EAAM,EAAE,MAAc;IAC9D,MAAM,IAAI,GAAG,MAAM,EAAE,CAUpB;;;;;;;wBAOqB,MAAM;;GAE3B,CAAC;IACF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACtB,QAAQ,EAAE,CAAC,CAAC,SAAS;QACrB,UAAU,EAAE,CAAC,CAAC,WAAW;QACzB,UAAU,EAAE,CAAC,CAAC,WAAW;QACzB,UAAU,EAAE,CAAC,CAAC,WAAW;QACzB,WAAW,EAAE,CAAC,CAAC,YAAY;QAC3B,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,OAAO,EAAE,CAAC,CAAC,QAAQ;KACpB,CAAC,CAAC,CAAC;AACN,CAAC;AAED,+DAA+D;AACxD,KAAK,UAAU,oBAAoB,CAAC,EAAM;IAC/C,KAAK,MAAM,CAAC,IAAI,qBAAQ,EAAE,CAAC;QACzB,MAAM,EAAE,CAAA;;gBAEI,IAAA,eAAM,GAAE,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,IAAI,IAAI,KAAK,CAAC,CAAC,QAAQ,IAAI,IAAI;;;;KAIhG,CAAC;IACJ,CAAC;AACH,CAAC;AAED,mDAAmD;AAC5C,KAAK,UAAU,mBAAmB,CAAC,EAAM,EAAE,QAAgB,EAAE,UAAkB;IACpF,MAAM,IAAA,wBAAW,EAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;QAC/C,MAAM,IAAI,GAAG,MAAM,EAAE,CAAkB,sCAAsC,UAAU,EAAE,CAAC;QAC1F,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,UAAU,EAAE,CAAC,CAAC;QACrE,MAAM,EAAE,CAAA;;gBAEI,IAAA,eAAM,GAAE,kDAAkD,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;;KAE/E,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.canDo = canDo;
|
|
4
|
+
exports.assertPermission = assertPermission;
|
|
5
|
+
exports.loadUserPermissions = loadUserPermissions;
|
|
6
|
+
const shared_1 = require("@baruk/shared");
|
|
7
|
+
/**
|
|
8
|
+
* Avaliação de permissão (04-rbac §6). Decisão sempre no backend; a RLS no banco
|
|
9
|
+
* é a última linha de defesa. Aqui trabalhamos sobre o conjunto de permissões já
|
|
10
|
+
* resolvido para o (usuário, tenant) corrente.
|
|
11
|
+
*/
|
|
12
|
+
function canDo(permissions, required) {
|
|
13
|
+
return permissions.has(required);
|
|
14
|
+
}
|
|
15
|
+
function assertPermission(permissions, required) {
|
|
16
|
+
if (!canDo(permissions, required)) {
|
|
17
|
+
throw new shared_1.ForbiddenError(`Permissão necessária: ${required}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Carrega as permissões efetivas de um usuário DENTRO do tenant corrente.
|
|
22
|
+
* Deve rodar dentro de `withContext({ tenantId, userId })` — a RLS de
|
|
23
|
+
* `user_role`/`role_permission` já restringe as linhas ao tenant ativo.
|
|
24
|
+
*/
|
|
25
|
+
async function loadUserPermissions(tx, userId) {
|
|
26
|
+
const rows = await tx `
|
|
27
|
+
SELECT DISTINCT p.key
|
|
28
|
+
FROM user_role ur
|
|
29
|
+
JOIN role_permission rp ON rp.role_id = ur.role_id
|
|
30
|
+
JOIN permission p ON p.id = rp.permission_id
|
|
31
|
+
WHERE ur.user_id = ${userId}
|
|
32
|
+
AND ur.deleted_at IS NULL
|
|
33
|
+
`;
|
|
34
|
+
return new Set(rows.map((r) => r.key));
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=authorize.js.map
|