@unchainedshop/core-enrollments 3.0.0-alpha7 → 3.0.0-rc.12

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 (53) hide show
  1. package/lib/addToDate.d.ts +2 -0
  2. package/lib/addToDate.d.ts.map +1 -0
  3. package/lib/addToDate.js +39 -0
  4. package/lib/addToDate.js.map +1 -0
  5. package/lib/db/EnrollmentsCollection.d.ts +50 -1
  6. package/lib/db/EnrollmentsCollection.d.ts.map +1 -1
  7. package/lib/db/EnrollmentsCollection.js +7 -0
  8. package/lib/db/EnrollmentsCollection.js.map +1 -1
  9. package/lib/enrollments-index.d.ts +2 -4
  10. package/lib/enrollments-index.d.ts.map +1 -1
  11. package/lib/enrollments-index.js +2 -4
  12. package/lib/enrollments-index.js.map +1 -1
  13. package/lib/enrollments-settings.d.ts +3 -3
  14. package/lib/enrollments-settings.d.ts.map +1 -1
  15. package/lib/enrollments-settings.js.map +1 -1
  16. package/lib/module/configureEnrollmentsModule.d.ts +41 -54
  17. package/lib/module/configureEnrollmentsModule.d.ts.map +1 -1
  18. package/lib/module/configureEnrollmentsModule.js +22 -143
  19. package/lib/module/configureEnrollmentsModule.js.map +1 -1
  20. package/package.json +14 -14
  21. package/src/addToDate.ts +58 -0
  22. package/src/db/EnrollmentsCollection.ts +49 -1
  23. package/src/enrollments-index.ts +2 -6
  24. package/src/enrollments-settings.ts +2 -3
  25. package/src/module/buildFindSelector.test.ts +1 -1
  26. package/src/module/configureEnrollmentsModule.ts +77 -339
  27. package/tsconfig.json +5 -7
  28. package/lib/db/EnrollmentStatus.d.ts +0 -7
  29. package/lib/db/EnrollmentStatus.d.ts.map +0 -1
  30. package/lib/db/EnrollmentStatus.js +0 -8
  31. package/lib/db/EnrollmentStatus.js.map +0 -1
  32. package/lib/director/EnrollmentAdapter.d.ts +0 -7
  33. package/lib/director/EnrollmentAdapter.d.ts.map +0 -1
  34. package/lib/director/EnrollmentAdapter.js +0 -73
  35. package/lib/director/EnrollmentAdapter.js.map +0 -1
  36. package/lib/director/EnrollmentDirector.d.ts +0 -3
  37. package/lib/director/EnrollmentDirector.d.ts.map +0 -1
  38. package/lib/director/EnrollmentDirector.js +0 -46
  39. package/lib/director/EnrollmentDirector.js.map +0 -1
  40. package/lib/director/EnrollmentError.d.ts +0 -7
  41. package/lib/director/EnrollmentError.d.ts.map +0 -1
  42. package/lib/director/EnrollmentError.js +0 -8
  43. package/lib/director/EnrollmentError.js.map +0 -1
  44. package/lib/types.d.ts +0 -100
  45. package/lib/types.d.ts.map +0 -1
  46. package/lib/types.js +0 -8
  47. package/lib/types.js.map +0 -1
  48. package/src/db/EnrollmentStatus.ts +0 -6
  49. package/src/director/EnrollmentAdapter.ts +0 -82
  50. package/src/director/EnrollmentDirector.ts +0 -60
  51. package/src/director/EnrollmentError.ts +0 -6
  52. package/src/module/periodForReferenceDate.test.ts +0 -23
  53. package/src/types.ts +0 -113
@@ -1,46 +0,0 @@
1
- import { log, LogLevel } from '@unchainedshop/logger';
2
- import { BaseDirector } from '@unchainedshop/utils';
3
- const baseDirector = BaseDirector('EnrollmentDirector', {
4
- adapterSortKey: 'orderIndex',
5
- });
6
- const findAppropriateAdapters = (productPlan) => baseDirector.getAdapters({
7
- adapterFilter: (Adapter) => {
8
- const activated = Adapter.isActivatedFor(productPlan);
9
- if (!activated) {
10
- log(`Enrollment Director -> ${Adapter.key} (${Adapter.version}) skipped`, {
11
- level: LogLevel.Warning,
12
- });
13
- }
14
- return activated;
15
- },
16
- });
17
- export const EnrollmentDirector = {
18
- ...baseDirector,
19
- transformOrderItemToEnrollment: async ({ orderPosition, product }, doc, unchainedAPI) => {
20
- const Adapter = findAppropriateAdapters(product.plan)?.[0];
21
- if (!Adapter) {
22
- throw new Error('No suitable enrollment plugin available for this item');
23
- }
24
- const enrollmentPlan = await Adapter.transformOrderItemToEnrollmentPlan(orderPosition, unchainedAPI);
25
- const enrollmentData = {
26
- ...doc,
27
- ...enrollmentPlan,
28
- configuration: [],
29
- };
30
- return enrollmentData;
31
- },
32
- actions: async (enrollmentContext, unchainedAPI) => {
33
- const context = { ...enrollmentContext, ...unchainedAPI };
34
- // Resolve adapter
35
- const product = await context.modules.products.findProduct({
36
- productId: context.enrollment.productId,
37
- });
38
- const Adapter = findAppropriateAdapters(product?.plan)?.[0];
39
- if (!Adapter) {
40
- throw new Error('No suitable enrollment plugin available for this plan configuration');
41
- }
42
- const adapter = Adapter.actions(context);
43
- return adapter;
44
- },
45
- };
46
- //# sourceMappingURL=EnrollmentDirector.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EnrollmentDirector.js","sourceRoot":"","sources":["../../src/director/EnrollmentDirector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,MAAM,YAAY,GAAG,YAAY,CAAqB,oBAAoB,EAAE;IAC1E,cAAc,EAAE,YAAY;CAC7B,CAAC,CAAC;AAEH,MAAM,uBAAuB,GAAG,CAAC,WAAyB,EAAE,EAAE,CAC5D,YAAY,CAAC,WAAW,CAAC;IACvB,aAAa,EAAE,CAAC,OAA2B,EAAE,EAAE;QAC7C,MAAM,SAAS,GAAG,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QACtD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,GAAG,CAAC,0BAA0B,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC,OAAO,WAAW,EAAE;gBACxE,KAAK,EAAE,QAAQ,CAAC,OAAO;aACxB,CAAC,CAAC;QACL,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,kBAAkB,GAAwB;IACrD,GAAG,YAAY;IAEf,8BAA8B,EAAE,KAAK,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,YAAY,EAAE,EAAE;QACtF,MAAM,OAAO,GAAG,uBAAuB,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC3E,CAAC;QAED,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,kCAAkC,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;QAErG,MAAM,cAAc,GAAmB;YACrC,GAAG,GAAG;YACN,GAAG,cAAc;YACjB,aAAa,EAAE,EAAE;SAClB,CAAC;QAEF,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,EAAE;QACjD,MAAM,OAAO,GAAG,EAAE,GAAG,iBAAiB,EAAE,GAAG,YAAY,EAAE,CAAC;QAE1D,kBAAkB;QAClB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;YACzD,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,SAAS;SACxC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,uBAAuB,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAE5D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;QACzF,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAEzC,OAAO,OAAO,CAAC;IACjB,CAAC;CACF,CAAC"}
@@ -1,7 +0,0 @@
1
- export declare enum EnrollmentError {
2
- ADAPTER_NOT_FOUND = "ADAPTER_NOT_FOUND",
3
- NOT_IMPLEMENTED = "NOT_IMPLEMENTED",
4
- INCOMPLETE_CONFIGURATION = "INCOMPLETE_CONFIGURATION",
5
- WRONG_CREDENTIALS = "WRONG_CREDENTIALS"
6
- }
7
- //# sourceMappingURL=EnrollmentError.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EnrollmentError.d.ts","sourceRoot":"","sources":["../../src/director/EnrollmentError.ts"],"names":[],"mappings":"AAAA,oBAAY,eAAe;IACzB,iBAAiB,sBAAsB;IACvC,eAAe,oBAAoB;IACnC,wBAAwB,6BAA6B;IACrD,iBAAiB,sBAAsB;CACxC"}
@@ -1,8 +0,0 @@
1
- export var EnrollmentError;
2
- (function (EnrollmentError) {
3
- EnrollmentError["ADAPTER_NOT_FOUND"] = "ADAPTER_NOT_FOUND";
4
- EnrollmentError["NOT_IMPLEMENTED"] = "NOT_IMPLEMENTED";
5
- EnrollmentError["INCOMPLETE_CONFIGURATION"] = "INCOMPLETE_CONFIGURATION";
6
- EnrollmentError["WRONG_CREDENTIALS"] = "WRONG_CREDENTIALS";
7
- })(EnrollmentError || (EnrollmentError = {}));
8
- //# sourceMappingURL=EnrollmentError.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EnrollmentError.js","sourceRoot":"","sources":["../../src/director/EnrollmentError.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,eAKX;AALD,WAAY,eAAe;IACzB,0DAAuC,CAAA;IACvC,sDAAmC,CAAA;IACnC,wEAAqD,CAAA;IACrD,0DAAuC,CAAA;AACzC,CAAC,EALW,eAAe,KAAf,eAAe,QAK1B"}
package/lib/types.d.ts DELETED
@@ -1,100 +0,0 @@
1
- import type { IBaseAdapter, IBaseDirector } from '@unchainedshop/utils';
2
- import type { TimestampFields, LogFields, Address, Contact } from '@unchainedshop/mongodb';
3
- import { Product, ProductPlan } from '@unchainedshop/core-products';
4
- import { OrderPosition } from '@unchainedshop/core-orders';
5
- import { UnchainedCore } from '@unchainedshop/core';
6
- export declare enum EnrollmentStatus {
7
- INITIAL = "INITIAL",
8
- ACTIVE = "ACTIVE",
9
- PAUSED = "PAUSED",
10
- TERMINATED = "TERMINATED"
11
- }
12
- export interface EnrollmentPeriod {
13
- start: Date;
14
- end: Date;
15
- orderId?: string;
16
- isTrial?: boolean;
17
- }
18
- export interface EnrollmentPlan {
19
- configuration: Array<{
20
- key: string;
21
- value: string;
22
- }>;
23
- productId: string;
24
- quantity: number;
25
- }
26
- export type EnrollmentQuery = {
27
- status?: Array<EnrollmentStatus>;
28
- userId?: string;
29
- queryString?: string;
30
- };
31
- export type Enrollment = {
32
- _id?: string;
33
- billingAddress: Address;
34
- configuration: Array<{
35
- key: string;
36
- value: string;
37
- }>;
38
- contact: Contact;
39
- context?: any;
40
- countryCode?: string;
41
- currencyCode?: string;
42
- delivery: {
43
- deliveryProviderId?: string;
44
- context?: any;
45
- };
46
- enrollmentNumber?: string;
47
- expires?: Date;
48
- meta?: any;
49
- payment: {
50
- paymentProviderId?: string;
51
- context?: any;
52
- };
53
- periods: Array<EnrollmentPeriod>;
54
- productId: string;
55
- quantity?: number;
56
- status: string;
57
- userId: string;
58
- } & LogFields & TimestampFields;
59
- export type EnrollmentContext = {
60
- enrollment: Enrollment;
61
- };
62
- export interface EnrollmentAdapterActions {
63
- configurationForOrder: (params: {
64
- period: EnrollmentPeriod;
65
- products: Array<Product>;
66
- }) => Promise<any>;
67
- isOverdue: () => Promise<boolean>;
68
- isValidForActivation: () => Promise<boolean>;
69
- nextPeriod: () => Promise<EnrollmentPeriod>;
70
- }
71
- export type IEnrollmentAdapter = IBaseAdapter & {
72
- isActivatedFor: (productPlan?: ProductPlan) => boolean;
73
- transformOrderItemToEnrollmentPlan: (orderPosition: OrderPosition, unchainedAPI: UnchainedCore) => Promise<EnrollmentPlan>;
74
- actions: (params: EnrollmentContext & UnchainedCore) => EnrollmentAdapterActions;
75
- };
76
- export interface EnrollmentData {
77
- billingAddress: Address;
78
- configuration?: Array<{
79
- key: string;
80
- value: string;
81
- }>;
82
- contact: Contact;
83
- countryCode?: string;
84
- currencyCode?: string;
85
- delivery: Enrollment['delivery'];
86
- meta?: any;
87
- orderIdForFirstPeriod?: string;
88
- payment: Enrollment['payment'];
89
- productId: string;
90
- quantity: number;
91
- userId: string;
92
- }
93
- export type IEnrollmentDirector = IBaseDirector<IEnrollmentAdapter> & {
94
- transformOrderItemToEnrollment: (item: {
95
- orderPosition: OrderPosition;
96
- product: Product;
97
- }, doc: Omit<EnrollmentData, 'configuration' | 'productId' | 'quantity'>, unchainedAPI: UnchainedCore) => Promise<EnrollmentData>;
98
- actions: (enrollmentContext: EnrollmentContext, unchainedAPI: UnchainedCore) => Promise<EnrollmentAdapterActions>;
99
- };
100
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/lib/types.js DELETED
@@ -1,8 +0,0 @@
1
- export var EnrollmentStatus;
2
- (function (EnrollmentStatus) {
3
- EnrollmentStatus["INITIAL"] = "INITIAL";
4
- EnrollmentStatus["ACTIVE"] = "ACTIVE";
5
- EnrollmentStatus["PAUSED"] = "PAUSED";
6
- EnrollmentStatus["TERMINATED"] = "TERMINATED";
7
- })(EnrollmentStatus || (EnrollmentStatus = {}));
8
- //# sourceMappingURL=types.js.map
package/lib/types.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAMA,MAAM,CAAN,IAAY,gBAKX;AALD,WAAY,gBAAgB;IAC1B,uCAAmB,CAAA;IACnB,qCAAiB,CAAA;IACjB,qCAAiB,CAAA;IACjB,6CAAyB,CAAA;AAC3B,CAAC,EALW,gBAAgB,KAAhB,gBAAgB,QAK3B"}
@@ -1,6 +0,0 @@
1
- export enum EnrollmentStatus {
2
- INITIAL = 'INITIAL',
3
- ACTIVE = 'ACTIVE',
4
- PAUSED = 'PAUSED',
5
- TERMINATED = 'TERMINATED',
6
- }
@@ -1,82 +0,0 @@
1
- import { log, LogLevel } from '@unchainedshop/logger';
2
- import { add } from 'date-fns/add';
3
- import { IEnrollmentAdapter } from '../types.js';
4
-
5
- export const periodForReferenceDate = (referenceDate: Date, intervalCount = 1, interval = 'WEEKS') => {
6
- const lowerCaseInterval = interval.toLowerCase();
7
-
8
- const start = new Date(referenceDate);
9
- if (lowerCaseInterval === 'hours') {
10
- start.setMinutes(0, 0, 0);
11
- } else {
12
- start.setSeconds(0, 0);
13
- }
14
-
15
- return {
16
- start,
17
- end: add(start, {
18
- [lowerCaseInterval]: intervalCount,
19
- }),
20
- };
21
- };
22
-
23
- export const EnrollmentAdapter: Omit<IEnrollmentAdapter, 'key' | 'label' | 'version'> = {
24
- isActivatedFor: () => {
25
- return false;
26
- },
27
-
28
- transformOrderItemToEnrollmentPlan: async (item) => {
29
- return {
30
- configuration: item.configuration,
31
- productId: item.productId,
32
- quantity: item.quantity,
33
- };
34
- },
35
-
36
- actions: (context) => {
37
- return {
38
- configurationForOrder: async () => {
39
- throw new Error(`Not implemented on EnrollmentAdapter`);
40
- },
41
-
42
- isOverdue: async () => false,
43
- isValidForActivation: async () => false,
44
-
45
- nextPeriod: async () => {
46
- const { enrollment } = context;
47
- const product = await context.modules.products.findProduct({
48
- productId: enrollment.productId,
49
- });
50
- const plan = product?.plan;
51
- const referenceDate = new Date();
52
- if (!plan) return null;
53
-
54
- if (plan.trialIntervalCount && !enrollment?.periods?.length) {
55
- return {
56
- ...periodForReferenceDate(referenceDate, plan.trialIntervalCount, plan.trialInterval),
57
- isTrial: true,
58
- };
59
- }
60
-
61
- const lastEnd = enrollment?.periods?.reduce((acc, item) => {
62
- if (!acc) return item.end;
63
- const endDate = new Date(item.end);
64
- if (acc.getTime() < endDate.getTime()) {
65
- return endDate;
66
- }
67
- return acc;
68
- }, referenceDate);
69
-
70
- return {
71
- ...periodForReferenceDate(lastEnd, plan.billingIntervalCount, plan.billingInterval),
72
- isTrial: false,
73
- };
74
- },
75
- };
76
- },
77
-
78
- // eslint-disable-next-line
79
- log(message: string, { level = LogLevel.Debug, ...options } = {}) {
80
- return log(message, { level, ...options });
81
- },
82
- };
@@ -1,60 +0,0 @@
1
- import { EnrollmentData, IEnrollmentAdapter, IEnrollmentDirector } from '../types.js';
2
- import { ProductPlan } from '@unchainedshop/core-products';
3
- import { log, LogLevel } from '@unchainedshop/logger';
4
- import { BaseDirector } from '@unchainedshop/utils';
5
-
6
- const baseDirector = BaseDirector<IEnrollmentAdapter>('EnrollmentDirector', {
7
- adapterSortKey: 'orderIndex',
8
- });
9
-
10
- const findAppropriateAdapters = (productPlan?: ProductPlan) =>
11
- baseDirector.getAdapters({
12
- adapterFilter: (Adapter: IEnrollmentAdapter) => {
13
- const activated = Adapter.isActivatedFor(productPlan);
14
- if (!activated) {
15
- log(`Enrollment Director -> ${Adapter.key} (${Adapter.version}) skipped`, {
16
- level: LogLevel.Warning,
17
- });
18
- }
19
- return activated;
20
- },
21
- });
22
-
23
- export const EnrollmentDirector: IEnrollmentDirector = {
24
- ...baseDirector,
25
-
26
- transformOrderItemToEnrollment: async ({ orderPosition, product }, doc, unchainedAPI) => {
27
- const Adapter = findAppropriateAdapters(product.plan)?.[0];
28
- if (!Adapter) {
29
- throw new Error('No suitable enrollment plugin available for this item');
30
- }
31
-
32
- const enrollmentPlan = await Adapter.transformOrderItemToEnrollmentPlan(orderPosition, unchainedAPI);
33
-
34
- const enrollmentData: EnrollmentData = {
35
- ...doc,
36
- ...enrollmentPlan,
37
- configuration: [],
38
- };
39
-
40
- return enrollmentData;
41
- },
42
-
43
- actions: async (enrollmentContext, unchainedAPI) => {
44
- const context = { ...enrollmentContext, ...unchainedAPI };
45
-
46
- // Resolve adapter
47
- const product = await context.modules.products.findProduct({
48
- productId: context.enrollment.productId,
49
- });
50
-
51
- const Adapter = findAppropriateAdapters(product?.plan)?.[0];
52
-
53
- if (!Adapter) {
54
- throw new Error('No suitable enrollment plugin available for this plan configuration');
55
- }
56
- const adapter = Adapter.actions(context);
57
-
58
- return adapter;
59
- },
60
- };
@@ -1,6 +0,0 @@
1
- export enum EnrollmentError {
2
- ADAPTER_NOT_FOUND = 'ADAPTER_NOT_FOUND',
3
- NOT_IMPLEMENTED = 'NOT_IMPLEMENTED',
4
- INCOMPLETE_CONFIGURATION = 'INCOMPLETE_CONFIGURATION',
5
- WRONG_CREDENTIALS = 'WRONG_CREDENTIALS',
6
- }
@@ -1,23 +0,0 @@
1
- import { periodForReferenceDate } from '../director/EnrollmentAdapter.js';
2
-
3
- describe('periodForReferenceDate', () => {
4
- it('Should return 1 week interval from When passed a given date', () => {
5
- expect(periodForReferenceDate(new Date('2022-12-03T17:00:00.000Z'))).toEqual({
6
- start: new Date('2022-12-03T17:00:00.000Z'),
7
- end: new Date('2022-12-10T17:00:00.000Z'),
8
- });
9
- });
10
- it('Should return 2 week interval from When passed 2 as interval', () => {
11
- expect(periodForReferenceDate(new Date('2022-12-03T17:00:00.000Z'), 2)).toEqual({
12
- start: new Date('2022-12-03T17:00:00.000Z'),
13
- end: new Date('2022-12-17T17:00:00.000Z'),
14
- });
15
- });
16
-
17
- it('Should return 2 HOURS when interval is set to HOURS', () => {
18
- expect(periodForReferenceDate(new Date('2022-12-03T17:00:00.000Z'), 2, 'HOURS')).toEqual({
19
- start: new Date('2022-12-03T17:00:00.000Z'),
20
- end: new Date('2022-12-03T19:00:00.000Z'),
21
- });
22
- });
23
- });
package/src/types.ts DELETED
@@ -1,113 +0,0 @@
1
- import type { IBaseAdapter, IBaseDirector } from '@unchainedshop/utils';
2
- import type { TimestampFields, LogFields, Address, Contact } from '@unchainedshop/mongodb';
3
- import { Product, ProductPlan } from '@unchainedshop/core-products';
4
- import { OrderPosition } from '@unchainedshop/core-orders';
5
- import { UnchainedCore } from '@unchainedshop/core';
6
-
7
- export enum EnrollmentStatus {
8
- INITIAL = 'INITIAL',
9
- ACTIVE = 'ACTIVE',
10
- PAUSED = 'PAUSED',
11
- TERMINATED = 'TERMINATED',
12
- }
13
-
14
- export interface EnrollmentPeriod {
15
- start: Date;
16
- end: Date;
17
- orderId?: string;
18
- isTrial?: boolean;
19
- }
20
-
21
- export interface EnrollmentPlan {
22
- configuration: Array<{ key: string; value: string }>;
23
- productId: string;
24
- quantity: number;
25
- }
26
-
27
- export type EnrollmentQuery = {
28
- status?: Array<EnrollmentStatus>;
29
- userId?: string;
30
- queryString?: string;
31
- };
32
-
33
- export type Enrollment = {
34
- _id?: string;
35
- billingAddress: Address;
36
- configuration: Array<{ key: string; value: string }>;
37
- contact: Contact;
38
- context?: any;
39
- countryCode?: string;
40
- currencyCode?: string;
41
- delivery: {
42
- deliveryProviderId?: string;
43
- context?: any;
44
- };
45
- enrollmentNumber?: string;
46
- expires?: Date;
47
- meta?: any;
48
- payment: {
49
- paymentProviderId?: string;
50
- context?: any;
51
- };
52
- periods: Array<EnrollmentPeriod>;
53
- productId: string;
54
- quantity?: number;
55
- status: string;
56
- userId: string;
57
- } & LogFields &
58
- TimestampFields;
59
-
60
- // Director
61
-
62
- export type EnrollmentContext = {
63
- enrollment: Enrollment;
64
- };
65
-
66
- export interface EnrollmentAdapterActions {
67
- configurationForOrder: (params: {
68
- period: EnrollmentPeriod;
69
- products: Array<Product>;
70
- }) => Promise<any>;
71
- isOverdue: () => Promise<boolean>;
72
- isValidForActivation: () => Promise<boolean>;
73
- nextPeriod: () => Promise<EnrollmentPeriod>;
74
- }
75
-
76
- export type IEnrollmentAdapter = IBaseAdapter & {
77
- isActivatedFor: (productPlan?: ProductPlan) => boolean;
78
-
79
- transformOrderItemToEnrollmentPlan: (
80
- orderPosition: OrderPosition,
81
- unchainedAPI: UnchainedCore,
82
- ) => Promise<EnrollmentPlan>;
83
-
84
- actions: (params: EnrollmentContext & UnchainedCore) => EnrollmentAdapterActions;
85
- };
86
-
87
- export interface EnrollmentData {
88
- billingAddress: Address;
89
- configuration?: Array<{ key: string; value: string }>;
90
- contact: Contact;
91
- countryCode?: string;
92
- currencyCode?: string;
93
- delivery: Enrollment['delivery'];
94
- meta?: any;
95
- orderIdForFirstPeriod?: string;
96
- payment: Enrollment['payment'];
97
- productId: string;
98
- quantity: number;
99
- userId: string;
100
- }
101
-
102
- export type IEnrollmentDirector = IBaseDirector<IEnrollmentAdapter> & {
103
- transformOrderItemToEnrollment: (
104
- item: { orderPosition: OrderPosition; product: Product },
105
- doc: Omit<EnrollmentData, 'configuration' | 'productId' | 'quantity'>,
106
- unchainedAPI: UnchainedCore,
107
- ) => Promise<EnrollmentData>;
108
-
109
- actions: (
110
- enrollmentContext: EnrollmentContext,
111
- unchainedAPI: UnchainedCore,
112
- ) => Promise<EnrollmentAdapterActions>;
113
- };