@antelopejs/dms-saas 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/README.md +257 -10
  2. package/dist/billing-state/index.d.ts +1 -0
  3. package/dist/billing-state/index.js +1 -0
  4. package/dist/billing-state/index.js.map +1 -1
  5. package/dist/billing-state/past-due-banner.d.ts +4 -0
  6. package/dist/billing-state/past-due-banner.js +25 -0
  7. package/dist/billing-state/past-due-banner.js.map +1 -0
  8. package/dist/config/runtime.d.ts +6 -1
  9. package/dist/config/runtime.js +50 -1
  10. package/dist/config/runtime.js.map +1 -1
  11. package/dist/crons/recompute-billing-state.js +4 -1
  12. package/dist/crons/recompute-billing-state.js.map +1 -1
  13. package/dist/data-api/platformOwner/index.d.ts +1 -0
  14. package/dist/data-api/platformOwner/index.js +1 -0
  15. package/dist/data-api/platformOwner/index.js.map +1 -1
  16. package/dist/data-api/platformOwner/invitations.d.ts +22 -0
  17. package/dist/data-api/platformOwner/invitations.js +121 -0
  18. package/dist/data-api/platformOwner/invitations.js.map +1 -0
  19. package/dist/data-api/platformOwner/workspaces.d.ts +3 -0
  20. package/dist/data-api/platformOwner/workspaces.js +64 -12
  21. package/dist/data-api/platformOwner/workspaces.js.map +1 -1
  22. package/dist/data-api/tenant/tenant-invoices.js +2 -10
  23. package/dist/data-api/tenant/tenant-invoices.js.map +1 -1
  24. package/dist/hooks/register.js +2 -1
  25. package/dist/hooks/register.js.map +1 -1
  26. package/dist/implementations/dms-saas/billing.d.ts +2 -1
  27. package/dist/implementations/dms-saas/billing.js +6 -0
  28. package/dist/implementations/dms-saas/billing.js.map +1 -1
  29. package/dist/index.js +5 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/invoice-line-items/injection.d.ts +10 -0
  32. package/dist/invoice-line-items/injection.js +7 -3
  33. package/dist/invoice-line-items/injection.js.map +1 -1
  34. package/dist/operator-actions/index.d.ts +1 -0
  35. package/dist/operator-actions/index.js +1 -0
  36. package/dist/operator-actions/index.js.map +1 -1
  37. package/dist/operator-actions/invitation-commands.d.ts +12 -0
  38. package/dist/operator-actions/invitation-commands.js +46 -0
  39. package/dist/operator-actions/invitation-commands.js.map +1 -0
  40. package/dist/operator-actions/types.d.ts +1 -1
  41. package/dist/pages/platform/dashboard.js +2 -4
  42. package/dist/pages/platform/dashboard.js.map +1 -1
  43. package/dist/pages/platform/workspaces/detail.js +40 -1
  44. package/dist/pages/platform/workspaces/detail.js.map +1 -1
  45. package/dist/pages/platform/workspaces/index.d.ts +2 -8
  46. package/dist/pages/platform/workspaces/index.js +27 -111
  47. package/dist/pages/platform/workspaces/index.js.map +1 -1
  48. package/dist/pages/public/legal/privacy-policy.js +2 -1
  49. package/dist/pages/public/legal/privacy-policy.js.map +1 -1
  50. package/dist/pages/public/legal/terms-and-conditions.js +2 -1
  51. package/dist/pages/public/legal/terms-and-conditions.js.map +1 -1
  52. package/dist/pages/public/legal/terms-of-use.js +2 -1
  53. package/dist/pages/public/legal/terms-of-use.js.map +1 -1
  54. package/dist/plans/index.d.ts +1 -0
  55. package/dist/plans/index.js +1 -0
  56. package/dist/plans/index.js.map +1 -1
  57. package/dist/plans/platform-support.d.ts +2 -0
  58. package/dist/plans/platform-support.js +19 -0
  59. package/dist/plans/platform-support.js.map +1 -0
  60. package/dist/plans/seat-capacity.d.ts +9 -2
  61. package/dist/plans/seat-capacity.js +59 -12
  62. package/dist/plans/seat-capacity.js.map +1 -1
  63. package/dist/plans/seat-hooks.js +34 -13
  64. package/dist/plans/seat-hooks.js.map +1 -1
  65. package/dist/routes/platformOwner/dashboard.d.ts +8 -6
  66. package/dist/routes/platformOwner/dashboard.js +31 -17
  67. package/dist/routes/platformOwner/dashboard.js.map +1 -1
  68. package/dist/routes/platformOwner/index.d.ts +1 -0
  69. package/dist/routes/platformOwner/index.js +1 -0
  70. package/dist/routes/platformOwner/index.js.map +1 -1
  71. package/dist/routes/platformOwner/workspace-invitations.d.ts +13 -0
  72. package/dist/routes/platformOwner/workspace-invitations.js +73 -0
  73. package/dist/routes/platformOwner/workspace-invitations.js.map +1 -0
  74. package/dist/routes/public/register.d.ts +7 -3
  75. package/dist/routes/public/register.js +42 -27
  76. package/dist/routes/public/register.js.map +1 -1
  77. package/dist/routes/tenant/tenant-billing.d.ts +7 -11
  78. package/dist/routes/tenant/tenant-billing.js +34 -26
  79. package/dist/routes/tenant/tenant-billing.js.map +1 -1
  80. package/dist/routes/tenant/tenant-plan.d.ts +1 -0
  81. package/dist/routes/tenant/tenant-plan.js +27 -2
  82. package/dist/routes/tenant/tenant-plan.js.map +1 -1
  83. package/dist/routes/tenant/tenant-seats.d.ts +2 -4
  84. package/dist/routes/tenant/tenant-seats.js.map +1 -1
  85. package/dist/routes/tenant/workspaces.d.ts +2 -0
  86. package/dist/routes/tenant/workspaces.js +10 -4
  87. package/dist/routes/tenant/workspaces.js.map +1 -1
  88. package/dist/stripe/upcoming-invoice.d.ts +21 -0
  89. package/dist/stripe/upcoming-invoice.js +42 -0
  90. package/dist/stripe/upcoming-invoice.js.map +1 -0
  91. package/dist/stripe/webhook-dispatch.js +2 -0
  92. package/dist/stripe/webhook-dispatch.js.map +1 -1
  93. package/dist/types/config.d.ts +9 -0
  94. package/dist/types/config.js +7 -0
  95. package/dist/types/config.js.map +1 -1
  96. package/dist/upcoming-invoice/db/preview-cache.model.d.ts +38 -0
  97. package/dist/upcoming-invoice/db/preview-cache.model.js +57 -0
  98. package/dist/upcoming-invoice/db/preview-cache.model.js.map +1 -0
  99. package/dist/upcoming-invoice/db/preview-cache.table.d.ts +10 -0
  100. package/dist/upcoming-invoice/db/preview-cache.table.js +42 -0
  101. package/dist/upcoming-invoice/db/preview-cache.table.js.map +1 -0
  102. package/dist/upcoming-invoice/eligibility.d.ts +17 -0
  103. package/dist/upcoming-invoice/eligibility.js +52 -0
  104. package/dist/upcoming-invoice/eligibility.js.map +1 -0
  105. package/dist/upcoming-invoice/invalidation.d.ts +2 -0
  106. package/dist/upcoming-invoice/invalidation.js +39 -0
  107. package/dist/upcoming-invoice/invalidation.js.map +1 -0
  108. package/dist/upcoming-invoice/mapping.d.ts +8 -0
  109. package/dist/upcoming-invoice/mapping.js +82 -0
  110. package/dist/upcoming-invoice/mapping.js.map +1 -0
  111. package/dist/upcoming-invoice/outcomes.d.ts +13 -0
  112. package/dist/upcoming-invoice/outcomes.js +15 -0
  113. package/dist/upcoming-invoice/outcomes.js.map +1 -0
  114. package/dist/upcoming-invoice/preview.d.ts +3 -0
  115. package/dist/upcoming-invoice/preview.js +80 -0
  116. package/dist/upcoming-invoice/preview.js.map +1 -0
  117. package/dist/upcoming-invoice/pricing.d.ts +3 -0
  118. package/dist/upcoming-invoice/pricing.js +84 -0
  119. package/dist/upcoming-invoice/pricing.js.map +1 -0
  120. package/dist/upcoming-invoice/usage.d.ts +14 -0
  121. package/dist/upcoming-invoice/usage.js +53 -0
  122. package/dist/upcoming-invoice/usage.js.map +1 -0
  123. package/dist/workspaces/billing-identity.d.ts +19 -0
  124. package/dist/workspaces/billing-identity.js +51 -0
  125. package/dist/workspaces/billing-identity.js.map +1 -0
  126. package/dist/workspaces/default-plan.d.ts +5 -0
  127. package/dist/workspaces/default-plan.js +109 -0
  128. package/dist/workspaces/default-plan.js.map +1 -0
  129. package/dist/workspaces/index.d.ts +2 -0
  130. package/dist/workspaces/index.js +2 -0
  131. package/dist/workspaces/index.js.map +1 -1
  132. package/dist/workspaces/invitations.d.ts +26 -0
  133. package/dist/workspaces/invitations.js +112 -0
  134. package/dist/workspaces/invitations.js.map +1 -0
  135. package/dist/workspaces/provisioning.d.ts +3 -3
  136. package/dist/workspaces/provisioning.js +39 -11
  137. package/dist/workspaces/provisioning.js.map +1 -1
  138. package/frontend-vue/app/components/BillingIdentityFields.vue +179 -0
  139. package/frontend-vue/app/components/PastDueBanner.vue +81 -0
  140. package/frontend-vue/app/components/PaymentMethodCard.vue +94 -38
  141. package/frontend-vue/app/components/PlanComparisonModal.vue +62 -26
  142. package/frontend-vue/app/components/PlanUpgradeModal.vue +181 -0
  143. package/frontend-vue/app/components/PlatformNotes.vue +4 -0
  144. package/frontend-vue/app/components/RefundButton.vue +10 -1
  145. package/frontend-vue/app/components/Register.vue +49 -92
  146. package/frontend-vue/app/components/SeatQuotaBanner.vue +28 -0
  147. package/frontend-vue/app/components/TenantBillingForm.vue +52 -128
  148. package/frontend-vue/app/components/TenantPlanCard.vue +68 -10
  149. package/frontend-vue/app/components/UserSummaryCard.vue +12 -10
  150. package/frontend-vue/app/components/WorkspaceAdminCreateModal.vue +202 -0
  151. package/frontend-vue/app/components/WorkspaceCreateModal.vue +46 -9
  152. package/frontend-vue/app/components/WorkspaceInvitationLink.vue +106 -0
  153. package/frontend-vue/app/components/WorkspaceSummaryCard.vue +39 -15
  154. package/frontend-vue/app/components/WorkspaceSuspended.vue +3 -5
  155. package/frontend-vue/app/components/WorkspaceSwitcherWidget.vue +8 -5
  156. package/frontend-vue/app/composables/useBillingCountries.ts +25 -5
  157. package/frontend-vue/app/composables/useBillingIdentity.ts +141 -0
  158. package/frontend-vue/app/composables/useInvitationLink.ts +69 -0
  159. package/frontend-vue/app/composables/usePastDueBannerAction.ts +20 -0
  160. package/frontend-vue/app/composables/usePlanComparison.ts +15 -0
  161. package/frontend-vue/app/composables/usePlanFeatureFormat.ts +312 -20
  162. package/frontend-vue/app/composables/usePlanFeatureLabel.ts +24 -0
  163. package/frontend-vue/app/composables/useSaasRegistration.ts +110 -223
  164. package/frontend-vue/app/composables/useSeatQuota.ts +8 -0
  165. package/frontend-vue/app/composables/useStripePaymentElement.ts +3 -3
  166. package/frontend-vue/app/composables/useWorkspaceAccessCache.ts +29 -2
  167. package/frontend-vue/app/composables/useWorkspaceFinalization.ts +7 -32
  168. package/frontend-vue/app/custom-pages/auth/no-workspace.vue +49 -194
  169. package/frontend-vue/app/plugins/auth-links.ts +0 -4
  170. package/frontend-vue/app/types/runtime-config.ts +13 -0
  171. package/frontend-vue/dms.frontend.ts +10 -4
  172. package/frontend-vue/i18n/locales/saas-en-GB.json +161 -36
  173. package/frontend-vue/i18n/locales/saas-fr-FR.json +162 -37
  174. package/frontend-vue/package.json +0 -1
  175. package/frontend-vue/pnpm-lock.yaml +1 -125
  176. package/package.json +5 -5
  177. package/frontend-vue/app/middleware/workspace-suspended.global.ts +0 -59
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.dispatchStripeWebhookEvent = dispatchStripeWebhookEvent;
4
4
  const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
5
5
  const db_1 = require("../db");
6
+ const invalidation_1 = require("../upcoming-invoice/invalidation");
6
7
  const webhook_handlers_1 = require("./webhook-handlers");
7
8
  const webhook_checkout_1 = require("./webhook-checkout");
8
9
  const webhook_credit_notes_1 = require("./webhook-credit-notes");
@@ -40,6 +41,7 @@ async function dispatchStripeWebhookEvent(event) {
40
41
  await stripeWebhookEventModel.markResult(event.id, claimed, "reconciliation_required", message);
41
42
  throw error;
42
43
  }
44
+ await (0, invalidation_1.invalidatePreviewForStripeEvent)(event);
43
45
  await stripeWebhookEventModel.markResult(event.id, claimed, "success", null);
44
46
  }
45
47
  //# sourceMappingURL=webhook-dispatch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-dispatch.js","sourceRoot":"","sources":["../../src/stripe/webhook-dispatch.ts"],"names":[],"mappings":";;AA2CA,gEA+BC;AA1ED,6FAAqE;AAErE,8BAAgD;AAChD,yDAW4B;AAC5B,yDAG4B;AAC5B,iEAGgC;AAIhC,MAAM,QAAQ,GAAmC;IAC/C,4BAA4B,EAAE,iDAA8B;IAC5D,0BAA0B,EAAE,+CAA4B;IACxD,iBAAiB,EAAE,uCAAoB;IACvC,mBAAmB,EAAE,yCAAsB;IAC3C,cAAc,EAAE,oCAAiB;IACjC,gBAAgB,EAAE,sCAAmB;IACrC,wBAAwB,EAAE,6CAA0B;IACpD,qBAAqB,EAAE,8CAAuB;IAC9C,oBAAoB,EAAE,6CAAsB;IAC5C,uBAAuB,EAAE,4CAAyB;IAClD,kBAAkB,EAAE,wCAAqB;IACzC,+BAA+B,EAAE,4CAAyB;IAC1D,sCAAsC,EAAE,qCAAkB;IAC1D,+BAA+B,EAAE,4CAAyB;CAC3D,CAAC;AAEK,KAAK,UAAU,0BAA0B,CAC9C,KAAmB;IAEnB,MAAM,uBAAuB,GAAG,IAAA,wCAAQ,EAAC,4BAAuB,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7E,IAAI,CAAC,OAAO;QAAE,OAAO;IAErB,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,uBAAuB,CAAC,UAAU,CACtC,KAAK,CAAC,EAAE,EACR,OAAO,EACP,SAAS,EACT,IAAI,CACL,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,uBAAuB,CAAC,UAAU,CACtC,KAAK,CAAC,EAAE,EACR,OAAO,EACP,yBAAyB,EACzB,OAAO,CACR,CAAC;QACF,MAAM,KAAK,CAAC;IACd,CAAC;IACD,MAAM,uBAAuB,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;AAC/E,CAAC"}
1
+ {"version":3,"file":"webhook-dispatch.js","sourceRoot":"","sources":["../../src/stripe/webhook-dispatch.ts"],"names":[],"mappings":";;AA4CA,gEAgCC;AA5ED,6FAAqE;AAErE,8BAAgD;AAChD,mEAAmF;AACnF,yDAW4B;AAC5B,yDAG4B;AAC5B,iEAGgC;AAIhC,MAAM,QAAQ,GAAmC;IAC/C,4BAA4B,EAAE,iDAA8B;IAC5D,0BAA0B,EAAE,+CAA4B;IACxD,iBAAiB,EAAE,uCAAoB;IACvC,mBAAmB,EAAE,yCAAsB;IAC3C,cAAc,EAAE,oCAAiB;IACjC,gBAAgB,EAAE,sCAAmB;IACrC,wBAAwB,EAAE,6CAA0B;IACpD,qBAAqB,EAAE,8CAAuB;IAC9C,oBAAoB,EAAE,6CAAsB;IAC5C,uBAAuB,EAAE,4CAAyB;IAClD,kBAAkB,EAAE,wCAAqB;IACzC,+BAA+B,EAAE,4CAAyB;IAC1D,sCAAsC,EAAE,qCAAkB;IAC1D,+BAA+B,EAAE,4CAAyB;CAC3D,CAAC;AAEK,KAAK,UAAU,0BAA0B,CAC9C,KAAmB;IAEnB,MAAM,uBAAuB,GAAG,IAAA,wCAAQ,EAAC,4BAAuB,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7E,IAAI,CAAC,OAAO;QAAE,OAAO;IAErB,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,uBAAuB,CAAC,UAAU,CACtC,KAAK,CAAC,EAAE,EACR,OAAO,EACP,SAAS,EACT,IAAI,CACL,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,uBAAuB,CAAC,UAAU,CACtC,KAAK,CAAC,EAAE,EACR,OAAO,EACP,yBAAyB,EACzB,OAAO,CACR,CAAC;QACF,MAAM,KAAK,CAAC;IACd,CAAC;IACD,MAAM,IAAA,8CAA+B,EAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,uBAAuB,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;AAC/E,CAAC"}
@@ -7,10 +7,19 @@ export interface DmsSaasPublicScreensConfig {
7
7
  register?: boolean;
8
8
  }
9
9
  export type PublicScreenId = keyof DmsSaasPublicScreensConfig;
10
+ export declare const REGISTRATION_PAYMENT_METHOD_POLICIES: readonly ["required", "optional", "none"];
11
+ export type RegistrationPaymentMethodPolicy = (typeof REGISTRATION_PAYMENT_METHOD_POLICIES)[number];
12
+ export declare const DEFAULT_REGISTRATION_PAYMENT_METHOD_POLICY: RegistrationPaymentMethodPolicy;
13
+ export interface DmsSaasRegistrationConfig {
14
+ paymentMethod?: RegistrationPaymentMethodPolicy;
15
+ }
10
16
  export interface DmsSaasConfig {
11
17
  stripe: DmsSaasStripeConfig;
12
18
  admissionMode?: "open" | "invitation-only";
19
+ registration?: DmsSaasRegistrationConfig;
13
20
  supportStorage?: string;
14
21
  publicScreens?: DmsSaasPublicScreensConfig;
15
22
  allowedRedirectHosts?: string[];
23
+ defaultPlanSlug?: string;
24
+ upcomingInvoicePreviewCacheTtlSeconds?: number;
16
25
  }
@@ -1,3 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_REGISTRATION_PAYMENT_METHOD_POLICY = exports.REGISTRATION_PAYMENT_METHOD_POLICIES = void 0;
4
+ exports.REGISTRATION_PAYMENT_METHOD_POLICIES = [
5
+ "required",
6
+ "optional",
7
+ "none",
8
+ ];
9
+ exports.DEFAULT_REGISTRATION_PAYMENT_METHOD_POLICY = "required";
3
10
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":";;;AAsBa,QAAA,oCAAoC,GAAG;IAClD,UAAU;IACV,UAAU;IACV,MAAM;CACE,CAAC;AAME,QAAA,0CAA0C,GACrD,UAAU,CAAC"}
@@ -0,0 +1,38 @@
1
+ import type { UpcomingInvoicePreview } from "@antelopejs/interface-dms-saas/billing";
2
+ import { UpcomingInvoicePreviewEntry } from "./preview-cache.table";
3
+ export interface PreviewCacheLookup {
4
+ tenantId: string;
5
+ sourceVersion: string;
6
+ computedNotBefore: Date;
7
+ }
8
+ export interface PreviewCacheWrite {
9
+ tenantId: string;
10
+ preview: UpcomingInvoicePreview;
11
+ sourceVersion: string;
12
+ computedAt: Date;
13
+ }
14
+ declare const UpcomingInvoicePreviewCacheModel_base: {
15
+ new (database: import("@antelopejs/interface-database").SchemaInstance<any>): {
16
+ readonly table: import("@antelopejs/interface-database").Table<UpcomingInvoicePreviewEntry>;
17
+ readonly database: import("@antelopejs/interface-database").SchemaInstance<any>;
18
+ get(id: string): PromiseLike<UpcomingInvoicePreviewEntry | undefined>;
19
+ getBy(index: keyof UpcomingInvoicePreviewEntry, ...keys: any[]): PromiseLike<UpcomingInvoicePreviewEntry[]>;
20
+ getAll(): PromiseLike<UpcomingInvoicePreviewEntry[]>;
21
+ insert(obj: import("@antelopejs/interface-database-decorators").DeepPartial<UpcomingInvoicePreviewEntry> | import("@antelopejs/interface-database-decorators").DeepPartial<UpcomingInvoicePreviewEntry>[], options?: import("@antelopejs/interface-database-decorators").ValidateOptions): Promise<string[]>;
22
+ update(id: string, obj: import("@antelopejs/interface-database-decorators").DeepPartial<UpcomingInvoicePreviewEntry>, options?: import("@antelopejs/interface-database-decorators").ValidateOptions): Promise<number>;
23
+ update(obj: import("@antelopejs/interface-database-decorators").DeepPartial<UpcomingInvoicePreviewEntry>, options?: import("@antelopejs/interface-database-decorators").ValidateOptions): Promise<number>;
24
+ delete(id: string): Promise<number>;
25
+ };
26
+ readonly schemaName: string;
27
+ fromPlainData(obj: any): UpcomingInvoicePreviewEntry;
28
+ fromDatabase(obj: any): UpcomingInvoicePreviewEntry | undefined;
29
+ toDatabase(obj: any): Record<string, any>;
30
+ validate(obj: unknown, options?: import("@antelopejs/interface-database-decorators").ValidateInputOptions): import("@antelopejs/interface-database-decorators").ValidationResult;
31
+ };
32
+ export declare class UpcomingInvoicePreviewCacheModel extends UpcomingInvoicePreviewCacheModel_base {
33
+ readFresh(lookup: PreviewCacheLookup): Promise<UpcomingInvoicePreview | null>;
34
+ store(write: PreviewCacheWrite): Promise<void>;
35
+ invalidate(tenantId: string, at: Date): Promise<void>;
36
+ private upsert;
37
+ }
38
+ export {};
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UpcomingInvoicePreviewCacheModel = void 0;
4
+ const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
5
+ const preview_cache_table_1 = require("./preview-cache.table");
6
+ const EMPTY_ENTRY = {
7
+ preview: null,
8
+ sourceVersion: null,
9
+ computedAt: null,
10
+ invalidatedAt: null,
11
+ };
12
+ function timeOf(date) {
13
+ return date ? new Date(date).getTime() : null;
14
+ }
15
+ function isFresh(entry, lookup) {
16
+ const computedAt = timeOf(entry.computedAt);
17
+ if (!entry.preview || computedAt === null)
18
+ return false;
19
+ if (entry.sourceVersion !== lookup.sourceVersion)
20
+ return false;
21
+ if (computedAt < lookup.computedNotBefore.getTime())
22
+ return false;
23
+ const invalidatedAt = timeOf(entry.invalidatedAt);
24
+ return invalidatedAt === null || computedAt > invalidatedAt;
25
+ }
26
+ class UpcomingInvoicePreviewCacheModel extends (0, interface_database_decorators_1.BasicDataModel)(preview_cache_table_1.UpcomingInvoicePreviewEntry, preview_cache_table_1.upcomingInvoicePreviewsTableName) {
27
+ async readFresh(lookup) {
28
+ const entry = await this.get(lookup.tenantId);
29
+ return entry && isFresh(entry, lookup) ? entry.preview : null;
30
+ }
31
+ async store(write) {
32
+ await this.upsert(write.tenantId, {
33
+ preview: write.preview,
34
+ sourceVersion: write.sourceVersion,
35
+ computedAt: write.computedAt,
36
+ });
37
+ }
38
+ async invalidate(tenantId, at) {
39
+ await this.upsert(tenantId, { invalidatedAt: at });
40
+ }
41
+ async upsert(tenantId, patch) {
42
+ if (await this.get(tenantId)) {
43
+ await this.update(tenantId, patch);
44
+ return;
45
+ }
46
+ try {
47
+ await this.insert({ ...EMPTY_ENTRY, ...patch, _id: tenantId });
48
+ }
49
+ catch (error) {
50
+ if (!(await this.get(tenantId)))
51
+ throw error;
52
+ await this.update(tenantId, patch);
53
+ }
54
+ }
55
+ }
56
+ exports.UpcomingInvoicePreviewCacheModel = UpcomingInvoicePreviewCacheModel;
57
+ //# sourceMappingURL=preview-cache.model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview-cache.model.js","sourceRoot":"","sources":["../../../src/upcoming-invoice/db/preview-cache.model.ts"],"names":[],"mappings":";;;AACA,6FAA2E;AAC3E,+DAG+B;AAmB/B,MAAM,WAAW,GAAe;IAC9B,OAAO,EAAE,IAAI;IACb,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE,IAAI;IAChB,aAAa,EAAE,IAAI;CACpB,CAAC;AAEF,SAAS,MAAM,CAAC,IAA6B;IAC3C,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAChD,CAAC;AAED,SAAS,OAAO,CACd,KAAkC,EAClC,MAA0B;IAE1B,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC5C,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACxD,IAAI,KAAK,CAAC,aAAa,KAAK,MAAM,CAAC,aAAa;QAAE,OAAO,KAAK,CAAC;IAC/D,IAAI,UAAU,GAAG,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE;QAAE,OAAO,KAAK,CAAC;IAClE,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAClD,OAAO,aAAa,KAAK,IAAI,IAAI,UAAU,GAAG,aAAa,CAAC;AAC9D,CAAC;AAGD,MAAa,gCAAiC,SAAQ,IAAA,8CAAc,EAClE,iDAA2B,EAC3B,sDAAgC,CACjC;IACC,KAAK,CAAC,SAAS,CACb,MAA0B;QAE1B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9C,OAAO,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IAChE,CAAC;IAGD,KAAK,CAAC,KAAK,CAAC,KAAwB;QAClC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE;YAChC,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,UAAU,EAAE,KAAK,CAAC,UAAU;SAC7B,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,QAAgB,EAAE,EAAQ;QACzC,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,CAAC;IACrD,CAAC;IAEO,KAAK,CAAC,MAAM,CAAC,QAAgB,EAAE,KAAiB;QACtD,IAAI,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACnC,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,WAAW,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QACjE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAAE,MAAM,KAAK,CAAC;YAC7C,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;CACF;AApCD,4EAoCC"}
@@ -0,0 +1,10 @@
1
+ import { Table } from "@antelopejs/interface-database-decorators";
2
+ import type { UpcomingInvoicePreview } from "@antelopejs/interface-dms-saas/billing";
3
+ export declare const upcomingInvoicePreviewsTableName = "saas_upcoming_invoice_previews";
4
+ export declare class UpcomingInvoicePreviewEntry extends Table {
5
+ _id: string;
6
+ preview: UpcomingInvoicePreview | null;
7
+ sourceVersion: string | null;
8
+ computedAt: Date | null;
9
+ invalidatedAt: Date | null;
10
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.UpcomingInvoicePreviewEntry = exports.upcomingInvoicePreviewsTableName = void 0;
13
+ const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
14
+ const constants_1 = require("@antelopejs/interface-dms/constants");
15
+ exports.upcomingInvoicePreviewsTableName = "saas_upcoming_invoice_previews";
16
+ let UpcomingInvoicePreviewEntry = class UpcomingInvoicePreviewEntry extends interface_database_decorators_1.Table {
17
+ };
18
+ exports.UpcomingInvoicePreviewEntry = UpcomingInvoicePreviewEntry;
19
+ __decorate([
20
+ (0, interface_database_decorators_1.Field)("string"),
21
+ __metadata("design:type", String)
22
+ ], UpcomingInvoicePreviewEntry.prototype, "_id", void 0);
23
+ __decorate([
24
+ (0, interface_database_decorators_1.Field)("any"),
25
+ __metadata("design:type", Object)
26
+ ], UpcomingInvoicePreviewEntry.prototype, "preview", void 0);
27
+ __decorate([
28
+ (0, interface_database_decorators_1.Field)("string"),
29
+ __metadata("design:type", Object)
30
+ ], UpcomingInvoicePreviewEntry.prototype, "sourceVersion", void 0);
31
+ __decorate([
32
+ (0, interface_database_decorators_1.Field)("date"),
33
+ __metadata("design:type", Object)
34
+ ], UpcomingInvoicePreviewEntry.prototype, "computedAt", void 0);
35
+ __decorate([
36
+ (0, interface_database_decorators_1.Field)("date"),
37
+ __metadata("design:type", Object)
38
+ ], UpcomingInvoicePreviewEntry.prototype, "invalidatedAt", void 0);
39
+ exports.UpcomingInvoicePreviewEntry = UpcomingInvoicePreviewEntry = __decorate([
40
+ (0, interface_database_decorators_1.RegisterTable)(exports.upcomingInvoicePreviewsTableName, constants_1.CORE_SCHEMA_NAME)
41
+ ], UpcomingInvoicePreviewEntry);
42
+ //# sourceMappingURL=preview-cache.table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview-cache.table.js","sourceRoot":"","sources":["../../../src/upcoming-invoice/db/preview-cache.table.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6FAImD;AACnD,mEAAuE;AAG1D,QAAA,gCAAgC,GAC3C,gCAAgC,CAAC;AAQ5B,IAAM,2BAA2B,GAAjC,MAAM,2BAA4B,SAAQ,qCAAK;CAiBrD,CAAA;AAjBY,kEAA2B;AAE9B;IADP,IAAA,qCAAK,EAAC,QAAQ,CAAC;;wDACI;AAGZ;IADP,IAAA,qCAAK,EAAC,KAAK,CAAC;;4DACkC;AAIvC;IADP,IAAA,qCAAK,EAAC,QAAQ,CAAC;;kEACqB;AAI7B;IADP,IAAA,qCAAK,EAAC,MAAM,CAAC;;+DACkB;AAGxB;IADP,IAAA,qCAAK,EAAC,MAAM,CAAC;;kEACqB;sCAhBxB,2BAA2B;IADvC,IAAA,6CAAa,EAAC,wCAAgC,EAAE,4BAAgB,CAAC;GACrD,2BAA2B,CAiBvC"}
@@ -0,0 +1,17 @@
1
+ import type { Plan, TenantSubscription } from "../db";
2
+ import { type PreviewOutcome } from "./outcomes";
3
+ export interface PreviewableSubscription {
4
+ subscription: TenantSubscription;
5
+ customerId: string;
6
+ subscriptionId: string;
7
+ }
8
+ export interface PreviewableEligibility {
9
+ isPreviewable: true;
10
+ target: PreviewableSubscription;
11
+ }
12
+ export interface SettledEligibility {
13
+ isPreviewable: false;
14
+ outcome: PreviewOutcome;
15
+ }
16
+ export type PreviewEligibility = PreviewableEligibility | SettledEligibility;
17
+ export declare function resolvePreviewEligibility(subscription: TenantSubscription | undefined, plan: Plan | undefined): PreviewEligibility;
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolvePreviewEligibility = resolvePreviewEligibility;
4
+ const client_1 = require("../stripe/client");
5
+ const complimentary_1 = require("../workspaces/complimentary");
6
+ const free_workspace_guard_1 = require("../workspaces/free-workspace-guard");
7
+ const outcomes_1 = require("./outcomes");
8
+ const ELIGIBILITY_RULES = [
9
+ {
10
+ outcome: (0, outcomes_1.absent)("complimentary"),
11
+ applies: (subscription) => (0, complimentary_1.isComplimentarySubscription)(subscription),
12
+ },
13
+ {
14
+ outcome: (0, outcomes_1.absent)("subscription_not_configured"),
15
+ applies: (_subscription, plan) => !plan,
16
+ },
17
+ {
18
+ outcome: (0, outcomes_1.absent)("free_plan"),
19
+ applies: (_subscription, plan) => !!plan && (0, free_workspace_guard_1.isFreePlan)(plan),
20
+ },
21
+ {
22
+ outcome: (0, outcomes_1.absent)("customer_not_configured"),
23
+ applies: (subscription) => !subscription.stripeCustomerId,
24
+ },
25
+ ];
26
+ function toPreviewable(subscription) {
27
+ const { stripeCustomerId, stripeSubscriptionId } = subscription;
28
+ if (!stripeCustomerId || !stripeSubscriptionId)
29
+ return null;
30
+ return {
31
+ subscription,
32
+ customerId: stripeCustomerId,
33
+ subscriptionId: stripeSubscriptionId,
34
+ };
35
+ }
36
+ function settled(outcome) {
37
+ return { isPreviewable: false, outcome };
38
+ }
39
+ function resolvePreviewEligibility(subscription, plan) {
40
+ if (!subscription)
41
+ return settled((0, outcomes_1.absent)("subscription_not_configured"));
42
+ const rule = ELIGIBILITY_RULES.find((candidate) => candidate.applies(subscription, plan));
43
+ if (rule)
44
+ return settled(rule.outcome);
45
+ const target = toPreviewable(subscription);
46
+ if (!target)
47
+ return settled((0, outcomes_1.absent)("subscription_not_configured"));
48
+ if (!(0, client_1.isStripeConfigured)())
49
+ return settled((0, outcomes_1.unavailable)("stripe_not_configured"));
50
+ return { isPreviewable: true, target };
51
+ }
52
+ //# sourceMappingURL=eligibility.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eligibility.js","sourceRoot":"","sources":["../../src/upcoming-invoice/eligibility.ts"],"names":[],"mappings":";;AA6EA,8DAcC;AA1FD,6CAAsD;AACtD,+DAA0E;AAC1E,6EAAgE;AAChE,yCAAsE;AAkCtE,MAAM,iBAAiB,GAAsB;IAC3C;QACE,OAAO,EAAE,IAAA,iBAAM,EAAC,eAAe,CAAC;QAChC,OAAO,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,IAAA,2CAA2B,EAAC,YAAY,CAAC;KACrE;IACD;QACE,OAAO,EAAE,IAAA,iBAAM,EAAC,6BAA6B,CAAC;QAC9C,OAAO,EAAE,CAAC,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI;KACxC;IACD;QACE,OAAO,EAAE,IAAA,iBAAM,EAAC,WAAW,CAAC;QAC5B,OAAO,EAAE,CAAC,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,IAAA,iCAAU,EAAC,IAAI,CAAC;KAC7D;IACD;QACE,OAAO,EAAE,IAAA,iBAAM,EAAC,yBAAyB,CAAC;QAC1C,OAAO,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,gBAAgB;KAC1D;CACF,CAAC;AAEF,SAAS,aAAa,CACpB,YAAgC;IAEhC,MAAM,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,GAAG,YAAY,CAAC;IAChE,IAAI,CAAC,gBAAgB,IAAI,CAAC,oBAAoB;QAAE,OAAO,IAAI,CAAC;IAC5D,OAAO;QACL,YAAY;QACZ,UAAU,EAAE,gBAAgB;QAC5B,cAAc,EAAE,oBAAoB;KACrC,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,OAAuB;IACtC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC3C,CAAC;AAMD,SAAgB,yBAAyB,CACvC,YAA4C,EAC5C,IAAsB;IAEtB,IAAI,CAAC,YAAY;QAAE,OAAO,OAAO,CAAC,IAAA,iBAAM,EAAC,6BAA6B,CAAC,CAAC,CAAC;IACzE,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAChD,SAAS,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CACtC,CAAC;IACF,IAAI,IAAI;QAAE,OAAO,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;IAC3C,IAAI,CAAC,MAAM;QAAE,OAAO,OAAO,CAAC,IAAA,iBAAM,EAAC,6BAA6B,CAAC,CAAC,CAAC;IACnE,IAAI,CAAC,IAAA,2BAAkB,GAAE;QACvB,OAAO,OAAO,CAAC,IAAA,sBAAW,EAAC,uBAAuB,CAAC,CAAC,CAAC;IACvD,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AACzC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type Stripe from "stripe";
2
+ export declare function invalidatePreviewForStripeEvent(event: Stripe.Event): Promise<void>;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.invalidatePreviewForStripeEvent = invalidatePreviewForStripeEvent;
4
+ const logging_1 = require("@antelopejs/interface-core/logging");
5
+ const webhook_shared_1 = require("../stripe/webhook-shared");
6
+ const preview_1 = require("./preview");
7
+ const LOG_PREFIX = "[dms-saas:upcoming-invoice]";
8
+ const CUSTOMER_OBJECT = "customer";
9
+ const INVALIDATING_EVENT_TYPES = new Set([
10
+ "invoice.created",
11
+ "invoice.finalized",
12
+ "invoice.paid",
13
+ "invoice.voided",
14
+ "customer.updated",
15
+ "customer.subscription.updated",
16
+ "customer.subscription.deleted",
17
+ ]);
18
+ function eventCustomerId(event) {
19
+ const object = event.data.object;
20
+ if (object.object === CUSTOMER_OBJECT)
21
+ return object.id ?? null;
22
+ return (0, webhook_shared_1.asCustomerId)(object.customer);
23
+ }
24
+ async function invalidatePreviewForStripeEvent(event) {
25
+ if (!INVALIDATING_EVENT_TYPES.has(event.type))
26
+ return;
27
+ const customerId = eventCustomerId(event);
28
+ if (!customerId)
29
+ return;
30
+ try {
31
+ const tenant = await (0, webhook_shared_1.findTenantByCustomerId)(customerId);
32
+ if (tenant)
33
+ await (0, preview_1.invalidateUpcomingInvoicePreview)(tenant._id);
34
+ }
35
+ catch (error) {
36
+ logging_1.Logging.Error(`${LOG_PREFIX} could not invalidate the preview after ${event.type} ${event.id}`, error);
37
+ }
38
+ }
39
+ //# sourceMappingURL=invalidation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invalidation.js","sourceRoot":"","sources":["../../src/upcoming-invoice/invalidation.ts"],"names":[],"mappings":";;AAyCA,0EAeC;AAxDD,gEAA6D;AAE7D,6DAAgF;AAChF,uCAA6D;AAE7D,MAAM,UAAU,GAAG,6BAA6B,CAAC;AACjD,MAAM,eAAe,GAAG,UAAU,CAAC;AAQnC,MAAM,wBAAwB,GAAG,IAAI,GAAG,CAAS;IAC/C,iBAAiB;IACjB,mBAAmB;IACnB,cAAc;IACd,gBAAgB;IAChB,kBAAkB;IAClB,+BAA+B;IAC/B,+BAA+B;CAChC,CAAC,CAAC;AAQH,SAAS,eAAe,CAAC,KAAmB;IAC1C,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,MAA6B,CAAC;IACxD,IAAI,MAAM,CAAC,MAAM,KAAK,eAAe;QAAE,OAAO,MAAM,CAAC,EAAE,IAAI,IAAI,CAAC;IAChE,OAAO,IAAA,6BAAY,EAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AACvC,CAAC;AAOM,KAAK,UAAU,+BAA+B,CACnD,KAAmB;IAEnB,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO;IACtD,MAAM,UAAU,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IAC1C,IAAI,CAAC,UAAU;QAAE,OAAO;IACxB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAA,uCAAsB,EAAC,UAAU,CAAC,CAAC;QACxD,IAAI,MAAM;YAAE,MAAM,IAAA,0CAAgC,EAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,iBAAO,CAAC,KAAK,CACX,GAAG,UAAU,2CAA2C,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,EAAE,EAChF,KAAK,CACN,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { AvailableUpcomingInvoicePreview } from "@antelopejs/interface-dms-saas/billing";
2
+ import type Stripe from "stripe";
3
+ export interface PreviewPricingContext {
4
+ billingDate: Date;
5
+ usageThrough: Date | null;
6
+ computedAt: Date;
7
+ }
8
+ export declare function toAvailablePreview(invoice: Stripe.Invoice, pricing: PreviewPricingContext): AvailableUpcomingInvoicePreview;
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toAvailablePreview = toAvailablePreview;
4
+ const invoice_line_items_1 = require("../invoice-line-items");
5
+ const MS_PER_SECOND = 1000;
6
+ const REVERSE_CHARGE_REASON = "reverse_charge";
7
+ const SUBSCRIPTION_LINE_TYPE = "subscription";
8
+ function toIsoDate(seconds) {
9
+ return new Date(seconds * MS_PER_SECOND).toISOString();
10
+ }
11
+ function sumAmounts(amounts) {
12
+ return (amounts ?? []).reduce((total, entry) => total + entry.amount, 0);
13
+ }
14
+ function toLineKind(line) {
15
+ if (line.type === SUBSCRIPTION_LINE_TYPE)
16
+ return "subscription";
17
+ return line.metadata?.[invoice_line_items_1.LINE_KEY_METADATA] ? "usage" : "invoice_item";
18
+ }
19
+ function toPreviewLine(line) {
20
+ return {
21
+ kind: toLineKind(line),
22
+ description: line.description,
23
+ amountMinorUnits: line.amount_excluding_tax ?? line.amount,
24
+ taxMinorUnits: sumAmounts(line.tax_amounts),
25
+ quantity: line.quantity,
26
+ periodStart: toIsoDate(line.period.start),
27
+ periodEnd: toIsoDate(line.period.end),
28
+ isProration: line.proration,
29
+ usageLineKey: line.metadata?.[invoice_line_items_1.LINE_KEY_METADATA] ?? null,
30
+ };
31
+ }
32
+ function toUppercase(value) {
33
+ return value ? value.toUpperCase() : null;
34
+ }
35
+ function expandedTaxRate(taxRate) {
36
+ return typeof taxRate === "string" ? null : taxRate;
37
+ }
38
+ function toPreviewTax(taxAmount) {
39
+ const rate = expandedTaxRate(taxAmount.tax_rate);
40
+ return {
41
+ amountMinorUnits: taxAmount.amount,
42
+ taxableAmountMinorUnits: taxAmount.taxable_amount,
43
+ isInclusive: taxAmount.inclusive,
44
+ ratePercentage: rate
45
+ ? (rate.effective_percentage ?? rate.percentage)
46
+ : null,
47
+ country: toUppercase(rate?.country),
48
+ taxType: rate?.tax_type ?? null,
49
+ displayName: rate?.display_name ?? null,
50
+ jurisdiction: rate?.jurisdiction ?? null,
51
+ taxabilityReason: taxAmount.taxability_reason,
52
+ isReverseCharge: taxAmount.taxability_reason === REVERSE_CHARGE_REASON,
53
+ };
54
+ }
55
+ function resolveTaxCountry(invoice, taxes) {
56
+ const taxedCountry = taxes.find((tax) => tax.country)?.country;
57
+ return taxedCountry ?? toUppercase(invoice.customer_address?.country);
58
+ }
59
+ function toAvailablePreview(invoice, pricing) {
60
+ const taxes = (invoice.total_tax_amounts ?? []).map(toPreviewTax);
61
+ const taxMinorUnits = sumAmounts(invoice.total_tax_amounts);
62
+ return {
63
+ status: "available",
64
+ currency: invoice.currency.toUpperCase(),
65
+ lines: invoice.lines.data.map(toPreviewLine),
66
+ hasMoreLines: invoice.lines.has_more,
67
+ subtotalMinorUnits: invoice.subtotal_excluding_tax ?? invoice.subtotal,
68
+ totalExcludingTaxMinorUnits: invoice.total_excluding_tax ?? invoice.total - taxMinorUnits,
69
+ taxMinorUnits,
70
+ taxes,
71
+ taxCountry: resolveTaxCountry(invoice, taxes),
72
+ isReverseCharge: taxes.some((tax) => tax.isReverseCharge),
73
+ totalMinorUnits: invoice.total,
74
+ amountDueMinorUnits: invoice.amount_due,
75
+ periodStart: toIsoDate(invoice.period_start),
76
+ periodEnd: toIsoDate(invoice.period_end),
77
+ billingDate: pricing.billingDate.toISOString(),
78
+ usageThrough: pricing.usageThrough?.toISOString() ?? null,
79
+ computedAt: pricing.computedAt.toISOString(),
80
+ };
81
+ }
82
+ //# sourceMappingURL=mapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapping.js","sourceRoot":"","sources":["../../src/upcoming-invoice/mapping.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { UpcomingInvoicePreview, UpcomingInvoicePreviewAbsenceReason, UpcomingInvoicePreviewUnavailableReason } from "@antelopejs/interface-dms-saas/billing";
2
+ export interface AbsentPreviewOutcome {
3
+ status: "absent";
4
+ reason: UpcomingInvoicePreviewAbsenceReason;
5
+ }
6
+ export interface UnavailablePreviewOutcome {
7
+ status: "unavailable";
8
+ reason: UpcomingInvoicePreviewUnavailableReason;
9
+ }
10
+ export type PreviewOutcome = AbsentPreviewOutcome | UnavailablePreviewOutcome;
11
+ export declare function absent(reason: UpcomingInvoicePreviewAbsenceReason): AbsentPreviewOutcome;
12
+ export declare function unavailable(reason: UpcomingInvoicePreviewUnavailableReason): UnavailablePreviewOutcome;
13
+ export declare function stampOutcome(outcome: PreviewOutcome, computedAt: Date): UpcomingInvoicePreview;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.absent = absent;
4
+ exports.unavailable = unavailable;
5
+ exports.stampOutcome = stampOutcome;
6
+ function absent(reason) {
7
+ return { status: "absent", reason };
8
+ }
9
+ function unavailable(reason) {
10
+ return { status: "unavailable", reason };
11
+ }
12
+ function stampOutcome(outcome, computedAt) {
13
+ return { ...outcome, computedAt: computedAt.toISOString() };
14
+ }
15
+ //# sourceMappingURL=outcomes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outcomes.js","sourceRoot":"","sources":["../../src/upcoming-invoice/outcomes.ts"],"names":[],"mappings":";;AAoBA,wBAIC;AAED,kCAIC;AAED,oCAKC;AAjBD,SAAgB,MAAM,CACpB,MAA2C;IAE3C,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;AACtC,CAAC;AAED,SAAgB,WAAW,CACzB,MAA+C;IAE/C,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC;AAC3C,CAAC;AAED,SAAgB,YAAY,CAC1B,OAAuB,EACvB,UAAgB;IAEhB,OAAO,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,UAAU,CAAC,WAAW,EAAE,EAAE,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { UpcomingInvoicePreview } from "@antelopejs/interface-dms-saas/billing";
2
+ export declare function getUpcomingInvoicePreview(tenantId: string): Promise<UpcomingInvoicePreview>;
3
+ export declare function invalidateUpcomingInvoicePreview(tenantId: string): Promise<void>;
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getUpcomingInvoicePreview = getUpcomingInvoicePreview;
4
+ exports.invalidateUpcomingInvoicePreview = invalidateUpcomingInvoicePreview;
5
+ const logging_1 = require("@antelopejs/interface-core/logging");
6
+ const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
7
+ const config_1 = require("../config");
8
+ const db_1 = require("../db");
9
+ const preview_cache_model_1 = require("./db/preview-cache.model");
10
+ const eligibility_1 = require("./eligibility");
11
+ const outcomes_1 = require("./outcomes");
12
+ const pricing_1 = require("./pricing");
13
+ const LOG_PREFIX = "[dms-saas:upcoming-invoice]";
14
+ const MISSING_ROW_VERSION = "none";
15
+ const SOURCE_VERSION_SEPARATOR = "|";
16
+ function rowVersion(row) {
17
+ return row?.updatedAt
18
+ ? new Date(row.updatedAt).toISOString()
19
+ : MISSING_ROW_VERSION;
20
+ }
21
+ function toSourceVersion(subscription, billingInfo) {
22
+ return [rowVersion(subscription), rowVersion(billingInfo)].join(SOURCE_VERSION_SEPARATOR);
23
+ }
24
+ async function readCachedPreview(tenantId, sourceVersion, computedNotBefore) {
25
+ try {
26
+ return await (0, interface_database_decorators_1.GetModel)(preview_cache_model_1.UpcomingInvoicePreviewCacheModel).readFresh({
27
+ tenantId,
28
+ sourceVersion,
29
+ computedNotBefore,
30
+ });
31
+ }
32
+ catch (error) {
33
+ logging_1.Logging.Error(`${LOG_PREFIX} cache read failed for ${tenantId}`, error);
34
+ return null;
35
+ }
36
+ }
37
+ async function cachePreview(tenantId, preview, sourceVersion, computedAt) {
38
+ if (preview.status === "unavailable")
39
+ return;
40
+ try {
41
+ await (0, interface_database_decorators_1.GetModel)(preview_cache_model_1.UpcomingInvoicePreviewCacheModel).store({
42
+ tenantId,
43
+ preview,
44
+ sourceVersion,
45
+ computedAt,
46
+ });
47
+ }
48
+ catch (error) {
49
+ logging_1.Logging.Error(`${LOG_PREFIX} cache write failed for ${tenantId}`, error);
50
+ }
51
+ }
52
+ async function getUpcomingInvoicePreview(tenantId) {
53
+ const now = new Date();
54
+ const [subscription, billingInfo] = await Promise.all([
55
+ (0, interface_database_decorators_1.GetModel)(db_1.TenantSubscriptionModel, tenantId).findOne(),
56
+ (0, interface_database_decorators_1.GetModel)(db_1.TenantBillingInfoModel, tenantId).findOne(),
57
+ ]);
58
+ const plan = subscription?.planId
59
+ ? await (0, interface_database_decorators_1.GetModel)(db_1.PlanModel).get(subscription.planId)
60
+ : undefined;
61
+ const eligibility = (0, eligibility_1.resolvePreviewEligibility)(subscription, plan);
62
+ if (!eligibility.isPreviewable)
63
+ return (0, outcomes_1.stampOutcome)(eligibility.outcome, now);
64
+ const ttlMs = (0, config_1.getUpcomingInvoicePreviewCacheTtlMs)();
65
+ const sourceVersion = toSourceVersion(subscription, billingInfo);
66
+ if (ttlMs > 0) {
67
+ const computedNotBefore = new Date(now.getTime() - ttlMs);
68
+ const cached = await readCachedPreview(tenantId, sourceVersion, computedNotBefore);
69
+ if (cached)
70
+ return cached;
71
+ }
72
+ const preview = await (0, pricing_1.priceUpcomingInvoice)(tenantId, eligibility.target, now);
73
+ if (ttlMs > 0)
74
+ await cachePreview(tenantId, preview, sourceVersion, now);
75
+ return preview;
76
+ }
77
+ async function invalidateUpcomingInvoicePreview(tenantId) {
78
+ await (0, interface_database_decorators_1.GetModel)(preview_cache_model_1.UpcomingInvoicePreviewCacheModel).invalidate(tenantId, new Date());
79
+ }
80
+ //# sourceMappingURL=preview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview.js","sourceRoot":"","sources":["../../src/upcoming-invoice/preview.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { UpcomingInvoicePreview } from "@antelopejs/interface-dms-saas/billing";
2
+ import type { PreviewableSubscription } from "./eligibility";
3
+ export declare function priceUpcomingInvoice(tenantId: string, target: PreviewableSubscription, computedAt: Date): Promise<UpcomingInvoicePreview>;